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

Commit 753fe4ea authored by Paul Colta's avatar Paul Colta
Browse files

HDMI: More reliable DSM setting disabling

Wait for ArcTerminationActionFromAvr to finish before giving up the LA 5
during Dynamic Soundbar mode disabling process.

Add callback inside ArcTerminationActionFromAvr.

Transfer the callback in HdmiCecLocalDeviceAudioSystem#handleRequestArcTermination so it doesn't get lost.

Callback is not transfered in the following situation, in HdmiCecLocalDeviceAudioSystem#initArcOnFromAvr ARC termination is interrupted by ARC initialization from AVR. This scenario would occur if user toggles DSM off then on before ARC termination process is completed, then the local device audio system tries establishing ARC connection when logical address allocation finished. In this case, DSM would be enabled and the callback from ARC termination action that retriggers logical address allocation wouldn't be necessary.

Bug: 260322563
Test: make && atest com.android.server.hdmi.HdmiControlServiceTest
Change-Id: Ib0a8b3a7da79da8cf3f9724a685a55c80760a755
parent 4ae8fc3e
Loading
Loading
Loading
Loading
+18 −3
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
 */
package com.android.server.hdmi;

import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.IHdmiControlCallback;
import android.hardware.tv.cec.V1_0.SendMessageResult;

