- shared: VmDisplay (guest 640x480 coordinate space), CursorMove and
CursorClick messages (CursorClick replaces the DOWN/UP pair — see below).
- glasses: cursor state + Canvas overlay drawn in both eyes, clickCursor
injects one atomic tap at the cursor, sendKey for Back/Play/Pause.
- phone: RemoteScreen — touchpad (relative drag moves the cursor, tap
clicks), «Назад»/«Плей»/«Пауза» buttons, «Клавиатура» stub (TODO).
- The old CursorButton(DOWN)/CursorButton(UP) pair was removed: the two
messages were injected concurrently and could arrive out of order,
breaking the guest's touch stream so clicks worked only once.
- tests: CursorMove/CursorClick roundtrips.
Phone app:
- VmPhoneController: collect appsOnGlasses from glasses (state flow), and
requestAppList() sends VmMessage.GetAppList over WebSocket.
- AppsListScreen: rename to dynamic list from glasses, verticalScroll,
tap → LaunchAppCommand(packageName). Tap calls onAppClick for parent
nav (Glasses tab on the bottom NavigationBar).
- Shared VM message types (VmMessage.GetAppList / AppListResponse /
AppEntry) move into :shared module so both phone and glasses can
serialize/deserialize them through the existing VmMessage.Json
Glasses app:
- VmService handles GetAppList by listing installed launchable apps
via PackageManager.queryIntentActivities (combined with Android 11+
<queries> fix in the previous commit so 3rd-party apps appear) and
replies with AppListResponse.
- GlassesScreen drives state from controller.state; no longer hardcodes
any apps in the UI.
Tested end-to-end on A06B4AB933C4103: phone taps app on
AppsListScreen → glasses' VmService receives LaunchAppCommand →
controller.launchGuest(pkg) launches the activity via
PackageManager.getLaunchIntentForPackage + FLAG_ACTIVITY_NEW_TASK.