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

Commit 32d06ea0 authored by Yan Han's avatar Yan Han
Browse files

On TVs, disable "skip next routing control" flag after a short delay

Currently, panel TVs use the mSkipRoutingControl flag to skip their next
routing control or outgoing <Active Source> after waking via CEC.

This was implemented to prevent the TV from stealing active source from
the device that woke it up (see b/17189114). However, because the flag
stays true until it is triggered, it can block a source change initiated
by the user a long time after the wakeup.

This CL adds a delayed Runnable that sets the flag to false after two
seconds. This preserves the intended use of the flag, but prevents it
from interfering with later source/routing changes.

Bug: 319716217
Bug: 259024330

Test: atest HdmiCecLocalDeviceTvTest

Change-Id: Ibe05228152600fd966cb19401e14a20ef9424a86
parent 84045971
Loading
Loading
Loading
Loading
+16 −1
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import android.media.AudioDeviceInfo;
import android.media.AudioProfile;
import android.media.tv.TvInputInfo;
import android.media.tv.TvInputManager.TvInputCallback;
import android.os.Handler;
import android.util.Slog;
import android.util.SparseBooleanArray;

@@ -97,9 +98,15 @@ public final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
    private boolean mSystemAudioMute = false;

    // If true, do not do routing control/send active source for internal source.
    // Set to true when the device was woken up by <Text/Image View On>.
    // Set to true for a short duration when the device is woken up by <Text/Image View On>.
    private boolean mSkipRoutingControl;

    // Handler for posting a runnable to set `mSkipRoutingControl` to false after a delay
    private final Handler mSkipRoutingControlHandler;

    // Runnable that sets `mSkipRoutingControl` to false
    private final Runnable mResetSkipRoutingControlRunnable = () -> mSkipRoutingControl = false;

    // Message buffer used to buffer selected messages to process later. <Active Source>
    // from a source device, for instance, needs to be buffered if the device is not
    // discovered yet. The buffered commands are taken out and when they are ready to
@@ -162,6 +169,7 @@ public final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
                HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL)
                    == HdmiControlManager.SYSTEM_AUDIO_CONTROL_ENABLED;
        mStandbyHandler = new HdmiCecStandbyModeHandler(service, this);
        mSkipRoutingControlHandler = new Handler(service.getServiceLooper());
    }

    @Override
@@ -184,7 +192,14 @@ public final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
        mService.getHdmiCecNetwork().addCecSwitch(
                mService.getHdmiCecNetwork().getPhysicalAddress());  // TV is a CEC switch too.
        mTvInputs.clear();

        mSkipRoutingControl = (reason == HdmiControlService.INITIATED_BY_WAKE_UP_MESSAGE);
        mSkipRoutingControlHandler.removeCallbacks(mResetSkipRoutingControlRunnable);
        if (mSkipRoutingControl) {
            mSkipRoutingControlHandler.postDelayed(mResetSkipRoutingControlRunnable,
                    HdmiConfig.TIMEOUT_MS);
        }

        launchRoutingControl(reason != HdmiControlService.INITIATED_BY_ENABLE_CEC &&
                reason != HdmiControlService.INITIATED_BY_BOOT_UP);
        resetSelectRequestBuffer();
+32 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static com.android.server.hdmi.Constants.ADDR_RECORDER_1;
import static com.android.server.hdmi.Constants.ADDR_TV;
import static com.android.server.hdmi.HdmiCecLocalDevice.ActiveSource;
import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_WAKE_UP_MESSAGE;

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

@@ -1807,4 +1808,35 @@ public class HdmiCecLocalDeviceTvTest {
        // TV should only send <Give Osd Name> once
        assertEquals(1, Collections.frequency(mNativeWrapper.getResultMessages(), giveOsdName));
    }

    @Test
    public void initiateCecByWakeupMessage_selectInternalSourceAfterDelay_broadcastsActiveSource() {
        HdmiCecMessage activeSourceFromTv =
                HdmiCecMessageBuilder.buildActiveSource(ADDR_TV, 0x0000);

        mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_WAKE_UP_MESSAGE);
        mTestLooper.dispatchAll();

        mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
        mTestLooper.dispatchAll();

        mHdmiCecLocalDeviceTv.deviceSelect(ADDR_TV, new TestCallback());
        mTestLooper.dispatchAll();

        assertThat(mNativeWrapper.getResultMessages()).contains(activeSourceFromTv);
    }

    @Test
    public void initiateCecByWakeupMessage_selectInternalSource_doesNotBroadcastActiveSource() {
        HdmiCecMessage activeSourceFromTv =
                HdmiCecMessageBuilder.buildActiveSource(ADDR_TV, 0x0000);

        mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_WAKE_UP_MESSAGE);
        mTestLooper.dispatchAll();

        mHdmiCecLocalDeviceTv.deviceSelect(ADDR_TV, new TestCallback());
        mTestLooper.dispatchAll();

        assertThat(mNativeWrapper.getResultMessages()).doesNotContain(activeSourceFromTv);
    }
}