Charging: Add HyperOS 3 Battery Protection support for qualified Xiaomi devices - #64
Merged
Conversation
… ledger The tanzanite contributor (issue #48) ran the requested protocol via on-device adb shell (shell UID, same path as the Shizuku service): external write of mode 2 below the cap activated Battery Protection with the Settings UI following, the device held 80% for ~20 minutes under active use, and writing 0 mid-hold resumed charging past 80. This answers the daemon-enforcement-of-external-writes question for tanzanite mode 2. No current reading (sysfs denied) and no hardware hold signal in dumpsys, so a future adapter is readback-only. Support still needs gate design (mode 2 is not HyperOS-3-wide), the reviewed write-domain widening, absent-key semantics, and a test-build qualification run.
…mi devices New XiaomiHyperOs3ChargingAdapter (xiaomi-hyperos3-v1) over the same secure key as HyperOS 2, adding mode 2 = Battery protection as FixedLimit(80). Gate: manufacturer + ro.mi.os.version.code == 3 + a qualified-codename allowlist (ships with tanzanite) + system user. Version-only gating is impossible: mode 2 is model-/build-dependent within HyperOS 3 (marblein on 3.0.2 lacks it) and cannot be probed at runtime (key absent in factory state). SYNC_READBACK only; dumpsys battery exposes no hardware hold signal on HyperOS 3. Both-direction hardware enforcement of external shell-UID writes was demonstrated on tanzanite (issue #48): write 2 below the cap holds at 80%, write 0 mid-hold resumes past 80, Settings UI follows, applied synchronously. Boundary: SettingWritePolicy widens the key's write domain to {0,1,2} globally; accepted on HyperOS 2 because no code path emits 2 there and its decode refuses it (AdapterMutationDomainTest pins the pairing). ContributionAllowlist discloses 2 as a named OEM mode. Absent-key decode (absent = Intelligent) mirrors HyperOS 2 but is unverified on HyperOS 3 — flagged in comments, pending the remote qualification run before this leaves draft.
…' into feat/xiaomi-hyperos3
Records the issue-#48 remote qualification (both-direction external shell-UID write enforcement) as a Verified-devices row and documents the GrapheneOS-precedent landing: app-level items (absent-key semantics, sessions, access tiers, R8) stay open as failing-closed known gaps, to be verified by the contributor on the next beta.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Adds charge control for HyperOS 3's Battery Protection mode on qualified Xiaomi devices, starting with the Redmi Note 14 (
tanzanite). On these devices Amply can now read and set all three native modes: Battery protection (fixed 80% cap), Intelligent charging, and Charge fully. The temporary full-charge session uses Charge fully as the override and restores the prior mode as on other supported devices. Unqualified HyperOS 3 devices keep the diagnostics-only experience with the contribution wizard.Technical Context
2is model-/build-dependent within HyperOS 3 (a Poco F5 on HyperOS 3.0.2 has only the two old modes),ro.mi.os.version.codehas no minor version, and mode-2 presence can't be probed at runtime (the key is absent in factory state; a read only returns the current value).2below the cap holds at 80% for ~20 min; write0mid-hold resumes past 80), Settings UI follows each write, applied synchronously. No hardware hold signal exists indumpsys battery, so verification is settings read-back only. The Verified-devices ledger row lands in this PR alongside the gate.SettingWritePolicywidens the key's write domain to{"0","1","2"}. The domain is global, so2becomes boundary-writable on HyperOS 2 too — accepted because no Amply code path emits it there and the HyperOS 2 decode refuses it.AdapterMutationDomainTestpins the adapter/boundary pairing.applymust value-matchFixedLimit(80)exactly (the OEM cap is hard-wired), and the registry insertion must not disturb the HyperOS 2 or lab fallthrough paths — both are pinned by new tests.Closes #48. Supersedes #63 (its ledger commit is folded into this branch).