Skip to content

Avoid redundant default-voice Binder calls during Android initialization - #654

Open
Wackymax wants to merge 1 commit into
dlutton:masterfrom
Wackymax:codex/android-tts-init-binder-calls
Open

Avoid redundant default-voice Binder calls during Android initialization#654
Wackymax wants to merge 1 commit into
dlutton:masterfrom
Wackymax:codex/android-tts-init-binder-calls

Conversation

@Wackymax

@Wackymax Wackymax commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Both Android initialization callbacks query TextToSpeech.defaultVoice, check its language, and apply that language again. These synchronous service calls can block the initialization callback on Binder IPC and voice-list deserialization; a production ANR was captured in onInitListenerWithoutCallback -> TextToSpeech.getDefaultVoice -> isLanguageAvailable -> BinderProxy.transact.

Remove the redundant default-language blocks from both callbacks. Android's own SetupConnectionAsyncTask already stores the engine's default language and voice before dispatching onInit (AOSP source). The plugin continues to register its utterance listener, drain pending calls, and complete setEngine. Explicit language and voice APIs retain their existing behavior. In particular, a queued setLanguage request is no longer overwritten by the subsequent default-language reset.

Related to #594, which identifies the same initialization ANR and proposes moving the calls to a worker thread alongside changes to pending-call handling. This is a smaller alternative for the redundant default-language work; it does not attempt to fix all TTS Binder operations or pending-call concurrency.

Validation: four parameterized Android JVM regression cases cover both initialization callbacks, verify that initialization performs no default-voice/language service calls, and verify that an explicit language request queued before initialization is preserved. Physical-device latency and engine-specific default-voice behavior still need validation.

The regression tests failed in all four cases against unpatched master and passed in all four cases with the fix. Command: ./gradlew --no-daemon --no-configuration-cache -PskipDependencyChecks=true :flutter_tts:testDebugUnitTest from example/android. Local test setup used JDK 21, Gradle 8.13, and the installed NDK 28.2; the newer local Flutter SDK required the version-check bypass. These example/toolchain adjustments are not included in this PR.

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