Repository navigation
Device state and build info
This page covers what the glasses push to the phone about their state and build. That is service 28 (device state), service 100 (build info and serial) and the capture signals on service 2000. Service 22 is covered too, although its messages are not decoded. Serial numbers, Bluetooth addresses and device uuids appear as placeholders: <serial>, AA:BB:CC:DD:EE:FF and <device-uuid>.
The phone sends the svc100 announce and then the svc28 subscribe, in that order. Neither needs identity auth. The glasses answer with a snapshot and then push one message per change. A push updates only the fields it carries. Fields it omits keep their last value.
The sequence below shows the subscribe and the pushes that follow it. The order of the service 100 answer and the service 28 pushes is unknown.
sequenceDiagram
participant Phone
participant Glasses
Phone->>Glasses: svc100 type 1 PeerAppInfo, empty, new channel
Phone->>Glasses: svc28 type 1000 subscribe, field 1 = 1, field 2 = interaction key
Glasses-->>Phone: svc28 type 1001 acknowledgement, about 30 ms later
Glasses-->>Phone: svc28 type 2005 full snapshot
Glasses-->>Phone: svc100 type 3 DeviceInfo
Glasses-->>Phone: svc28 type 2007 battery, on each change
Glasses-->>Phone: svc28 type 2015 mount, on each change
Phone->>Glasses: svc28 type 1000 again, on the same channel
Glasses-->>Phone: svc28 type 2005 fresh snapshot
A refresh sends the subscribe again on the same svc28 channel. The glasses answer with a new snapshot, and no extra push stream starts. A second svc28 channel would add a full set of pushes.
Service 28 is smartglasses_appmanager. The table lists the message types the glasses use on it, with the field that carries each one.
| Type | Direction | Kind | Notes |
|---|---|---|---|
| 1000 | Phone to glasses | subscribe |
CompanionDeviceInit, field 1 is a packed varint 1, field 2 is the interaction key |
| 1001 | Glasses to phone | acknowledgement | Two-byte protobuf |
| 2000 | Phone to glasses | start app | See the start-app section. This is a message type, not service 2000 |
| 2001 | Glasses to phone | start app response | See the start-app section |
| 2005 | Glasses to phone | device_state |
Full snapshot, once after the subscribe |
| 2006 | Glasses to phone | device_state_update |
General update, same shape as 2005 |
| 2007 | Glasses to phone | battery |
field 1 |
| 2008 | Glasses to phone | case_battery |
field 2 |
| 2009 | Glasses to phone | camera |
field 3 |
| 2010 | Glasses to phone | capture_button |
field 4 |
| 2011 | Glasses to phone | captouch |
field 5 |
| 2012 | Glasses to phone | hinge |
field 6 |
| 2013 | Glasses to phone | hardware |
field 7 |
| 2014 | Glasses to phone | led |
field 8 |
| 2015 | Glasses to phone | mount |
field 9 |
| 2016 | Glasses to phone | power |
field 10 |
| 2017 | Glasses to phone | storage |
field 11, the storage level |
| 2018 | Glasses to phone | tampering |
field 12 |
| 2019 | Glasses to phone | thermal |
field 13 |
| 2020 | Glasses to phone | verified_session |
field 14 |
| 2021 | Glasses to phone | peak_power |
field 15 |
| 2022 | Glasses to phone | audio_active |
field 16 |
| 2023 | Glasses to phone | streaming_active |
field 17 |
| 2024 | Glasses to phone | hot_car |
field 18 |
| 2025 | Glasses to phone | bluetooth |
field 19 |
| 2026 | Glasses to phone | app_interrupt |
field 20 |
| 2027 | Glasses to phone | storage_details |
field 21, the free and total space |
| 2028 | Glasses to phone | device_lock |
field 26 |
| 2029 | Glasses to phone | registered_apps |
field 22 |
| 2032 | Glasses to phone | volume |
field 25 |
| 2033 | Glasses to phone | apps |
field 27 |
| 2034 | Glasses to phone | call |
field 28 |
| 2035 | Glasses to phone | action_button |
field 29 |
| 2037 | Glasses to phone | assistant_attention |
field 31 |
| 2039 | Glasses to phone | peak_power_throttling |
No field is known. Its content is unknown |
| 2041 | Glasses to phone | water_detect |
field 35 |
| 2042 | Glasses to phone | camera_sensing |
field 36 |
| 2043 | Glasses to phone | odc |
field 37 |
| 2044 | Glasses to phone | verified_session_info |
No field is known. Its content is unknown |
| 2030, 2031, 2036, 2040 | Glasses to phone | EMG band | The glasses do not send these types |
The mapping from kind to field is inferred from the names.
The fields present in a message decide what it updates. The type number does not choose the fields.
The device state keeps every field as optional. A field that a message does not carry stays empty, so a partial push does not erase a reading. The table lists each field number, its name, its content and its unit.
| Field | Name | Content | Unit or value |
|---|---|---|---|
| 1 | battery |
sub-fields: 1 health enum, 2 charge enum, 3 level, 4 temperature, 5 voltage | level in percent. Temperature in milli-degrees C and voltage in millivolts. Divide each by 1000 once |
| 2 | case_battery |
sub-fields listed in the case section | see the case section |
| 3 | camera |
enum CAMERA_STATE
|
values 0 to 10, such as CAPTURE_READY (5) and CAPTURE_VIDEO_STARTED (2) |
| 4 | capture_button |
enum CAPTURE_BUTTON
|
values 0 to 8, such as SHORT_PRESS_DOWN (1) and DOUBLE_PRESS (8) |
| 5 | captouch |
enum CAPTOUCH
|
values 0 to 12, such as SINGLE_TAP (1) and SWIPE_FORWARD (5) |
| 6 | hinge |
enum HINGE
|
UNKNOWN (0), OPEN (1), CLOSED (2) |
| 7 | hardware |
1 dsp_ok, 2 imu_ok, 3 mcu_ok, 4 microphone_ok, 5 speaker_ok, 6 captouch_ok, all booleans | none |
| 8 | led |
1 led_ok, 2 privacy_led_ok, 3 led_active, 4 privacy_led_active, all booleans | none |
| 9 | mount |
enum MOUNT_STATE
|
NONE (0), DON (1, worn), DOFF (2, removed) |
| 10 | power |
1 deep_sleep_pending, 2 in_deep_sleep, both booleans | none |
| 11 | storage |
enum STORAGE_LEVEL
|
UNDEFINED (0), STABLE (1), LOW (2), ZERO (3) |
| 12 | tampering |
1 is_tampered, 2 lux, 3 is_indoor | lux, as given |
| 13 | thermal |
1 health enum, 2 temperature, 3 throttling boolean, 4 throttle reason | temperature unit unknown |
| 14 | verified_session |
boolean | none |
| 15 | peak_power |
repeated: 1 app id, 2 state enum | state enum PEAK_POWER
|
| 16 | audio_active |
boolean | none |
| 17 | streaming_active |
boolean | none |
| 18 | hot_car |
boolean | none |
| 19 | bluetooth |
1 ancs, 2 map, 3 pbap, 4 btc | ancs, map and pbap use the enum ANCS_STATE. btc uses BTC_STATE
|
| 20 | app_interrupt |
varint | app id |
| 21 | storage_details |
1 free, 2 total | megabytes. Field 1 is the space still free, not the space used |
| 22 | registered_apps |
repeated, 1 app id | app ids |
| 25 | volume |
1 level, 2 stream enum, 3 percent | percent for field 3. Level has no known unit |
| 26 | device_lock |
enum LOCK_STATE
|
NO_LOCK (0), LOCKED (1), UNLOCKED (2) |
| 27 | apps |
repeated: 1 app id, 2 state enum APP_STATE
|
UNKNOWN, ACTIVE, INACTIVE, PAUSED
|
| 28 | call |
1 state enum, 2 calling state enum, 3 platform enum, 4 start time | start time in milliseconds |
| 29 | action_button |
enum ACTION_BUTTON
|
UNKNOWN (0), SHORT_PRESS_DOWN (1), SHORT_PRESS_UP (2), LONG_PRESS_UP (3) |
| 31 | assistant_attention |
1 attention enum | see the attention section |
| 35 | water_detect |
enum WATER_DETECT
|
UNKNOWN, DETECTED, NOT_DETECTED
|
| 36 | camera_sensing |
enum CAMERA_SENSING
|
values 0 to 6 |
| 37 | odc |
enum ODC_STATE
|
values 0 to 5 |
| 39 | overhead |
boolean | none |
| 10000 | interaction_key |
string | the subscribe's uuid, echoed on every push |
The unit of field 12 is inferred from its name.
The glasses know the case only through the charging pins. Their last reading stays until the glasses lose it. After enough time out of the case the reading is empty: level -1, an empty serial, firmware 0.0.0 and the present flag 0. Sent as a varint, -1 is 0xFFFFFFFF, five bytes.
| Field | Name | Content |
|---|---|---|
| 1 | health |
enum BATTERY_HEALTH
|
| 2 | charging |
boolean, is charging |
| 3 | level |
signed 32-bit. -1 when the case is unknown |
| 4 | serial |
string. Empty means none |
| 5 | firmware |
string, the case firmware. 0.0.0 means none |
| 6 | incompatible_charger |
boolean |
| 7 | scale |
100 for a percentage, 4 for bars. Absent means 4 |
| 8 | present |
boolean, the case is present |
| 9 | platform |
enum CASE_PLATFORM, for example 253 is COCOS
|
| 10 | liquid_detected |
boolean |
The reading follows these steps:
- Read level as a signed 32-bit value. An unsigned read of -1 gives 4294967295 percent.
- Use scale 4 when field 7 is absent or zero.
- The case is known when 0 is at most the level, and the level is at most the scale.
- A percentage applies only when the case is known and the scale is 100.
Field 31 holds one enum: UNKNOWN (0), IDLE (1), WAKE (2), LISTENING (3), PROCESSING (4), RESPONDING (5) and LONG_RUNNING_SESSION_ACTIVATED (6). Value 6 is unconfirmed. It is unknown whether the glasses send it. The order of the attention values is unknown, so this page has no state diagram for them.
The phone starts an app on the glasses before a live stream. It sends service 28 type 2000 with field 1 set to the app id as a varint. The glasses answer on type 2001 with field 1 as a varint status code.
| Code | Meaning |
|---|---|
| 1 | started |
| 5 | unsupported app |
| 6 | not enough battery |
| 7 | thermal throttling |
| 9 | start failed |
| 12 | already running |
| 13 | not enough priority |
| 15 | denied by peak power |
| other | error, not listed here |
Before the phone starts an app on a Wi-Fi session, it subscribes to device state. See Live-stream.
Service 100 is peer_build_info. The phone sends type 1, PeerAppInfo, with an empty payload. The glasses answer on type 3 with DeviceInfo. The glasses send DeviceInfo only in answer to the empty announce, not on their own.
| Field | Content |
|---|---|
| 1 | build fingerprint string |
| 2 | serial number, <serial>
|
| 4 | device uuid, <device-uuid>, 36 characters in the 8-4-4-4-12 shape |
| 5 | not identified |
| 6 | Bluetooth address, AA:BB:CC:DD:EE:FF form |
| 7 | hardware stage, seen as PVT
|
| 8 | model codename, seen as greathammerhead
|
| 9 | not identified |
The build fingerprint has this shape. Firmware explains each part.
Meta/<product>/<device>:<release>/<build id>/<firmware version>:user/release-keys
A sample reads:
Meta/hammerhead/greathammerhead:14/UKQ1.250303.001/70523680060800100:user/release-keys
The number before :user is the firmware version. The same number names the newer firmware table in Service-catalogue.
Field 4 is needed for settings. The settings namespace is <device-uuid>@individual_device_settings. The phone cannot start a settings read until service 100 has answered. See Settings-and-RLDrive.
The strings use ISO-8859-1. Every byte maps to a character, so decoding cannot fail.
Service 22 is smartglasses_device_info. Its messages are flatbuffers, carried by a framework that is not named. The request appears to be a system-info call.
A type 2 message on svc22 is 180 or 198 bytes. The svc100 type 3 answer has the same size. The build and the serial come from svc100, so the svc22 content stays undecoded.
Service 2000 is media_capture_state. The glasses open a channel for it at link setup, within about 40 ms of the end of link setup. They send a ConcurrentSignal on message type 1. Field 1 is the signal name. Field 6 is the signal type.
The first message carries the name media_capture_state and the type ready. Only this signal is confirmed on hardware. Later signals come in start and stop pairs. These names are unconfirmed on the wire:
-
VIDEO_STARTEDandVIDEO_STOPPED -
HYPERLAPSE_STARTEDandHYPERLAPSE_STOPPED -
SLOWMOTION_STARTEDandSLOWMOTION_STOPPED -
DYNAMIC_PHOTO_STARTEDandDYNAMIC_PHOTO_STOPPED
A _STOPPED signal marks the end of a recording. A plain photo makes svc28 report CAPTURE_COMPLETED.
stateDiagram-v2
[*] --> Ready : ready signal, confirmed on hardware
Ready --> Recording : any *_STARTED signal
Recording --> Ready : the matching *_STOPPED signal
The diagram shows the start and stop pairs. The order between recording kinds is unknown, so the diagram has one recording state.
Reference code: Status.kt, DeviceInfo.kt, GlassesConnection.kt, LiveStream.kt
- Whether the field-to-kind mapping for svc28 is exact is unknown. The mapping above is inferred from the names.
- No svc28 type for field 39 (
overhead) is known. - The content of types 2039 and 2044 is unknown. No field is known for them.
- The thermal temperature unit is unknown.
- The lux unit in field 12 is inferred from its name.
- Fields 5 and 9 of the svc100 answer are not identified.
- Whether value 6 of the attention enum (
LONG_RUNNING_SESSION_ACTIVATED) arrives from the glasses is unknown. - The start-app status list may not be complete.
- Whether the pushes come back on the subscribe channel is unconfirmed.
- The content of the 1001 acknowledgement beyond its size is unknown.
- The svc22 content and transport are unknown.
- Only the
readysignal on service 2000 is confirmed. The other signal names are unconfirmed.
The glasses
The link
Identity
Media
Settings
Assistant