Fix USB audio death-loop; show real version in splash & About#82
Merged
Conversation
…bout
Three things bundled because they ship together to the same Play release.
1. USB audio death-loop fix. On the car-dash Android 11 tablet, the
isochronous capture loop in UsbAudioDevice exits immediately —
connection.requestWait() returns null on the first iteration — and
the onCaptureStopped callback was unconditionally reinitializing the
recorder. That triggered open -> activate -> start -> die ->
reinit -> ... at ~30ms per cycle. Symptom in debug.log: hundreds of
`openUsbAudioInput: SUCCESS at 48000 Hz` lines per second.
- MicRecorder now rate-limits self-rebind to one per 2s.
- After 3 consecutive failures without ever delivering audio data,
it gives up on the raw USB path and falls back to AudioRecord+mic
so the app stops thrashing the USB bus. Degraded but functional.
- UsbAudioDevice.captureLoop now writes the reason (requestWait
null vs exception) and iteration count to debug.log so the next
car-dash capture tells us why isochronous transfers are failing.
2. Splash screen version is now dynamic — reads
GeneralVariables.VERSION + VERSION_CODE so each shipped release
shows a unique identifier. Replaces the hardcoded "v1.0 · Forked
from FT8CN" line. CI bumps versionCode from GITHUB_RUN_NUMBER + 100.
3. About dialog: removed the "Based on FT8CN by BG7YOZ" line and
replaced it with the tagline "FT8, made easy." Upstream
attribution remains in README.md and LICENSE so this is purely a
UI cleanup.
Co-Authored-By: Claude Opus 4.7 (1M context) <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
Three things bundled because they ship together to the same Play release.
1. USB audio death-loop fix (the main one)
The car-dash debug.log from #81 revealed that
openUsbAudioInputwas firing hundreds of times per second on the tablet, each call succeeding. Root cause:UsbAudioDevice.captureLoopblocks onconnection.requestWait(), which returnsnullon the first iteration on that host (the kernel/USB stack apparently can't deliver isochronous URBs to userspace viaUsbRequest). The capture thread exits, thefinallyblock firesonCaptureStopped(), MicRecorder unconditionally callsreinitialize(), which reopens the USB handle and starts capture again, which dies immediately, ... ~30ms per cycle, forever.This PR doesn't fix the underlying isochronous-transfer issue (we still need more data to know whether it's worth retrying at a different sample rate or claiming a different alt-setting), but it does stop the spin and produce clear diagnostic output:
MicRecorderrate-limits self-rebind to one per 2s.AudioRecord+mic. App is degraded but stops thrashing the USB bus.usbAudioSawData— first valid callback resets the failure counter so intermittent hiccups don't accumulate.UsbAudioDevice.captureLoopnow writes its exit reason todebug.log(requestWaitreturned null after N iterations, or exception class + message) plus device params (sample rate, channels, packet size, ratio). The next car-dash repro will tell us exactly when and why the loop dies.2. Splash version is dynamic
Replaces hardcoded
"v1.0 · Forked from FT8CN"with"v${VERSION} · build ${VERSION_CODE}". CI bumpsversionCodeper release (GITHUB_RUN_NUMBER + 100), so each shipped build shows a unique identifier matching what Play displays.3. About dialog tagline
Removed the FT8CN attribution line from the About dialog. The fork credit and BG7YOZ thanks remain in
README.md:5,52andLICENSE. Replaced with"FT8, made easy."plus a slightly cleaner description blurb.Test plan
installDebugbuilds + installs clean on Pixel 8.v1.0.2 · build 4(local build; CI will assign the real code).(USB direct), open Debug screen, share log. Expected outcome: hundreds ofSUCCESS at 48000 Hzlines replaced with a singleUsbAudio.captureLoop: requestWait returned null after 0 iterations+ a couple of throttled reinits + finalgiving up on raw USB ... forcing fallback to AudioRecord. App ends up on the mic but stops spinning. The captureLoop log line will tell us the next move.🤖 Generated with Claude Code