Skip to content

Fast-drain alert: warn when battery drains abnormally fast for a sustained time (#109)#121

Merged
almothafar merged 2 commits into
masterfrom
feat/109-fast-drain-alert
Jul 12, 2026
Merged

Fast-drain alert: warn when battery drains abnormally fast for a sustained time (#109)#121
almothafar merged 2 commits into
masterfrom
feat/109-fast-drain-alert

Conversation

@almothafar

Copy link
Copy Markdown
Owner

Closes #109.

Stacked on #120 (#108). Target base is feat/108-drain-rate; review/merge that first. This diff shows only the #109 changes on top.

What

The alerting layer on top of #108's smoothed drain rate. No per-app data needed (it watches the whole-battery %/h), so it's fully buildable by a normal app.

  • FastDrainDetector — fires when the (already smoothed) drain rate stays at/above the user's limit for a sustained window (default 5 min). A brief spike breaks the streak. The decision core is a pure, unit-tested function; the streak/hysteresis state is persisted so it survives process restarts (like BatteryHealthTracker).
  • Context-aware repeats, no new timer (reminders piggyback the battery broadcasts):
    • screen on and unlocked → warn once per episode (user can see it),
    • screen off or lockedremind every 15 min (default) while it continues — the highest-value case.
    • Re-arms only after the rate drops back below the limit (hysteresis, like the temperature alert).
  • Only while discharging. When Show battery charge/drain rate (e.g. "9%/h") in details table and status notification #108 can't produce a %/h yet (warm-up), the alert sleeps rather than firing — fail-quiet.
  • Transparent message: real measured rate + how long sustained + the user's own limit. Own notification channel + id (never replaces a level/temperature alert); respects quiet-hours / silent / vibrate.
  • Settings: enable (default on), the shared high-drain limit (Show battery charge/drain rate (e.g. "9%/h") in details table and status notification #108's red line), sustained-minutes, locked-reminder-gap. Screen/lock state via PowerManager.isInteractive + KeyguardManager (no special permission).

Testing

  • FastDrainDetectorTest covers the pure decide() core: streak start, not-yet-sustained, first-alert-fires-even-when-used, once-vs-reminder split, gap gating, sleep-on-no-rate, and re-arm-then-re-alert. testDebugUnitTest + lintDebug green; installed on the Kirin Mate 10 Pro.

On-device TODO (maintainer)

  • Simulate sustained high drain via adb shell dumpsys battery unplug + set level <n> stepping down, and verify: the streak (fires only after the sustained window), the once-vs-reminder split (lock the phone to get reminders), and that a brief spike stays silent. Restore with adb shell dumpsys battery reset.

Needs review

  • Arabic strings (values-ar) are my drafts.

@almothafar almothafar force-pushed the feat/108-drain-rate branch from 16c3619 to 225d49a Compare July 11, 2026 19:35
Base automatically changed from feat/108-drain-rate to master July 11, 2026 19:51
…ained time (#109)

Adds the alerting layer on top of #108's smoothed drain rate. Needs no per-app
data — it watches the whole-battery %/h — so it is buildable by a normal app.

- FastDrainDetector fires when the (already smoothed) drain rate stays at/above
  the user's limit for a sustained window (default 5 min); a brief spike breaks
  the streak. The decision core is pure and unit-tested; the streak/hysteresis
  state is persisted so it survives process restarts (like BatteryHealthTracker).
- Context-aware repeats with no new timer/alarm/wakelock (reminders piggyback the
  battery broadcasts): warn once per episode while the screen is on and unlocked,
  but remind every 15 min (default) while off/locked — the highest-value case.
  Re-arms only after the rate drops back below the limit, like the temperature
  alert's hysteresis.
- Only while discharging. When #108 can't produce a %/h yet (warm-up), the alert
  sleeps rather than firing — fail-quiet, no false alarms.
- Transparent message stating the real measured rate, how long it's been
  sustained, and the user's own limit. Own notification channel + id (never
  replaces a level/temperature alert); respects quiet-hours / silent / vibrate.
- The limit is the single setting shared with #108's red colour. Adds enable +
  sustained-minutes + locked-reminder-gap settings. New strings drafted in Arabic.

Screen/lock state read via PowerManager.isInteractive + KeyguardManager
(no special permission).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@almothafar almothafar force-pushed the feat/109-fast-drain-alert branch from d357c6b to d111454 Compare July 12, 2026 01:39
- Bound the streak's survival across data gaps: the sleep-on-no-rate
  rule kept a streak alive indefinitely, so the first tick after a long
  gap (process death, doze) could alert immediately with a "sustained
  for N minutes" claim built on unobserved time. The state now records
  when the rate was last seen at/above the limit; a gap longer than the
  rate's own smoothing window (BatteryRateTracker.WINDOW_MS) lapses the
  episode and starts fresh.
- Persist the streak state only when it changed: the common case
  (discharging below the limit) re-decided CLEARED and rewrote identical
  values into SharedPreferences on every battery broadcast.
- Clamp the sustained-minutes and reminder-gap preferences to their
  slider ranges on read, mirroring clampDrainLimit: a corrupt 0-minute
  sustained window would have turned the alert into the spike alarm the
  design forbids.

Tests: lapse-rule scenarios (long gap restarts the episode, boundary at
exactly WINDOW_MS, re-alert after a lapsed episode), observation
refresh, and timing clamps; existing scenarios updated for the new
lastSeenAbove field.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012LC6Qt7Nr8MpJHXuszizNF
@almothafar almothafar merged commit f72bec5 into master Jul 12, 2026
2 checks passed
@almothafar almothafar deleted the feat/109-fast-drain-alert branch July 12, 2026 08:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fast-drain alert: warn when battery drains abnormally fast for a sustained time

2 participants