前言
在手机和平板上面,我们实际上能调节的也就5个音量:
流类型 | 最大音量 | 音量 | 默认音量 | 含义 |
---|---|---|---|---|
STREAM_VOICE_CALL | 5 | 1 | 4 | 通话音量 |
STREAM_RING | 7 | 0 | 5 | 铃声,通知音量等 |
STREAM_MUSIC | 15 | 0 | 5 | 多媒体音量 |
STREAM_ALARM | 7 | 0 | 6 | 闹钟音量 |
STREAM_BLUETOOTH_SCO | 15 | 0 | 7 | 蓝牙音量 |
1 按键的处理流程
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
// pre-condition: event.getKeyCode() is one of KeyEvent.KEYCODE_VOLUME_UP,
// KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_VOLUME_MUTE
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;
}
}
try {
getAudioService().handleVolumeKey(event, mUseTvRouting,
mContext.getOpPackageName(), TAG);
} catch (Exception e) {
Log.e(TAG, "Error dispatching volume key in handleVolumeKey for event:"
+ event, e);
}
}
// 这里通过AIDL获取IAudioService的实例,
static IAudioService getAudioService() {
IAudioService audioService = IAudioService.Stub.asInterface(
ServiceManager.checkService(Context.AUDIO_SERVICE));
if (audioService == null) {
Log.w(TAG, "Unable to find IAudioService interface.");
}
return audioService;
}
在这里,通过Binder获取到了AudioService的实例,调用AudioService的handleVolumeKey()方法。
// pre-condition: event.getKeyCode() is one of KeyEvent.KEYCODE_VOLUME_UP,
// KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_VOLUME_MUTE
public void handleVolumeKey(@NonNull KeyEvent event, boolean isOnTv,
@NonNull String callingPackage, @NonNull String caller) {
int keyEventMode = VOL_ADJUST_NORMAL;
if (isOnTv) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
keyEventMode = VOL_ADJUST_START;
} else {
// may catch more than ACTION_UP, but will end vol adjustement
// the vol key is either released (ACTION_UP), or multiple keys are pressed
// (ACTION_MULTIPLE) and we don't know what to do for volume control on CEC, end
// the repeated volume adjustement
keyEventMode = VOL_ADJUST_END;
}
} else if (event.getAction() != KeyEvent.ACTION_DOWN) {
return;
}
int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
| AudioManager.FLAG_FROM_KEY;
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_VOLUME_UP:
adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
AudioManager.USE_DEFAULT_STREAM_TYPE, flags, callingPackage, caller,
Binder.getCallingUid(), true, keyEventMode);
break;
case KeyEvent.KEYCODE_VOLUME_DOWN:
adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
AudioManager.USE_DEFAULT_STREAM_TYPE, flags, callingPackage, caller,
Binder.getCallingUid(), true, keyEventMode);
break;
case KeyEvent.KEYCODE_VOLUME_MUTE:
if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
adjustSuggestedStreamVolume(AudioManager.ADJUST_TOGGLE_MUTE,
AudioManager.USE_DEFAULT_STREAM_TYPE, flags, callingPackage, caller,
Binder.getCallingUid(), true, VOL_ADJUST_NORMAL)