/**
@@ -33,6 +35,10 @@ public class ArcTerminationActionFromAvr extends HdmiCecFeatureAction {
        super(source);
    }

    ArcTerminationActionFromAvr(HdmiCecLocalDevice source, IHdmiControlCallback callback) {
        super(source, callback);
    }

    @Override
    boolean start() {
        mState = STATE_WAITING_FOR_INITIATE_ARC_RESPONSE;
@@ -47,10 +53,19 @@ public class ArcTerminationActionFromAvr extends HdmiCecFeatureAction {
            return false;
        }
        switch (cmd.getOpcode()) {
            case Constants.MESSAGE_FEATURE_ABORT:
                int originalOpcode = cmd.getParams()[0] & 0xFF;
                if (originalOpcode == Constants.MESSAGE_TERMINATE_ARC) {
                    mState = STATE_ARC_TERMINATED;
                    audioSystem().processArcTermination();
                    finishWithCallback(HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
                    return true;
                }
                return false;
            case Constants.MESSAGE_REPORT_ARC_TERMINATED:
                mState = STATE_ARC_TERMINATED;
                audioSystem().processArcTermination();
                finish();
                finishWithCallback(HdmiControlManager.RESULT_SUCCESS);
                return true;
        }
        return false;
@@ -79,7 +94,7 @@ public class ArcTerminationActionFromAvr extends HdmiCecFeatureAction {
                        audioSystem().setArcStatus(false);
                    }
                    HdmiLogger.debug("Terminate ARC was not successfully sent.");
                    finish();
                    finishWithCallback(HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
                }
            });
    }
@@ -88,6 +103,6 @@ public class ArcTerminationActionFromAvr extends HdmiCecFeatureAction {
        // Disable ARC if TV didn't respond with <Report ARC Terminated> in time.
        audioSystem().setArcStatus(false);
        HdmiLogger.debug("handleTerminateArcTimeout");
        finish();
        finishWithCallback(HdmiControlManager.RESULT_TIMEOUT);
    }
}
+10 −2
Original line number Diff line number Diff line
@@ -457,9 +457,17 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
        } else if (!isArcEnabled()) {
            HdmiLogger.debug("ARC is not established between TV and AVR device");
            return Constants.ABORT_NOT_IN_CORRECT_MODE;
        } else {
            if (!getActions(ArcTerminationActionFromAvr.class).isEmpty()
                    && !getActions(ArcTerminationActionFromAvr.class).get(0).mCallbacks.isEmpty()) {
                IHdmiControlCallback callback =
                        getActions(ArcTerminationActionFromAvr.class).get(0).mCallbacks.get(0);
                removeAction(ArcTerminationActionFromAvr.class);
                addAndStartAction(new ArcTerminationActionFromAvr(this, callback));
            } else {
                removeAction(ArcTerminationActionFromAvr.class);
                addAndStartAction(new ArcTerminationActionFromAvr(this));
            }
            return Constants.HANDLED;
        }
    }
+19 −5
Original line number Diff line number Diff line
@@ -878,17 +878,31 @@ public class HdmiControlService extends SystemService {
            Slog.w(TAG, "Device type doesn't support ARC.");
            return;
        }
        boolean isArcEnabled = false;
        if (settingValue == SOUNDBAR_MODE_DISABLED && audioSystem != null) {
            if (audioSystem.isArcEnabled()) {
                audioSystem.addAndStartAction(new ArcTerminationActionFromAvr(audioSystem));
            }
            isArcEnabled = audioSystem.isArcEnabled();
            if (isSystemAudioActivated()) {
                audioSystem.terminateSystemAudioMode();
            }
            if (isArcEnabled) {
                if (audioSystem.hasAction(ArcTerminationActionFromAvr.class)) {
                    audioSystem.removeAction(ArcTerminationActionFromAvr.class);
                }
                audioSystem.addAndStartAction(new ArcTerminationActionFromAvr(audioSystem,
                        new IHdmiControlCallback.Stub() {
                            @Override
                            public void onComplete(int result) {
                                mAddressAllocated = false;
                                initializeCecLocalDevices(INITIATED_BY_SOUNDBAR_MODE);
                            }
                        }));
            }
        }
        if (!isArcEnabled) {
            mAddressAllocated = false;
            initializeCecLocalDevices(INITIATED_BY_SOUNDBAR_MODE);
        }
    }

    /**
     * Checks if the Device Discovery is handled by the local device playback.
+45 −1
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ import static org.mockito.Mockito.spy;

import android.content.Context;
import android.content.ContextWrapper;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.IHdmiControlCallback;
import android.hardware.tv.cec.V1_0.SendMessageResult;
import android.media.AudioManager;
import android.os.Looper;
@@ -52,6 +54,7 @@ public class ArcTerminationActionFromAvrTest {
    private Context mContextSpy;
    private HdmiCecLocalDeviceAudioSystem mHdmiCecLocalDeviceAudioSystem;
    private FakePowerManagerWrapper mPowerManager;
    private TestCallback mCallback;
    private ArcTerminationActionFromAvr mAction;

    private FakeNativeWrapper mNativeWrapper;
@@ -112,7 +115,9 @@ public class ArcTerminationActionFromAvrTest {
            }
        };
        mHdmiCecLocalDeviceAudioSystem.init();
        mAction = new ArcTerminationActionFromAvr(mHdmiCecLocalDeviceAudioSystem);
        mCallback = new TestCallback();
        mAction = new ArcTerminationActionFromAvr(mHdmiCecLocalDeviceAudioSystem,
                mCallback);

        mLocalDevices.add(mHdmiCecLocalDeviceAudioSystem);
        hdmiControlService.onBootPhase(PHASE_SYSTEM_SERVICES_READY);
@@ -121,6 +126,20 @@ public class ArcTerminationActionFromAvrTest {
        mTestLooper.dispatchAll();
    }

    private static class TestCallback extends IHdmiControlCallback.Stub {
        private final ArrayList<Integer> mCallbackResult = new ArrayList<Integer>();

        @Override
        public void onComplete(int result) {
            mCallbackResult.add(result);
        }

        private int getResult() {
            assertThat(mCallbackResult.size()).isEqualTo(1);
            return mCallbackResult.get(0);
        }
    }

    @Test
    public void testSendMessage_sendFailed() {
        mNativeWrapper.setMessageSendResult(Constants.MESSAGE_TERMINATE_ARC,
@@ -133,6 +152,7 @@ public class ArcTerminationActionFromAvrTest {
        assertThat(mNativeWrapper.getResultMessages()).contains(terminateArc);

        assertThat(mHdmiCecLocalDeviceAudioSystem.isArcEnabled()).isFalse();
        assertThat(mCallback.getResult()).isEqualTo(HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
    }

    @Test
@@ -149,6 +169,7 @@ public class ArcTerminationActionFromAvrTest {
        mTestLooper.dispatchAll();

        assertThat(mHdmiCecLocalDeviceAudioSystem.isArcEnabled()).isFalse();
        assertThat(mCallback.getResult()).isEqualTo(HdmiControlManager.RESULT_TIMEOUT);
    }

    @Test
@@ -167,5 +188,28 @@ public class ArcTerminationActionFromAvrTest {
        mTestLooper.dispatchAll();

        assertThat(mHdmiCecLocalDeviceAudioSystem.isArcEnabled()).isFalse();
        assertThat(mCallback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
    }

    @Test
    public void testReportArcTerminated_featureAbort() {
        mHdmiCecLocalDeviceAudioSystem.addAndStartAction(mAction);
        mTestLooper.dispatchAll();
        HdmiCecMessage terminateArc = HdmiCecMessageBuilder.buildTerminateArc(
                Constants.ADDR_AUDIO_SYSTEM, Constants.ADDR_TV);

        assertThat(mNativeWrapper.getResultMessages()).contains(terminateArc);

        HdmiCecMessage arcTerminatedResponse = HdmiCecMessageBuilder.buildFeatureAbortCommand(
                Constants.ADDR_TV,
                Constants.ADDR_AUDIO_SYSTEM,
                Constants.MESSAGE_TERMINATE_ARC,
                Constants.ABORT_REFUSED);

        mNativeWrapper.onCecMessage(arcTerminatedResponse);
        mTestLooper.dispatchAll();

        assertThat(mHdmiCecLocalDeviceAudioSystem.isArcEnabled()).isFalse();
        assertThat(mCallback.getResult()).isEqualTo(HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
    }
}
+28 −0
Original line number Diff line number Diff line
@@ -534,6 +534,25 @@ public class HdmiCecLocalDeviceAudioSystemTest {
        assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage);
    }

    @Test
    public void handleRequestArcTerminate_callbackIsPreserved() throws Exception {
        TestCallback callback = new TestCallback();

        mHdmiCecLocalDeviceAudioSystem.setArcStatus(true);
        assertThat(mHdmiCecLocalDeviceAudioSystem.isArcEnabled()).isTrue();
        mHdmiCecLocalDeviceAudioSystem.addAndStartAction(
                new ArcTerminationActionFromAvr(mHdmiCecLocalDeviceAudioSystem, callback));

        HdmiCecMessage message =
                HdmiCecMessageBuilder.buildRequestArcTermination(ADDR_TV, ADDR_AUDIO_SYSTEM);
        assertThat(mHdmiCecLocalDeviceAudioSystem.handleRequestArcTermination(message))
                .isEqualTo(Constants.HANDLED);

        mTestLooper.dispatchAll();
        assertThat(mHdmiCecLocalDeviceAudioSystem.getActions(
                ArcTerminationActionFromAvr.class).get(0).mCallbacks.get(0)).isEqualTo(callback);
    }

    @Test
    public void handleRequestArcInit_arcIsNotSupported() throws Exception {
        HdmiCecMessage message =
@@ -880,4 +899,13 @@ public class HdmiCecLocalDeviceAudioSystemTest {
        assertThat(mNativeWrapper.getResultMessages()).doesNotContain(
                systemAudioModeRequest_fromAudioSystem);
    }

    private static class TestCallback extends IHdmiControlCallback.Stub {
        private final ArrayList<Integer> mCallbackResult = new ArrayList<Integer>();

        @Override
        public void onComplete(int result) {
            mCallbackResult.add(result);
        }
    }
}
Loading