Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5c03084e authored by Yan Han's avatar Yan Han
Browse files

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
parent 0c7c8dae
Loading
Loading
Loading
Loading
+20 −56
Original line number Diff line number Diff line
@@ -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);
            }
+5 −5
Original line number Diff line number Diff line
@@ -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);
        }