当前位置: 首页 > news >正文

【Audio】切换至静音或振动模式时媒体音自动置 0

一、问题描述

基于 Android 14平台,AudioService 中当用户切换到静音模式(RINGER_MODE_SILENT)或振动模式(RINGER_MODE_VIBRATE)时会自动将响铃和通知音量置0,当切换成响铃模式(RINGER_MODE_NORMAL)时,响铃和通知音量恢复原来大小。现在需要添加开关,当切换到静音或振动模式时将媒体音量置为0,切换到响铃模式时恢复之前音量大小。

请添加图片描述

二、问题分析

首先可以根据 SystemUI 下拉快速设置的 ProfileTile 点击切换模式的所执行的代码找到切入点,这里我们可以看到执行的方法是 audioManager.setRingerModeInternal

src/com/android/systemui/qs/tiles/ProfileTile.java

@Override
protected void handleClick(@Nullable View view) {if (ActivityManager.isUserAMonkey()) {return;}if (audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_NORMAL) {audioManager.setRingerModeInternal(AudioManager.RINGER_MODE_VIBRATE);} else if (audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE) {audioManager.setRingerModeInternal(AudioManager.RINGER_MODE_SILENT);} else if (audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT) {audioManager.setRingerModeInternal(AudioManager.RINGER_MODE_NORMAL);}boolean newState = true;refreshState(newState);
}

接着在 AudioManager -> AudioService 找到 setRingerModeInternal 的具体实现方法

frameworks/base/media/java/android/media/AudioManager.java

/*** Only useful for volume controllers.* @hide*/
@UnsupportedAppUsage
public void setRingerModeInternal(int ringerMode) {try {getService().setRingerModeInternal(ringerMode, getContext().getOpPackageName());} catch (RemoteException e) {throw e.rethrowFromSystemServer();}
}

frameworks/base/services/core/java/com/android/server/audio/AudioService.java

public void setRingerModeInternal(int ringerMode, String caller) {/*** Unisoc: testAdjustVolumeInTotalSilenceMode failed,to improve audioservice priority* BUG: 2314524* Unisoc Code @{*/int prePriority = Thread.currentThread().getPriority();Thread.currentThread().setPriority(Thread.MAX_PRIORITY);enforceVolumeController("setRingerModeInternal");setRingerMode(ringerMode, caller, false /*external*/);Thread.currentThread().setPriority(prePriority);/* @}*/
}

setRingerMode -> setRingerModeInt -> muteRingerModeStreams 通过这几层的调用找到将响铃和通知音量置为0会恢复音量的逻辑

@GuardedBy("mSettingsLock")
private void muteRingerModeStreams() {// Mute stream if not previously muted by ringer mode and (ringer mode// is not RINGER_MODE_NORMAL OR stream is zen muted) and stream is affected by ringer mode.// Unmute stream if previously muted by ringer/zen mode and ringer mode// is RINGER_MODE_NORMAL or stream is not affected by ringer mode.int numStreamTypes = AudioSystem.getNumStreamTypes();if (mNm == null) {mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);}final int ringerMode = mRingerMode; // Read ringer mode as reading primitives is atomicfinal boolean ringerModeMute = ringerMode == AudioManager.RINGER_MODE_VIBRATE|| ringerMode == AudioManager.RINGER_MODE_SILENT;final boolean shouldRingSco = ringerMode == AudioManager.RINGER_MODE_VIBRATE&& mDeviceBroker.isBluetoothScoActive();// Ask audio policy engine to force use Bluetooth SCO channel if neededfinal String eventSource = "muteRingerModeStreams() from u/pid:" + Binder.getCallingUid()+ "/" + Binder.getCallingPid();sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, AudioSystem.FOR_VIBRATE_RINGING,shouldRingSco ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE, eventSource, 0);for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {final boolean isMuted = isStreamMutedByRingerOrZenMode(streamType);final boolean muteAllowedBySco =!(shouldRingSco && streamType == AudioSystem.STREAM_RING);final boolean shouldZenMute = shouldZenMuteStream(streamType);final boolean shouldMute = shouldZenMute || (ringerModeMute&& isStreamAffectedByRingerMode(streamType) && muteAllowedBySco);if (isMuted == shouldMute) continue;if (!shouldMute) {// unmute// ring and notifications volume should never be 0 when not silencedif (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING|| mStreamVolumeAlias[streamType] == AudioSystem.STREAM_NOTIFICATION) {synchronized (VolumeStreamState.class) {final VolumeStreamState vss = mStreamStates[streamType];for (int i = 0; i < vss.mIndexMap.size(); i++) {int device = vss.mIndexMap.keyAt(i);int value = vss.mIndexMap.valueAt(i);if (value == 0) {vss.setIndex(10, device, TAG, true /*hasModifyAudioSettings*/);}}// Persist volume for stream ring when it is changed herefinal int device = getDeviceForStream(streamType);sendMsg(mAudioHandler,MSG_PERSIST_VOLUME,SENDMSG_QUEUE,device,0,mStreamStates[streamType],PERSIST_DELAY);}}sRingerAndZenModeMutedStreams &= ~(1 << streamType);sMuteLogger.enqueue(new AudioServiceEvents.RingerZenMutedStreamsEvent(sRingerAndZenModeMutedStreams, "muteRingerModeStreams"));mStreamStates[streamType].mute(false, "muteRingerModeStreams");} else {// mutesRingerAndZenModeMutedStreams |= (1 << streamType);sMuteLogger.enqueue(new AudioServiceEvents.RingerZenMutedStreamsEvent(sRingerAndZenModeMutedStreams, "muteRingerModeStreams"));mStreamStates[streamType].mute(true, "muteRingerModeStreams");}}
}

三、解决方案

直接在 AudioService 的 muteRingerModeStreams 中将 STREAM_MUSIC 音频流设置为 mute 或 unmute 来达到置 0 和恢复效果

frameworks/base/services/core/java/com/android/server/audio/AudioService.java

diff --git a/sprdroid14_sys_main/frameworks/base/services/core/java/com/android/server/audio/AudioService.java b/sprdroid14_sys_main/frameworks/base/services/core/java/com/android/server/audio/AudioService.java
index 2359afe..4451852 100755
--- a/sprdroid14_sys_main/frameworks/base/services/core/java/com/android/server/audio/AudioService.java
+++ b/sprdroid14_sys_main/frameworks/base/services/core/java/com/android/server/audio/AudioService.java
@@ -5628,6 +5628,13 @@ public class AudioService extends IAudioService.StubsendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, AudioSystem.FOR_VIBRATE_RINGING,shouldRingSco ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE, eventSource, 0);+        //*/ support auto mute media.
+        if (mSettings.getSecureIntForUser(mContentResolver,
+                Settings.Secure.AUTO_MUTE_MEDIA_ENABLED, 0, UserHandle.USER_CURRENT) == 1) {
+            mStreamStates[AudioSystem.STREAM_MUSIC].mute(ringerModeMute ? true : false, "muteRingerModeStreams");
+        }
+        //*/
+for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {final boolean isMuted = isStreamMutedByRingerOrZenMode(streamType);final boolean muteAllowedBySco =
http://www.xdnf.cn/news/1417501.html

相关文章:

  • docker安装redis,进入命令窗口基操练习命令
  • 优化括号匹配检查:从Stack到计数器的性能提升
  • MOS管学习
  • Linux 进程状态 — 僵尸进程
  • FDTD_梯度波导学习(1)
  • HOW - 前端团队产出评定方案参考
  • 携程旅行 web 验证码 分析
  • JavaEE 进阶第一期:开启前端入门之旅(上)
  • GitLab 18.3 正式发布,更新多项 DevOps、CI/CD 功能【二】
  • 餐饮门店的小程序怎么做?如何开发餐饮店下单小程序?
  • C++11模板优化大揭秘:让你的代码更简洁、更安全、更高效
  • CICD实战(2) - 使用Arbess+GitLab+SonarQube实现Java项目快速扫描/构建/部署
  • 简单实现Ai音乐suno-api
  • TCP粘包
  • 考研复习-计算机网络-第一章-计算机网络概述
  • keil MDK如何使用第三方软件Keil2Json.exe生成compile_commands.json文件,方便vscode+clangd环境使用
  • 深度解析条件编译:#ifdef与#ifndef的本质区别与应用实践
  • [Android] 京墨 v1.15.2 —— 古诗词文、汉语字典、黄历等查询阅读学习宝典(可离线)
  • MTK-Android13-实现拷贝预置资源到vendor分区下
  • Scikit-learn Python机器学习 - 字典特征提取-DictVectorizer
  • 电脑没加域却能获取到IP地址
  • 基于单片机宠物项圈/宠物防丢失设计
  • 关于命名参数占位符的分析(主要以PHP为例)
  • 设计支持多代WiFi协议的DCF信道访问控制Verilog模块:技术挑战与实现策略
  • Spring Boot配置优化:Tomcat+数据库+缓存+日志,全场景教程
  • c# winform 拼图游戏
  • 预处理——嵌入式学习笔记
  • leetcode 1576 替换所有的问号
  • Linux 定时任务 crontab 完全指南 —— 让服务器自动干活,解放双手
  • Kubernetes集群升级与etcd备份恢复指南