Skip to content

Keep listening after headset/assist triggers when the phone is locked - #443

Open
yannikism wants to merge 2 commits into
DicioTeam:mainfrom
yannikism:fix-assist-on-lock-screen
Open

yannikism wants to merge 2 commits into
DicioTeam:mainfrom
yannikism:fix-assist-on-lock-screen

Conversation

@yannikism

Copy link
Copy Markdown

Follow-up to #228 / #213: ACTION_VOICE_COMMAND from a Bluetooth headset already reaches Dicio, but it only works while the phone is unlocked. With the phone locked, nothing happens, and after a cold start the first button press is ignored.

What happens today (from logcat)

A long press on the headset button makes the headset send AT+BVRA, and HeadsetService.startVoiceRecognitionByHeadset then starts MainActivity with ACTION_VOICE_COMMAND. This path is the same whether the phone is locked or not.

  • Locked: MainActivity receives the intent and starts listening, but it does not show above the keyguard (setShowWhenLocked is only used for the wake word). It is stopped about 130 ms later, and AudioFlinger silences the recording (AF::RecordTrack: setSilenced ... (silenced)), so Vosk only receives silence.
  • Cold start: if the process was killed, Android first recreates MainActivity with its original launcher intent. That preloads the Vosk model with tryLoad(null). The assist intent then arrives through onNewIntent, while the model is still Loading(null). tryLoad(listener) returns false in that state, so the press is dropped and a second press is needed.

Changes

  1. MainActivity: assist intents (ACTION_ASSIST, ACTION_VOICE_COMMAND) now set setShowWhenLocked(true), as the wake word already does. setTurnScreenOn(true) is used only for ACTION_ASSIST and the wake word. For ACTION_VOICE_COMMAND (headsets) the screen stays off, since the phone is usually in a pocket.
  2. New SttForegroundService (foregroundServiceType="microphone"). It is started from MainActivity.onResume() after an assist intent and stops as soon as the STT is no longer listening (at most 60 s). Once the activity is not visible anymore (locked, or the screen turns off while listening), this is what keeps the microphone from being silenced. It is started only while the activity is resumed, because that is when Android 14+ allows starting a microphone foreground service.
  3. VoskInputDevice.tryLoad(): if the model is Loading without a listener, the listener is attached, so listening starts once loading finishes.

Tested

Android 16 phone with a Bluetooth headset that starts voice recognition via HFP:

  • Unlocked: one press → listens → answers.
  • Locked, screen off: one press → the screen stays off, the recording is unsilenced about 300 ms after the press, Vosk recognizes the speech and the answer is spoken.
  • Cold start (process killed), locked: one press is enough.
  • :app:testDebugUnitTest passes.

Related, not addressed here

🤖 Generated with Claude Code

yannikism and others added 2 commits September 27, 2026 12:21
Assist intents (ACTION_ASSIST, ACTION_VOICE_COMMAND from e.g. Bluetooth
headsets) now show MainActivity above the lock screen, like the wake
word already does. The screen is only turned on for ACTION_ASSIST and
the wake word, not for headset buttons, since the phone is usually in
a pocket then.

A new SttForegroundService of type microphone is started when the
activity is resumed after an assist intent, and stops once the STT is
not listening anymore. Without it Android silences the microphone as
soon as the activity is not visible (locked phone, screen turning off
while listening), so the STT only received silence.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When the process was killed, Android recreates MainActivity with its
original launcher intent first, which preloads the Vosk model with
tryLoad(null). The assist intent then arrives via onNewIntent while the
model is Loading(null), and tryLoad(listener) returned false, so the
first headset/assist trigger was ignored. Now the listener is attached
to the ongoing loading, and listening starts once it finishes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant