ExoPlayer assigns a new audio session id after transient audio-focus interruptions (navigation prompts, radar warnings), leaving the AndroidEqualizer attached to the dead session so playback resumed without equalization until the next station switch. The session-id listener now detects genuine rotations through a dedicated guard and re-activates the equalizer with the current preset, gated on EQ availability to stay clear of player teardown/rebuild.
64 lines
3.7 KiB
Markdown
64 lines
3.7 KiB
Markdown
# Proposal: EQ Re-Apply After Audio-Focus Ducking
|
|
|
|
## Intent
|
|
|
|
When another app interrupts playback (Radarbot warnings, Google Maps directions), the native Android audio session id rotates on the audio-focus transition. ExoPlayer orphans the effect attached to the dead session (documented upstream, issue #5302), so `just_audio`'s `AndroidEqualizer` keeps its gain state but never re-pushes it to the new session. Music resumes flat/un-equalized. Re-attachment currently only fires on explicit station switch (`_cambiarFuente` -> `_activarEcualizador`, `servicio_audio.dart:449/526`). The user requires the music to ALWAYS stay equalized. This is Part B; disconnect-revert (Part A) is the separate `eq-device-disconnect-revert` change.
|
|
|
|
## Scope
|
|
|
|
### In Scope
|
|
- Subscribe to `androidAudioSessionIdStream` inside `PluriWaveAudioHandler` for EQ purposes
|
|
- On a changed + non-null session id, re-attach and re-push current gains via existing `_activarEcualizador()` / `aplicarPreset(_presetActual)`
|
|
- Change-guard + `_eqDisponible` gate so it never re-fires redundantly nor races `_recrearPlayer()` teardown
|
|
- New tests covering re-apply after session-id rotation, first-activation no-op, and teardown race
|
|
|
|
### Out of Scope
|
|
- Part A device disconnect/cold-start revert (`eq-device-disconnect-revert`)
|
|
- Any `ServicioAudioSession` interruption/duck/pause logic change
|
|
- `EstadoEcualizador` / multi-device toggle logic
|
|
- Kotlin/platform-channel changes
|
|
- `VisualizadorAudio` (reference pattern only)
|
|
|
|
## Capabilities
|
|
|
|
### New Capabilities
|
|
- `eq-audiofocus-reapply`: Equalizer re-attaches and re-applies current gains whenever the native audio session id rotates mid-playback
|
|
|
|
### Modified Capabilities
|
|
- None (no existing equalizer spec)
|
|
|
|
## Approach
|
|
|
|
Extend the existing `_androidAudioSessionIdSub` listener (`servicio_audio.dart:258-265`), which today only stores/broadcasts the id. After broadcast, if the id changed and is non-null AND `_eqDisponible` is true, call the idempotent choke-point to re-enable and re-write band gains for `_presetActual`. This mirrors `VisualizadorAudio._onSessionId` (`visualizador_audio.dart:82-88`) — the proven in-repo reaction pattern. The fix lives entirely below the multi-device layer (`_eqMultiDeviceEnabled` is an `EstadoEcualizador` concern, absent from this file), so it applies regardless of that toggle.
|
|
|
|
## Affected Areas
|
|
|
|
| Area | Impact | Description |
|
|
|------|--------|-------------|
|
|
| `lib/servicios/servicio_audio.dart` | Modified | Add EQ re-apply to `_androidAudioSessionIdSub` listener |
|
|
| `test/servicios/` | New | Session-id rotation re-apply + guard/race coverage |
|
|
|
|
## Risks
|
|
|
|
| Risk | Likelihood | Mitigation |
|
|
|------|------------|------------|
|
|
| Redundant re-fire on first/legit activation | Med | Change-guard (`== _lastSessionId` return), mirrors visualizer |
|
|
| Race with `_recrearPlayer()` rebuild | Med | Gate on `_eqDisponible == true`; teardown sets it false + nulls id |
|
|
| Regress station-switch / manual slider path | Low | Different call sites unchanged; full `flutter test` regression |
|
|
|
|
## Rollback Plan
|
|
|
|
Change is a self-contained addition to one listener block plus new tests. Revert the commit to restore prior (broken) behavior — no persistence, schema, or API surface change, so no data migration or downstream impact.
|
|
|
|
## Dependencies
|
|
|
|
- None. `androidAudioSessionIdStream`, `_activarEcualizador()`, `aplicarPreset()` all already exist.
|
|
|
|
## Success Criteria
|
|
|
|
- [ ] After another app ducks/interrupts playback, resumed music stays equalized
|
|
- [ ] EQ re-applies on every changed non-null session id, regardless of `_eqMultiDeviceEnabled`
|
|
- [ ] No redundant re-apply on first activation or during `_recrearPlayer()` teardown
|
|
- [ ] Station-switch and manual slider (`setBanda`) paths unchanged
|
|
- [ ] All new behavior covered by passing tests (Strict TDD)
|