记录Android 8声音调整过程。

  1. frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java
  2. private void dispatchDirectAudioEvent(KeyEvent event) {
  3. if (event.getAction() != KeyEvent.ACTION_DOWN) {
  4. return;
  5. }
  6. int keyCode = event.getKeyCode();
  7. int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
  8. | AudioManager.FLAG_FROM_KEY;
  9. String pkgName = mContext.getOpPackageName();
  10. switch (keyCode) {
  11. case KeyEvent.KEYCODE_VOLUME_UP:
  12. try {
  13. getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
  14. AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
  15. } catch (Exception e) {
  16. Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
  17. }
  18. break;
  19. case KeyEvent.KEYCODE_VOLUME_DOWN:
  20. try {
  21. getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
  22. AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
  23. } catch (Exception e) {
  24. Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
  25. }
  26. break;
  27. case KeyEvent.KEYCODE_VOLUME_MUTE:
  28. try {
  29. if (event.getRepeatCount() == 0) {
  30. getAudioService().adjustSuggestedStreamVolume(
  31. AudioManager.ADJUST_TOGGLE_MUTE,
  32. AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
  33. }
  34. } catch (Exception e) {
  35. Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
  36. }
  37. break;
  38. }
  39. }
  40. frameworks\base\services\core\java\com\android\server\audio\AudioService.java
  41. /** @see AudioManager#adjustVolume(int, int) */
  42. public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
  43. String callingPackage, String caller) {
  44. adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, callingPackage,
  45. caller, Binder.getCallingUid());
  46. }
  47. private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
  48. String callingPackage, String caller, int uid) {
  49. mVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_SUGG_VOL, suggestedStreamType,
  50. direction/*val1*/, flags/*val2*/, new StringBuilder(callingPackage)
  51. .append("/").append(caller).append(" uid:").append(uid).toString()));
  52. final int streamType;
  53. synchronized (mForceControlStreamLock) {
  54. if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream=" + suggestedStreamType
  55. + ", flags=" + flags + ", caller=" + caller
  56. + ", volControlStream=" + mVolumeControlStream
  57. + ", userSelect=" + mUserSelectedVolumeControlStream);
  58. if (mUserSelectedVolumeControlStream) { // implies mVolumeControlStream != -1
  59. streamType = mVolumeControlStream;
  60. } else {
  61. // 获取当前StreamType类型,传入的是AudioManager.USE_DEFAULT_STREAM_TYPE
  62. // AudioSystem.STREAM_MUSIC
  63. final int maybeActiveStreamType = getActiveStreamType(suggestedStreamType);
  64. final boolean activeForReal;
  65. if (maybeActiveStreamType == AudioSystem.STREAM_MUSIC) {
  66. // 判断AudioFlinger当前是否是用AudioSystem.STREAM_MUSIC
  67. activeForReal = isAfMusicActiveRecently(0);
  68. } else {
  69. activeForReal = AudioSystem.isStreamActive(maybeActiveStreamType, 0);
  70. }
  71. // 获取声音类型, 就是前面getActiveStreamType得到的AudioSystem.STREAM_MUSIC
  72. if (activeForReal || mVolumeControlStream == -1) {
  73. streamType = maybeActiveStreamType;
  74. } else {
  75. streamType = mVolumeControlStream;
  76. }
  77. }
  78. }
  79. // 判断是否是MUTE操作
  80. final boolean isMute = isMuteAdjust(direction);
  81. // 判断类型是否合法
  82. ensureValidStreamType(streamType);
  83. final int resolvedStream = mStreamVolumeAlias[streamType];
  84. // RING类型声音处理
  85. // Play sounds on STREAM_RING only.
  86. if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 &&
  87. resolvedStream != AudioSystem.STREAM_RING) {
  88. flags &= ~AudioManager.FLAG_PLAY_SOUND;
  89. }
  90. // 通知或者电话,显示UI,但是不进行MUTE操作
  91. // For notifications/ring, show the ui before making any adjustments
  92. // Don't suppress mute/unmute requests
  93. if (mVolumeController.suppressAdjustment(resolvedStream, flags, isMute)) {
  94. direction = 0;
  95. // 将相应的位清零
  96. flags &= ~AudioManager.FLAG_PLAY_SOUND;
  97. flags &= ~AudioManager.FLAG_VIBRATE;
  98. if (DEBUG_VOL) Log.d(TAG, "Volume controller suppressed adjustment");
  99. }
  100. adjustStreamVolume(streamType, direction, flags, callingPackage, caller, uid);
  101. }
  102. /** @see AudioManager#adjustStreamVolume(int, int, int) */
  103. public void adjustStreamVolume(int streamType, int direction, int flags,
  104. String callingPackage) {
  105. if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
  106. Log.w(TAG, "Trying to call adjustStreamVolume() for a11y without"
  107. + "CHANGE_ACCESSIBILITY_VOLUME / callingPackage=" + callingPackage);
  108. return;
  109. }
  110. mVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_STREAM_VOL, streamType,
  111. direction/*val1*/, flags/*val2*/, callingPackage));
  112. adjustStreamVolume(streamType, direction, flags, callingPackage, callingPackage,
  113. Binder.getCallingUid());
  114. }
  115. private void adjustStreamVolume(int streamType, int direction, int flags,
  116. String callingPackage, String caller, int uid) {
  117. if (mUseFixedVolume) {
  118. return;
  119. }
  120. if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream=" + streamType + ", dir=" + direction
  121. + ", flags=" + flags + ", caller=" + caller);
  122. // 判断参数是否合法
  123. ensureValidDirection(direction);
  124. ensureValidStreamType(streamType);
  125. boolean isMuteAdjust = isMuteAdjust(direction);
  126. // 判断声音是否受MUTE影响
  127. if (isMuteAdjust && !isStreamAffectedByMute(streamType)) {
  128. return;
  129. }
  130. // use stream type alias here so that streams with same alias have the same behavior,
  131. // including with regard to silent mode control (e.g the use of STREAM_RING below and in
  132. // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION)
  133. // 获取声音类型的别名
  134. int streamTypeAlias = mStreamVolumeAlias[streamType];
  135. VolumeStreamState streamState = mStreamStates[streamTypeAlias];
  136. // 获取声音对应的device
  137. final int device = getDeviceForStream(streamTypeAlias);
  138. int aliasIndex = streamState.getIndex(device);
  139. boolean adjustVolume = true;
  140. int step;
  141. // 跳过蓝牙请求,如果对应的设备不是蓝牙
  142. // skip a2dp absolute volume control request when the device
  143. // is not an a2dp device
  144. if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
  145. (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
  146. return;
  147. }
  148. // 获取UID
  149. // If we are being called by the system (e.g. hardware keys) check for current user
  150. // so we handle user restrictions correctly.
  151. if (uid == android.os.Process.SYSTEM_UID) {
  152. uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));
  153. }
  154. if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
  155. != AppOpsManager.MODE_ALLOWED) {
  156. return;
  157. }
  158. // reset any pending volume command
  159. synchronized (mSafeMediaVolumeState) {
  160. mPendingVolumeCommand = null;
  161. }
  162. flags &= ~AudioManager.FLAG_FIXED_VOLUME;
  163. if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
  164. ((device & mFixedVolumeDevices) != 0)) {
  165. flags |= AudioManager.FLAG_FIXED_VOLUME;
  166. // Always toggle between max safe volume and 0 for fixed volume devices where safe
  167. // volume is enforced, and max and 0 for the others.
  168. // This is simulated by stepping by the full allowed volume range
  169. if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
  170. (device & mSafeMediaVolumeDevices) != 0) {
  171. step = safeMediaVolumeIndex(device);
  172. } else {
  173. step = streamState.getMaxIndex();
  174. }
  175. if (aliasIndex != 0) {
  176. aliasIndex = step;
  177. }
  178. } else {
  179. // 更改UI上的显示,增加/减少一格
  180. // convert one UI step (+/-1) into a number of internal units on the stream alias
  181. step = rescaleIndex(10, streamType, streamTypeAlias);
  182. }
  183. // 对与RINGER_MODES有关的声音组处理
  184. // If either the client forces allowing ringer modes for this adjustment,
  185. // or the stream type is one that is affected by ringer modes
  186. if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
  187. (streamTypeAlias == getUiSoundsStreamType())) {
  188. int ringerMode = getRingerModeInternal();
  189. // do not vibrate if already in vibrate mode
  190. if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
  191. flags &= ~AudioManager.FLAG_VIBRATE;
  192. }
  193. // Check if the ringer mode handles this adjustment. If it does we don't
  194. // need to adjust the volume further.
  195. final int result = checkForRingerModeChange(aliasIndex, direction, step,
  196. streamState.mIsMuted, callingPackage, flags);
  197. adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0;
  198. // If suppressing a volume adjustment in silent mode, display the UI hint
  199. if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {
  200. flags |= AudioManager.FLAG_SHOW_SILENT_HINT;
  201. }
  202. // If suppressing a volume down adjustment in vibrate mode, display the UI hint
  203. if ((result & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0) {
  204. flags |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
  205. }
  206. }
  207. // If the ringermode is suppressing media, prevent changes
  208. if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {
  209. adjustVolume = false;
  210. }
  211. int oldIndex = mStreamStates[streamType].getIndex(device);
  212. if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
  213. mAudioHandler.removeMessages(MSG_UNMUTE_STREAM);
  214. // 判断是否要更新蓝牙的音量
  215. // Check if volume update should be send to AVRCP
  216. if (streamTypeAlias == AudioSystem.STREAM_MUSIC &&
  217. (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
  218. (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
  219. synchronized (mA2dpAvrcpLock) {
  220. if (mA2dp != null && mAvrcpAbsVolSupported) {
  221. mA2dp.adjustAvrcpAbsoluteVolume(direction);
  222. }
  223. }
  224. }
  225. if (isMuteAdjust) {
  226. boolean state;
  227. if (direction == AudioManager.ADJUST_TOGGLE_MUTE) {
  228. state = !streamState.mIsMuted;
  229. } else {
  230. state = direction == AudioManager.ADJUST_MUTE;
  231. }
  232. if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
  233. setSystemAudioMute(state);
  234. }
  235. for (int stream = 0; stream < mStreamStates.length; stream++) {
  236. if (streamTypeAlias == mStreamVolumeAlias[stream]) {
  237. if (!(readCameraSoundForced()
  238. && (mStreamStates[stream].getStreamType()
  239. == AudioSystem.STREAM_SYSTEM_ENFORCED))) {
  240. mStreamStates[stream].mute(state);
  241. }
  242. }
  243. }
  244. } else if ((direction == AudioManager.ADJUST_RAISE) &&
  245. !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
  246. Log.e(TAG, "adjustStreamVolume() safe volume index = " + oldIndex);
  247. mVolumeController.postDisplaySafeVolumeWarning(flags);
  248. } else if (streamState.adjustIndex(direction * step, device, caller)
  249. || streamState.mIsMuted) {
  250. // Post message to set system volume (it in turn will post a
  251. // message to persist).
  252. if (streamState.mIsMuted) {
  253. // 静音的情况下先unmute设备
  254. // Unmute the stream if it was previously muted
  255. if (direction == AudioManager.ADJUST_RAISE) {
  256. // unmute immediately for volume up
  257. streamState.mute(false);
  258. } else if (direction == AudioManager.ADJUST_LOWER) {
  259. if (mIsSingleVolume) {
  260. sendMsg(mAudioHandler, MSG_UNMUTE_STREAM, SENDMSG_QUEUE,
  261. streamTypeAlias, flags, null, UNMUTE_STREAM_DELAY);
  262. }
  263. }
  264. }
  265. // 调整声音大小,并保存声音的数据
  266. sendMsg(mAudioHandler,
  267. MSG_SET_DEVICE_VOLUME,
  268. SENDMSG_QUEUE,
  269. device,
  270. 0,
  271. streamState,
  272. 0);
  273. }
  274. // Check if volume update should be sent to Hdmi system audio.
  275. int newIndex = mStreamStates[streamType].getIndex(device);
  276. if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
  277. setSystemAudioVolume(oldIndex, newIndex, getStreamMaxVolume(streamType), flags);
  278. }
  279. if (mHdmiManager != null) {
  280. synchronized (mHdmiManager) {
  281. // mHdmiCecSink true => mHdmiPlaybackClient != null
  282. if (mHdmiCecSink &&
  283. streamTypeAlias == AudioSystem.STREAM_MUSIC &&
  284. oldIndex != newIndex) {
  285. synchronized (mHdmiPlaybackClient) {
  286. int keyCode = (direction == -1) ? KeyEvent.KEYCODE_VOLUME_DOWN :
  287. KeyEvent.KEYCODE_VOLUME_UP;
  288. final long ident = Binder.clearCallingIdentity();
  289. try {
  290. mHdmiPlaybackClient.sendKeyEvent(keyCode, true);
  291. mHdmiPlaybackClient.sendKeyEvent(keyCode, false);
  292. } finally {
  293. Binder.restoreCallingIdentity(ident);
  294. }
  295. }
  296. }
  297. }
  298. }
  299. }
  300. int index = mStreamStates[streamType].getIndex(device);
  301. sendVolumeUpdate(streamType, oldIndex, index, flags); //更新UI显示
  302. }
  303. frameworks\base\services\core\java\com\android\server\audio\AudioService.java
  304. private class AudioHandler extends Handler {
  305. @Override
  306. public void handleMessage(Message msg) {
  307. switch (msg.what) {
  308. case MSG_SET_DEVICE_VOLUME:
  309. setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1);
  310. break;
  311. case MSG_SET_ALL_VOLUMES:
  312. setAllVolumes((VolumeStreamState) msg.obj);
  313. break;
  314. case MSG_PERSIST_VOLUME:
  315. persistVolume((VolumeStreamState) msg.obj, msg.arg1);
  316. break;
  317. case MSG_PERSIST_RINGER_MODE:
  318. // note that the value persisted is the current ringer mode, not the
  319. // value of ringer mode as of the time the request was made to persist
  320. persistRingerMode(getRingerModeInternal());
  321. break;
  322. private void setDeviceVolume(VolumeStreamState streamState, int device) {
  323. synchronized (VolumeStreamState.class) {
  324. // Apply volume
  325. streamState.applyDeviceVolume_syncVSS(device); // 将声音的数据写到底层
  326. // Apply change to all streams using this one as alias
  327. int numStreamTypes = AudioSystem.getNumStreamTypes();
  328. for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
  329. if (streamType != streamState.mStreamType &&
  330. mStreamVolumeAlias[streamType] == streamState.mStreamType) {
  331. // Make sure volume is also maxed out on A2DP device for aliased stream
  332. // that may have a different device selected
  333. int streamDevice = getDeviceForStream(streamType);
  334. if ((device != streamDevice) && mAvrcpAbsVolSupported &&
  335. ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
  336. mStreamStates[streamType].applyDeviceVolume_syncVSS(device);
  337. }
  338. mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice);
  339. }
  340. }
  341. }
  342. // Post a persist volume msg
  343. sendMsg(mAudioHandler,
  344. MSG_PERSIST_VOLUME,
  345. SENDMSG_QUEUE,
  346. device,
  347. 0,
  348. streamState,
  349. PERSIST_DELAY);
  350. }
  351. private void persistVolume(VolumeStreamState streamState, int device) {
  352. if (mUseFixedVolume) {
  353. return;
  354. }
  355. if (mIsSingleVolume && (streamState.mStreamType != AudioSystem.STREAM_MUSIC)) {
  356. return;
  357. }
  358. if (streamState.hasValidSettingsName()) {
  359. // 将参数保存
  360. System.putIntForUser(mContentResolver,
  361. streamState.getSettingNameForDevice(device),
  362. (streamState.getIndex(device) + 5)/ 10,
  363. UserHandle.USER_CURRENT);
  364. }
  365. }

