Skip to content

Commit f7e11a2

Browse files
committed
Charging: Record the confirmed HONOR telemetry defect in the ledger
Settles the open "needs one device reading" item on the HONOR entry. The contributor's screenshot (EXIF model=BKQ-N49, 10.0.0.193 C636E4R106P1) shows Amply's own Charge counter row reading 7 mAh, which is round(6978 / 1000) of the same raw value their dumpsys reported, so both read one source and it is scaled by 1000 on a 7100 mAh cell. Unprompted second corroboration in the same screenshot: Current now reads 0 mA while Status reads Discharging with the screen on, which is impossible. The competing "genuine end-of-charge trickle" explanation is dead. Records the shipped design and, more usefully, the two pure-inference designs that were built and abandoned before it, with the reason each failed. The second failure is the one worth keeping: the states that look like this defect are states Amply itself manufactures, since a device at a charge-limit hold reports CHARGING with current near zero, which is the same signature StatsLimitHitDetector uses to detect a hold. That makes a purely data-driven unit inference unsound in this codebase specifically, which is not obvious from the outside and would otherwise be rediscovered the hard way. Also notes that the ~4% cap figure recorded earlier is a ratio, so it is unaffected by the scaling question.
1 parent c33775b commit f7e11a2

1 file changed

Lines changed: 45 additions & 13 deletions

File tree

  • .claude/skills/device-qualification

