# Тест автономного автозапуска 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 ` и публикует 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 сам.