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

Commit ed479aa2 authored by Paul Colta's avatar Paul Colta
Browse files

HDMI: Improve behavior of TVs ignoring standby from non-active source

Currently, TVs ignore standby from non-AS devices only if another source reported <Active Source>. TVs can switch the active path to non-CEC connected devices which won't report <Active Source>. This patch is solving the issue.

Flag: EXEMPT bugfix
Bug: 364646168
Test: atest HdmiCecLocalDeviceTvTest
Change-Id: I0e731a0144ebb47a47fe4dc671bc1db5a6458883
parent 3648b316
Loading
Loading
Loading
Loading
+16 −8
Original line number Diff line number Diff line
@@ -116,11 +116,11 @@ public class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
    private boolean mWasActiveSourceSetToConnectedDevice = false;

    @VisibleForTesting
    protected boolean getWasActiveSourceSetToConnectedDevice() {
    protected boolean getWasActivePathSetToConnectedDevice() {
        return mWasActiveSourceSetToConnectedDevice;
    }

    protected void setWasActiveSourceSetToConnectedDevice(
    protected void setWasActivePathSetToConnectedDevice(
            boolean wasActiveSourceSetToConnectedDevice) {
        mWasActiveSourceSetToConnectedDevice = wasActiveSourceSetToConnectedDevice;
    }
@@ -404,6 +404,15 @@ public class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
        }
    }

    @Override
    void setActivePath(int path) {
        super.setActivePath(path);
        if (path != Constants.INVALID_PHYSICAL_ADDRESS
                && path != Constants.TV_PHYSICAL_ADDRESS) {
            setWasActivePathSetToConnectedDevice(true);
        }
    }

    @ServiceThreadOnly
    void updateActiveInput(int path, boolean notifyInputChange) {
        assertRunOnServiceThread();
@@ -512,7 +521,6 @@ public class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
                || info.getDeviceType() == HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM) {
            mService.getHdmiCecNetwork().updateDevicePowerStatus(logicalAddress,
                    HdmiControlManager.POWER_STATUS_ON);
            setWasActiveSourceSetToConnectedDevice(true);
            ActiveSource activeSource = ActiveSource.of(logicalAddress, physicalAddress);
            ActiveSourceHandler.create(this, null).process(activeSource, info.getDeviceType());
        } else {
@@ -528,16 +536,16 @@ public class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
    protected int handleStandby(HdmiCecMessage message) {
        assertRunOnServiceThread();

        // If a device has previously asserted the active source status, ignore <Standby> from
        // non-active source.
        if (getWasActiveSourceSetToConnectedDevice()
        // If the TV has previously changed the active path, ignore <Standby> from non-active
        // source.
        if (getWasActivePathSetToConnectedDevice()
                && getActiveSource().logicalAddress != message.getSource()) {
            Slog.d(TAG, "<Standby> was not sent by the current active source, ignoring."
                    + " Current active source has logical address "
                    + getActiveSource().logicalAddress);
            return Constants.HANDLED;
        }
        setWasActiveSourceSetToConnectedDevice(false);
        setWasActivePathSetToConnectedDevice(false);
        return super.handleStandby(message);
    }

@@ -1505,7 +1513,7 @@ public class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
            invokeStandbyCompletedCallback(callback);
            return;
        }
        setWasActiveSourceSetToConnectedDevice(false);
        setWasActivePathSetToConnectedDevice(false);
        boolean sendStandbyOnSleep =
                mService.getHdmiCecConfig().getIntValue(
                    HdmiControlManager.CEC_SETTING_NAME_TV_SEND_STANDBY_ON_SLEEP)
+2 −1
Original line number Diff line number Diff line
@@ -44,7 +44,8 @@ final class RoutingControlAction extends HdmiCecFeatureAction {
    static final int STATE_WAIT_FOR_ROUTING_INFORMATION = 1;

    // Time out in millseconds used for <Routing Information>
    private static final int TIMEOUT_ROUTING_INFORMATION_MS = 1000;
    @VisibleForTesting
    static final int TIMEOUT_ROUTING_INFORMATION_MS = 1000;

    // If set to true, call {@link HdmiControlService#invokeInputChangeListener()} when
    // the routing control/active source change happens. The listener should be called if
+41 −10
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_WAKE_UP_ME
import static com.android.server.hdmi.HdmiControlService.STANDBY_SCREEN_OFF;
import static com.android.server.hdmi.HdmiControlService.WAKE_UP_SCREEN_ON;
import static com.android.server.hdmi.RequestActiveSourceAction.TIMEOUT_WAIT_FOR_LAUNCHERX_API_CALL_MS;
import static com.android.server.hdmi.RoutingControlAction.TIMEOUT_ROUTING_INFORMATION_MS;

import static com.google.common.truth.Truth.assertThat;

@@ -77,6 +78,7 @@ import java.util.concurrent.TimeUnit;
public class HdmiCecLocalDeviceTvTest {
    private static final int TIMEOUT_MS = HdmiConfig.TIMEOUT_MS + 1;
    private static final int PORT_1 = 1;
    private static final int PORT_2 = 2;

    private static final String[] SADS_NOT_TO_QUERY = new String[]{
            HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_MPEG1,
@@ -215,7 +217,7 @@ public class HdmiCecLocalDeviceTvTest {
                .setEarcSupported(false)
                .build();
        hdmiPortInfos[1] =
                new HdmiPortInfo.Builder(2, HdmiPortInfo.PORT_INPUT, 0x2000)
                new HdmiPortInfo.Builder(PORT_2, HdmiPortInfo.PORT_INPUT, 0x2000)
                        .setCecSupported(true)
                        .setMhlSupported(false)
                        .setArcSupported(true)
@@ -2021,7 +2023,7 @@ public class HdmiCecLocalDeviceTvTest {
                ADDR_TV);
        mTestLooper.dispatchAll();

        assertThat(mHdmiCecLocalDeviceTv.getWasActiveSourceSetToConnectedDevice())
        assertThat(mHdmiCecLocalDeviceTv.getWasActivePathSetToConnectedDevice())
                .isFalse();
        mPowerManager.setInteractive(true);
        mTestLooper.dispatchAll();
@@ -2031,14 +2033,14 @@ public class HdmiCecLocalDeviceTvTest {
                "HdmiCecLocalDeviceTvTest");
        mTestLooper.dispatchAll();

        assertThat(mHdmiCecLocalDeviceTv.getWasActiveSourceSetToConnectedDevice())
        assertThat(mHdmiCecLocalDeviceTv.getWasActivePathSetToConnectedDevice())
                .isTrue();
        assertThat(mHdmiCecLocalDeviceTv.dispatchMessage(standbyMessage))
                .isEqualTo(Constants.HANDLED);
        mTestLooper.dispatchAll();

        assertThat(mPowerManager.isInteractive()).isFalse();
        assertThat(mHdmiCecLocalDeviceTv.getWasActiveSourceSetToConnectedDevice())
        assertThat(mHdmiCecLocalDeviceTv.getWasActivePathSetToConnectedDevice())
                .isFalse();
    }

@@ -2051,7 +2053,7 @@ public class HdmiCecLocalDeviceTvTest {
        mHdmiCecLocalDeviceTv = new MockTvDevice(mHdmiControlService);
        mTestLooper.dispatchAll();

        assertThat(mHdmiCecLocalDeviceTv.getWasActiveSourceSetToConnectedDevice())
        assertThat(mHdmiCecLocalDeviceTv.getWasActivePathSetToConnectedDevice())
                .isFalse();
        mPowerManager.setInteractive(true);

@@ -2060,7 +2062,7 @@ public class HdmiCecLocalDeviceTvTest {
                "HdmiCecLocalDeviceTvTest");
        mTestLooper.dispatchAll();

        assertThat(mHdmiCecLocalDeviceTv.getWasActiveSourceSetToConnectedDevice())
        assertThat(mHdmiCecLocalDeviceTv.getWasActivePathSetToConnectedDevice())
                .isTrue();
        assertThat(mHdmiCecLocalDeviceTv.dispatchMessage(standbyMessage))
                .isEqualTo(Constants.HANDLED);
@@ -2076,21 +2078,50 @@ public class HdmiCecLocalDeviceTvTest {
        mHdmiCecLocalDeviceTv = new MockTvDevice(mHdmiControlService);
        mTestLooper.dispatchAll();

        assertThat(mHdmiCecLocalDeviceTv.getWasActiveSourceSetToConnectedDevice())
        assertThat(mHdmiCecLocalDeviceTv.getWasActivePathSetToConnectedDevice())
                .isFalse();
        mPowerManager.setInteractive(true);

        assertThat(mHdmiCecLocalDeviceTv.getWasActiveSourceSetToConnectedDevice())
        assertThat(mHdmiCecLocalDeviceTv.getWasActivePathSetToConnectedDevice())
                .isFalse();
        assertThat(mHdmiCecLocalDeviceTv.dispatchMessage(standbyMessage))
                .isEqualTo(Constants.HANDLED);
        mTestLooper.dispatchAll();

        assertThat(mPowerManager.isInteractive()).isFalse();
        assertThat(mHdmiCecLocalDeviceTv.getWasActiveSourceSetToConnectedDevice())
        assertThat(mHdmiCecLocalDeviceTv.getWasActivePathSetToConnectedDevice())
                .isFalse();
    }

    @Test
    public void handleStandby_fromNonActiveSource_previousActivePathSetToNonCecDevice_Standby() {
        HdmiCecLocalDeviceTv hdmiCecLocalDeviceTv = new MockTvDevice(mHdmiControlService);
        hdmiCecLocalDeviceTv.setDeviceInfo(mHdmiCecLocalDeviceTv.getDeviceInfo());
        mTestLooper.dispatchAll();

        assertThat(hdmiCecLocalDeviceTv.getWasActivePathSetToConnectedDevice())
                .isFalse();
        mPowerManager.setInteractive(true);
        hdmiCecLocalDeviceTv.doManualPortSwitching(PORT_2, null);
        mTestLooper.dispatchAll();

        // Timeout the action RoutingControlAction such that the active path would be updated.
        mTestLooper.moveTimeForward(TIMEOUT_ROUTING_INFORMATION_MS);
        mTestLooper.dispatchAll();

        assertThat(hdmiCecLocalDeviceTv.getWasActivePathSetToConnectedDevice())
                .isTrue();
        HdmiCecMessage standbyMessage = HdmiCecMessageBuilder.buildStandby(
                ADDR_PLAYBACK_1, ADDR_TV);
        assertThat(hdmiCecLocalDeviceTv.dispatchMessage(standbyMessage))
                .isEqualTo(Constants.HANDLED);
        mTestLooper.dispatchAll();

        assertThat(mPowerManager.isInteractive()).isTrue();
        assertThat(hdmiCecLocalDeviceTv.getWasActivePathSetToConnectedDevice())
                .isTrue();
    }

    @Test
    public void handleReportPhysicalAddress_DeviceDiscoveryActionInProgress_noNewDeviceAction() {
        mHdmiControlService.getHdmiCecNetwork().clearDeviceList();
@@ -2155,7 +2186,7 @@ public class HdmiCecLocalDeviceTvTest {

        @Override
        protected int handleActiveSource(HdmiCecMessage message) {
            setWasActiveSourceSetToConnectedDevice(true);
            setWasActivePathSetToConnectedDevice(true);
            return super.handleActiveSource(message);
        }
    }