-
Notifications
You must be signed in to change notification settings - Fork 312
Fallback when glasses mic stops streaming #3189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: cloud-v2-auth
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -203,6 +203,7 @@ class DeviceManager { | |
| private var lastReadyHandledAtMs: Long = 0L | ||
| private var lastReadyHandledKey: String = "" | ||
| private var lastSystemTimeSyncConnectionKey: String = "" | ||
| private var glassesMicDegradedUntilMs: Long = 0L | ||
|
|
||
| private var systemMicUnavailable: Boolean | ||
| get() = DeviceStore.store.get("bluetooth", "systemMicUnavailable") as? Boolean ?: false | ||
|
|
@@ -354,8 +355,19 @@ class DeviceManager { | |
| // actually attempt recovery (was 0 before, which made the watchdog a no-op). | ||
| val timeSinceLastLc3Event = System.currentTimeMillis() - (lastLc3Event ?: 0L) | ||
| if (timeSinceLastLc3Event > 5000) { | ||
| Bridge.log("MAN: No audio activity in the last 5 seconds from glasses, reinitializing glasses mic") | ||
| sgc?.setMicEnabled(true) | ||
| if (currentMic == MicTypes.GLASSES_CUSTOM && | ||
| preferredMic != "glasses" && | ||
| micRanking.any { it != MicTypes.GLASSES_CUSTOM } | ||
| ) { | ||
| glassesMicDegradedUntilMs = System.currentTimeMillis() + 15_000 | ||
| Bridge.log( | ||
| "MAN: No audio activity in the last 5 seconds from glasses, temporarily falling back from glasses mic" | ||
| ) | ||
| updateMicState() | ||
| } else { | ||
| Bridge.log("MAN: No audio activity in the last 5 seconds from glasses, reinitializing glasses mic") | ||
| sgc?.setMicEnabled(true) | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -708,6 +720,7 @@ class DeviceManager { | |
| */ | ||
| fun handleGlassesMicData(rawLC3Data: ByteArray, frameSize: Int = 40) { | ||
| lastLc3Event = System.currentTimeMillis() | ||
| glassesMicDegradedUntilMs = 0L | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Degrade cleared before decodeMedium Severity
Additional Locations (1)Reviewed by Cursor Bugbot for commit d292e51. Configure here. |
||
| val pcmData: ByteArray? | ||
| synchronized(lc3Lock) { | ||
| if (lc3DecoderPtr == 0L) { | ||
|
|
@@ -809,6 +822,20 @@ class DeviceManager { | |
| } | ||
|
|
||
| if (micMode == MicTypes.GLASSES_CUSTOM) { | ||
| val glassesConnected = | ||
| DeviceStore.get("glasses", "connected") as? Boolean ?: false | ||
| if (!glassesConnected) { | ||
| Bridge.log("MAN: glasses mic skipped because glasses are not connected") | ||
| continue | ||
| } | ||
|
|
||
| if (glassesMicDegradedUntilMs > System.currentTimeMillis() && | ||
| preferredMic != "glasses" && | ||
| micRanking.any { it != MicTypes.GLASSES_CUSTOM } | ||
| ) { | ||
| Bridge.log("MAN: glasses mic temporarily skipped due to missing LC3 frames") | ||
| continue | ||
| } | ||
| if (sgc?.hasMic == true) { | ||
| // enable the mic if it's not already on: | ||
| if (sgc?.micEnabled == false) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -296,6 +296,7 @@ struct ViewState { | |
| /// Last time we received an LC3 frame from the glasses (used by the mic | ||
| /// inactivity watchdog). | ||
| private var lastLc3Event: Date? | ||
| private var glassesMicDegradedUntil: Date? | ||
| private var micReinitTimer: Timer? | ||
|
|
||
| /// STT: | ||
|
|
@@ -394,6 +395,7 @@ struct ViewState { | |
| */ | ||
| func handleGlassesMicData(_ lc3Data: Data, _ frameSize: Int = 20) { | ||
| lastLc3Event = Date() | ||
| glassesMicDegradedUntil = nil | ||
| guard let lc3Converter = lc3Converter else { | ||
| Bridge.log("MAN: LC3 converter not initialized") | ||
| return | ||
|
|
@@ -464,6 +466,20 @@ struct ViewState { | |
| } | ||
|
|
||
| if micMode == MicTypes.GLASSES_CUSTOM { | ||
| let glassesConnected = DeviceStore.shared.get("glasses", "connected") as? Bool ?? false | ||
| if !glassesConnected { | ||
| Bridge.log("MAN: glasses mic skipped because glasses are not connected") | ||
| continue | ||
| } | ||
|
|
||
| if let degradedUntil = glassesMicDegradedUntil, | ||
| degradedUntil > Date(), | ||
| preferredMic != "glasses", | ||
| micRanking.contains(where: { $0 != MicTypes.GLASSES_CUSTOM }) | ||
| { | ||
| Bridge.log("MAN: glasses mic temporarily skipped due to missing LC3 frames") | ||
| continue | ||
| } | ||
| // Bridge.log( | ||
| // "MAN: glasses custom mic found - hasMic: \(sgc?.hasMic ?? false), micEnabled: \(sgc?.micEnabled ?? false)" | ||
| // ) | ||
|
|
@@ -775,10 +791,21 @@ struct ViewState { | |
| return | ||
| } | ||
|
|
||
| let timeSinceLastLc3Event = Date().timeIntervalSince(lastLc3Event ?? Date()) | ||
| let timeSinceLastLc3Event = lastLc3Event.map { Date().timeIntervalSince($0) } ?? .greatestFiniteMagnitude | ||
| if timeSinceLastLc3Event > 5 { | ||
| Bridge.log("MAN: No audio activity in the last 5 seconds from glasses, reinitializing glasses mic") | ||
| sgc?.setMicEnabled(true) | ||
| if currentMic == MicTypes.GLASSES_CUSTOM, | ||
| preferredMic != "glasses", | ||
| micRanking.contains(where: { $0 != MicTypes.GLASSES_CUSTOM }) | ||
| { | ||
| glassesMicDegradedUntil = Date().addingTimeInterval(15) | ||
| Bridge.log( | ||
| "MAN: No audio activity in the last 5 seconds from glasses, temporarily falling back from glasses mic" | ||
| ) | ||
| updateMicState() | ||
|
Comment on lines
+800
to
+804
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When this auto-mode fallback path runs, Useful? React with 👍 / 👎. |
||
| } else { | ||
| Bridge.log("MAN: No audio activity in the last 5 seconds from glasses, reinitializing glasses mic") | ||
| sgc?.setMicEnabled(true) | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When this auto-mode fallback path runs,
updateMicState()skips glasses, selects the phone mic, and the cleanup loop disables the non-selected glasses mic withsetMicEnabled(false). The watchdog then returns early on future ticks becauseglasses.micEnabledis false, and nothing callsupdateMicState()whenglassesMicDegradedUntilMsexpires, so the intended 15-second fallback can persist indefinitely until an unrelated route or setting change occurs and the preferred auto glasses mic may never recover.Useful? React with 👍 / 👎.