Skip to content

🟠 Charge cycles always 0 and battery health always 100% #7

Description

@almothafar

Summary

The Battery Insights screen always shows Charge Cycles: 0 and Health: 100%, regardless of how old the device/battery is. On a 3-year-old phone where other apps report ~86% health, this app shows 100%.

Root causes (three compounding problems)

1. The tracker almost never runs

BatteryHealthTracker.recordBatteryState() is only called from BatteryLevelReceiver.onReceive (BatteryLevelReceiver.java:60). Because battery monitoring only runs while the app is in the foreground (see the foreground-service / background-monitoring issue), recordBatteryState is rarely invoked, so cycle progress is essentially never recorded → cycles stay at 0.

2. The cycle-counting logic is too strict and lossy

BatteryHealthTracker.recordBatteryState (BatteryHealthTracker.java:67-97) only counts a cycle when the battery goes from <= 20% to >= 95% while the app is actively observing both ends. The class Javadoc claims "partial charges accumulate to form complete cycles," but the implementation does not accumulate partial charge — it requires a single full low→high swing. Most users top up before hitting 20% and unplug before 95%, so cycles are almost never counted even when monitoring works.

3. "Health %" is a fabricated estimate, not real data

getEstimatedHealthPercentage (BatteryHealthTracker.java:158-184) derives health purely from the (broken) cycle counter using a hard-coded degradation curve. With cycles stuck at 0 it always returns 100 - (0 * 5 / 300) = 100%. It never reads any real battery wear signal, so it can never match what hardware-aware apps report.

Proposed fix

  • Fix background monitoring first (prerequisite) so state is actually recorded.
  • Replace the fabricated estimate with real signals where available:
    • BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER (µAh) integrated over charge sessions to estimate full-charge-equivalent cycles and design-vs-current capacity.
    • On Android 14+ (API 35 getBatteryCycleCount() via EXTRA_CYCLE_COUNT in ACTION_BATTERY_CHANGED) read the OS-reported cycle count directly.
    • Derive health % from measured charge throughput vs. design capacity rather than a fixed curve.
  • If a real signal isn't available, label the value as an estimate in the UI instead of presenting "100%" as fact.

Acceptance criteria

  • Charge cycles increase over real usage (and/or reflect EXTRA_CYCLE_COUNT where the OS provides it).
  • Health % reflects measured wear and is not permanently pinned at 100%; if estimated, it is clearly labeled as an estimate.

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions