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

Commit a7d59142 authored by Yan Han's avatar Yan Han
Browse files

Disable absolute volume behavior on standby

Currently, AbsoluteVolumeAudioStatusAction is always removed on Standby,
but we do not always switch away from absolute volume behavior.

AVB is usually disabled on standby when System Audio Mode is disabled.
However, some soundbars don't do this, creating a situation where AVB is
enabled but no AbsoluteVolumeAudioStatusAction exists. This prevents
AudioService from receiving volume changes and displaying UI.

This CL fixes the issue by ensuring that AVB is always disabled when
AbsoluteVolumeAudioStatusAction is removed. It should no longer be
possible to have AVB enabled without the action existing.

Bug: 312381205
Test: atest TvToAudioSystemArcAvbTest#avbEnabled_standby_avbDisabled

Change-Id: Ib430b1f2f7a0683551d424084d1b038c2d23913f
parent 330a4fc2
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -1314,7 +1314,6 @@ abstract class HdmiCecLocalDevice extends HdmiLocalDevice {
     */
    protected void disableDevice(
            boolean initiatedByCec, final PendingActionClearedCallback originalCallback) {
        removeAction(AbsoluteVolumeAudioStatusAction.class);
        removeAction(SetAudioVolumeLevelDiscoveryAction.class);
        removeAction(ActiveSourceAction.class);
        removeAction(ResendCecCommandAction.class);
+0 −1
Original line number Diff line number Diff line
@@ -307,7 +307,6 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
    protected void disableDevice(boolean initiatedByCec, PendingActionClearedCallback callback) {
        removeAction(OneTouchPlayAction.class);
        removeAction(DevicePowerStatusAction.class);
        removeAction(AbsoluteVolumeAudioStatusAction.class);

        super.disableDevice(initiatedByCec, callback);
    }
+0 −1
Original line number Diff line number Diff line
@@ -1331,7 +1331,6 @@ public final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
        removeAction(OneTouchRecordAction.class);
        removeAction(TimerRecordingAction.class);
        removeAction(NewDeviceAction.class);
        removeAction(AbsoluteVolumeAudioStatusAction.class);
        // Remove pending actions.
        removeAction(RequestActiveSourceAction.class);

+24 −8
Original line number Diff line number Diff line
@@ -3792,6 +3792,11 @@ public class HdmiControlService extends SystemService {
                }
            }
        });

        // Make sure we switch away from absolute volume behavior (AVB) when entering standby.
        // We do this because AVB should not be used unless AbsoluteVolumeAudioStatusAction exists,
        // and the action cannot exist in standby because there are no local devices.
        checkAndUpdateAbsoluteVolumeBehavior();
    }

    boolean canGoToStandby() {
@@ -4445,10 +4450,11 @@ public class HdmiControlService extends SystemService {
     * This allows the volume level of the System Audio device to be tracked and set by Android.
     *
     * Absolute volume behavior requires the following conditions:
     * 1. If the System Audio Device is an Audio System: System Audio Mode is active
     * 2. All AVB-capable audio output devices are already using full/absolute volume behavior
     * 3. CEC volume is enabled
     * 4. The System Audio device supports the <Set Audio Volume Level> message
     * 1. The device is not in standby or transient to standby
     * 2. If the System Audio Device is an Audio System: System Audio Mode is active
     * 3. All AVB-capable audio output devices are already using full/absolute volume behavior
     * 4. CEC volume is enabled
     * 5. The System Audio device supports the <Set Audio Volume Level> message
     *
     * This method enables adjust-only absolute volume behavior on TV panels when conditions
     * 1, 2, and 3 are met, but condition 4 is not. This allows TVs to track the volume level of
@@ -4464,10 +4470,16 @@ public class HdmiControlService extends SystemService {
            return;
        }

        // Condition 1: The device is not in standby or transient to standby
        if (mPowerStatusController != null && isPowerStandbyOrTransient()) {
            switchToFullVolumeBehavior();
            return;
        }

        HdmiCecLocalDevice localCecDevice;
        if (isTvDevice() && tv() != null) {
            localCecDevice = tv();
            // Condition 1: TVs need System Audio Mode to be active
            // Condition 2: TVs need System Audio Mode to be active
            // (Doesn't apply to Playback Devices, where if SAM isn't active, we assume the
            // TV is the System Audio Device instead.)
            if (!isSystemAudioActivated()) {
@@ -4484,7 +4496,7 @@ public class HdmiControlService extends SystemService {
        HdmiDeviceInfo systemAudioDeviceInfo = getDeviceInfo(
                localCecDevice.findAudioReceiverAddress());

        // Condition 2: All AVB-capable audio outputs already use full/absolute volume behavior
        // Condition 3: All AVB-capable audio outputs already use full/absolute volume behavior
        // We only need to check the first AVB-capable audio output because only TV panels
        // have more than one of them, and they always have the same volume behavior.
        @AudioManager.DeviceVolumeBehavior int currentVolumeBehavior =
@@ -4492,7 +4504,7 @@ public class HdmiControlService extends SystemService {
        boolean alreadyUsingFullOrAbsoluteVolume =
                FULL_AND_ABSOLUTE_VOLUME_BEHAVIORS.contains(currentVolumeBehavior);

        // Condition 3: CEC volume is enabled
        // Condition 4: CEC volume is enabled
        boolean cecVolumeEnabled =
                getHdmiCecVolumeControl() == HdmiControlManager.VOLUME_CONTROL_ENABLED;

@@ -4508,7 +4520,7 @@ public class HdmiControlService extends SystemService {
            return;
        }

        // Condition 4: The System Audio device supports <Set Audio Volume Level>
        // Condition 5: The System Audio device supports <Set Audio Volume Level>
        switch (systemAudioDeviceInfo.getDeviceFeatures().getSetAudioVolumeLevelSupport()) {
            case DeviceFeatures.FEATURE_SUPPORTED:
                if (currentVolumeBehavior != AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE) {
@@ -4555,6 +4567,8 @@ public class HdmiControlService extends SystemService {
     * are currently used. Removes the action for handling volume updates for these behaviors.
     */
    private void switchToFullVolumeBehavior() {
        Slog.d(TAG, "Switching to full volume behavior");

        if (playback() != null) {
            playback().removeAvbAudioStatusAction();
        } else if (tv() != null) {
@@ -4596,12 +4610,14 @@ public class HdmiControlService extends SystemService {
        // Otherwise, enable adjust-only AVB on TVs only.
        if (systemAudioDevice.getDeviceFeatures().getSetAudioVolumeLevelSupport()
                == DeviceFeatures.FEATURE_SUPPORTED) {
            Slog.d(TAG, "Enabling absolute volume behavior");
            for (AudioDeviceAttributes device : getAvbCapableAudioOutputDevices()) {
                getAudioDeviceVolumeManager().setDeviceAbsoluteVolumeBehavior(
                        device, volumeInfo, mServiceThreadExecutor,
                        mAbsoluteVolumeChangedListener, true);
            }
        } else if (tv() != null) {
            Slog.d(TAG, "Enabling adjust-only absolute volume behavior");
            for (AudioDeviceAttributes device : getAvbCapableAudioOutputDevices()) {
                getAudioDeviceVolumeManager().setDeviceAbsoluteVolumeAdjustOnlyBehavior(
                        device, volumeInfo, mServiceThreadExecutor,
+8 −0
Original line number Diff line number Diff line
@@ -455,6 +455,14 @@ public abstract class BaseAbsoluteVolumeBehaviorTest {
                AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL);
    }

    @Test
    public void avbEnabled_standby_avbDisabled() {
        enableAbsoluteVolumeBehavior();
        mHdmiControlService.onStandby(HdmiControlService.STANDBY_SCREEN_OFF);
        assertThat(mAudioManager.getDeviceVolumeBehavior(getAudioOutputDevice())).isEqualTo(
                AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL);
    }

    @Test
    public void avbEnabled_cecVolumeDisabled_avbDisabled() {
        enableAbsoluteVolumeBehavior();