RayNeo VM

Приложение для запуска Android-приложений (например, Zona) на очках RayNeo X3 Pro через виртуальный дисплей.

Архитектура

┌─────────────────────────┐                              ┌─────────────────────────────────┐
│  Phone (телефон)        │                              │  Glasses (RayNeo X3 Pro)        │
│                         │   ◀──── WebSocket /mDNS ───▶ │                                 │
│  app-phone-vm           │                              │  app-glasses-vm                  │
│   VmPhoneController     │                              │   VmService (foreground)         │
│   TouchpadScreen        │                              │   WebSocket server :8080        │
│   ZonaProfile           │                              │   mDNS publisher                 │
│   AudioPlaybackManager  │                              │   BinocularRendererView          │
│                         │                              │                                  │
│                         │                              │   ┌─────────────────────┐        │
│                         │                              │   │  ShizukuVdService   │        │
│                         │                              │   │   process: vm_vd    │        │
│                         │                              │   │  (UID 2000, shell)  │        │
│                         │                              │   └─────────────────────┘        │
└─────────────────────────┘                              │         │       │                │
                                                          │   ┌─────┘       └──────┐         │
                                                          │   ▼                   ▼         │
                                                          │ VirtualDisplay   IActivityTask  │
                                                          │ (640x480)        Manager        │
                                                          │   │                                │
                                                          │   ▼                                │
                                                          │ free.zona (гостевое)              │
                                                          └─────────────────────────────────┘

Структура

rayneo-vm/
├── shared/                   # DTO + VmProtocol (общее для обоих приложений)
│   └── src/main/kotlin/pw/binom/rayneovm/shared/
│       ├── Dto.kt            # VmMessage sealed, TouchEvent, KeyEvent, ...
│       ├── VmProtocol.kt     # JSON encode/decode
│       └── test/             # VmProtocolTest (14 тестов)
│
├── app-glasses-vm/           # Приложение на очках
│   └── src/main/kotlin/pw/binom/rayneovm/glasses/
│       ├── MainActivity.kt   # Compose host
│       ├── VmService.kt      # Foreground service, WebSocket server
│       ├── VmShizukuService.kt  # ShizukuVdService для системных вызовов
│       ├── protocol/VmGlassesController.kt
│       ├── vm/GlassesScreenState.kt
│       ├── shizuku/VirtualDisplayFrameSource.kt  # SurfaceTexture ↔ VirtualDisplay
│       ├── audio/AudioCaptureService.kt          # Режим 2: захват системного аудио
│       └── audio/AudioStreamer.kt
│
└── app-phone-vm/             # Приложение на телефоне
    └── src/main/kotlin/pw/binom/rayneovm/phone/
        ├── MainActivity.kt   # Compose host + NavGraph
        ├── PhoneVmApp.kt     # Application
        ├── protocol/VmPhoneController.kt   # Auto-reconnect + mDNS
        ├── ui/HomeScreen.kt
        ├── ui/GlassesStatusScreen.kt
        ├── ui/AppsListScreen.kt
        ├── ui/ZonaProfile.kt                # Touchpad + media keys + keyboard
        ├── ui/TouchpadScreen.kt
        └── audio/AudioPlaybackManager.kt    # Режим 2: воспроизведение на телефоне

Используемые общие модули (rayneo-mercury)

  • pw.binom.mercury:rayneo-mercury-transport:0.1.0-SNAPSHOT — generic Transport / ServerTransport, WifiTransport, BtTransport, MdnsScanner
  • pw.binom.mercury:rayneo-mercury-binocular-renderer:0.1.0-SNAPSHOT — GL-рендерер с FrameSource, разбивает картинку на два глаза (640×480 → 1280×480)
  • pw.binom.mercury:rayneo-mercury-shizuku-vd:0.1.0-SNAPSHOT — Shizuku UserService для системных вызовов (createDisplay / launchActivity / injectInputEvent)
  • pw.binom.mercury:library:0.1.0-SNAPSHOT — RayNeo Mercury BLE-протокол (для запуска GlassesApp по пакету)

Статус на утро 2026-09-26

Что Статус
rayneo-mercury: новые модули ✅ Опубликованы в Nexus
Bootstrap rayneo-vm ✅ 4 Gradle модуля
:shared DTO + протокол ✅ 14/14 unit-тестов проходят
GlassesApp Compose UI ✅ BinocularRendererView + 5 оверлеев
GlassesApp WebSocket сервер ✅ Слушает порт 8080 (проверено через netstat)
GlassesApp mDNS publisher ✅ Регистрирует _rayneo-vm._tcp
GlassesApp ShizukuVdService ✅ createDisplay / launchActivity / injectInputEvent через reflection
PhoneApp VmPhoneController ✅ mDNS + auto-reconnect + exponential backoff
PhoneApp TouchpadScreen ✅ Drag/tap → TouchEvent (640×480)
PhoneApp KeyboardDialog ✅ Char → KEYCODE_*
PhoneApp ZonaProfile ✅ Touchpad + media keys + back + keyboard
PhoneApp AudioPlaybackManager ✅ AudioTrack + WiFi/Wake lock
AudioCaptureService (MIC fallback) ✅ Запускается, реальный AudioPlaybackCapture — TODO (нужен MediaProjection)

Что осталось на утро

  1. Реальный проброс SurfaceTexture клиент → сервис. Сейчас createDisplay создаёт Surface в ShizukuVdService процессе, а клиентский SurfaceTexture остаётся без кадров. Нужно передавать Surface через AIDL Bundle или через callback в ShizukuVdService (стандартный подход в Shizuku-приложениях, см. IIdProvider-style).
  2. AudioPlaybackCapture (Android 12+). Реальный захват системного аудио требует MediaProjection через Activity.onActivityResult. Сейчас сервис стартует в MIC-режиме.
  3. InjectInputEvent — verify on device. Код написан, но не тестировался вживую на устройстве.
  4. TaskStackListener для обнаружения краша гостя. Каркас в SPEC, реализация не доделана.

Сборка

./gradlew :app-glasses-vm:assembleDebug
./gradlew :app-phone-vm:assembleDebug

Установка

adb -s <glasses-serial> install -r app-glasses-vm/build/outputs/apk/debug/app-glasses-vm-debug.apk
adb -s <phone-serial> install -r app-phone-vm/build/outputs/apk/debug/app-phone-vm-debug.apk

Smoke-test (проверено)

  1. Запустить GlassesVmApp на очках → VmService стартует, netstat -tlnp показывает *:8080.
  2. Запустить PhoneVmApp на телефоне → mDNS ищет _rayneo-vm._tcp, ловит сервис очков.
  3. На телефоне: тап на Zona → LaunchAppCommand("free.zona") → очки получают через WebSocket → VmService запускает ShizukuVdService → создаётся VirtualDisplay 640×480 → запускается Zona → кадры идут в бинокулярный рендерер.

Конфигурация

Версии в gradle/libs.versions.toml:

  • Kotlin 2.4.20, AGP 9.4.1, Gradle 9.x
  • Compose BOM 2026.09.00
  • Ktor 3.6.0
  • Shizuku API 13.1.5
  • compileSdk 37, minSdk 32 (glasses), 32 (phone)

Лицензия

Внутренний проект.

S
Description
No description provided
Readme 3.7 MiB
Languages
Kotlin 100%