feat(wear): performance toggles for offline watch playback, set from the phone - #24
Open
PonceGL wants to merge 1 commit into
Open
feat(wear): performance toggles for offline watch playback, set from the phone#24PonceGL wants to merge 1 commit into
PonceGL wants to merge 1 commit into
Conversation
…the phone Adds a "Watch" category to the phone's Settings hub with three switches that only affect the watch's standalone local playback (no phone connected) — the running/exercise scenario where a fitness app is competing for the same CPU/RAM/battery and the screen is on the whole time, so the existing isInteractive-based lifecycle gating (ambient/ background) can't help. Evaluated the whole player screen for what's actually worth toggling and landed on three real, measurable costs (ruled out the rest — progress bar, PlayingEqIcon, lyrics — as already lifecycle-gated or already inert during local playback): - Album art: up to a ~16MB uncompressed bitmap per song, no cache, no recycle. By far the biggest win. - Dynamic color theming: a redundant main-thread bitmap resample in WearTheme when a cheap IO-thread seed color was already available (fixed unconditionally regardless of the toggle, since it's a pure inefficiency either way). - Play button ring animation: continuous per-frame 320-point path rebuild, kept alive by the pager even off-page. Sync is phone -> watch via a DataItem (WearDataPaths.WEAR_PERFORMANCE_ SETTINGS), not MessageClient — same reasoning as the playlist-sync ack fix earlier this stack: MessageClient only confirms local hand-off, and a DataItem instead durably reaches the watch once it reconnects, no ack needed. The watch caches the last-synced values locally (WearPerformanceSettingsRepository, same DataStore singleton as WearPlaybackStatePersistence) so they still apply when the phone isn't reachable at the moment local playback starts — the whole point. Toggles only gate WearLocalPlayerRepository's local decode path, never remote-controller mode: that path already gets its art/theme pre-resolved from the phone and never decodes anything heavy locally, so there's nothing to save there. New/changed test coverage: 6 tests for WearPerformanceSettingsRepository (default-true, per-flag round-trip via Turbine, overwrite semantics). WearPerformanceSettingsPublisher isn't unit tested — same constraint as the existing WearStatePublisher it mirrors (Wearable.getDataClient() is a static GMS call, no test double without the inline-mocking agent that hangs in this sandbox). Fixed two pre-existing test files broken by WearLocalPlayerRepository's new constructor parameter. Verified :wear and :app both still build clean in release (R8 + shrinkResources) with the new resources/classes, given the resource- shrinker incident earlier this stack.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Qué es esto
Sección nueva "Reloj" en Ajustes del teléfono con 3 switches que solo afectan la reproducción standalone local del reloj (sin teléfono conectado) — el escenario de hacer ejercicio, donde una app de fitness compite por CPU/RAM/batería y la pantalla está encendida todo el tiempo, así que el gating automático de
isInteractive(ambient/segundo plano) de la sesión pasada no ayuda aquí.Los 3 toggles (evaluación completa en el plan)
.recycle(). El de mayor impacto con diferencia.WearTheme.ktahora prefiere el seed color ya calculado en hilo IO en vez de recalcularlo (esto aplica siempre, no solo con el toggle apagado).Evalué toda la pantalla del reproductor y descarté el resto (barra de progreso,
PlayingEqIcon, letras) por ya estar gateados o ya no correr durante reproducción local — no hay relleno, los 3 son costos medibles reales.Arquitectura: teléfono configura, reloj cachea
Sync vía
DataItem, noMessageClient— misma razón que el fix de sync de playlist de este stack:MessageClientsolo confirma entrega local, no que el reloj lo recibió. UnDataItemsí llega de forma durable cuando el reloj reconecta, sin necesitar ack propio.El reloj guarda lo último sincronizado en un
WearPerformanceSettingsRepositorylocal (mismoDataStorequeWearPlaybackStatePersistence) — así aplica aunque el teléfono no esté conectado en el momento de reproducir, que es todo el punto.Los toggles solo afectan el decode local (
WearLocalPlayerRepository) — en modo controlador remoto la carátula/tema ya llegan resueltos del teléfono, no hay nada que ahorrar ahí, así que se ignoran por completo en ese modo.Tests
6 tests nuevos para
WearPerformanceSettingsRepository(defaulttrue, round-trip por flag vía Turbine, semántica de sobrescritura).WearPerformanceSettingsPublishersin test unitario — misma limitación queWearStatePublisher(llamada estática aWearable.getDataClient(), sin agente de mockeo inline en este sandbox). Arreglé 2 archivos de test existentes rotos por el nuevo parámetro del constructor deWearLocalPlayerRepository.Verifiqué
:wear:assembleReleasey:app:assembleRelease(R8 + shrinkResources) limpios — con lo del shrinker de hace unas horas, no iba a dar nada por sentado esta vez.Pendiente de verificación en hardware: efecto inmediato de cada toggle sin reiniciar la app, comportamiento correcto en modo remoto, y que un reloj recién reconectado reciba el valor vigente.