Repository navigation
Keep keys through transient Keystore errors and drop stale paired state - #138
Merged
Merged
Conversation
keystore2 reports a failed key lookup (busy, system error) as an UnrecoverableKeyException, which counted as a definite key loss and deleted the key. On Android 13+ its cause, android.security .KeyStoreException, says whether the failure is transient. If it is, load() now returns null and keeps the key. Below Android 13 nothing changes. Part of #116. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129RzhbEE2cboMcYyZMuxqX
A cached key slot, or a pairing OK, kept a car shown as paired after its key was removed in the car, or after a restore brought back a key the car no longer has. The only way out was Settings, Clear pairing cache. When a whitelist listing is complete and our key ID is not in it, forget the cached slot and a stale OK, so the car shows as unpaired and offers pairing. Complete means the car reports at least one key, lists an ID for each, its slot mask has the same count, and every ID is long enough to compare. A partial or failed read changes nothing, and a pairing in progress is left alone. handleSessionInfo now uses the same helper for keys the store dropped. Part of #116. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129RzhbEE2cboMcYyZMuxqX
Contributor
ScreenshotsCaptured from the demo build at 6aa3a72. |
Contributor
ScreenshotsCaptured from the demo build at 8f8fb14. Debug APK: zip from Android CI (GitHub sign-in needed) |
3 of 9 tasks
A value pasted on Windows ends in CRLF, and base64 -d rejects the
carriage return ("invalid input"), which failed the build job before
it produced an APK. Strip all whitespace before decoding; this also
accepts line-wrapped encoder output such as certutil's.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0129RzhbEE2cboMcYyZMuxqX
Contributor
|
The Generated by Claude Code |
Contributor
ScreenshotsCaptured from the demo build at 6ac4527. Debug APK: zip from Android CI (GitHub sign-in needed) |
6 tasks
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
Follow-up to #135. Part of #116.
This implements the two follow-ups from #135's review notes:
1.
PairingKeyStore: a transient Keystore lookup failure no longer deletes the key (Android 13+)UnrecoverableKeyException, which Keep pairing keys through transient Keystore errors #135 counts as a definite loss.android.security.KeyStoreExceptionwithisTransientFailure() == true,load()now returns null and keeps the key.Build.VERSION.SDK_INT >= TIRAMISU, so the API 33 class and method are only reached there.2.
TeslaBleController: a complete whitelist without our key drops the stale paired statehandleSessionInfonow uses the same helper. Its behavior is unchanged.Type
Testing
The app module can't be built where this was written (Google Maven is blocked). Verified there:
PairingKeyStoreandTeslaBleControllercompile againstmain'scoreplus minimal Android stubs.AndroidKeyStoreprovider (real AES-GCM), in-memory prefs and a fake GATT transport fed with real Wire-encoded responses. 32 checks pass.Needs a real-car check:
With the phone key removed in the car (Controls > Locks), reconnect: the car shows "Not paired" and offers pairing.
With the key still enrolled, it keeps "Paired · slot N" after a reconnect.
./gradlew :core:test(core untouched)./gradlew :app:testDebugUnitTest(left to CI)./gradlew :app:lintDebug(left to CI; also checks the NewApi guard)Real car (see above)
Checklist
expected.txtregenerated, not hand-edited (n/a: no protocol change)SPDX-License-Identifier: AGPL-3.0-only(n/a: no new files)Notes for review
🤖 Generated with Claude Code
https://claude.ai/code/session_0129RzhbEE2cboMcYyZMuxqX
Generated by Claude Code