# Blockers Сюда пишутся только те задачи/проблемы, в которых застряли. Каждая запись — задача, что сделано, в чём стена, что проверено, варианты обхода. Записи ведутся по правилам ночной сессии (см. `TASKS.md`, секция «Правила ночной сессии»). --- ## B-1 · Периодический лаунч `Mercury/.NetConfigActivity` — ПОДТВЕРЖДЁН, источник не найден **Когда замечено:** 2026-09-27, во время тестов запуска Zona через `DEBUG_LAUNCH`. **Что я видел в логах:** `ShizukuVdService: launchActivity pkg=com.ffalconxr.mercury.launcher cls=com.ffalconxr.mercury.launcher.wizard.netconfig.NetConfigActivity displayId=2` повторялось каждые 5 секунд, постоянно. **Что это на самом деле:** Непонятно. Это мог быть мой собственный `GlassesDebugReceiver`, который я перепосылал несколько раз и он где-то зациклился; мог быть артефакт system-job’а; мог быть какой-то fallback в `VmGlassesController.ensureNetworking()`. **Повторно замечено:** 2026-09-27 12:28:40, `START ... NetConfigActivity from uid 2000` (shell) в логах очков во время отладки звука. `uid 2000` = shell ⇒ запускает **Shizuku UserService** (наш код через Shizuku). Значит источник — где-то в нашем Shizuku-пути (не Mercury BLE). На аудио-grant влияния не оказал (график grant сломался по другой причине — см. B-3). **Что НЕ сделано:** не остановил очки в момент пика, не нашёл источник цикла. Пользователь утром сказал «сейчас вижу наше приложение», значит цикл или закончился, или не повторяется. **Следующий шаг:** если повторится — переписать GlassesDebugReceiver с rate-limit + проверить нет ли в `VmService`/`VmGlassesController` периодического `launchActivity(Mercury)` для Wi-Fi/network fallback. --- ## B-2 · rayneo-mercury: `enableWirelessAdb` через BLE на X3 Pro не возвращает адрес **Когда выяснено:** 2026-09-27, аудит прошивки RayNeoLauncher по smali (`adb pull /system/app/RayNeoLauncher`). **Что происходит (по smali + логам):** 1. Телефон шлёт BLE-команду `ble.request.debug` с `payload.cmd="enableWirelessAdb"`. 2. Очки **принимают** команду и реально поднимают беспроводной adb (мы видим `adb_wifi_enabled=1` и `service.adb.tcp.port` после). **Это работает.** 3. Очки **должны** прислать событие `WirelessAdbAddress` обратно. **Это не происходит.** 4. В smali `BleResponse` есть `RESPONSE_MAP`, в котором зарегистрированы Wi-Fi / media / netconfig ответы — но **`DebugResponse` отсутствует**. Поэтому маршрутизация ответа по URI `ble.request.debug` не настроена, и событие теряется. 5. Телефон вечно ждёт `Event.WirelessAdbAddress`, не получает его и уходит в таймаут. **Что это значит для provisioning:** - Команда `enableWirelessAdb` через BLE **включает adb** — но адрес `ip:port` мы узнать не можем. - Provisioning сейчас работает только потому, что **adb уже был включён раньше** (например, руками или через shizuku) и не выключился после ребута. После ребута очков — если `adb_wifi_enabled` сбросится в 0 — provisioning сломается, потому что новый адрес мы узнать не сможем. **Обходной путь (уже работает):** ```bash # Через shizuku shell на очках: service call adb 4 i32 1 s16 'Caffeine Portable' # включить adb settings put global adb_wifi_enabled 1 # не дать ему автоотключиться ``` После этого `adb_wifi_enabled` остаётся 1, телефон через mDNS `_adb-tls-connect._tcp` находит `ip:port` и подключается. Это уже используется как fallback в `AdbController`. **Следующий шаг:** при первом удобном случае — поднять через shizuku-shell и убедиться, что provisioning пройдёт полностью через этот путь. --- ## B-3 · Звук end-to-end — РЕШЕНО **Когда замечено:** 2026-09-27, E2E-проверка после восстановления общей сети «O2 5». **Симптом:** звук на телефон работал только в первый раз; после `ON_GLASSES` → `ON_PHONE` тишина и на очках, и на телефоне. **Корень (найден по логам 2026-09-27):** не сеть и не телефон, а **grant MediaProjection на очках**. `ensureAudioCaptureLoop` ре-запрашивал проекцию каждые 2.5 c, а `requestProjection()` каждый раз дёргал `startActivity(MainActivity, NEW_TASK|SINGLE_TOP)`. Система: ``` START com.android.systemui/.media.MediaProjectionPermissionActivity from uid 10090 → UsageStats event :23 (ACTIVITY_STOPPED) через ~30 мс → MainActivity: MediaProjection не выдан: resultCode=0 ``` то есть grant-активити гасится, если её запускает только что перезапущенная Activity. Ручной `KEYCODE_HOME` (уводит нашу Activity с переднего плана) «разблокировал» grant — подтверждало гипотезу гонки. **Фикс (вариант A):** 1. `MainActivity` собирает `requestTick` в `repeatOnLifecycle(**RESUMED**)` (был `STARTED`) и флагом `AudioBridge.activityResumed` сообщает сервису, что она наверху. 2. `requestProjection()` больше **не** вызывает `startActivity(MainActivity)`, пока Activity уже `RESUMED` (убрана гонка с запуском consent-активити). 3. `ensureAudioCaptureLoop` запрашивает проекцию **один раз**; повтор — не чаще `AUDIO_RETRY_MS=20 c`. 4. Проекция **одна на процесс и не гасится**: `GlassesAudioCapture.stop()` останавливает только `AudioRecord`, а `AudioBridge.onProjectionGranted` не трогает уже имеющуюся. Следующий `ON_PHONE` переиспользует ту же проекцию — новый grant не нужен вовсе. **Проверено вживую 2026-09-27 (очки A06B4AB933C4103 → телефон AXGL024B05001337):** - `[1] ON_PHONE` → `MediaProjection получен` **без HOME** → захват запущен. - `[2] ON_GLASSES` → `остановлен (проекцию сохраняю)`. - `[3] ON_PHONE` → `аудио-захват поднят`, **без нового grant** (переиспользование). - Тестовый тон 440 Гц: очки `rms=5673`, телефон `playing ... rms=5620..5698`, байты совпали (`bytes=4751360` с обеих сторон). **PCM реально дошёл по `/vm-audio`.** **Проверено с руки пользователя 2026-09-27:** полный сценарий с Zona — `ON_PHONE` → `ON_GLASSES` → `ON_PHONE` — звук корректно переключается, повторный `ON_PHONE` больше не ломается. **B-3 закрыт полностью.** --- ## B-4 · Финал: гашение экрана обязательно в конце По ночным правилам — на завершении всех задач ИЛИ при невозможности продолжать — выполняется: ``` adb -s A06B4AB933C4103 shell input keyevent 223 ``` и проверка `mWakefulness=Dozing/Asleep`. Если не работает — через `ScreenControl` (Канал 1) / Shizuku `SET_SCREEN`. **Статус:** выполнено (mWakefulness=Dozing подтверждён в конце ночной сессии). --- ## B-5 · Телефон показывал «подключено» при мёртвом TCP-канале — РЕШЕНО **Когда замечено:** 2026-09-27, пользователь: «телефон говорит подключено, очки говорят что нет связи». **Причина:** у очков Wi-Fi был выключен (`wifi_on=0`, нет default network) — реального Канала 1 не было. Очки при выключении Wi-Fi локально теряют сокеты мгновенно и честно писали «нет связи». Телефон же об этом не узнавал: FIN/RST до него не доходит (у очков уже нет интерфейса), а у **клиента `:transport` не было ни пинга, ни таймаута** — `WifiTransport.connect` вечно висел в `for (frame in s.incoming)`. TCP-сокет телефона оставался в `ESTAB`, `onDisconnected` не срабатывал, `VmPhoneController` оставался в `Connected` → UI показывал «подключено». **Доказательство (воспроизведено):** выключили Wi-Fi очкам — через 20 c с телефона: ``` ESTAB 192.168.76.121:50438 → 192.168.76.248:8080 ``` сокет так и висел, телефон даже не переподключался (те же local-порты после возврата Wi-Fi). **Фикс (`rayneo-mercury :transport` 0.1.1-SNAPSHOT):** клиентским транспортам добавлен `install(WebSockets) { pingIntervalMillis = WS_PING_INTERVAL_MS }` (15 c) — `WifiTransport` и `WifiByteTransport`; константа в `Transport.kt`. Серверные транспорты пингуют и так (`pingPeriod=15s`, `timeout=30s`), но они ловят мёртвого клиента, а не наоборот. **Проверено вживую 2026-09-27:** Wi-Fi очкам выключен → на 10-й секунде у телефона `Send-Q=82` (пошли пинги, недоставленные) → на ~41-й секунде сокет ушёл в `FIN-WAIT-1` (клиент сам закрыл мёртвую сессию, `onDisconnected` сработал) → после возврата Wi-Fi новый `ESTAB :57996` и в логах очков `Phone connected: ws-83ad…` (авто-реконнект). **Побочно:** в UI телефона обе строки назывались одинаково — «Связь» (Канал 1 WebSocket и Канал 2 Mercury BLE), из-за чего статус BLE читался как статус TCP. Теперь вверху вкладки «Очки» сводка «Связь» с отдельными строками **BLE (Mercury)** и **TCP/IP (Wi-Fi)**, а в секциях каналов строки переименованы в «BLE» и «TCP/IP».