Files
pluriwave/openspec/changes/snooze-reschedule-fix/explore.md
T
FreeTLab bccc5c48b8
Build & Deploy PluriWave / Análisis de código (push) Successful in 38s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 2m30s
docs(openspec): add SDD artifact trail for recent alarm and EQ changes
Persist the exploration, proposal, spec, design, tasks, and
verify/archive reports produced during the multi-device EQ,
alarm-countdown, and notification-visual-polish SDD cycles.
2026-07-04 12:42:11 +02:00

3.3 KiB

Exploration: snooze-reschedule-fix

Root Cause (single defect explains all 3 symptoms)

lib/estado/estado_alarmas.dartposponerAlarma() (L194-212) and posponerProximaDesdePreaviso() (L214-236) call await android.programar(actualizada) with no try/catch, unlike guardarAlarma() (L98-115) which wraps the identical call in try/catch and still reaches notifyListeners() on failure.

Failure chain

  1. Native scheduleMainAlarm() likely fails (most probable: exact-alarm permission revoked on Android 14+/OEM battery manager — posponerAlarma never re-requests permission before scheduling, unlike guardarAlarma which calls _solicitarPermisosNecesariosParaAlarma() first)
  2. AlarmScheduler.scheduleSpec() (Kotlin, L108-118): if scheduleMainAlarm() returns false, returns false immediately — before reaching scheduleSnoozeCountdown() at L126. This is why the countdown notification never appears too — same root cause as the no-refire bug.
  3. scheduleAlarm() returns falseServicioAlarmasAndroid.programar() throws StateError
  4. Exception propagates out of posponerAlarma() uncaughtnotifyListeners() (L211) never reached, even though _aplicar(config) (L206) already mutated _alarmas in memory
  5. _posponer() in pantalla_alarma_sonando.dart (L181-187) catches it only to debugPrint and dismiss the screen — no user feedback, no retry
  6. Result: (A) no real fire alarm scheduled; (B) scheduleSnoozeCountdown never runs; (C) proximaAlarma/proximaProgramable getters hold correct data in memory but UI never rebuilds because notifyListeners() was skipped

Ruled out (verified)

  • PendingIntent requestCode collision — different formulas (31x vs 47x), correctly scoped
  • Notification channel mismatch — channel created identically by both classes
  • "Missing initial countdown post" — scheduleSnoozeCountdown() posts notification AND arms first tick in one call
  • Dart→Kotlin Long encoding, alarma.activa flag, periodic resync, fire-vs-snooze race — all verified correct

Affected Areas

  • lib/estado/estado_alarmas.dartposponerAlarma(), posponerProximaDesdePreaviso(): missing try/catch, missing notifyListeners()-on-failure, missing permission pre-check
  • android/.../AlarmScheduler.ktscheduleSpec() (81-137): early return false skips scheduleSnoozeCountdown entirely (by design, but compounds the silent Dart-side failure)
  • lib/pantallas/pantalla_alarma_sonando.dart_posponer(): swallows exception with only debugPrint, no user-facing signal

Recommendation

  1. Wrap android.programar() in both snooze methods in try/catch mirroring guardarAlarma() — always reach notifyListeners()
  2. Add the same permission pre-check (_solicitarPermisosNecesariosParaAlarma()) before scheduling in both snooze methods
  3. Surface failure to user in _posponer() (SnackBar) since the screen always dismisses regardless by design
  4. Device-test with exact-alarm permission both granted and revoked

Risks

  • Root cause is permission-dependent; cannot be 100% confirmed without adb logcat from the device at failure time. Fix should land regardless since missing try/catch + missing notifyListeners is a confirmed defect independent of which native call failed underneath
  • posponerProximaDesdePreaviso shares the identical defect, must be fixed together