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

Commit 807dfb30 authored by Yan Han's avatar Yan Han
Browse files

Fix and move old One Touch Play tests

Moves the One Touch Play tests in HdmiControlServiceBinderApiTest to
OneTouchPlayActionTest. This fixes tests failures on ADT-3, which were
caused by the test setup responding with the <Report Power Status>
message on same callstack as the <Give Device Power Status> message,
causing it to be processed before OneTouchPlayAction updated its state.

Bug: 182910754
Test: atest com.android.server.hdmi.OneTouchPlayActionTest
Change-Id: I11e8e2a5259739325d1dd9aae92113e85ecad47a
parent 9f5392e8
Loading
Loading
Loading
Loading
+0 −248
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.server.hdmi;

import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;

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

import static junit.framework.Assert.assertEquals;

import android.content.Context;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiPortInfo;
import android.hardware.hdmi.IHdmiControlCallback;
import android.os.Looper;
import android.os.test.TestLooper;
import android.provider.Settings;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Tests for {@link HdmiControlServiceBinderAPITest} class.
 */
@SmallTest
@RunWith(JUnit4.class)
public class HdmiControlServiceBinderAPITest {

    private Context mContext;

    private class HdmiCecLocalDeviceMyDevice extends HdmiCecLocalDevice {

        private boolean mCanGoToStandby;
        private boolean mIsStandby;
        private boolean mIsDisabled;

        protected HdmiCecLocalDeviceMyDevice(HdmiControlService service, int deviceType) {
            super(service, deviceType);
        }

        @Override
        protected void onAddressAllocated(int logicalAddress, int reason) {
        }

        @Override
        protected int getPreferredAddress() {
            return 0;
        }

        @Override
        protected void setPreferredAddress(int addr) {
        }

        @Override
        protected boolean canGoToStandby() {
            return mCanGoToStandby;
        }

        @Override
        protected void disableDevice(
            boolean initiatedByCec, final PendingActionClearedCallback originalCallback) {
            mIsDisabled = true;
            originalCallback.onCleared(this);
        }

        @Override
        protected void onStandby(boolean initiatedByCec, int standbyAction) {
            mIsStandby = true;
        }

        protected boolean isStandby() {
            return mIsStandby;
        }

        protected boolean isDisabled() {
            return mIsDisabled;
        }

        protected void setCanGoToStandby(boolean canGoToStandby) {
            mCanGoToStandby = canGoToStandby;
        }

        @Override
        protected int getRcProfile() {
            return 0;
        }

        @Override
        protected List<Integer> getRcFeatures() {
            return Collections.emptyList();
        }

        @Override
        protected List<Integer> getDeviceFeatures() {
            return Collections.emptyList();
        }
    }

    private static final String TAG = "HdmiControlServiceBinderAPITest";
    private HdmiControlService mHdmiControlService;
    private HdmiCecController mHdmiCecController;
    private HdmiCecLocalDevicePlayback mPlaybackDevice;
    private FakeNativeWrapper mNativeWrapper;
    private Looper mMyLooper;
    private TestLooper mTestLooper = new TestLooper();
    private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
    private HdmiPortInfo[] mHdmiPortInfo;
    private int mResult;
    private int mPowerStatus;

    @Before
    public void SetUp() {
        mContext = InstrumentationRegistry.getTargetContext();
        // Some tests expect no logical addresses being allocated at the beginning of the test.
        setHdmiControlEnabled(false);

        HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(mContext);

        mHdmiControlService =
            new HdmiControlService(mContext) {
                @Override
                void sendCecCommand(HdmiCecMessage command) {
                    switch (command.getOpcode()) {
                        case Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS:
                            HdmiCecMessage message =
                                HdmiCecMessageBuilder.buildReportPowerStatus(
                                    Constants.ADDR_TV,
                                    Constants.ADDR_PLAYBACK_1,
                                    HdmiControlManager.POWER_STATUS_ON);
                            handleCecCommand(message);
                            break;
                        default:
                            return;
                    }
                }

                @Override
                boolean isPowerStandby() {
                    return mPowerStatus == HdmiControlManager.POWER_STATUS_STANDBY;
                }

                @Override
                protected HdmiCecConfig getHdmiCecConfig() {
                    return hdmiCecConfig;
                }
            };
        mMyLooper = mTestLooper.getLooper();

        mPlaybackDevice = new HdmiCecLocalDevicePlayback(mHdmiControlService) {
            @Override
            protected void wakeUpIfActiveSource() {}

            @Override
            protected void setPreferredAddress(int addr) {}

            @Override
            protected int getPreferredAddress() {
                return Constants.ADDR_PLAYBACK_1;
            }
        };
        mPlaybackDevice.init();

        mHdmiControlService.setIoLooper(mMyLooper);

        mNativeWrapper = new FakeNativeWrapper();
        mHdmiCecController = HdmiCecController.createWithNativeWrapper(
                mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
        mHdmiControlService.setCecController(mHdmiCecController);
        mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
        mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));

