8a0b7832c0
AdbClient wraps the bundled libadb.so (useLegacyPackaging -> exec from nativeLibraryDir, HOME/TMPDIR overridden, adb key injected into BuildConfig from ~/.android at build time and never committed). ShizukuProvisioner: on each BLE+WiFi connect it enables ADB-over-WiFi via Mercury, connects with mDNS fallback, pushes the Shizuku starter and runs it; runs once per BLE session, does not relaunch GlassesApp when the WS channel is already up, and exposes runShell() for arbitrary commands. DebugReceiver (DUMP) + am start --ez provision for diagnostics. Protocol: ShizukuStatus(running/granted) + RequestShizukuStatus; glasses push it on connect and on Shizuku state change, using a passive probe() that never shows a permission dialog. Glasses kill-guard now recreates its UserService when the Shizuku binder dies instead of spamming DeadObjectException. Mercury: brightness disables auto-brightness first (was silently ignored), BLE auto-connect loop retries every 6s (fixes 'searches then stops'). New phone section 'Экран очков' with wake/sleep via adb (input keyevent 224/223).
141 lines
10 KiB
Markdown
141 lines
10 KiB
Markdown
# Тест автономного автозапуска GlassesApp (HOME + adb-бутстрап Shizuku) — ВЫВОДЫ
|
||
|
||
Цель: доказать, что GlassesApp может подниматься и оживлять Shizuku после холодной
|
||
перезагрузки **без Mercury-лаунчера и без USB-компьютера**.
|
||
|
||
Устройство: RayNeo X3 Pro, adb serial `A06B4AB933C4103`.
|
||
Дата экспериментов: 2026-09-25/26.
|
||
|
||
---
|
||
|
||
## ИТОГОВЫЙ ВЫВОД (кратко)
|
||
|
||
1. **Автозапуск через HOME не работает.** Наш пакет можно назначить дефолтным HOME
|
||
(`cmd package set-home-activity pw.binom.rayneovm.glasses/.MainActivity`, `isDefault=true`),
|
||
но при загрузке ROM-патч system_server всё равно поднимает **свою**
|
||
`com.ffalconxr.mercury.launcher/.home.LauncherHomeActivity`. Ручной HOME-intent
|
||
(`am start -a MAIN -c HOME`) открывает наш `MainActivity` правильно — то есть наш
|
||
домашний экран рабочий, но boot-резолв перехвачен Mercury.
|
||
|
||
2. **Mercury-лаунчер убрать нельзя.** `pm disable-user com.ffalconxr.mercury.launcher`
|
||
применяется (`enabled=0`), но system_server всё равно стартует Mercury при буте
|
||
(PID uid system), и **его BLE продолжает работать** (телефон по Bluetooth соединяется).
|
||
Значит: убийца `BackgroundAppManager` присутствует всегда → стража
|
||
NetConfigActivity-на-скрытом-дисплее **обязательна**. Отключение лаунчера проблему не решает.
|
||
|
||
3. **BLE жив всегда.** Раз Mercury стартует при буте в любом случае, Channel 2 (BLE:
|
||
запуск приложения, яркость, WiFi, статус) доступен всегда. Это надёжный канал.
|
||
|
||
4. **`com.rayneo.mercury.app=true`** у нас уже стоит в манифесте, но **иммунитета от
|
||
убийцы не даёт** — нас всё равно убивало.
|
||
|
||
## Про adb-бутстрап Shizuku после ребута
|
||
|
||
| Способ | Результат |
|
||
|--------|-----------|
|
||
| legacy plain-TCP `persist.adb.tcp.port` / `service.adb.tcp.port` из shell (uid 2000) | ❌ SELinux запрещает (`Unable to set property ... adbd_config_prop, u:r:shell:s0`) |
|
||
| Wireless-ADB `settings put global adb_wifi_enabled 1` | ⚠️ включается, но сбрасывается ребутом и требует подключённого WiFi; при выключенном WiFi очки полностью пропадают из сети |
|
||
| «Второй adbd» на `127.0.0.1:8872` | ❌ это не adbd, а Bluetooth HCI-snoop (`btsnoop`), uid android.uid.bluetooth |
|
||
| Единственный настоящий adbd | штатный `adbd --root_seclabel=u:r:su:s0` (uid shell), слушает USB/WiFi |
|
||
|
||
**Вывод:** автономного сетевого бутстрапа Shizuku без WiFi у нас нет. После ребута
|
||
очки оживают либо через USB, либо через WiFi+wireless-adb (если сеть есть).
|
||
Self-bootstrap (встроенный adb-клиент в приложении + авторизованный ключ) возможен,
|
||
но только когда сеть уже поднята, т.е. холодный старт им не закрыть.
|
||
|
||
## RayDesk (github.com/Quad-Labs/RayDesk) — почему «без приседаний»
|
||
|
||
RayDesk — Moonlight-клиент: стримит рабочий стол ПК в **свой** GL-рендер. Он:
|
||
- НЕ создаёт VirtualDisplay, НЕ использует Shizuku, НЕ запускает чужие Activity;
|
||
- «оба глаза» = свой `TextureView` (левый) + Mercury SDK `MirroringView` (правый);
|
||
- использует проприетарный Mercury SDK (`BaseMirrorActivity`, `TempleAction`), нужен
|
||
developer access от RayNeo.
|
||
|
||
Их подход **неприменим** к нашей задаче: мы запускаем чужие приложения на VD — это
|
||
принципиально другой сценарий. Заимствовать нечего (наш meta-data уже стоит).
|
||
|
||
## Остаётся рабочих варианта
|
||
|
||
- **A (текущий):** Mercury живёт как сервис (BLE + убийца), стража NetConfigActivity
|
||
держит гостя, Shizuku держим (USB / wireless-adb при наличии WiFi).
|
||
- **B:** встроить в приложение adb-клиент (dadb) + один раз авторизовать наш ключ —
|
||
поднимает Shizuku по сети, когда WiFi есть (не закрывает холодный старт без сети).
|
||
|
||
---
|
||
|
||
## Журнал (детали по этапам)
|
||
|
||
### Этап A/B — HOME после ребута
|
||
- Назначили наш пакет дефолтным HOME. После ребута `topResumedActivity=`
|
||
`com.ffalconxr.mercury.launcher/.home.LauncherHomeActivity` — нас система не подняла.
|
||
- `resolve-activity` при этом указывает на нас (`isDefault=true`) — то есть boot идёт
|
||
мимо обычного HOME-резолва (ROM-патч).
|
||
|
||
### Этап C — adb после ребута
|
||
- `settings put global adb_wifi_enabled 1` ✅ (запись из shell проходит).
|
||
- `setprop service.adb.tcp.port` / `persist.adb.tcp.port` ❌ SELinux.
|
||
- boot-лог: `AdbDebuggingManager: Not connected to any wireless network. Not enabling adbwifi.`
|
||
- Wireless-adb поднялся по WiFi: `adb connect 192.168.76.248:40481` → `device`.
|
||
|
||
### Этап D — WiFi off (ложная «тыква»)
|
||
- При `svc wifi disable` очки пропали из сети полностью (ping unreachable) — wireless-adb
|
||
живёт на WiFi-интерфейсе, loopback снаружи недоступен. Внутренний loopback не проверялся.
|
||
|
||
### Этап E — отключение Mercury
|
||
- `pm disable-user` → `enabled=0`, но после ребута Mercury запущен и держит стол;
|
||
телефон по BLE соединился. Откат: `pm enable --user 0 com.ffalconxr.mercury.launcher`
|
||
выполнен (`enabled=1`).
|
||
|
||
### Ложная зацепка
|
||
- `127.0.0.1:8872` (uid 1002) — при коннекте отдаёт поток с магией `btsnoop` → это
|
||
Bluetooth HCI-логгер, не adbd. ADB-хендшейк не проходит.
|
||
|
||
---
|
||
|
||
## Этап F — автономный подъём Shizuku С ТЕЛЕФОНА (успех)
|
||
|
||
### Механизм включения wireless-adb на очках
|
||
- Нужно **два** действия (иначе TLS-сервер не поднимается):
|
||
1. `IAdbManager.allowWirelessDebugging(true, ssid)` — транзакция binder `adb` №4,
|
||
добавляет доверенную сеть (`adb_temp_keys.xml` + запись wifiAP/bssid).
|
||
2. `settings put global adb_wifi_enabled 1` — adbd стартует
|
||
`TlsServer running on port <random>` и публикует mDNS `_adb-tls-connect._tcp`.
|
||
- Порт — **случайный**; узнать: binder-транзакция `adb` №10 (`getAdbWirelessPort`).
|
||
- Shell (uid 2000) вправе делать оба вызова — root не нужен.
|
||
|
||
### Критично: wireless-adb сам гаснет
|
||
- Как только очки теряют ту WiFi-сеть, к которой были привязаны, `adb_wifi_enabled`
|
||
сбрасывается в 0, порт становится `-1`. Поэтому при каждом бутстрапе его надо
|
||
перевключать (через Mercury `enableWirelessAdb`, который и вызывает оба шага).
|
||
|
||
### Авторизация без сопряжения
|
||
- Встроенный adb-ключ рабочей машины уже лежит в `/data/misc/adb/adb_keys` очков.
|
||
`AdbDebuggingManager.addUserKeysToKeyStore()` подмешивает user-ключи в wireless-keystore,
|
||
поэтому при connect по TLS ключ принимается без pairing-кода. Проверено.
|
||
|
||
### Реализация в PhoneApp
|
||
- `jniLibs/arm64-v8a/libadb.so` — AOSP adb (префилд LADB, Apache-2.0);
|
||
`useLegacyPackaging = true` → распаковывается в `nativeLibraryDir`, откуда
|
||
разрешён `exec` (W^X запрещает exec из filesDir/cacheDir — первая ошибка была `EACCES`).
|
||
- Ключ `~/.android/adbkey` зашивается в `BuildConfig` на сборке (в репо не коммитится).
|
||
- `AdbClient`: HOME=filesDir/.android (ключ кладём и в `.android/.android`),
|
||
TMPDIR=cacheDir, `ANDROID_USER_CONFIG`=HOME.
|
||
- `ShizukuProvisioner`: Mercury адрес → mDNS fallback → `start-server` → `connect` →
|
||
`pidof shizuku_server` → push `assets/shizuku/starter` → `chmod` →
|
||
`starter --apk=$(pm path moe.shizuku.privileged.api)` → проверка `pidof` → `appMarketLaunch`.
|
||
|
||
### Проверено на устройстве (через TCP-релей ПК, т.к. телефон и очки были в разных сетях)
|
||
```
|
||
forceWithAddress(192.168.76.142:39998)
|
||
exec: -s ... shell /data/local/tmp/shizuku_starter --apk=.../base.apk
|
||
info: shizuku_server pid is 4342
|
||
pidof shizuku_server -> '4342'
|
||
Shizuku поднят
|
||
```
|
||
Диагностика: `am broadcast -a pw.binom.rayneovm.phone.DEBUG_PROVISION [--es address ip:port]`
|
||
или `am start -n pw.binom.rayneovm.phone/.MainActivity --ez provision true [--es address ip:port]`.
|
||
|
||
### Остаётся проверить «в бою»
|
||
- Реальный сценарий: телефон держит хотспот, очки к нему подключены, BLE соединён →
|
||
`enableWirelessAdb` отдаёт адрес (или mDNS), телефон поднимает Shizuku сам.
|