Conversation
updateSettings(), updateMetadata() and saveCache() read the whole AppleEntity and upsert it back. The cache is saved on every state change, so these ran concurrently and overwrote each other with stale columns. In practice the metadata written right after the information packet was lost almost every time, and the db kept an empty AppleMetadata. Mark them @transaction so each read-modify-write is serialized. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
startHr()/stopHr() and head tracking used metadata.version3.first(), which throws on an empty string. With the heart rate alert enabled, onDeviceConnected() calls startHr() right after loading the (empty, see previous commit) metadata from the db, so the app crashed on every reconnect. Parse the firmware major version null-safely and skip starting the sensor service while it is unknown; start heart rate monitoring once the information packet provides it if the alert is enabled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Summary
With Heart rate alert enabled, the app crashed every time the AirPods reconnected. I saw 6 crashes in about 4 minutes:
Two bugs combine to cause this. Each is fixed in its own commit.
1. Device metadata was persisted empty (lost update)
AppleDao.updateSettings(),updateMetadata()andsaveCache()each read the wholeAppleEntityand upsert it back.saveCache()runs on every state change. When the AirPods connect, about 20 control-command updates arrive together with the information packet, so these calls race. The metadata written after the information packet was almost always overwritten with the stale, emptyAppleMetadata().The log showed the pattern clearly:
Saving AppleMetadata ... version3=9442752was followed on the next load byLoaded metadata: AppleMetadata(model=UNKNOWN, ..., version3=).Fix: annotate the three methods with
@Transaction. Room generatesperformInTransactionSuspendingwrappers, so each read-modify-write is serialized.2.
version3.first()throws when the firmware version isn't knownstartHr()/stopHr()andstartHeadTracking()/stopHeadTracking()pick the sensor service withmetadata.value.version3.first().digitToInt().onDeviceConnected()callsstartHr()right afterloadInitialState()whenever the alert is on. With the empty metadata from the DB, that call throws.Fix:
firmwareMajorVersion().observeAppleMetadata()once the information packet supplies the version, if the alert is enabled and HRM is inactive.Testing
Tested on a Galaxy S26 Ultra (One UI 9.0, SDK 37) with AirPods Pro 3 (fw 9442752), with the heart rate alert enabled.
04 00 04 00 17 ...) is sent as soon as the metadata arrives.am force-stopand relaunch,Loaded metadatareturnsmodel=AIRPODS_PRO_3, version3=9442752instead of an emptyAppleMetadata.This branch builds on its own and is independent of the other two PRs.
🤖 Generated with Claude Code