        mLocalDevices.add(mPlaybackDevice);
        mHdmiPortInfo = new HdmiPortInfo[1];
        mHdmiPortInfo[0] =
            new HdmiPortInfo(1, HdmiPortInfo.PORT_INPUT, 0x2100, true, false, false);
        mNativeWrapper.setPortInfo(mHdmiPortInfo);
        mHdmiControlService.initService();
        mResult = -1;
        mPowerStatus = HdmiControlManager.POWER_STATUS_ON;

        mTestLooper.dispatchAll();
    }

    @Test
    public void oneTouchPlay_addressNotAllocated() {
        assertThat(mHdmiControlService.isAddressAllocated()).isFalse();
        mHdmiControlService.oneTouchPlay(new IHdmiControlCallback.Stub() {
            @Override
            public void onComplete(int result) {
                mResult = result;
            }
        });
        assertEquals(mResult, -1);
        assertThat(mPlaybackDevice.isActiveSource()).isFalse();

        setHdmiControlEnabled(true);
        mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
        mTestLooper.dispatchAll();
        assertThat(mHdmiControlService.isAddressAllocated()).isTrue();
        assertEquals(mResult, HdmiControlManager.RESULT_SUCCESS);
        assertThat(mPlaybackDevice.isActiveSource()).isTrue();
    }

    @Test
    public void oneTouchPlay_addressAllocated() {
        setHdmiControlEnabled(true);

        mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
        mTestLooper.dispatchAll();
        assertThat(mHdmiControlService.isAddressAllocated()).isTrue();
        mHdmiControlService.oneTouchPlay(new IHdmiControlCallback.Stub() {
            @Override
            public void onComplete(int result) {
                mResult = result;
            }
        });
        assertEquals(mResult, HdmiControlManager.RESULT_SUCCESS);
        assertThat(mPlaybackDevice.isActiveSource()).isTrue();
    }

    private void setHdmiControlEnabled(boolean enabled) {
        int value = enabled ? 1 : 0;
        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.HDMI_CONTROL_ENABLED,
                value);
    }
}
+107 −10
Original line number Diff line number Diff line
@@ -37,13 +37,13 @@ import android.os.IThermalService;
import android.os.Looper;
import android.os.PowerManager;
import android.os.test.TestLooper;
import android.provider.Settings;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;

import com.android.server.hdmi.HdmiCecFeatureAction.ActionTimer;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -79,12 +79,18 @@ public class OneTouchPlayActionTest {
    @Mock
    private IThermalService mIThermalServiceMock;

    @Before
    public void setUp() throws Exception {
    /**
     * Manually called before tests, because some tests require HDMI control to be disabled.
     * @param hdmiControlEnabled whether to enable the global setting hdmi_control.
     * @throws Exception
     */
    public void setUp(boolean hdmiControlEnabled) throws Exception {
        MockitoAnnotations.initMocks(this);

        mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));

        setHdmiControlEnabled(hdmiControlEnabled);

        PowerManager powerManager = new PowerManager(mContextSpy, mIPowerManagerMock,
                mIThermalServiceMock, new Handler(mTestLooper.getLooper()));
        when(mContextSpy.getSystemService(Context.POWER_SERVICE)).thenReturn(powerManager);
@@ -146,7 +152,9 @@ public class OneTouchPlayActionTest {
    }

    @Test
    public void succeedWithUnknownTvDevice() {
    public void succeedWithUnknownTvDevice() throws Exception {
        setUp(true);

        HdmiCecLocalDevicePlayback playbackDevice = new HdmiCecLocalDevicePlayback(
                mHdmiControlService);
        playbackDevice.init();
@@ -185,7 +193,9 @@ public class OneTouchPlayActionTest {
    }

    @Test
    public void succeedAfterGettingPowerStatusOn_Cec14b() {
    public void succeedAfterGettingPowerStatusOn_Cec14b() throws Exception {
        setUp(true);

        mHdmiControlService.getHdmiCecNetwork().addCecDevice(INFO_TV);
        HdmiCecLocalDevicePlayback playbackDevice = new HdmiCecLocalDevicePlayback(
                mHdmiControlService);
@@ -225,7 +235,9 @@ public class OneTouchPlayActionTest {
    }

    @Test
    public void succeedAfterGettingTransientPowerStatus_Cec14b() {
    public void succeedAfterGettingTransientPowerStatus_Cec14b() throws Exception {
        setUp(true);

        mHdmiControlService.getHdmiCecNetwork().addCecDevice(INFO_TV);
        HdmiCecLocalDevicePlayback playbackDevice = new HdmiCecLocalDevicePlayback(
                mHdmiControlService);
@@ -275,7 +287,9 @@ public class OneTouchPlayActionTest {
    }

    @Test
    public void timeOut_Cec14b() {
    public void timeOut_Cec14b() throws Exception {
        setUp(true);

        mHdmiControlService.getHdmiCecNetwork().addCecDevice(INFO_TV);
        HdmiCecLocalDevicePlayback playbackDevice = new HdmiCecLocalDevicePlayback(
                mHdmiControlService);
@@ -316,7 +330,9 @@ public class OneTouchPlayActionTest {
    }

    @Test
    public void succeedIfPowerStatusOn_Cec20() {
    public void succeedIfPowerStatusOn_Cec20() throws Exception {
        setUp(true);

        mHdmiControlService.getHdmiCecNetwork().addCecDevice(INFO_TV);
        HdmiCecLocalDevicePlayback playbackDevice = new HdmiCecLocalDevicePlayback(
                mHdmiControlService);
@@ -348,7 +364,9 @@ public class OneTouchPlayActionTest {
    }

    @Test
    public void succeedIfPowerStatusUnknown_Cec20() {
    public void succeedIfPowerStatusUnknown_Cec20() throws Exception {
        setUp(true);

        mHdmiControlService.getHdmiCecNetwork().addCecDevice(INFO_TV);
        HdmiCecLocalDevicePlayback playbackDevice = new HdmiCecLocalDevicePlayback(
                mHdmiControlService);
@@ -390,7 +408,9 @@ public class OneTouchPlayActionTest {
    }

    @Test
    public void succeedIfPowerStatusStandby_Cec20() {
    public void succeedIfPowerStatusStandby_Cec20() throws Exception {
        setUp(true);

        mHdmiControlService.getHdmiCecNetwork().addCecDevice(INFO_TV);
        HdmiCecLocalDevicePlayback playbackDevice = new HdmiCecLocalDevicePlayback(
                mHdmiControlService);
@@ -431,6 +451,73 @@ public class OneTouchPlayActionTest {
        assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
    }

    @Test
    public void succeedWithAddressNotAllocated_Cec14b() throws Exception {
        setUp(false);

        assertThat(mHdmiControlService.isAddressAllocated()).isFalse();

        HdmiCecLocalDevicePlayback playbackDevice = new HdmiCecLocalDevicePlayback(
                mHdmiControlService);
        playbackDevice.init();
        mLocalDevices.add(playbackDevice);

        TestCallback callback = new TestCallback();

        mHdmiControlService.oneTouchPlay(callback);
        mTestLooper.dispatchAll();

        assertThat(callback.hasResult()).isFalse();
        assertThat(playbackDevice.isActiveSource()).isFalse();

        setHdmiControlEnabled(true);
        mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);

        mTestLooper.dispatchAll();

        HdmiCecMessage reportPowerStatusMessage = HdmiCecMessageBuilder.buildReportPowerStatus(
                Constants.ADDR_TV,
                playbackDevice.mAddress,
                HdmiControlManager.POWER_STATUS_ON
        );
        mNativeWrapper.onCecMessage(reportPowerStatusMessage);

        mTestLooper.dispatchAll();

        assertThat(mHdmiControlService.isAddressAllocated()).isTrue();
        assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
        assertThat(playbackDevice.isActiveSource()).isTrue();
    }

    @Test
    public void succeedWithAddressAllocated_Cec14b() throws Exception {
        setUp(true);

        HdmiCecLocalDevicePlayback playbackDevice = new HdmiCecLocalDevicePlayback(
                mHdmiControlService);
        playbackDevice.init();
        mLocalDevices.add(playbackDevice);

        mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
        mTestLooper.dispatchAll();
        assertThat(mHdmiControlService.isAddressAllocated()).isTrue();

        TestCallback callback = new TestCallback();
        mHdmiControlService.oneTouchPlay(callback);

        HdmiCecMessage reportPowerStatusMessage = HdmiCecMessageBuilder.buildReportPowerStatus(
                Constants.ADDR_TV,
                playbackDevice.mAddress,
                HdmiControlManager.POWER_STATUS_ON
        );
        mNativeWrapper.onCecMessage(reportPowerStatusMessage);

        mTestLooper.dispatchAll();

        assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
        assertThat(playbackDevice.isActiveSource()).isTrue();
    }

    private static class TestActionTimer implements ActionTimer {
        private int mState;

@@ -456,9 +543,19 @@ public class OneTouchPlayActionTest {
            mCallbackResult.add(result);
        }

        private boolean hasResult() {
            return mCallbackResult.size() != 0;
        }

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

    private void setHdmiControlEnabled(boolean enabled) {
        int value = enabled ? 1 : 0;
        Settings.Global.putInt(mContextSpy.getContentResolver(),
                Settings.Global.HDMI_CONTROL_ENABLED, value);
    }
}