Tv的遥控器传递普通的keyevent是通过Tv的dispatchKeyEvent函数,经ITvInputSession onKeyUp/onKeyDown,最终调用HdmiControlService的sendKeyEvent方法将KeyEvent变成HdmiCecKeyCode,发送message MESSAGE_USER_CONTROL_PRESSED/MESSAGE_USER_CONTROL_RELEASED通过hdmi cec总线发送给playbacks/amplifiers.
音量键的传递流程则是由AudioService来控制的。
1.在调节音量的实现方法最后,会判断是否需要将volume update信息发送给hdmi system audio。
protected void adjustStreamVolume(int streamType, int direction, int flags,
String callingPackage, String caller, int uid) {
if (mUseFixedVolume) {
return;
}
if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream=" + streamType + ", dir=" + direction
+ ", flags=" + flags + ", caller=" + caller);
......
// Check if volume update should be sent to Hdmi system audio.
if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
setSystemAudioVolume(oldIndex, newIndex, getStreamMaxVolume(streamType), flags);
}
if (mHdmiManager != null) {
synchronized (mHdmiManager) {
// mHdmiCecSink true => mHdmiPlaybackClient != null
if (mHdmiCecSink &&
streamTypeAlias == AudioSystem.STREAM_MUSIC &&
oldIndex != newIndex) {
synchronized (mHdmiPlaybackClient) {
int keyCode = (direction == -1) ? KeyEvent.KEYCODE_VOLUME_DOWN :
KeyEvent.KEYCODE_VOLUME_UP;
final long ident = Binder.clearCallingIdentity();
try {
mHdmiPlaybackClient.sendKeyEvent(keyCode, true);
mHdmiPlaybackClient.sendKeyEvent(keyCode, false);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
}
}
}
int index = mStreamStates[streamType].getIndex(device);
sendVolumeUpdate(streamType, oldIndex, index, flags);
......
}
1.1如果平台是tv,并且此时连接avr并进入system audio mode on,那么直接通过HdmiCecLocalDeviceTv来通过VolumeControlAction来处理avr的volume。
private void setSystemAudioVolume(int oldVolume, int newVolume, int maxVolume, int flags) {
if (mHdmiManager == null
|| mHdmiTvClient == null
|| oldVolume == newVolume
|| (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) != 0) return;
// Sets the audio volume of AVR when we are in system audio mode. The new volume in