Skip to content

Revisit battery-health basis (cycle-count accuracy) and charging guidance (20–80% range) #114

Description

@almothafar

Summary

Revisit how we judge and talk about battery health. Two related parts:

Part A — Is the cycle count an accurate basis for health?

Today, when no design capacity is set, health is derived purely from a cycle count via fixed buckets (BatteryHealthTracker.java:474-500, thresholds at lines 55-57):

  • The cycle count is either the OS value (Android 14+ EXTRA_CYCLE_COUNT) or our own estimate, which accrues 100 percentage-points of charge = 1 cycle (BatteryHealthTracker.java:144-151).
  • Mapping cycles → health % is a generic lithium-ion curve, not measured for this specific battery.

Questions to answer:

  • How accurate is our cycle estimate in practice? It only counts positive level deltas while charging, so it can under- or over-count real cycles.
  • Is a generic cycle→health curve meaningful, or misleading, when we already have a measured figure (current capacity ÷ design capacity) whenever a design capacity is set (BatteryHealthTracker.java:358-364)?
  • Should we prefer/measure capacity harder and treat cycle-based health as a clearly-labelled rough estimate (the UI already distinguishes "measured" vs "estimated" via health_basis_*)?

Goal: decide whether cycle-based health stays, gets de-emphasised, or is better explained.

Part B — Charging guidance should reflect the healthy 20–80% range

The app's "healthy charge" concept currently only means "you started charging while low" (≤20%): HEALTHY_CHARGE_THRESHOLD = 20 in PowerConnectionReceiver.java, which flips a healthy/regular title on the charge-started and full notifications.

Modern lithium-ion guidance is to keep the battery roughly between 20% and 80% and avoid habitually charging to 100%. The current messaging/logic doesn't capture the "don't fill to 100%" half.

To revisit:

  • Review all charge-related copy (notification_charge_started_*, notification_full_level_*, health descriptions) so we don't encourage charging to 100%.
  • Consider whether "full battery" alerts should nudge the user to unplug around 80%, and whether "healthy" should mean "kept in the 20–80 band", not just "started low".
  • Any new/changed strings need Arabic translations (values-ar).

Out of scope

Actively stopping charging is tracked separately (see the stop-charging feasibility issue #115 — an "unplug reminder at X%" would also live there).


Design settled 2026-07-13 (session discussion with maintainer) — decisions recorded below.

Settled decisions

Part A — keep the cycle estimate, make it honest (maintainer chose "honest caption")

The measured basis (capacity ÷ rated capacity) stays preferred — it measures the actual battery, sidestepping chemistry entirely. The cycle-based fallback stays, but its blind spot is now labelled:

  • Basis caption distinguishes the cycle source: Estimated from charge cycles (reported by Android) (lifetime count, Android 14+) vs Estimated from cycles tracked since install — real wear may be higher (the app-tracked count starts at zero on install, so it understates wear on any phone older than the app). New helper: BatteryHealthTracker.isCycleCountFromOs().
  • "How it works" rewritten to explain all three bases (measured / OS cycles / app-tracked cycles) and their caveats, plus the 20–80 care tip.
  • No chemistry branching: Li-ion vs Li-Po (discussed for the maintainer's Mate 10 vs Samsung) doesn't change the curve — both are lithium-ion chemistry; real cycle-life spread is per-manufacturer/cell, and EXTRA_TECHNOLOGY is unreliable free-text anyway. Handled as a caveat sentence in the explainer instead.
  • Curve/buckets themselves unchanged.

Part B — retire the "healthy charge" concept (maintainer chose "retire it")

Starting low isn't a virtue under 20–80 guidance, so the ≤20% title flip is deleted along with its plumbing (HEALTHY_CHARGE_THRESHOLD, setIsHealthy, title pairs):

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions