willowtreeapps / willowtreeapps/vocable-android
TTS speak() blocks the main thread on every spoken selection, freezing the gaze cursor
@MicGon7 is already working on this.
Since Aug 14, 2026.
- Dominant language
- Kotlin
- Stars
- 127
- Forks
- 21
- Avg merge
- 16m
- Merged PRs (30d)
- 4
Description
Why
VocableTextToSpeech.speak() performs blocking binder IPC into the TTS engine process on the caller's thread — setLanguage() (up to twice, with locale fallback) plus the per-call tts.voices enumeration that powers #632's live default-voice fallback — and every production call site invokes it from the main thread. The calls can take tens to hundreds of milliseconds, during which the Choreographer stops ticking: the gaze cursor visibly freezes and gaze input effectively pauses on every spoken selection. This is currently masked by GazeClickable's post-selection hold (the button is deliberately frozen green during the same window), which is how it went unnoticed — it was exposed during #678's smoothing work when that hold was temporarily disabled.
Scope
Move speak()'s blocking engine work off the main thread without changing spoken behavior.
Acceptance Criteria
-
speak()performs no blocking TTS engine calls (setLanguage, voices enumeration, speak) on the caller's thread - Engine work is serialized so concurrent
speak()calls cannot interleave engine-state mutations (single dedicated thread, not a pool) - The stale-selection signal still clears the persisted voice name at all call sites (return value becomes a callback or equivalent)
- Spoken behavior is unchanged: utterance ordering, QUEUE_FLUSH semantics, and
isSpeakingFlowtransitions - Verified on-device: the gaze cursor keeps moving through the selection-to-speech gap
Out of Scope
- Whether the post-selection hold itself should remain coupled to TTS completion (a confirmed iOS/Android behavior difference — product question, not yet tracked)
- Any debug flag for skipping the selection hold (not yet tracked)
Links
- https://github.com/willowtreeapps/vocable-android/issues/678 (where the stall was discovered; its work-log documents the smoothing pipeline this stall interrupts)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.