4.6 KiB
Proposal: Android Auto EQ preset selection
Intent
Drivers cannot change the audio equalizer while on Android Auto — EQ selection is phone-UI only today. Expose the 6 fixed presets as a browsable folder in the existing Auto media tree so a preset can be applied from the car, without reaching for the phone and without interrupting the current station.
Scope
In Scope
- New top-level browsable
Ecualizadorfolder inConstructorArbolAuto.raiz(), listing the 6 fixedPresetEcualizador.presetsby name. - New media-id scheme
eq_preset:<nombre>, intercepted inplayFromMediaIdBEFORE theemisora:/grupo:routing. - Tapping a preset applies it through the existing headless-safe EQ seam and persists it as the principal preset (phone/car parity), with NO call to
playMediaItemand NOmediaItemmutation. - Strict-TDD tests: tree shape,
eq_preset:id resolution, and the "preset tap does not disturb playback / now-playing" invariant. - Optional (lower priority): mark the active preset in its row title (see Risks — no native selection UI exists in this model).
Out of Scope
- Custom band-level EQ editing or arbitrary EQ from the car (media-browser capability ceiling; stays phone-only).
- Per-station / per-device / matrix EQ writes from the car (global principal only).
- Custom transport-button EQ actions (button real-estate fits ~1-2 slots, not 6 named presets).
- Favorite-groups browse work (separate, already-shipped
android-auto-favorite-groups).
Capabilities
New Capabilities
- None
Modified Capabilities
android-auto-media: the browse tree gains anEcualizadorroot folder plus aneq_preset:selection action that applies an EQ preset without starting or altering playback.
Approach
Mirror the proven emisora:/grupo: interception pattern already in navegacion_auto.dart + servicio_audio.dart. Preset rows are playable: true (the only tappable non-folder item type in the legacy MediaBrowserService model) and therefore route through playFromMediaId; a new eq_preset: branch resolves the preset by name and calls the EQ apply seam instead of the audio player. Reuse the phone's global-preset semantics (apply via PluriWaveAudioHandler.aplicarPreset + persist via ServicioEcualizador.guardarPrincipal, matching cambiarPresetPrincipal) so phone and car stay in sync. The write path MUST be headless-safe (handler + service, NOT the widget-tree EstadoEcualizador, which may never build on an Auto bind).
Affected Areas
| Area | Impact | Description |
|---|---|---|
lib/servicios/navegacion_auto.dart |
Modified | Add Ecualizador root folder, eq_preset: id scheme, preset-row builder, resolver + selection routing helper |
lib/servicios/servicio_audio.dart |
Modified | Branch playFromMediaId on eq_preset: to the apply/persist seam before emisora:/grupo: |
lib/modelos/preset_ecualizador.dart |
Read-only | Source of the 6 fixed presets (name is the id key) |
lib/servicios/servicio_ecualizador.dart |
Read-only reuse | guardarPrincipal persistence seam (headless-safe) |
openspec/specs/android-auto-media/spec.md |
Delta only | Modified-capability delta in this change folder; base spec untouched |
Risks
| Risk | Likelihood | Mitigation |
|---|---|---|
| Preset tap looks like "now playing a new track" (playable item) | Med | Never call playMediaItem, never mutate mediaItem; dedicated eq_preset: branch + invariant test |
| Shared-file merge drift with just-shipped favorite-groups | Med | Read CURRENT post-f368bcc/066fedb state; add branch alongside existing grupo:/emisora: dispatch |
| No native "selected" UI for browsable rows | High | Active-preset marker only via title text (prefix); ship as optional, be explicit it is not a real checkmark |
| Persist path unavailable on headless Auto bind | Med | Route through service + handler (SharedPreferences), not EstadoEcualizador |
Rollback Plan
Additive only — revert the feature commits. No schema/migration changes: removing the Ecualizador folder and the eq_preset: branch restores the exact prior tree (favorite-groups behavior unaffected).
Dependencies
- Sequenced after
android-auto-favorite-groups(now on main) to avoid conflicts in the two shared files.
Success Criteria
Ecualizadorfolder appears at the Auto root with all 6 presets by name.- Tapping a preset applies it (native EQ gains change) and persists as principal.
- Current station playback / now-playing metadata is unchanged by a preset tap.
- Selecting a preset in the car is reflected in the phone EQ UI and vice versa.
- Unknown/stale
eq_preset:id is a no-op (no throw).