Repository navigation
Wi Fi Direct
Wi-Fi Direct is the second link to the glasses, next to Bluetooth. The phone owns a Wi-Fi Direct group, the glasses join it, and the same session then runs over TCP. Bulk media and live video use it, because Bluetooth is too slow for either.
Bluetooth carries about 120 to 165 KB/s of media. Over Wi-Fi Direct the same media moves about 10 MB/s. A 4 Mbit/s HEVC stream does not fit in the Bluetooth figure of about 1 Mbit/s, which is unconfirmed. See Throughput.
Service 10 is ATC LinkManager2. It moves the glasses onto a network. It needs a scoped link, which the session gets at EndLinkSetup. The join carries a v4 UUID of its own as well. See Link-setup-and-AirShield.
| Type | Name | Direction | Use |
|---|---|---|---|
| 0x1010 | JoinAccessPoint | phone to glasses | Puts the glasses on the phone's group |
| 0x1011 | JoinAccessPointResult | glasses to phone | Status, address and port |
| 0x1012 | LeaveAccessPoint | phone to glasses | Sent before the group goes, empty body |
JoinWifiDirectGroup (0x100b) fails with status 3 (JOIN_FAILED). The phone uses JoinAccessPoint instead.
An unknown type gets answer 0xd001. A known type with a body that will not parse gets 0xd010.
The phone sends the join over the Bluetooth session.
| Field | Type | Content | Rule |
|---|---|---|---|
| 1 | string | SSID | The group name the phone chose |
| 2 | string | Passphrase | 20 characters |
| 3 | bytes, 16 | UUID | Must be version 4: byte 6 high nibble 0x4, byte 8 high bits 10 |
| 4 | varint | Bandwidth | 0 unspecified, 1 20 MHz, 2 40 MHz, 3 80 MHz |
A join without a valid v4 UUID gets status 2 and never reaches the radio. The rule is the same one EndLinkSetup needs.
Field 4 is sent but has no effect on a join. The glasses use the bandwidth only for a SoftAP of their own. A join that asked for 20 MHz still brought the group up at 80 MHz.
| Field | Type | Content | Notes |
|---|---|---|---|
| 1 | varint | Status | 1 SUCCESS, 2 INTERNAL_ERROR, 3 JOIN_FAILED, 4 UNAVAILABLE, 5 BAD_INPUT, 6 TIMED_OUT, 7 CANCELLED, 8 BUSY, 9 WIFI_NOT_ENABLED, 10 THROTTLED_THERMAL, 11 THROTTLED_LOW_BATTERY |
| 2 | message, repeated | Addresses | Each NetworkAddress holds the address as text in field 3 |
| 3 | varint | Port | Chosen by the glasses for each join |
A usable result has status 1, an address and a port above zero.
After a Wi-Fi firmware restart the join answers INTERNAL_ERROR for 15 to 45 s. See The 80 MHz firmware hang.
The phone owns the group. The glasses only join.
The glasses have a client that joins a group. No request makes them create one. The Meta app works the same way: the phone is the group owner and gives the glasses a client address. The phone's group-owner address is usually 192.168.49.1. The glasses report their own address in the join result.
The phone starts the group, asks for the join over Bluetooth, connects TCP, and only then pauses Bluetooth.
sequenceDiagram
participant Phone
participant Glasses
Note over Phone: group up with SSID and passphrase
Phone->>Glasses: 0x1010 JoinAccessPoint over Bluetooth
Glasses-->>Phone: 0x1011 status 1, address, port
Phone->>Glasses: TCP connect to address and port
Phone->>Glasses: AirShield handshake, trust, EndLinkSetup
Glasses-->>Phone: EndLinkSetup, services ready
Note over Phone: Bluetooth session paused
Note over Glasses: leaves Bluetooth once on Wi-Fi
The steps in order:
- The phone starts the group with its SSID and passphrase.
- The phone sends JoinAccessPoint over Bluetooth. Once the glasses are on Wi-Fi they leave Bluetooth, and a later request on Bluetooth never arrives.
- The glasses answer with JoinAccessPointResult. A usable result has status 1, an address and a port.
- The phone opens TCP to the address and port. The socket carries raw SDUs with no length prefix, framed as on RFCOMM. See Transport-and-framing.
- The phone runs the normal session over TCP: AirShield, trust, EndLinkSetup. The glasses answer with EndLinkSetup and services ready.
- Only then does the phone pause the Bluetooth session.
Going back to Bluetooth:
- The phone sends LeaveAccessPoint over Wi-Fi. The Meta app sends it before the group goes.
- The phone stops the TCP session and removes the group.
- The phone resumes the Bluetooth session.
The glasses hold one AirShield session across all their links. A new session closes the old one.
An RFCOMM session that reaches READY while an LE session is ready closes the LE session within 50 ms. Each retry repeats this. A Wi-Fi session closes the LE session. An LE reconnect then closes the Wi-Fi session in the middle of a transfer.
So the phone pauses the Bluetooth session for the whole Wi-Fi job. The LE GATT link stays up. Only the session is paused.
A Live AI session is the exception. It runs over the Bluetooth session and does not pause it. See Live-stream.
| Path | Rate |
|---|---|
| Media over Wi-Fi Direct, 1.1 MB file | 10,036 KB/s |
| Media over Wi-Fi Direct, 20.8 MB video | 10,480 KB/s, about 2 s |
| Same media over Bluetooth Classic | 120 to 165 KB/s |
| 1080p at 4 Mbit/s HEVC on a 2.4 GHz group | Runs at 30 fps |
| Bluetooth link for video | About 1 Mbit/s, unconfirmed |
The rate does not fall as files get bigger. The 20 MB transfer ran slightly faster per byte than the 1 MB one.
On 5 GHz the video stream stops every time. The fault is in the glasses' Wi-Fi firmware.
- The group follows the phone's own Wi-Fi. On 5180 MHz the group runs at 80 MHz. Each join logs "Configured bandwidth is 80000000".
- The firmware logs "Received firmware hang event", then RDDM, then a subsystem restart. The phone sees the stream stall at that same moment.
- On 5 GHz the stream stops 6 to 15 s after it starts, every time.
- Right after the restart, JoinAccessPoint answers INTERNAL_ERROR for 15 to 45 s.
- A bulk transfer at 5 GHz did not hit the hang. The fault is in the video stream, not in throughput alone.
- On a 2.4 GHz group (20 MHz), 1080p at 4 Mbit/s runs clean.
- Setting field 4 of the join to 20 MHz does not prevent the hang.
Reference code: Wifi.kt
- Unconfirmed: whether 5 GHz at 20 or 40 MHz avoids the hang.
- Unconfirmed: whether a long bulk transfer at 5 GHz can hit the hang.
- Unconfirmed: whether LeaveAccessPoint is needed for the next join to succeed.
- Why the join answers INTERNAL_ERROR for up to 45 s after a restart is unknown.
- The effect of SetSessionInfo (0x1009) on a join is unknown. The phone does not send it.
- Unconfirmed: whether the group-owner address is 192.168.49.1 on every phone.
The glasses
The link
Identity
Media
Settings
Assistant