Skip to content

[android] 悬浮窗划词追问失败:finalize QA 与进行中的 Dictation 会话互斥 #1088

Description

@HKLHaoBin

Summary

Android 悬浮窗上配置「划词追问 / QA」手势后,用户在录音过程中滑动触发 QA 时,追问面板打不开,日志反复报:

finalize_qa_from_overlay failed: another voice session is active: Dictation

这是可复现的会话互斥问题,不是偶发网络/ASR 故障。同设备日志里,该失败从 2026-09-13 起持续出现,到 2026-09-19 导出日志时仍在发生。

环境

  • 平台:Android(com.openless.app)
  • 日志文件:openless-2026-09-19T03-56-02.log(约 63k 行,覆盖 2026-08-03 → 2026-09-19)
  • ASR:bailian;LLM:deepseek
  • 触发入口:悬浮窗手势 action = qa

复现步骤(根据日志与代码路径还原)

  1. 在其他 App 中划选一段文字(期望作为追问上下文)
  2. 按住 / 点击悬浮球开始录音(此时走的是 Dictation,不是 QA)
  3. 说话(追问内容)
  4. 滑动悬浮球,触发配置为 qa 的手势(划词追问)
  5. 观察:追问面板未打开;可反复滑动,仍无 QA 面板

实际行为

  1. 悬浮球按下 → beginDictationFromOverlay() → 占用 VoiceSessionKind::Dictation
  2. QA 手势 → finalizeQaFromOverlay() → Rust finalize_qa_from_overlay() → qa.toggle_recording()
  3. 此时 QA phase 仍是 Idle,toggle_recording 会走 begin_recording(),试图再抢一把 VoiceSessionKind::Qa
  4. VoiceSessionGate 拒绝:another voice session is active: Dictation
  5. 用户连滑多次 → 同一错误刷屏;录音结束后走普通听写润色/粘贴路径,常再报 NO_FOCUSED_EDITOR(选区场景下没有可编辑焦点)

期望行为

悬浮窗「划词追问」手势应能:

  1. 在结束/转换当前 Dictation 录音的同时进入 QA 流程;或
  2. 录音开始时就按 QA 会话启动(而不是 Dictation);并
  3. 在打开 QA 面板前抓取当前选区(旧日志路径:capturing selection before opening panel)

日志证据

A. 成功路径(旧实现,2026-08 ~ 2026-09-09)

[android-native] finalize_qa_from_overlay requested
[coord] QA finalize from overlay: capturing selection before opening panel
[qa] android requested MainActivity foreground for QA
[qa] android emit qa:state to main kind=idle

本日志中该成功模式出现约 15 次(最后一次约 2026-09-09)。

B. 失败路径(回归后,2026-09-13 起)

2026-09-13T17:28:08 … [recorder] android forcing mono input channels …
2026-09-13T17:28:09 … finalize_qa_from_overlay requested
2026-09-13T17:28:09 … [coord] overlay QA finalize requested
2026-09-13T17:28:09 … finalize_qa_from_overlay failed: another voice session is active: Dictation

同一次录音期间用户连试多次,全部失败;Dictation 结束后才走 polish_streaming + NO_FOCUSED_EDITOR。

C. 导出前最后一次复现(2026-09-19T03:54–03:55)

03:54:14  capsule … state=recording
03:54:15  recorder started
03:54:18  finalize_qa_from_overlay failed: another voice session is active: Dictation  (×4)
03:54:23  mic released → polish → NO_FOCUSED_EDITOR
03:55:01–08  再次录音中连滑 QA → 同一错误 ×11
03:55:48–55  第三次录音中连滑 QA → 同一错误 ×9

本日志统计:

模式 次数
finalize_qa_from_overlay failed: … Dictation 36
旧成功日志 capturing selection before opening panel 15(均在 09-13 前)
全程 open_qa_from_overlay 0
NO_FOCUSED_EDITOR(次生粘贴失败) 1144(含历史听写场景,不单指 QA)

代码侧嫌疑(本地树对照)

  1. OpenLessOverlayService.commitSwipe("qa") 始终调用 finalizeQaFromOverlay(),从不调用已存在的 openQaFromOverlay()。
  2. 录音启动走 beginDictationFromOverlay()(Dictation),与 QA 手势语义不一致。
  3. Coordinator::finalize_qa_from_overlay 目前只是:
pub async fn finalize_qa_from_overlay(&self) -> Result<(), String> {
    log::info!("[coord] overlay QA finalize requested");
    self.inner.backend.services().qa.toggle_recording().await…
}

日志文案已从旧的 capturing selection before opening panel 变为 overlay QA finalize requested,与 09-13 起的失败时间线吻合,疑似回归:去掉了「先抓选区 / 协调 Dictation→QA」的逻辑,只剩盲目 toggle_recording。

  1. VoiceSessionGate 对 Dictation / Qa 互斥是正确的保护;问题在于 overlay QA 入口没有先释放/转换 Dictation。

建议修复方向

  • Overlay qa 手势:若当前是 Dictation 录音,应 stop/cancel Dictation 并转入 QA(抓选区 → 开面板 → 用已录音频或重新开 QA 录音),而不是对 Idle QA 再 begin_recording
  • 或:按住悬浮球开始录音前,若手势目标是 QA,直接 open_qa_from_overlay / QA begin_recording,避免先占 Dictation
  • 恢复「打开面板前 capture selection」行为;失败时给用户可见反馈(toast),不要静默 Busy
  • 补测试:Android overlay QA 在 Dictation active 时 finalize 不应返回 Busy,应完成会话转换

附件

完整设备日志:openless-2026-09-19T03-56-02.log(微信文件,可按需另行上传到 issue / gist;此处已摘关键片段)。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions