feat: бинокулярный видеорендер в app-glasses + иммерсивный режим + тест-план
- render/: Grafika-связка (EglCore/WindowSurface/FullFrameRect/Texture2dProgram/GlUtil/Drawable2d/EglSurfaceBase) — перенос из pair-view - ui/BinocularVideoPlayer: один SimpleExoPlayer → SurfaceTexture → EGL-блит в оба глаза (EglVideoRenderer шарится между LEFT/RIGHT) - ui/ViewUtils: Binocular/BinocularScreenSide/BinocularScreenSize (Compose, из pair-view) - ui/GlassesMovieScreen: «нос к носу», calculateVideoSizeFull, FLAG_KEEP_SCREEN_ON - MovieController: PlayVideo/MediaCommand (PLAY/PAUSE/TOGGLE/SEEK/CLOSE), доступ к ExoPlayer только с main-потока - HostConnection: PlayVideo→плеер, реальная позиция в PlaybackPosition (withContext Main) - MainActivity: иммерсивный режим (setDecorFitsSystemWindows(false) + hide systemBars) - TESTING.md: 10 тест-кейсов human-style; QA-прогон (opencode, 88.19) — 10/10 ПРОЙДЕН
This commit is contained in:
+189
@@ -0,0 +1,189 @@
|
||||
# TESTING.md — view-mate, app-glasses (очки RayNeo X2)
|
||||
|
||||
Тест-план для стенда (88.19): AVD `glasses35` (emulator-5554, 1280×480), app-host на :8080
|
||||
(консоль FIFO `/tmp/host.in`, лог `/tmp/host.log`), http.server :8081 с `test-video.mp4`,
|
||||
APK `pw.binom.viewmate.glasses` установлен.
|
||||
|
||||
Кейсы написаны человеческим языком, без координат. Координаты/точные значения агент
|
||||
добывает сам (скрины, logcat, uiautomator). «Консоль хоста» = FIFO `/tmp/host.in`
|
||||
(команды: `play <url>`, `mode <MODE>`, `cmd <CMD> [ms]`, `catalog`, `watch`, `mirror`).
|
||||
|
||||
## Общие предусловия
|
||||
|
||||
- Стенд поднят: app-host слушает :8080, http.server :8081, AVD загружен
|
||||
- Приложение очков установлено (последняя сборка) и запущено
|
||||
- Logcat очищен перед кейсом (`adb logcat -c`)
|
||||
|
||||
---
|
||||
|
||||
## TC-01 Подключение очков к серверу
|
||||
|
||||
**Предусловия:** app-host запущен и слушает :8080.
|
||||
|
||||
**Шаги:**
|
||||
1. Запусти приложение очков (launch `pw.binom.viewmate.glasses/.MainActivity`)
|
||||
2. Подожди 5–10 секунд
|
||||
3. Посмотри на экран очков (скрин)
|
||||
4. Загляни в лог приложения (logcat) и в лог хоста
|
||||
|
||||
**Ожидаемо:**
|
||||
- На экране статус «подключено к телефону» (ConnectionScreen, без системных панелей)
|
||||
- В logcat: «соединение установлено», «Welcome: режим MOVIE...»
|
||||
- В `/tmp/host.log` приходят периодические `glasses статус: батарея 80%...`
|
||||
- Крашей и ошибок нет
|
||||
|
||||
---
|
||||
|
||||
## TC-02 Воспроизведение тестового видео (play по прямому URL)
|
||||
|
||||
**Предусловия:** TC-01 пройден.
|
||||
|
||||
**Шаги:**
|
||||
1. Через консоль хоста пошли: `play http://10.0.2.2:8081/test-video.mp4`
|
||||
2. Подожди 5–10 секунд
|
||||
3. Сними скрин экрана очков
|
||||
4. Проверь logcat и лог хоста
|
||||
|
||||
**Ожидаемо:**
|
||||
- В обеих половинах экрана (левой и правой) — **одинаковое** видеоизображение
|
||||
(движущийся тестовый паттерн: цветные полосы, сетка)
|
||||
- В logcat: «получено видео», «SimpleExoPlayer создан», «EglVideoRenderer: GL-стэйт создан»
|
||||
- Крашей нет; процесс жив
|
||||
|
||||
---
|
||||
|
||||
## TC-03 Воспроизведение видео из живого Jellyfin
|
||||
|
||||
**Предусловия:** TC-01 пройден. Живой стрим-URL (например, фильм «Акира»:
|
||||
`https://jellyfin.binom.pw/Videos/a3ca9fbf926fe9f60448f591ea945ac8/stream?static=true&MediaSourceId=a3ca9fbf926fe9f60448f591ea945ac8&api_key=59e6380a96a94364ae25d2b7cf9f1359`).
|
||||
|
||||
**Шаги:**
|
||||
1. Через консоль хоста пошли: `play <jellyfin-url>`
|
||||
2. Подожди 10–15 секунд (стрим с сетевой задержкой)
|
||||
3. Сними скрин экрана очков
|
||||
4. Проверь logcat: ошибок загрузки быть не должно (если была ошибка — проверь, что приложение не упало)
|
||||
|
||||
**Ожидаемо:**
|
||||
- На экране кадр фильма (не чёрный экран), одинаковый в обеих половинах
|
||||
- Приложение живо, крашей нет
|
||||
- В логе хоста позиция растёт
|
||||
|
||||
---
|
||||
|
||||
## TC-04 Полноэкранный режим (без системных панелей)
|
||||
|
||||
**Предусловия:** приложение запущено (любой экран: статус или кино).
|
||||
|
||||
**Шаги:**
|
||||
1. Посмотри на экран очков (скрин) — и на статус-экране, и во время кино
|
||||
2. Убедись, что сверху нет системной панели (часы, зарядка, иконки)
|
||||
3. Убедись, что снизу нет навигационной панели
|
||||
|
||||
**Ожидаемо:**
|
||||
- Системные панели скрыты: приложение занимает весь экран 1280×480
|
||||
- Даже после паузы/воспроизведения панели не появляются сами
|
||||
- ⚠️ При первом входе в иммерсивный режим система может показать разовый оверлей
|
||||
«Viewing full screen / To exit, swipe down... [Got it]» — это НЕ баг приложения,
|
||||
это системная подсказка. Нажми «Got it» (или свайпни) и проверь, что панели скрыты.
|
||||
|
||||
---
|
||||
|
||||
## TC-05 Пауза и продолжение (media PAUSE / PLAY)
|
||||
|
||||
**Предусловия:** TC-02 пройден (видео играет).
|
||||
|
||||
**Шаги:**
|
||||
1. Через консоль хоста пошли: `cmd PAUSE`
|
||||
2. Подожди 3–5 секунд
|
||||
3. Проверь лог хоста (позиция) и сними скрин
|
||||
4. Через консоль пошли: `cmd PLAY`
|
||||
5. Подожди 3–5 секунд, снова проверь лог хоста
|
||||
|
||||
**Ожидаемо:**
|
||||
- После PAUSE: в логе хоста `позиция: N мс, пауза` (playing=false), позиция не растёт
|
||||
- После PLAY: позиция снова растёт (playing=true)
|
||||
- Кадр на экране не меняется на паузе (стоп-кадр)
|
||||
|
||||
---
|
||||
|
||||
## TC-06 Перемотка вперёд (media SEEK_FWD)
|
||||
|
||||
**Предусловия:** TC-02 пройден.
|
||||
|
||||
**Шаги:**
|
||||
1. Запомни текущую позицию из лога хоста
|
||||
2. Через консоль пошли: `cmd SEEK_FORWARD 10000`
|
||||
3. Подожди 3–5 секунд
|
||||
4. Проверь позицию в логе хоста
|
||||
|
||||
**Ожидаемо:**
|
||||
- Позиция выросла примерно на 10 секунд относительно запомненной
|
||||
- Видео продолжает играть, крашей нет
|
||||
|
||||
---
|
||||
|
||||
## TC-07 Закрытие фильма (media CLOSE)
|
||||
|
||||
**Предусловия:** TC-02 пройден.
|
||||
|
||||
**Шаги:**
|
||||
1. Через консоль пошли: `cmd CLOSE`
|
||||
2. Подожди 3–5 секунд
|
||||
3. Посмотри на экран очков (скрин)
|
||||
4. Проверь лог хоста (позиция)
|
||||
|
||||
**Ожидаемо:**
|
||||
- Экран вернулся на статус-экран (ConnectionScreen)
|
||||
- Позиция сброшена (0 мс / нет плеера)
|
||||
- В logcat: «CLOSE: плеер остановлен и освобождён» (или эквивалент)
|
||||
- Приложение живо
|
||||
|
||||
---
|
||||
|
||||
## TC-08 Ошибка загрузки (битый URL) — приложение не падает
|
||||
|
||||
**Предусловия:** TC-01 пройден.
|
||||
|
||||
**Шаги:**
|
||||
1. Через консоль хоста пошли: `play http://10.0.2.2:8081/nonexistent.mp4`
|
||||
2. Подожди 10–15 секунд
|
||||
3. Проверь logcat и живость процесса
|
||||
4. Сними скрин
|
||||
|
||||
**Ожидаемо:**
|
||||
- В logcat ошибка загрузки (ExoPlaybackException / 404), НО:
|
||||
- Приложение живо (pid существует), краша нет
|
||||
- Экран не «завис» — можно вернуться в рабочее состояние командой `play <валидный url>`
|
||||
|
||||
---
|
||||
|
||||
## TC-09 Реконнект при обрыве связи
|
||||
|
||||
**Предусловия:** TC-01 пройден.
|
||||
|
||||
**Шаги:**
|
||||
1. Останови app-host (убить процесс) — очки потеряют сервер
|
||||
2. Подожди 10–15 секунд
|
||||
3. Проверь logcat (сообщение о разрыве/реконнекте)
|
||||
4. Запусти app-host заново
|
||||
5. Подожди 10–15 секунд
|
||||
6. Проверь logcat и экран
|
||||
|
||||
**Ожидаемо:**
|
||||
- При обрыве: в logcat сообщение о потере соединения, приложение живо
|
||||
- После подъёма хоста: «соединение установлено» снова, Welcome получен
|
||||
- Повторный `play` работает
|
||||
|
||||
---
|
||||
|
||||
## TC-10 Статус очков уходит на хост
|
||||
|
||||
**Предусловия:** TC-01 пройден, видео играет.
|
||||
|
||||
**Шаги:**
|
||||
1. Подожди 10–15 секунд
|
||||
2. Загляни в `/tmp/host.log`
|
||||
|
||||
**Ожидаемо:**
|
||||
- В логе периодически (раз в ~5 секунд): `glasses статус: батарея 80%, память 10.5/32.0 ГБ`
|
||||
- И `glasses позиция: NNN мс, играет/пауза` с реально растущей позицией во время воспроизведения
|
||||
Reference in New Issue
Block a user