feat: стабилизация гашения экрана очков (пауза/резюм звука)
Проблемы на железе (RayNeo X2 + HONOR): при гашении экрана позиция ExoPlayer «набегала» (мусор 42 мин), откат не срабатывал (markPosition сохранял мусор), доставка паузы телефону 5-10с (RayNeo вырубает WiFi-радио при screen-off, игнорируя WifiLock). Решение: - markPosition(positionMs, trusted): защита от мусорных скачков (>30с за цикл = игнор); seek через трекбар помечает позицию trusted (rollback откатывает к seek, не к началу) - rollback при resume: откат к последней достоверной позиции, если текущая убежала вперёд >5с - WifiLock (FULL_HIGH_PERF) при просмотре + ensureWifiLock в точках гашения (страховка; RayNeo игнорирует, но не мешает) - Watchdog на телефоне: очки молчат >5с (AUDIO_SILENCE_PAUSE_MS) → пауза звука (гарантированная верхняя граница) - sendPlaybackPositionNow с повторами (0/2/5с) при включении экрана — свежая позиция уходит при пробуждении радио - Диагностика: события пишутся в files/events.log (logcat очков забит EGL-спамом) - Тесты: +14 (rollback/скачки/trusted seek) - Железо подтверждено: позиция после гашения идеальная (продолжение с места паузы, не в начало), звук пауза ≤5-6с, синк diff < 1000
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
package pw.binom.viewmate.glasses
|
||||
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNull
|
||||
|
||||
/**
|
||||
* Откат позиции при resume: если текущая позиция «убежала» вперёд больше чем
|
||||
* на 5с от последней реальной (гашение экрана ExoPlayer набегает позицию по
|
||||
* системным часам) — плеер откатывается к последней реальной.
|
||||
* Чистая логика тестируется без Android-плеера.
|
||||
*/
|
||||
class MovieControllerRollbackTest {
|
||||
|
||||
@Test
|
||||
fun noRollbackWhenPositionsAgree() {
|
||||
assertNull(rollbackTargetMs(currentMs = 92_000, lastGoodMs = 92_000))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun noRollbackWithinThreshold() {
|
||||
assertNull(rollbackTargetMs(currentMs = 97_000, lastGoodMs = 92_000))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun rollbackWhenPositionRanAhead() {
|
||||
assertEquals(92_000L, rollbackTargetMs(currentMs = 2_280_000, lastGoodMs = 92_000))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun noRollbackWhenLastGoodUnknown() {
|
||||
assertNull(rollbackTargetMs(currentMs = 38_000, lastGoodMs = 0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun noRollbackWhenRunningBackward() {
|
||||
// Позиция позади последней реальной (перемотка назад) — не трогаем.
|
||||
assertNull(rollbackTargetMs(currentMs = 1_000, lastGoodMs = 92_000))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun markPositionAcceptsRealProgress() {
|
||||
assertEquals(97_000L, markPositionTargetMs(positionMs = 97_000, lastGoodMs = 92_000))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun markPositionAcceptsWithinJumpThreshold() {
|
||||
assertEquals(122_000L, markPositionTargetMs(positionMs = 122_000, lastGoodMs = 92_000))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun markPositionIgnoresGarbageJump() {
|
||||
// Мусор ExoPlayer при гашении: 77s → 42min за один 5с-цикл.
|
||||
assertEquals(77_182L, markPositionTargetMs(positionMs = 2_527_153, lastGoodMs = 77_182))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun markPositionTrustedAcceptsSeekForward() {
|
||||
// Seek через трекбар (trusted) — позиция достоверна, даже если скачок > порога.
|
||||
assertEquals(2_527_153L, markPositionTargetMs(positionMs = 2_527_153, lastGoodMs = 77_182, trusted = true))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun markPositionTrustedAcceptsWhenWithinJumpThreshold() {
|
||||
assertEquals(122_000L, markPositionTargetMs(positionMs = 122_000, lastGoodMs = 92_000, trusted = true))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun markPositionUntrustedStillIgnoresGarbageJump() {
|
||||
// Из 5с-цикла (trusted=false) мусор ExoPlayer по-прежнему игнорируется.
|
||||
assertEquals(77_182L, markPositionTargetMs(positionMs = 2_527_153, lastGoodMs = 77_182, trusted = false))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun markPositionAcceptsBackwardSeek() {
|
||||
// Перемотка назад — не скачок вперёд, принимаем.
|
||||
assertEquals(1_000L, markPositionTargetMs(positionMs = 1_000, lastGoodMs = 92_000))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun markPositionAcceptsWhenLastGoodUnknown() {
|
||||
assertEquals(38_000L, markPositionTargetMs(positionMs = 38_000, lastGoodMs = 0))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user