From 5c03084e32d521c485d2e657f036a786f1f3b74c Mon Sep 17 00:00:00 2001 From: Yan Han Date: Mon, 14 Jun 2021 16:56:39 +0200 Subject: [PATCH] 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 --- .../android/server/audio/AudioService.java | 76 +++++-------------- .../server/hdmi/HdmiCecLocalDeviceTv.java | 10 +-- 2 files changed, 25 insertions(+), 61 deletions(-) diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 17cee670c9ac6..9ba17485bb259 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -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 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 mFullVolumeDevices = new HashSet<>(); + Set 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); } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index a887463802e2a..1d099da18d129 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -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); }