Android 8 声音调整过程的更多相关文章

  1. android调节声音大小

    android调节声音大小 1.背景音乐的一些知识 网上好多关于背景音乐添加用到的类: MediaPlayer,SoundPool,AudioManager的资料,可是有时候解决不了我们在开发中遇到的 ...

  2. android绘制view的过程

    1 android绘制view的过程简单描述  简单描述可以解释为:计算大小(measure),布局坐标计算(layout),绘制到屏幕(draw):            下面看看每一步的动作到底是 ...

  3. 【转】Android绘制View的过程研究——计算View的大小

    Android绘制View的过程研究——计算View的大小 转自:http://liujianqiao398.blog.163.com/blog/static/18182725720121023218 ...

  4. Android Activity的启动过程

    文章编辑的太长了,请移步我的csdn博客:http://blog.csdn.net/xyh269 Android Activity的启动过程原文链接:http://blog.csdn.net/xyh2 ...

  5. Android应用打包安装过程具体解释

    Android应用打包安装过程(Run as Android Application ): 1,过程:Android Project --> Compilation and Packaging ...

  6. Android系统进程Zygote启动过程的源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6768304 在Android系统中,所有的应用 ...

  7. Android 6.0启动过程具体解析

    在之前的一篇文章中.从概念上学习了Andoird系统的启动过程.Android系统启动过程学习 而在这篇文章中,我们将从代码角度细致学习Android系统的启动过程,同一时候,学习Android启动过 ...

  8. android基础-Apk打包过程(了解)

    此文来源于<Android软件安全与逆向分析> 一.打包资料文件,生成R.java文件. 二.处理aidl文件,生成相应的Java文件. 三.编译工程源代码,生成相应的class文件. 四 ...

  9. 使用Android Studio调试UiAutomator过程中遇到的问题

    声明: 这里纪录了个人学习和使用Android Studio调试UiAutomator过程中遇到遇到的问题,不定时进行更新,欢迎一起交流学习 1.Excution faild for task ‘:a ...

随机推荐

  1. vim中权限不足时不用退出而强制保存

    命令: :w !sudo tee % 此命令是把当前文件(即%)作为stdin传给sudo tee命令来执行.说起来挺绕口,其实就是:用sudo强制保存.   有时候在自己机器上折腾的时候需要更改一些 ...

  2. 【转】asp.net中@page指令的属性Inherits、Src、CodeBehind区别

    Inherits.Src.CodeBehind 在 ASP.NET 中使用代码隐藏方法来设计Web 窗体,可使页代码能够更清晰地从 HTML 内容中分离到完全单独的文件中. 通常一个 @page 指令 ...

  3. 一个有趣的python排序模块:bisect

    今天同事说到了一个python的排序模块bisect,觉得挺有趣的,跟大家分享分享. 先看看模块的结构: 前面五个属性大家感兴趣可以打出来看看数值,这里就不介绍了. 先说明的是,使用这个模块的函数前先 ...

  4. java 多线程 28 : 多线程组件之 Semaphore 信号量

    Semaphore是非常有用的一个组件,它相当于是一个并发控制器,是用于管理信号量的.构造的时候传入可供管理的信号量的数值,这个数值就是控制并发数量的,就是同时能几个线程访问.我们需要控制并发的代码, ...

  5. linux笔记——一些命令工具

    ntpdate 时间同步 netstat aux网络状态 htpasswd du -h 文件大小 df 文件信息 fdisk 磁盘分区 查找删除 rm `ls |grep ` ls |grep |xa ...

  6. SVN下载时提示“已经锁定”

    问题现象:同事让我提交代码,我就先下载后提交,但下载时提示“D:\ABC”已经锁定. 问题原因:原因不明. 问题处理:向上退一级,右击目录->SVN->"清理"-> ...

  7. ARKit从入门到精通(3)-ARKit自定义实现

    转载:http://blog.csdn.net/u013263917/article/details/73038566 在上一小节中ARKit从入门到精通(2)-ARKit工作原理及流程介绍,我们完整 ...

  8. hashCode()方法与equals()方法的说明

    1,一般我们自己用时,只使用equals()方法,用于判断两个对象是否是业务上等价的.2,在重写equals()方法时,强烈推荐也要重写hashCode()方法,因为有的集合用到了hashCode() ...

  9. JVM——代空间的划分

    首先看在JVM的堆中,按代的划分: Young:主要是用来存放新生的对象. Old:主要存放应用程序中生命周期长的内存对象. Permanent:是指内存的永久保存区域,主要存放Class和Meta的 ...

  10. textmate常用快捷键备忘

    视图切换 Ctrl + Cmd + F # 折叠第三层 代码编辑 Cmd + Shift + V # 按照历史拷贝顺序来粘贴 Ctrl + Cmd + Option + V # 显示剪贴板 Cmd + ...