.claude/skills/device-qualification/SKILL.md

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -471,19 +471,51 @@ only after adding a row here. Detailed run narratives live in each adapter's lan
471471
`Build.DEVICE`, which is exactly what an allowlist entry needs. This contributor hand-dumped properties
472472
because of it. Held rather than changed: reversing a deliberate decision on one data point is thin, and
473473
the Shizuku wizard path was still open to them. Revisit if another unknown-ROM contributor hits it.
474-
- **OPEN (needs one device reading): charge power renders `0.0 W` / `4 mA` while charging.** Both figures
475-
come from one field, `BATTERY_PROPERTY_CURRENT_NOW`. A ROM reporting mA where Android documents µA turns
476-
a real 4 A into the integer `4000`, which formats as "4 mA" and computes to
477-
`4551 mV × 4000 µA / 1e6 = 18 mW`, printing as "0.0 W" — reproduced exactly in
478-
`StatsPowerCalculatorTest`. `Charge counter: 6978` points the same way (documented µAh; 6978 µAh would be
479-
6.98 mAh). **But an end-of-charge trickle at level 100 produces the identical value**, so the number
480-
alone cannot decide, and a low-side clamp would break correct readings on healthy devices — the
481-
`MAX_PLAUSIBLE_MILLIWATTS` guard only ever caught the *over*-reporting direction, and its test comment
482-
asserted the wrong direction outright (both corrected). Deciding reading requested: Amply's own
483-
"Charge counter" row should render **~7 mAh** if the ROM scales that property, independent of charging
484-
state. No per-device telemetry seam exists (`ChargingAdapter` carries no unit capability and
485-
`BatteryReader` never sees a `DeviceInfo`), so a fix is new work — and it is adapter-independent, since
486-
this device has no adapter to hang it on.
474+
- **CONFIRMED and FIXED: the ROM reports battery telemetry in milli-units.** Symptom was charge power
475+
rendering `0.0 W` / `4 mA` while charging. Both figures come from one field,
476+
`BATTERY_PROPERTY_CURRENT_NOW`: a ROM reporting mA where Android documents µA turns a real 4 A into the
477+
integer `4000`, which formats as "4 mA" and computes to `4551 mV × 4000 µA / 1e6 = 18 mW`, printing as
478+
"0.0 W" (reproduced exactly in `StatsPowerCalculatorTest`).
479+
**Settled 2026-08-17 by screenshot** (`Screenshot_…_MainActivity.jpg`, EXIF `model=BKQ-N49`,
480+
`10.0.0.193(C636E4R106P1)`): Amply's own "Charge counter" row reads **7 mAh**, which is
481+
`round(6978 / 1000)` — the same raw `6978` the contributor's `dumpsys` showed, so both read one source
482+
and it is scaled by 1000 on a 7100 mAh cell. Second, unprompted corroboration in the same screenshot:
483+
**`Current now` = 0 mA while `Status` = Discharging with the screen on**, which is impossible; a real
484+
~300 mA arrives as `300` and `round(300/1000)` is 0. The competing "genuine end-of-charge trickle"
485+
explanation is dead.
486+
**Fix: a ROM gate AND the anomaly, both required** (`BatteryUnitCalibration.romMisreportsUnits` +
487+
`BatteryReadoutFactory.chargeCounterLooksMilliScaled`). MagicOS is recognised by system feature
488+
(`com.hihonor.software.features.honor` / `com.hihonor.system.feature`, either suffices, no `<queries>`
489+
and no permission), and the reading must *also* show an implied full-charge capacity below 100_000 µAh
490+
`counter × 100 / percent`, which normalizes out the charge level, separating a correct phone
491+
(≥ ~1_000_000 µAh at any level) from a milli device (single-digit thousands) by an order of magnitude
492+
on both sides. So a correctly-reporting MagicOS build is left alone, and no other ROM can ever be
493+
touched.
494+
**Two pure-inference designs were built and abandoned first. Record the reason, it is not obvious:**
495+
1. *Counter anomaly alone rescales both fields.* Refuted in review — `CURRENT_NOW` and
496+
`CHARGE_COUNTER` are independent HAL fields, so an impossible counter proves nothing about
497+
current. A device with a broken, stale or freshly-reset counter but healthy current would have
498+
had a real 50 mA turned into 50 A, computing to ~200 W, which slips under
499+
`StatsPowerCalculator`'s 250 W ceiling and lands in recorded stats as a *believable* lie.
500+
2. *Require the defect in both fields at once* (impossible counter AND `BATTERY_STATUS_CHARGING`
501+
while drawing under 5 mA), latched because that evidence only exists while charging. Also
502+
refuted, and by Amply's own domain: **a device at a charge-limit hold reports exactly that**
503+
`StatsLimitHitDetector` uses `abs(current) < 50_000 µA` while `CHARGING` as its hold signal.
504+
Amply *creates* holds deliberately, so a healthy phone holding at 80% with a broken counter
505+
satisfied the conjunction and latched. There is no impossibility boundary here to build on.
506+
The lesson generalizes: **the states that look like this defect are states this app manufactures**, so
507+
a purely data-driven unit inference is unsound in this codebase specifically. Being wrong about a ROM's
508+
units shows wrong numbers; being wrong about a healthy device corrupts good ones — the gate can only
509+
ever do the former. Generalizing "all MagicOS" from one device is a deliberate bounded bet, far cheaper
510+
than the adapter equivalent because the failure mode is a wrong battery figure, not a false claim that
511+
a battery is protected. Other affected ROMs stay uncorrected until one is confirmed and added.
512+
Other accepted limits: a device reporting **no** counter is undetectable, and the charger-advertised
513+
`max_charging_*` extras are deliberately not rescaled, being separate extras never observed populated
514+
on such a device.
515+
**Known wart, accepted:** `ChargeStatsRecorder` persists the readout, so history recorded before the fix
516+
keeps the uncorrected values and a chart spanning the upgrade shows a 1000× step. Only affects devices
517+
that were already reporting garbage, and no migration can identify which stored rows came from a
518+
milli-reporting device.
487519
- **Status after the 2026-08-17 follow-up: still NOT qualified.** Blocker 1's hardware half is now ANSWERED
488520
but the answer is unfavourable — the cap is real yet only ~4%, and neither key is a hard limit, so the open
489521
question is no longer "does it work" but "is an Adaptive-only MagicOS adapter worth building". Blocker 2's

0 commit comments

Comments
 (0)