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
@@ -40,6 +40,10 @@ class VirtualDisplayFrameSource private constructor(
runCatching { ShizukuVdBinder.releaseDisplay(binder, displayId) }
runCatching { surface.release() }
super.release()
// Убиваем процесс UserService: `unbindUserService(remove = true)` сам по себе его не
// завершает (Shizuku держит UserService живым для переиспользования), и после каждого
// запуска гостя оставался висеть процесс-сирота (~13 МБ). `destroy` шлёт System.exit.
runCatching { ShizukuVdBinder.destroy(binder) }
// Отвязываем UserService — держим его живым ровно на время жизни дисплея.
runCatching { client.stop() }
Log.i(TAG, "VirtualDisplayFrameSource released: displayId=$displayId")