fix(auto): restore the equalizer toggle and list the user's own presets

Two Android Auto regressions reported from the car.

1. The on/off equalizer action disappeared from the playback screen.

That was self-inflicted: commit cacd3ec removed it on the theory that a
custom action in `controls` aborts `AudioService.setState` and kills the
media notification. Reading the plugin source refutes it. setState
(AudioService.java:513-520) SPLITS the list -- a control carrying a
customAction goes to `customActions` (PlaybackStateCompat, i.e. the car),
everything else becomes a NotificationCompat.Action in `nativeActions`
(the phone notification). The two never mix. And the throw the theory
depended on cannot happen here: ic_auto_eq_on/ic_auto_eq_off both exist
under res/drawable, and the labels are non-empty in all 13 locales.

The notification outage was already fixed by abc6b47 (transient idle on
a source change, which setState turns into a full stop() at :557).

The action is back, with both state-aware icons. The real invariant --
a custom action's icon must resolve and its label must be non-empty --
is now a test that reads res/drawable and fails on a missing file,
instead of a comment claiming custom actions are forbidden outright.

2. The Ecualizador folder never listed the user's saved presets.

itemsEcualizadorAuto iterated PresetEcualizador.presets, so only the six
factory presets appeared -- the user's own were unreachable from the
car, the surface where a preset picker matters most. They now arrive
through a registered read function (same seam as stations and local
music, re-read per browse so a preset saved on the phone shows up
without an app restart).

presetsEcualizadorAuto is the single source of truth for the ordered
universe, used to BUILD the items and to RESOLVE a tap, so the folder
cannot show an item that resolution then refuses -- which is what the
factory-only default in seleccionarPresetEqPorMediaId would have caused.
A custom preset whose name collides with a factory one is dropped: the
media id is the raw name, so it could only ever resolve to the factory
entry, and an item that applies a preset other than the one it names is
worse than an absent one.

Tests: 1108 -> 1120.
This commit is contained in:
2026-08-03 21:32:09 +02:00
parent d3999a20fb
commit f2f706b342
5 changed files with 430 additions and 98 deletions
+9
View File
@@ -11,6 +11,7 @@ import 'servicios/musica_local_auto.dart';
import 'servicios/navegacion_auto.dart';
import 'servicios/servicio_audio.dart';
import 'servicios/servicio_audio_session.dart';
import 'servicios/servicio_presets_personalizados.dart';
import 'tema/pluriwave_tokens.dart';
const _anchoMinimoLandscape = 600.0;
@@ -55,6 +56,14 @@ Future<void> main() async {
// permanently hidden (`hayCarpetaConfigurada()` has no fuente to ask).
registrarFuenteMusicaLocal(FuenteMusicaLocalAutoImpl(prefs: prefs));
// User-saved EQ presets for the car's Ecualizador folder, same
// injectable-prefs DI convention and same pre-init placement as the two
// registrations above (neither depends on the AudioHandler). Passed as a
// read function, not the service, so the folder re-reads on every browse:
// a preset saved on the phone appears in the car without an app restart.
final presetsPersonalizados = ServicioPresetsPersonalizados(prefs: prefs);
registrarFuentePresetsPersonalizados(presetsPersonalizados.listar);
// Silent-error channel (fix/notificacion-media): `AudioService.asyncError`
// had ZERO subscribers app-wide, and a `PublishSubject` with no listeners
// drops what it is given — so every exception `audio_service` catches