Skip to content

Device: Show Optimized Charging status, add Pro 3 toggle#545

Merged
d4rken merged 2 commits into
mainfrom
feat/optimized-charge-limit
Apr 24, 2026
Merged

Device: Show Optimized Charging status, add Pro 3 toggle#545
d4rken merged 2 commits into
mainfrom
feat/optimized-charge-limit

Conversation

@d4rken

@d4rken d4rken commented Apr 24, 2026

Copy link
Copy Markdown
Member

What changed

When your AirPods pause charging around 80% as part of Apple's Optimized Battery Charging, the overview card now shows an Optimized chip next to the affected battery instead of the generic "Charging" one — so you know why the percentage isn't climbing. On AirPods Pro 3, a new Battery section in device settings lets you toggle Apple's Optimized Charge Limit on or off, matching what iOS exposes for those pods.

Technical Context

  • The indicator uses the per-battery CHARGING_OPTIMIZED wire value (0x05) that the AAP battery notification already carries — it was being collapsed into a plain isCharging = true before. StatusChipRow now takes an AapPodState.ChargingState? and picks the chip from that. It self-gates via the wire value: models that never emit 0x05 never show the chip, so Pro 2 USB-C users get the indicator for free even though the toggle doesn't apply to them.
  • Toggle is gated by a new Features.hasDynamicEndOfCharge flag, currently enabled only on Pro 3 where setting 0x3B has been observed on the initial settings burst. Decoder uses decodeAppleBool so unknown byte values fall through to the unhandled-setting log path instead of silently becoming false.
  • SetDynamicEndOfCharge bypasses the ear-detection send queue (same carve-out as SetDeviceName). Without this the toggle would silently queue while pods sit in the closed case, which is the exact context a user would be in when flipping it.
  • Added a generic settingRejectedEvents flow on AapConnectionManager alongside the existing offRejectedEvents, so future setting-write failures can surface their own snackbar. The ViewModel filters for SetDynamicEndOfCharge and shows a dedicated message when verification fails.
  • The 0x3B wire format is an educated guess matching the Apple-bool convention every other boolean setting uses. Verified end-to-end on a real Pro 3 — toggling off visibly flips the battery wire state from CHARGING_OPTIMIZED back to plain CHARGING. The UI marks the feature experimental (warning below the toggle when enabled, matching Sleep Detection).

Review checklist

  • Optimized chip renders on Pro 2 USB-C (indicator only) and Pro 3 (indicator + toggle)
  • Toggling the Battery setting off on Pro 3 makes the pods continue charging past 80%
  • Battery section does not appear on Pro 1 / AirPods 3 / AirPods 4 / AirPods Max / non-Pro models
  • Previews render: StatusChipRowOptimizedPreview, BatteryCardEnabledPreview, BatteryCardDisabledPreview

Adds a per-battery 'Optimized' chip on the overview card when pods report wire value 0x05 (CHARGING_OPTIMIZED), which was already decoded but collapsed into a plain 'Charging' in the UI. On AirPods Pro 3, also adds a user-facing toggle for the device-side Optimized Charge Limit (AAP setting 0x3B).

- Decode setting 0x3B via decodeAppleBool so unknown values fall through instead of coercing to false

- Bypass ear-detection queue for SetDynamicEndOfCharge so the toggle works while pods sit in the closed case

- Expose per-slot ChargingState? on PodDevice; StatusChipRow renders 'Optimized' for CHARGING_OPTIMIZED, 'Charging' for CHARGING

- New BatteryCard in device settings with experimental warning (pattern matches Sleep Detection)

- Generic settingRejectedEvents flow alongside the existing offRejectedEvents so the toggle can show a dedicated snackbar on verification failure
@d4rken d4rken added enhancement Add a new feature of improve an existing feature device support coms/AAP Uses Apples AirPod Protocol. Requires Android ROM with fixed L2CAP support on the Bluetooth sockets. labels Apr 24, 2026
Verified on a real AirPods Pro 3: toggling flips pod charging state from CHARGING_OPTIMIZED to CHARGING and persists across reconnects. Apple-bool wire format is confirmed, so the 'experimental' warning box is no longer warranted.
@d4rken d4rken merged commit 498f040 into main Apr 24, 2026
10 checks passed
@d4rken d4rken deleted the feat/optimized-charge-limit branch April 24, 2026 15:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

coms/AAP Uses Apples AirPod Protocol. Requires Android ROM with fixed L2CAP support on the Bluetooth sockets. device support enhancement Add a new feature of improve an existing feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant