Skip to content

fix(android): keep stale PTT from restarting capture#100552

Merged
steipete merged 17 commits into
mainfrom
codex/android-background-voice
Jul 6, 2026
Merged

fix(android): keep stale PTT from restarting capture#100552
steipete merged 17 commits into
mainfrom
codex/android-background-voice

Conversation

@steipete

@steipete steipete commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Related: #99840
Follow-up to #100483

What Problem This Solves

Fixes an issue where Android gateway push-to-talk could restart microphone capture after the app backgrounded, or let a stale stop/cancel tear down a newer Manual Mic or push-to-talk session when preparation, retries, and lifecycle changes overlapped.

Why This Change Was Made

The initial background-stop fix landed from #99840 in #100483, but its check occurred before suspended configuration work and its cleanup was not capture-scoped. This follow-up gives each capture explicit ownership, performs lifecycle-sensitive preparation on Main, serializes preparation and cleanup, and rejects stale work again at the recognizer-start boundary.

User Impact

Android no longer leaves Talk foreground-service state active after a cancelled, permission-revoked, or backgrounded gateway PTT request, and delayed work cannot replace or stop a newer microphone session. Cancellation invalidates preparation before waiting, while later starts retain their new command epoch. Idempotent one-shot retries return the active capture as busy without opening a second recognizer.

Evidence

  • Exact head: 2dbd12f4fd2e85d2c5cb5ed9c182c3e8ac4ad4aa, rebased onto 89f911f322c90c3e7e3ec51120686256de19b4b1.
  • Added regression coverage for lifecycle-invalidated starts, cancellation ordering, stale stop/cancel callbacks, cancelled one-shot waits, permission loss, busy retries, Manual Mic ownership, and foreground cleanup.
  • Sanitized AWS Crabbox run run_8168a951e06e passed the complete TalkModeManagerTest and GatewayBootstrapAuthTest classes on both Play and third-party Android flavors (65 Gradle tasks) for the identical pre-rebase patch.
  • pnpm native:i18n:check passed with 2,583 entries and no drift; git diff --check origin/main...HEAD passed.
  • Fresh post-overlap autoreview reported no accepted/actionable findings (correctness 0.90); git range-diff showed the production patch unchanged apart from regenerated i18n line metadata.
  • Exact-head GitHub CI is rerunning after the clean rebase; the prior exact-head Android Play and third-party unit lanes passed.

@openclaw-barnacle openclaw-barnacle Bot added the app: android App: android label Jul 6, 2026
@steipete steipete self-assigned this Jul 6, 2026
@openclaw-barnacle openclaw-barnacle Bot added size: L maintainer Maintainer-authored PR labels Jul 6, 2026
@steipete
steipete force-pushed the codex/android-background-voice branch from 381c93e to 08c95cf Compare July 6, 2026 02:21
@clawsweeper

clawsweeper Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 6, 2026, 1:50 AM ET / 05:50 UTC.

Summary
The PR rewrites Android gateway push-to-talk ownership and preparation, adds capture-scoped TalkModeManager stop/cancel/one-shot handling, updates Android regression tests and native i18n metadata, and adds a changelog entry.

PR surface: Docs +1, Other +648. Total +649 across 6 files.

Reproducibility: yes. from source inspection: gateway node.invoke preserves paramsJSON, Android dispatch forwards paramsJson, but the PR-head TalkHandler adapter ignores it and the changed stop/cancel handlers still call the no-arg active-capture methods. I did not run an Android device repro.

Review metrics: none identified.

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🦪 silver shellfish
Patch quality: 🦐 gold shrimp
Result: blocked until real behavior proof from a real setup is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Parse and honor requested captureId for Android PTT stop/cancel, with a regression that stale stop/cancel params preserve a newer capture.
  • [P1] Add real Android mic/background proof from a device or emulator, redacting private data such as IPs, tokens, phone numbers, and endpoints.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR provides Android unit/CI and Crabbox test evidence, but no after-fix physical or emulator Android microphone/background run; add a redacted device/emulator recording, logs, or terminal transcript showing the stale PTT lifecycle behavior before and after. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Risk before merge

  • [P1] Merging this as-is leaves the stale stop/cancel hole in the central Android gateway PTT path: caller params can carry an old captureId, but the adapter still stops whatever capture is active when the release runs.
  • [P1] The PR rewrites Android microphone capture ownership, foreground-service cleanup, and serialization around suspended gateway config work; unit coverage helps, but physical/emulator microphone lifecycle behavior remains unproven.

Maintainer options:

  1. Fix scoped release before merge (recommended)
    Repair Android stop/cancel request handling so stale capture IDs return idle instead of ending the active recognizer, then refresh focused Android proof.
  2. Accept test-only lifecycle risk
    Maintainers can intentionally merge with unit-only proof, but they would own any physical Android microphone or foreground-service regression that CI did not exercise.

Next step before merge

  • [P1] Human/contributor follow-up is needed because the PR has a concrete scoped-release correctness blocker and only test-only behavior proof for a native microphone lifecycle change.

Security
Cleared: The diff changes Android runtime and tests only; I found no concrete supply-chain, permissions broadening, secret handling, or code-execution regression beyond the microphone lifecycle correctness risk already called out.

Review findings

  • [P2] Scope stop/cancel to the requested capture — apps/android/app/src/main/java/ai/openclaw/app/NodeRuntime.kt:1750
Review details

Best possible solution:

Parse the optional Android PTT stop/cancel captureId from node.invoke paramsJson, pass it into the capture-scoped TalkModeManager methods, add a regression for stale requested capture IDs preserving a newer capture, and include real Android mic/background proof before merge.

Do we have a high-confidence way to reproduce the issue?

Yes from source inspection: gateway node.invoke preserves paramsJSON, Android dispatch forwards paramsJson, but the PR-head TalkHandler adapter ignores it and the changed stop/cancel handlers still call the no-arg active-capture methods. I did not run an Android device repro.

Is this the best way to solve the issue?

No: the ownership refactor is in the right layer, but it is not yet the best complete fix because request-scoped release/cancel still does not reach the capture-scoped methods. A narrow paramsJson-to-captureId bridge plus regression coverage is the safer completion.

Full review comments:

  • [P2] Scope stop/cancel to the requested capture — apps/android/app/src/main/java/ai/openclaw/app/NodeRuntime.kt:1750
    The PR adds capture-scoped endPushToTalk(captureId)/cancelPushToTalk(captureId), but talk.ptt.stop and talk.ptt.cancel still ignore paramsJson and call the no-arg methods. Since gateway node.invoke forwards caller params unchanged, a delayed release for an old capture can still stop the newer active recognizer instead of returning idle; parse the requested captureId and pass it through for both stop and cancel.
    Confidence: 0.9

Overall correctness: patch is incorrect
Overall confidence: 0.89

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 7e81f1596107.

Label changes

Label changes:

  • add merge-risk: 🚨 availability: The diff changes Android microphone capture ownership and foreground-service cleanup in ways that can leave capture running, fail to stop, or stop the wrong active recognizer if the state machine is wrong.
  • add rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🦐 gold shrimp.
  • add status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR provides Android unit/CI and Crabbox test evidence, but no after-fix physical or emulator Android microphone/background run; add a redacted device/emulator recording, logs, or terminal transcript showing the stale PTT lifecycle behavior before and after. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Label justifications:

  • P1: The PR targets an urgent Android microphone/PTT lifecycle regression where stale work can keep capture active or stop the wrong session.
  • merge-risk: 🚨 availability: The diff changes Android microphone capture ownership and foreground-service cleanup in ways that can leave capture running, fail to stop, or stop the wrong active recognizer if the state machine is wrong.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🦐 gold shrimp.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR provides Android unit/CI and Crabbox test evidence, but no after-fix physical or emulator Android microphone/background run; add a redacted device/emulator recording, logs, or terminal transcript showing the stale PTT lifecycle behavior before and after. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Docs +1, Other +648. Total +649 across 6 files.

View PR surface stats
Area Files Added Removed Net
Source 0 0 0 0
Tests 0 0 0 0
Docs 1 1 0 +1
Config 0 0 0 0
Generated 0 0 0 0
Other 5 855 207 +648
Total 6 856 207 +649

Acceptance criteria:

  • [P1] Focused Android regression covering talk.ptt.stop and talk.ptt.cancel with stale requested captureId preserving a newer active capture.
  • [P1] Android Play and third-party unit lanes for GatewayBootstrapAuthTest and TalkModeManagerTest.
  • [P1] Real Android device or emulator proof for background/cancel/retry PTT lifecycle, with private data redacted.

What I checked:

Likely related people:

  • steipete: Authored the merged follow-up batch that landed the initial Android background voice-capture fix and authored the current PR head that changes the same Android PTT lifecycle files. (role: recent area contributor and likely follow-up owner; confidence: high; commits: aaf5ab910cbe, 0d04c3f34510, 2dbd12f4fd2e; files: apps/android/app/src/main/java/ai/openclaw/app/NodeRuntime.kt, apps/android/app/src/main/java/ai/openclaw/app/voice/TalkModeManager.kt, apps/android/app/src/test/java/ai/openclaw/app/GatewayBootstrapAuthTest.kt)
  • xialonglee: Opened the Android background TalkMode capture PR that this follow-up cites, and that work was credited in the merged reliability batch touching this code path. (role: original source-work contributor; confidence: medium; commits: 12bd3c528b15, 0d04c3f34510; files: apps/android/app/src/main/java/ai/openclaw/app/NodeRuntime.kt, apps/android/app/src/main/java/ai/openclaw/app/voice/TalkModeManager.kt)
  • Mariano Belinky: Git history shows earlier iOS node PTT command work, which is the closest sibling implementation for Talk node invoke behavior and capture lifecycle semantics. (role: adjacent PTT protocol contributor; confidence: low; commits: 9f101d3a9aae, 1a48bce2947e; files: apps/ios/Sources/Model/NodeAppModel.swift, apps/ios/Sources/Voice/TalkModeManager.swift)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (3 earlier review cycles)
  • reviewed 2026-07-06T02:26:18.324Z sha 08c95cf :: needs real behavior proof before merge. :: [P3] Remove the release-owned changelog edit
  • reviewed 2026-07-06T02:41:17.505Z sha fcf3e5a :: needs real behavior proof before merge. :: [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-06T04:51:39.577Z sha ea0b099 :: needs real behavior proof before merge. :: [P2] Honor the requested PTT captureId on release | [P3] Remove the release-owned changelog entry

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. labels Jul 6, 2026
@clawsweeper clawsweeper Bot removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jul 6, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fcf3e5a928

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

runTalkPttCommand {
val payload = talkMode.endPushToTalk()
finishTalkCaptureIfIdle()
val payload = stopPreparedTalkPttCapture { talkMode.endPushToTalk() }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Honor captureId when stopping PTT

When a delayed talk.ptt.stop/talk.ptt.cancel arrives after a newer PTT capture has started, this still calls the no-arg endPushToTalk()/cancelPushToTalk(), which resolves activePttCaptureId at execution time (TalkModeManager.kt:421-423) and stops the newer capture. The gateway already forwards paramsJson unchanged (src/gateway/node-invoke-sanitize.ts:7-28) and GatewaySession passes it to this handler, while this commit added capture-scoped stale-safe methods in TalkModeManager; parse the requested captureId from paramsJson and pass it through so stale stop/cancel requests return idle instead of tearing down the current session.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. labels Jul 6, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ab816c4de9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1710 to +1712
val payload =
withPreparedTalkPttCommand(lifecycleEpoch, commandEpoch) { ownershipEpoch ->
val started =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid blocking PTT release behind retry preparation

When a foreground talk.ptt.start is just an idempotent retry for an already-active capture, this path still enters serialized preparation before TalkModeManager can return the existing capture. That preparation calls refreshConfig()/talk.config via GatewaySession.request with the 15s default timeout, and stop/cancel now acquire the same voiceCapturePreparationMutex, so if a retry is waiting on config, the user's release cannot stop or cancel the active recognizer until that request finishes. Short-circuit the existing activePushToTalkCaptureId retry before serialized preparation, or avoid sharing this lock with stop/cancel for retry-only work.

Useful? React with 👍 / 👎.

@blacksmith-sh

This comment has been minimized.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1ea513089e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1767 to +1768
if (start is TalkPttOnceStart.Started) {
finishTalkCaptureIfIdleAfterPreparation(start.captureId)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Invalidate queued one-shot retries after completion

When a duplicate talk.ptt.once has already read commandEpoch at the start of handleTalkPttOnce and is delayed in prepareTalkCapture/talk.config, the original one-shot can auto-stop via silence or timeout before the duplicate reaches beginPushToTalkOnce; this cleanup only clears ownership and never advances talkPttCommandEpoch, so the stale duplicate still passes the epoch check and opens a second microphone capture. Advance the command epoch as part of terminal one-shot cleanup so only requests that begin after the previous capture ends can start a new capture.

Useful? React with 👍 / 👎.

@steipete

steipete commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Land-ready review complete at exact head a5bcdd89cd2f3dc305a9ddb72eb166e81c5b0841.

What changed:

  • serialized Android gateway PTT preparation and teardown across lifecycle and command transitions;
  • scoped stop, cancel, timeout, silence, and one-shot cleanup to the owning capture ID;
  • made permission loss perform the canonical full Off transition;
  • invalidated a pending start before cancel waits, while preserving starts submitted after cancel;
  • returned active one-shot retries as busy before preparation can reopen the microphone.

Proof:

  • sanitized AWS Crabbox run_8168a951e06e: :app:testPlayDebugUnitTest and :app:testThirdPartyDebugUnitTest, filtered to the complete TalkModeManagerTest and GatewayBootstrapAuthTest classes; 65 Gradle tasks passed;
  • pnpm native:i18n:check: 2,552 entries, no drift;
  • git diff --check: passed;
  • fresh mandatory autoreview: no accepted/actionable findings, patch correct (0.87);
  • exact-head GitHub Android Play and third-party unit lanes: passed.

The remaining broad CI failures do not touch this Android diff: they report current UI navigation type drift, Workboard hook-allowlist drift, and generated docs-map drift from the synthetic merge with current main. The native Testbox prepare gate will provide the final baseline-aware merge proof.

Proof gap: no physical Android microphone device was available. Both Android flavors and deterministic Robolectric lifecycle coverage exercise the changed ownership state machine.

@steipete
steipete force-pushed the codex/android-background-voice branch from a5bcdd8 to ea0b099 Compare July 6, 2026 04:43
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jul 6, 2026
@steipete
steipete force-pushed the codex/android-background-voice branch from 81d24ba to 2dbd12f Compare July 6, 2026 05:38
@clawsweeper clawsweeper Bot removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 6, 2026
@steipete

steipete commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Land-ready at exact head 2dbd12f4fd2e85d2c5cb5ed9c182c3e8ac4ad4aa.

  • Rebased onto the latest overlapping Android base 89f911f322c90c3e7e3ec51120686256de19b4b1; git range-diff confirms unchanged production semantics, with only regenerated native-i18n line metadata.
  • Sanitized AWS Crabbox run run_8168a951e06e passed the complete TalkModeManagerTest and GatewayBootstrapAuthTest classes on both Play and third-party flavors (65 Gradle tasks) for the identical patch.
  • Exact-head GitHub CI run 28770301739 passed Android Play tests, third-party tests, the Play build, and the broad repository gates.
  • node --import tsx scripts/native-app-i18n.ts check: 2,583 entries, no drift.
  • git diff --check origin/main...HEAD: passed.
  • Fresh post-overlap autoreview: no accepted/actionable findings, correctness 0.90.

Known proof gap: no physical-device microphone session was available. The changed lifecycle/ownership state machine is covered deterministically in Robolectric and both Android CI flavors.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. labels Jul 6, 2026
@steipete
steipete merged commit f9bf5f5 into main Jul 6, 2026
105 of 112 checks passed
@steipete
steipete deleted the codex/android-background-voice branch July 6, 2026 05:51
@steipete

steipete commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 6, 2026
* fix(android): serialize background PTT lifecycle

Follow-up hardening for openclaw#99840 after the initial fix landed in openclaw#100483.

Co-authored-by: xialonglee <[email protected]>

* docs(changelog): note Android PTT lifecycle hardening

* fix(android): order PTT ownership transitions

* test(android): opt in to coroutine scheduler API

* fix(android): serialize voice capture ownership

* test(android): drive PTT ordering with test dispatcher

* test(android): isolate PTT ordering preferences

* test(android): control PTT invoke dispatchers

* test(android): isolate PTT coroutine dispatchers

* test(android): use current Robolectric resolver API

* test(android): register speech service without deprecated APIs

* test(android): control stale PTT cleanup dispatch

* test(android): isolate voice mode reassertion

* fix(android): clean voice capture on permission loss

* fix(android): invalidate PTT before cancel wait

* test(android): preserve starts queued after cancel

* fix(android): keep one-shot PTT retries idempotent

---------

Co-authored-by: xialonglee <[email protected]>
giodl73-repo pushed a commit to giodl73-repo/openclaw that referenced this pull request Jul 8, 2026
* fix(android): serialize background PTT lifecycle

Follow-up hardening for openclaw#99840 after the initial fix landed in openclaw#100483.

Co-authored-by: xialonglee <[email protected]>

* docs(changelog): note Android PTT lifecycle hardening

* fix(android): order PTT ownership transitions

* test(android): opt in to coroutine scheduler API

* fix(android): serialize voice capture ownership

* test(android): drive PTT ordering with test dispatcher

* test(android): isolate PTT ordering preferences

* test(android): control PTT invoke dispatchers

* test(android): isolate PTT coroutine dispatchers

* test(android): use current Robolectric resolver API

* test(android): register speech service without deprecated APIs

* test(android): control stale PTT cleanup dispatch

* test(android): isolate voice mode reassertion

* fix(android): clean voice capture on permission loss

* fix(android): invalidate PTT before cancel wait

* test(android): preserve starts queued after cancel

* fix(android): keep one-shot PTT retries idempotent

---------

Co-authored-by: xialonglee <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: android App: android maintainer Maintainer-authored PR merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. P1 High-priority user-facing bug, regression, or broken workflow. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. size: XL status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant