当前位置: 首页 > 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.dtcms.com/a/362258.html

相关文章:

  • 基于SpringBoot+MYSQL开发的师生成果管理系统
  • 解锁Git仓库瘦身秘籍,git-sizer真香警告
  • Next.js渲染模式:SSR、SSG与ISR揭秘
  • Python实现点云渲染可视化杂记(直接、彩虹渐变、柱状、饼状和T-SNE赋色)
  • The Algorithmic Foundations of Differential Privacy - 2
  • 8Lane V-by-One HS LVDS FMC Card
  • 【开题答辩全过程】以 智慧药店管理系统的实现与设计为例,包含答辩的问题和答案
  • 基于单片机智能空调/温度控制系统
  • GaussDB 集群故障cm_ctl: can‘t connect to cm_server
  • API安全厂商F5首发后量子加密方案,为企业后量子时代加固防线
  • Java中方法的参数传递
  • TFT屏幕:STM32硬件SPI+DMA+队列自动传输
  • 【无标题】训练、推理适用的数据类型
  • C++ 学习与 CLion 使用:(五)数据类型,包括整型、实型、字符型、转义字符、字符串、布尔型
  • 椭圆曲线的数学基础
  • 【算法专题训练】17、双向链表
  • openEuler2403部署Redis8集群
  • AI推理方法演进:Chain-of-Thought、Tree-of-Thought与Graph-of-Thought技术对比分析
  • Spring 控制器参数注解
  • LangGraph 边(Edge)机制完全指南
  • Java 不支持在非静态内部类中声明静态 Static declarations in inner classes are not supported异常处理
  • 2025我“生发”了『折行』|『内注』|『终端正偿』|『中文负偿』四大“邪术”(前二造福python代码阅读者;后二助力所有艺术人)
  • nrf52840 解锁
  • 2025年09月01日Github流行趋势
  • 数据结构初阶:详解栈和队列(下)——队列
  • 并发编程--线程池(1)线程池概念 Java 线程池体系(Executor、ThreadPoolExecutor、Executors)
  • resnet网络
  • 甲烷浓度时空演变趋势分析与异常值计算(附下载脚本)
  • 洛谷 P5836 [USACO19DEC] Milk Visits S-普及/提高-
  • 基于MCP架构的OpenWeather API服务端设计与实现