Change the HDMI_ARC audio output device to full volume.

Much of our logic for volume handling using ARC relies on incorrect assumptions. Alongside the switch to full volume, this CL makes the following changes to align our logic with the current capabilities of HDMI CEC.
1. We no longer attempt to track the Audio System's volume/mute state.
2. We no longer support setting the Audio System's volume to a precise
level, or setting its absolute mute state.
3. When adjusting stream volume, depending on the adjustment, we send a single CEC UI command out of "Volume Up", "Volume Down", and "Mute" (which toggles mute).

Bug: 191230338
Test: Manual with TV connected to Audio System
Change-Id: If4d5e2042bbadcec1903152c29de7c55bb0ace22
This commit is contained in:
Yan Han
2021-06-14 16:56:39 +02:00
parent 0c7c8dae06
commit 5c03084e32
2 changed files with 25 additions and 61 deletions

View File

@@ -64,6 +64,7 @@ import android.database.ContentObserver;
import android.hardware.SensorPrivacyManager;
import android.hardware.SensorPrivacyManagerInternal;
import android.hardware.hdmi.HdmiAudioSystemClient;
import android.hardware.hdmi.HdmiClient;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiPlaybackClient;
import android.hardware.hdmi.HdmiTvClient;
@@ -588,11 +589,12 @@ public class AudioService extends IAudioService.Stub
Set<Integer> mFixedVolumeDevices = new HashSet<>(Arrays.asList(
AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET,
AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET,
AudioSystem.DEVICE_OUT_HDMI_ARC,
AudioSystem.DEVICE_OUT_HDMI_EARC,
AudioSystem.DEVICE_OUT_AUX_LINE));
// Devices for which the volume is always max, no volume panel
Set<Integer> mFullVolumeDevices = new HashSet<>();
Set<Integer> mFullVolumeDevices = new HashSet<>(Arrays.asList(
AudioSystem.DEVICE_OUT_HDMI_ARC,
AudioSystem.DEVICE_OUT_HDMI_EARC
));
// Devices for the which use the "absolute volume" concept (framework sends audio signal
// full scale, and volume control separately) and can be used for multiple use cases reflected
// by the audio mode (e.g. media playback in MODE_NORMAL, and phone calls in MODE_IN_CALL).
@@ -2283,7 +2285,6 @@ public class AudioService extends IAudioService.Stub
if (DEBUG_VOL) {
Log.d(TAG, String.format("Master mute %s, user=%d", masterMute, currentUser));
}
setSystemAudioMute(masterMute);
AudioSystem.setMasterMute(masterMute);
broadcastMasterMuteStatus(masterMute);
@@ -2865,9 +2866,6 @@ public class AudioService extends IAudioService.Stub
} else {
state = direction == AudioManager.ADJUST_MUTE;
}
if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
setSystemAudioMute(state);
}
for (int stream = 0; stream < mStreamStates.length; stream++) {
if (streamTypeAlias == mStreamVolumeAlias[stream]) {
if (!(readCameraSoundForced()
@@ -2933,11 +2931,6 @@ public class AudioService extends IAudioService.Stub
mDeviceBroker.postSetHearingAidVolumeIndex(newIndex, streamType);
}
}
// Check if volume update should be sent to Hdmi system audio.
if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
setSystemAudioVolume(oldIndex, newIndex, getStreamMaxVolume(streamType), flags);
}
}
final int newIndex = mStreamStates[streamType].getIndex(device);
@@ -2945,7 +2938,13 @@ public class AudioService extends IAudioService.Stub
if (adjustVolume) {
synchronized (mHdmiClientLock) {
if (mHdmiManager != null) {
if (mHdmiPlaybackClient != null
// At most one of mHdmiPlaybackClient and mHdmiTvClient should be non-null
HdmiClient fullVolumeHdmiClient = mHdmiPlaybackClient;
if (mHdmiTvClient != null) {
fullVolumeHdmiClient = mHdmiTvClient;
}
if (fullVolumeHdmiClient != null
&& mHdmiCecVolumeControlEnabled
&& streamTypeAlias == AudioSystem.STREAM_MUSIC
// vol change on a full volume device
@@ -2959,6 +2958,10 @@ public class AudioService extends IAudioService.Stub
keyCode = KeyEvent.KEYCODE_VOLUME_DOWN;
break;
case AudioManager.ADJUST_TOGGLE_MUTE:
case AudioManager.ADJUST_MUTE:
case AudioManager.ADJUST_UNMUTE:
// Many CEC devices only support toggle mute. Therefore, we send the
// same keycode for all three mute options.
keyCode = KeyEvent.KEYCODE_VOLUME_MUTE;
break;
default:
@@ -2967,17 +2970,16 @@ public class AudioService extends IAudioService.Stub
if (keyCode != KeyEvent.KEYCODE_UNKNOWN) {
final long ident = Binder.clearCallingIdentity();
try {
final long time = java.lang.System.currentTimeMillis();
switch (keyEventMode) {
case VOL_ADJUST_NORMAL:
mHdmiPlaybackClient.sendVolumeKeyEvent(keyCode, true);
mHdmiPlaybackClient.sendVolumeKeyEvent(keyCode, false);
fullVolumeHdmiClient.sendVolumeKeyEvent(keyCode, true);
fullVolumeHdmiClient.sendVolumeKeyEvent(keyCode, false);
break;
case VOL_ADJUST_START:
mHdmiPlaybackClient.sendVolumeKeyEvent(keyCode, true);
fullVolumeHdmiClient.sendVolumeKeyEvent(keyCode, true);
break;
case VOL_ADJUST_END:
mHdmiPlaybackClient.sendVolumeKeyEvent(keyCode, false);
fullVolumeHdmiClient.sendVolumeKeyEvent(keyCode, false);
break;
default:
Log.e(TAG, "Invalid keyEventMode " + keyEventMode);
@@ -3032,27 +3034,6 @@ public class AudioService extends IAudioService.Stub
Binder.restoreCallingIdentity(identity);
}
private void setSystemAudioVolume(int oldVolume, int newVolume, int maxVolume, int flags) {
// Sets the audio volume of AVR when we are in system audio mode. The new volume info
// is tranformed to HDMI-CEC commands and passed through CEC bus.
synchronized (mHdmiClientLock) {
if (mHdmiManager == null
|| mHdmiTvClient == null
|| oldVolume == newVolume
|| (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) != 0
|| !mHdmiSystemAudioSupported
|| !mHdmiCecVolumeControlEnabled) {
return;
}
final long token = Binder.clearCallingIdentity();
try {
mHdmiTvClient.setSystemAudioVolume(oldVolume, newVolume, maxVolume);
} finally {
Binder.restoreCallingIdentity(token);
}
}
}
// StreamVolumeCommand contains the information needed to defer the process of
// setStreamVolume() in case the user has to acknowledge the safe volume warning message.
static class StreamVolumeCommand {
@@ -3556,10 +3537,6 @@ public class AudioService extends IAudioService.Stub
mDeviceBroker.postSetHearingAidVolumeIndex(index, streamType);
}
if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
setSystemAudioVolume(oldIndex, index, getStreamMaxVolume(streamType), flags);
}
flags &= ~AudioManager.FLAG_FIXED_VOLUME;
if (streamTypeAlias == AudioSystem.STREAM_MUSIC && isFixedVolumeDevice(device)) {
flags |= AudioManager.FLAG_FIXED_VOLUME;
@@ -3821,18 +3798,6 @@ public class AudioService extends IAudioService.Stub
}
}
private void setSystemAudioMute(boolean state) {
synchronized (mHdmiClientLock) {
if (mHdmiManager == null || mHdmiTvClient == null || !mHdmiSystemAudioSupported) return;
final long token = Binder.clearCallingIdentity();
try {
mHdmiTvClient.setSystemAudioMute(state);
} finally {
Binder.restoreCallingIdentity(token);
}
}
}
/** get stream mute state. */
public boolean isStreamMute(int streamType) {
if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
@@ -3983,7 +3948,6 @@ public class AudioService extends IAudioService.Stub
if ((isPlatformAutomotive() && userId == UserHandle.USER_SYSTEM)
|| (getCurrentUserId() == userId)) {
if (mute != AudioSystem.getMasterMute()) {
setSystemAudioMute(mute);
AudioSystem.setMasterMute(mute);
sendMasterMuteUpdate(mute, flags);
}

View File

@@ -38,7 +38,6 @@ import android.hardware.hdmi.HdmiRecordSources;
import android.hardware.hdmi.HdmiTimerRecordSources;
import android.hardware.hdmi.IHdmiControlCallback;
import android.hardware.tv.cec.V1_0.SendMessageResult;
import android.media.AudioManager;
import android.media.AudioSystem;
import android.media.tv.TvInputInfo;
import android.media.tv.TvInputManager.TvInputCallback;
@@ -409,6 +408,11 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
return Constants.ADDR_INVALID;
}
@Override
protected int findAudioReceiverAddress() {
return Constants.ADDR_AUDIO_SYSTEM;
}
@Override
@ServiceThreadOnly
@Constants.HandleMessageResult
@@ -925,10 +929,6 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
synchronized (mLock) {
mSystemAudioMute = mute;
mSystemAudioVolume = volume;
int maxVolume = mService.getAudioManager().getStreamMaxVolume(
AudioManager.STREAM_MUSIC);
mService.setAudioStatus(mute,
VolumeControlAction.scaleToCustomVolume(volume, maxVolume));
displayOsd(HdmiControlManager.OSD_MESSAGE_AVR_VOLUME_CHANGED,
mute ? HdmiControlManager.AVR_VOLUME_MUTED : volume);
}