Repository navigation
Fix Infotainment reads blocked by a handshake that never finished - #170
Merged
Merged
Conversation
The controller passed sessionReady = !chargeAfterSession to the poll policy. The flag was cleared only when the Infotainment session was established or the link was closed, so a handshake that ended any other way (retries gave up, car went to sleep, link dropped) blocked every later read and handshake. Track the waiting read in InfotainmentSessionGate, which is ended by establishment, give-up, asleep or link drop. Request the Infotainment session only on demand, from a due read on an awake car, and never on connect or while asleep. Do not resend a request while one is in flight. Record the real-car measurements in docs/research. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129RzhbEE2cboMcYyZMuxqX
Contributor
ScreenshotsLight Dark Captured from the demo build at 06d6a59. Debug APK: zip from Android CI (GitHub sign-in needed) |
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
Real-car log (owner test, 2026-10-09): with #161 the app logged VCSEC status all morning (wake, unlock, doors, a 20-minute drive) but sent no charge or drive read.
InfotainmentPollPolicyasked for reads; the controller blocked them.Cause, confirmed in
TeslaBleController.VehicleLink: the status handler passedsessionReady = !chargeAfterSession && ...to the policy.chargeAfterSessionwas set byrequestChargeState()when it started the Infotainment handshake and cleared only on session establishment orclose(). Any other end of the handshake left it set forever:sessionRetrygiving up afterSESSION_MAX_ATTEMPTS, the retry loop returning early when the car went back to sleep or the phase was not READY,startSession()returning early (no key/VIN), or the link dropping (the FAILED/DISCONNECTED path never cleared it). The policy then gotsessionReady=falsefor the rest of the link's life, so no read and no new handshake followed.One detail differs from the report:
neededSessions()already left Infotainment out while the stored status said asleep, so the READY branch did not itself request it for a sleeping car. But that status is the last one seen before the link dropped, so after a reconnect it can be stale and say awake. The fix removes the dependency on it.Changes:
InfotainmentSessionGate(core): tracks "a due read is waiting for the handshake". Ended by session established, retries giving up, car asleep, link dropped, or handshake not startable.requestChargeState()(driven by the policy) when the car is awake. Never on connect, never while VCSEC says asleep. On READY only the VCSEC session is requested.pendingSessionsare dropped when a wait ends so none looks like a live handshake.sessionReadyis nowsession exists || VIN valid("a read can be attempted now"); no double gating on the flag.docs/research/real-car-log-2026-10-09.mdholds the measurements (no VIN, car ID, BLE name or raw logs), linked frominfotainment-polling-and-sleep.mdunder "To measure".Type
Testing
./gradlew :core:test :app:assembleDebug :app:testDebugUnitTest :app:lintDebug ktlintCheck detektall pass locally (VehicleLinkstays under the LargeClass cap).InfotainmentSessionGateTest(core): stuck wait cleared on give-up, asleep, link drop and unstartable; no handshake while asleep; no duplicate request while in flight; read released once on establishment.VehicleLink, Android handler/BLE) has no unit harness; it is read-reviewed only. The decision logic lives in the tested gate; the controller just calls it at the points listed above.session request DOMAIN_INFOTAINMENTline appears in the debug log while the car is asleep.Checklist
expected.txtregenerated, not hand-edited (no protocol change)SPDX-License-Identifier: AGPL-3.0-only🤖 Generated with Claude Code
https://claude.ai/code/session_0129RzhbEE2cboMcYyZMuxqX
Generated by Claude Code