Skip to content

fix(sound): improve bluetooth audio mode switching debounce mechanism#3315

Open
Ivy233 wants to merge 1 commit into
linuxdeepin:masterfrom
Ivy233:fix-bluetooth-audio-debounce
Open

fix(sound): improve bluetooth audio mode switching debounce mechanism#3315
Ivy233 wants to merge 1 commit into
linuxdeepin:masterfrom
Ivy233:fix-bluetooth-audio-debounce

Conversation

@Ivy233

@Ivy233 Ivy233 commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

… to prevent UI flicker

修复蓝牙音频模式切换时输出设备列表闪烁问题

  • Add debounce flag and timer in SoundModel/SoundWorker to block UI updates during mode switching
  • Skip output device list, balance, and bluetooth mode options updates when debounce is active
  • Disable output device combobox during transition and re-enable after stabilization
  • Use 500ms debounce timer with retry mechanism to ensure device switching completion
  • Prevent intermediate device states from causing UI flicker in SpeakerPage

PMS: BUG-362189

@Ivy233 Ivy233 requested a review from caixr23 June 24, 2026 07:43

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Sorry @Ivy233, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: Ivy233

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@deepin-bot

deepin-bot Bot commented Jun 24, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 6.1.96
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #3314

@Ivy233 Ivy233 force-pushed the fix-bluetooth-audio-debounce branch from 14b9904 to 3805a07 Compare June 24, 2026 07:59
@Ivy233 Ivy233 requested review from mhduiy and robertkill and removed request for caixr23 June 24, 2026 07:59
Comment thread src/plugin-sound/operation/soundworker.cpp Outdated
@Ivy233 Ivy233 force-pushed the fix-bluetooth-audio-debounce branch from 3805a07 to d9a14e4 Compare June 24, 2026 10:20
@Ivy233 Ivy233 requested a review from mhduiy June 24, 2026 10:22
@Ivy233 Ivy233 force-pushed the fix-bluetooth-audio-debounce branch from d9a14e4 to 8b1014b Compare June 24, 2026 10:25
… to prevent UI flicker

Monitor DefaultSink changes via D-Bus to accurately detect device switching completion.
Use sink name to identify target device and end debounce early when matched.
Add content change detection in setOutPutPortCombo to filter redundant UI updates.
Block output device list, balance, and bluetooth mode options updates during debounce.
Use 1.5s timeout with early termination when target device detected (~100-600ms typical).

Log: add debounce mechanism for bluetooth audio mode switching to prevent UI flicker

fix(sound): 添加蓝牙音频模式切换防抖机制以防止UI闪烁

通过 D-Bus 监听 DefaultSink 变化,精确检测设备切换完成。
使用 sink name 识别目标设备,匹配成功时提前结束防抖。
在 setOutPutPortCombo 中添加内容变化检测,过滤冗余UI更新。
防抖期间阻止输出设备列表、平衡和蓝牙模式选项更新。
使用 1.5 秒超时,检测到目标设备时提前结束(典型耗时约 100-600ms)。

Log: 添加蓝牙音频模式切换防抖机制以防止UI闪烁

PMS: BUG-362189
@Ivy233 Ivy233 force-pushed the fix-bluetooth-audio-debounce branch from 8b1014b to 0a7d94b Compare June 24, 2026 10:32
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

★ 总体评分:79分

■ 【总体评价】

代码实现了蓝牙音频模式切换的UI防抖机制,但存在期望设备匹配逻辑失效和代码重复问题
逻辑基本正确但因期望Sink名称在模式切换时必定改变导致提前结束防抖失效,且存在大量重复防抖判断扣21分

■ 【详细分析】

  • 1.语法逻辑(存在错误)✕

SoundWorker::setBluetoothMode 中记录的 m_expectedSinkName 是切换前的旧Sink名称。在蓝牙模式(如A2DP切换到HFP)变更时,底层音频服务通常会销毁旧Sink并创建新Sink,导致 onDefaultSinkChangedForDebouncecurrentSinkName == m_expectedSinkName 永远无法成立,提前结束防抖的优化逻辑完全失效,退化为必定等待1.5秒超时。此外 soundworker.cpp 中引入了 #include <QDateTime> 但未使用。
潜在问题:防抖优化逻辑失效导致UI冻结时间固定为1.5秒;引入了冗余的头文件。
建议:修改期望设备匹配逻辑,可通过正则提取并比对设备MAC地址或蓝牙设备唯一标识符来判断是否切换到目标设备,而非直接比对Sink名称;移除未使用的 #include <QDateTime>

  • 2.代码质量(一般)✕

SoundModel 中的 setOutPutPortCombosetOutPutPortComboIndexsetSpeakerBalanceaddPortremovePortsetBluetoothAudioModeOptssetShowBluetoothMode 等多达7个函数内部均重复添加了 if (m_debounceOutputDeviceList) { return; } 判断,违反DRY原则,增加了后续维护成本。此外,sounddbusproxy.hsoundmodel.hsoundworker.h 等文件中的版权年份从2027被错误修改为2026。
潜在问题:防抖拦截逻辑高度分散导致维护困难;版权年份被逆向修改。
建议:考虑在Model层使用 blockSignals 机制或在Worker层切换时直接断开相关更新信号的连接以集中处理防抖拦截;恢复版权年份为2027。

  • 3.代码性能(高效)✓

引入防抖机制有效避免了蓝牙模式切换期间底层多次Sink变更事件引发的QML界面频繁重绘和属性绑定连锁更新,减少了不必要的UI渲染开销和CPU占用,整体性能表现良好。
建议:无。

  • 4.代码安全(存在0个安全漏洞)✓

漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个
代码仅涉及本地D-Bus通信与UI状态控制,未引入命令注入、越权访问或内存破坏等安全风险,新增的 nameSink 接口仅作只读属性获取,安全可控。
建议:保持现有的安全编码规范。

■ 【改进建议代码示例】

// soundworker.cpp
#include <QRegularExpression>

// 提取蓝牙设备MAC地址的辅助函数,用于准确判断设备切换
static QString extractBluetoothMac(const QString &sinkName) {
    // 匹配 bluez_output.XX_XX_XX_XX_XX_XX.xxx 或类似格式
    QRegularExpression re("bluez_output\\.([0-9A-Fa-f_]+)\\.");
    QRegularExpressionMatch match = re.match(sinkName);
    if (match.hasMatch()) {
        return match.captured(1);
    }
    return QString();
}

void SoundWorker::setBluetoothMode(const QString &mode)
{
    // 记录期望的蓝牙设备MAC地址,而非会随Mode改变的Sink名称
    m_expectedSinkName = extractBluetoothMac(m_soundDBusInter->nameSink());

    // 停止可能正在运行的其他定时器,避免干扰防抖
    m_waitOutputReceiptTimer->stop();

    // 启动防抖:阻止Output Device列表更新,禁用相关控件
    m_model->setDebounceOutputDeviceList(true);
    m_model->setOutPutPortComboEnable(false);
    m_debounceChangeModeTimer->start(1500);  // 蓝牙Mode切换需要更长时间

    m_soundDBusInter->SetBluetoothAudioMode(mode);
}

void SoundWorker::onDefaultSinkChangedForDebounce(const QDBusObjectPath &)
{
    if (!m_model->debounceOutputDeviceList() || !m_debounceChangeModeTimer->isActive()) {
        return;
    }

    QString currentMac = extractBluetoothMac(m_soundDBusInter->nameSink());

    // 基于MAC地址匹配,解决Mode切换时Sink名称改变导致无法提前结束防抖的问题
    if (!currentMac.isEmpty() && currentMac == m_expectedSinkName) {
        m_debounceChangeModeTimer->stop();
        onBluetoothModeDebounceTimeout();
    } else {
        // 设备仍在切换中,重启定时器
        m_debounceChangeModeTimer->start(1500);
    }
}

@deepin-bot

deepin-bot Bot commented Jun 29, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 6.1.97
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #3322

@deepin-bot

deepin-bot Bot commented Jul 1, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 6.1.98
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #3328

@deepin-bot

deepin-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 6.1.99
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #3348

@deepin-bot

deepin-bot Bot commented Jul 16, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 6.1.100
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #3354

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.

3 participants