上一篇文章描述了在app开发中怎么调节系统不同音频流的音量大小。这次我们看下在android10中系统调节音量的实现和系统默认音量的修改。(本次源码以Android10为主梳理系统音量修改的实现)
一 按实体音量键修改音量
// frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java //以下按键事件中 if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) { if (mUseTvRouting || mHandleVolumeKeysInWM) { // On TVs or when the configuration is enabled, volume keys never // go to the foreground app. dispatchDirectAudioEvent(event); return -1; }
private void dispatchDirectAudioEvent(KeyEvent event) {
// When System Audio Mode is off, volume keys received by AVR can be either consumed by AVR
// or forwarded to the TV. It's up to Amplifier manufacturer’s implementation.
HdmiControlManager hdmiControlManager = getHdmiControlManager();
if (null != hdmiControlManager
&& !hdmiControlManager.getSystemAudioMode()
&& shouldCecAudioDeviceForwardVolumeKeysSystemAudioModeOff()) {
HdmiAudioSystemClient audioSystemClient = hdmiControlManager.getAudioSystemClient();
if (audioSystemClient != null) {
audioSystemClient.sendKeyEvent(
event.getKeyCode(), event.getAction() == KeyEvent.ACTION_DOWN);
return;
}
}
if (event.getAction() != KeyEvent.ACTION_DOWN) {
return;
}
int keyCode = event.getKeyCode();
int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
| AudioManager.FLAG_FROM_KEY;
String pkgName = mContext.getOpPackageName();
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP:
try {
getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
} catch (Exception e) {
Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
}
break;
case KeyEvent.KEYCODE_VOLUME_DOWN:
try {
getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
} catch (Exception e) {
Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
}
break;
case KeyEvent.KEYCODE_VOLUME_MUTE:
try {
if (event.getRepeatCount() == 0) {
getAudioService().adjustSuggestedStreamVolume(
AudioManager.ADJUST_TOGGLE_MUTE,
AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
}
} catch (Exception e) {
Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
}
break;
}
}
以上方法dispatchDirectAudioEvent()方法体中,根据不同的按键事件处理音量调节(增大、减小、静音) 说明:
按键类型 | Audio Service操作类型 | 含义 |
KEYCODE_VOLUME_UP | AudioManager.ADJUST_RAISE | 音量减 |
KEYCODE_VOLUME_DOWN | AudioManager.ADJUST_LOWER | 音量加 |
KEYCODE_VOLUME_MUTE | AudioManager.ADJUST_TOGGLE_MUTE | 改变静音状态 |
二 进入AudioService
getAudioService()获取AudioService实例,
接下来就到了AudioService中的adjustSuggestedStreamVolume方法里面了:
public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
String callingPackage, String caller) {
final IAudioPolicyCallback extVolCtlr;
synchronized (mExtVolumeControllerLock) {
extVolCtlr = mExtVolumeController;
}
if (extVolCtlr != null) {
sendMsg(mAudioHandler, MSG_NOTIFY_VOL_EVENT, SENDMSG_QUEUE,
direction, 0 /*ignored*/,
extVolCtlr, 0 /*delay*/);
} else {
adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, callingPackage,
caller, Binder.getCallingUid());
}
}
以上代码中,extVolCtrlr是外部设备(如蓝牙设备,有线耳机等可操作音量的设备)实例,
1)若extVolCtrlr!=null,执行
onNotifyVolumeEvent((IAudioPolicyCallback) msg.obj, msg.arg1);
然后外部设备发送信号到系统。系统再调用adjustSuggestedStreamVolume方法实现音量调节(该部分未找到源码麻烦指正)
2)若extVolCtrlr == null 执行
private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags, String callingPackage, String caller, int uid) {
//...省略部分代码
final int streamType;
synchronized (mForceControlStreamLock) {
// Request lock in case mVolumeControlStream is changed by other thread.
if (mUserSelectedVolumeControlStream) { // implies mVolumeControlStream != -1
streamType = mVolumeControlStream;
} else {
final int maybeActiveStreamType = getActiveStreamType(suggestedStreamType);
final boolean activeForReal;
if (maybeActiveStreamType =