feat(alarm): make the ring immune to device media volume
The alarm's steady-state audio runs on the Flutter media-stream player after the native handoff, so device volume 0 silenced it entirely. The ring now forces STREAM_MUSIC to an audible reference: Dart requests the override before pre-starting alarm audio (fallback WAV included), Kotlin captures the current volume once and restores it idempotently on every exit path (dismiss, snooze, dispose), with a native best-effort backstop in service teardown. The backstop is handoff-aware via PluriWaveAlarmService.flutterOwnsRing: confirmFlutterAudio marks the handoff before triggering the native stop, so the backstop cannot restore the volume mid-ring right as the Flutter player takes over (that would re-silence the alarm at volume 0). The flag resets at every ring start; Flutter process death after handoff remains a documented best-effort gap. The alarm's perceived loudness keeps ramping 5% to the configured volume through the player as before; normal radio playback and call ducking never touch the override. Work unit 2/3 of alarm-volume-ramp-restore (ring volume override).
This commit is contained in:
@@ -143,6 +143,19 @@ abstract class PuertoAlarmasAndroid {
|
||||
Future<bool> solicitarPermisoPantallaCompleta();
|
||||
Future<bool> solicitarExencionBateria();
|
||||
Future<void> confirmarAudioFlutter(String alarmaId);
|
||||
|
||||
/// Forces `STREAM_MUSIC` to the fixed audible reference level for the
|
||||
/// duration of an alarm ring so the alarm cannot be silenced by a device
|
||||
/// media volume of 0 (Requirement: Ring-scoped device-volume override).
|
||||
/// [fraccion] is reserved for future tuning; the current native
|
||||
/// implementation always targets the device max regardless of its value.
|
||||
Future<void> forzarVolumenMediaParaAlarma(double fraccion);
|
||||
|
||||
/// Restores `STREAM_MUSIC` to the value captured by
|
||||
/// [forzarVolumenMediaParaAlarma]. Idempotent: safe to call even when no
|
||||
/// override is active or it was already restored.
|
||||
Future<void> restaurarVolumenMedia();
|
||||
|
||||
Future<DiagnosticoAlarmasAndroid> diagnostico();
|
||||
Future<EventoAlarmaAndroid?> obtenerEventoInicial();
|
||||
Future<List<EjecucionAlarmaNativa>> obtenerEjecucionesNativasGestionadas();
|
||||
@@ -281,6 +294,14 @@ class ServicioAlarmasAndroid implements PuertoAlarmasAndroid {
|
||||
Future<void> confirmarAudioFlutter(String alarmaId) =>
|
||||
_logAndInvokeVoid('confirmFlutterAudio', {'id': alarmaId});
|
||||
|
||||
@override
|
||||
Future<void> forzarVolumenMediaParaAlarma(double fraccion) =>
|
||||
_logAndInvokeVoid('overrideMediaVolumeForRing', {'fraction': fraccion});
|
||||
|
||||
@override
|
||||
Future<void> restaurarVolumenMedia() =>
|
||||
_logAndInvokeVoid('restoreMediaVolume', {});
|
||||
|
||||
@override
|
||||
Future<bool> solicitarPermisoAlarmasExactas() async {
|
||||
final abierto = await _channel.invokeMethod<bool>(
|
||||
|
||||
Reference in New Issue
Block a user