phone: keep-alive foreground service + notification perm; glasses: clear NoConnection on reconnect

- ConnectionKeepAliveService (foreground, PARTIAL_WAKE_LOCK + WIFI_MODE_FULL_HIGH_PERF,
  started in PhoneVmApp.onCreate): without it HONOR deep-sleeps the phone process on
  screen-off and the glasses lose the WebSocket link. Same mechanic as view-mate.
- MainActivity: request POST_NOTIFICATIONS so the FGS notification is visible.
- VmGlassesController.onPhoneConnected(): drop a stuck NoConnection state when the
  phone (re)connects; returns to Running if a guest is active, else NoAppSelected.
- VmService: call it from onConnected.
- stopGuest/switch: force-stop the previous guest before releasing its display
  (releasing first migrates the guest task to display 0 full-screen); VirtualDisplay
  frame source now destroys its UserService on release.
- Mercury status: retry the first pullGeneralStatus until it lands, refresh every 15s
  and on tab open; GlassesStatusScreen shows 'Ждём статус от очков…' instead of fake zeros.
- MainActivity(glasses): HOME candidate flag + finish() on a non-default display (recursion guard).
- README: Home-launcher setup/rollback section.
- BOOTSTRAP_TEST.md: post-reboot Shizuku bootstrap investigation log.
This commit is contained in:
2026-09-26 13:59:54 +03:00
parent 94f0ed28fc
commit 59069a741e
13 changed files with 436 additions and 12 deletions
+91
View File
@@ -0,0 +1,91 @@
# Тест автономного автозапуска 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-хендшейк не проходит.