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

Commit 288c3ed3 authored by Marvin Ramin's avatar Marvin Ramin
Browse files

Fix mute issue when changing audio routes

When audio device routing changes, verify that streams now routed via
fixed/full volume properly update volume index and mute state to ensure
the user does not get into a state where the stream is muted, but full
volume behavior does not allow mute changes.

AudioService#onObserveDevicesForAllStreams() is called as a result of AudioDeviceInventory#onReportNewRoutes().

Bug: 162480816
Test: manual
Change-Id: Ia5298178338e70684176c5c8a6dc6a864bab6efe
parent 370e885c
Loading
Loading
Loading
Loading
+57 −19
Original line number Diff line number Diff line
@@ -1282,7 +1282,6 @@ public class AudioService extends IAudioService.Stub
            }

            if (isPlatformTelevision()) {
                checkAddAllFixedVolumeDevices(AudioSystem.DEVICE_OUT_HDMI, caller);
                synchronized (mHdmiClientLock) {
                    if (mHdmiManager != null && mHdmiPlaybackClient != null) {
                        updateHdmiCecSinkLocked(mHdmiCecSink | false);
@@ -1302,9 +1301,33 @@ public class AudioService extends IAudioService.Stub
        }
    }

    private void checkAddAllFixedVolumeDevices(int device, String caller) {
    /**
     * Update volume states for the given device.
     *
     * This will initialize the volume index if no volume index is available.
     * If the device is the currently routed device, fixed/full volume policies will be applied.
     *
     * @param device a single audio device, ensure that this is not a devices bitmask
     * @param caller caller of this method
     */
    private void updateVolumeStatesForAudioDevice(int device, String caller) {
        final int numStreamTypes = AudioSystem.getNumStreamTypes();
        for (int streamType = 0; streamType < numStreamTypes; streamType++) {
            updateVolumeStates(device, streamType, caller);
        }
    }

    /**
     * Update volume states for the given device and given stream.
     *
     * This will initialize the volume index if no volume index is available.
     * If the device is the currently routed device, fixed/full volume policies will be applied.
     *
     * @param device a single audio device, ensure that this is not a devices bitmask
     * @param streamType streamType to be updated
     * @param caller caller of this method
     */
    private void updateVolumeStates(int device, int streamType, String caller) {
        if (!mStreamStates[streamType].hasIndexForDevice(device)) {
            // set the default value, if device is affected by a full/fix/abs volume rule, it
            // will taken into account in checkFixedVolumeDevices()
@@ -1313,14 +1336,22 @@ public class AudioService extends IAudioService.Stub
                            .getIndex(AudioSystem.DEVICE_OUT_DEFAULT),
                    device, caller, true /*hasModifyAudioSettings*/);
        }

        // Check if device to be updated is routed for the given audio stream
        List<AudioDeviceAttributes> devicesForAttributes = getDevicesForAttributes(
                new AudioAttributes.Builder().setInternalLegacyStreamType(streamType).build());
        for (AudioDeviceAttributes deviceAttributes : devicesForAttributes) {
            if (deviceAttributes.getType() == AudioDeviceInfo.convertInternalDeviceToDeviceType(
                    device)) {
                mStreamStates[streamType].checkFixedVolumeDevices();

            // Unmute streams if device is full volume
            if (mFullVolumeDevices.contains(device)) {
                // Unmute streams if required if device is full volume
                if (isStreamMute(streamType) && mFullVolumeDevices.contains(device)) {
                    mStreamStates[streamType].mute(false);
                }
            }
        }
    }

    private void checkAllFixedVolumeDevices()
    {
@@ -4901,7 +4932,15 @@ public class AudioService extends IAudioService.Stub
        synchronized (VolumeStreamState.class) {
            for (int stream = 0; stream < mStreamStates.length; stream++) {
                if (stream != skipStream) {
                    mStreamStates[stream].observeDevicesForStream_syncVSS(false /*checkOthers*/);
                    int devices = mStreamStates[stream].observeDevicesForStream_syncVSS(
                            false /*checkOthers*/);

                    Set<Integer> devicesSet = AudioSystem.generateAudioDeviceTypesSet(devices);
                    for (Integer device : devicesSet) {
                        // Update volume states for devices routed for the stream
                        updateVolumeStates(device, stream,
                                "AudioService#observeDevicesForStreams");
                    }
                }
            }
        }
@@ -4970,7 +5009,7 @@ public class AudioService extends IAudioService.Stub
                      + Integer.toHexString(audioSystemDeviceOut) + " from:" + caller));
        // make sure we have a volume entry for this device, and that volume is updated according
        // to volume behavior
        checkAddAllFixedVolumeDevices(audioSystemDeviceOut, "setDeviceVolumeBehavior:" + caller);
        updateVolumeStatesForAudioDevice(audioSystemDeviceOut, "setDeviceVolumeBehavior:" + caller);
    }

    /**
@@ -7192,11 +7231,10 @@ public class AudioService extends IAudioService.Stub
                // HDMI output
                removeAudioSystemDeviceOutFromFullVolumeDevices(AudioSystem.DEVICE_OUT_HDMI);
            }
        }

        checkAddAllFixedVolumeDevices(AudioSystem.DEVICE_OUT_HDMI,
            updateVolumeStatesForAudioDevice(AudioSystem.DEVICE_OUT_HDMI,
                    "HdmiPlaybackClient.DisplayStatusCallback");
        }
    }

    private class MyHdmiControlStatusChangeListenerCallback
            implements HdmiControlManager.HdmiControlStatusChangeListener {