diff options
3 files changed, 459 insertions, 3 deletions
diff --git a/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java b/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java index 02b09b15b464..73ecbe0432b7 100644 --- a/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java +++ b/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java @@ -20,6 +20,7 @@ import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback; import android.hardware.hdmi.IHdmiControlCallback; import android.util.Slog; +import com.android.internal.annotations.VisibleForTesting; /** * Feature action that performs one touch play against TV/Display device. This action is initiated @@ -40,13 +41,15 @@ final class OneTouchPlayAction extends HdmiCecFeatureAction { // standby mode, and do not accept the command until their power status becomes 'ON'. // For a workaround, we send <Give Device Power Status> commands periodically to make sure // the device switches its status to 'ON'. Then we send additional <Active Source>. - private static final int STATE_WAITING_FOR_REPORT_POWER_STATUS = 1; + @VisibleForTesting + static final int STATE_WAITING_FOR_REPORT_POWER_STATUS = 1; // The maximum number of times we send <Give Device Power Status> before we give up. // We wait up to RESPONSE_TIMEOUT_MS * LOOP_COUNTER_MAX = 20 seconds. private static final int LOOP_COUNTER_MAX = 10; private final int mTargetAddress; + private final boolean mIsCec20; private int mPowerStatusCounter = 0; @@ -65,8 +68,19 @@ final class OneTouchPlayAction extends HdmiCecFeatureAction { private OneTouchPlayAction(HdmiCecLocalDevice localDevice, int targetAddress, IHdmiControlCallback callback) { + this(localDevice, targetAddress, callback, + localDevice.getDeviceInfo().getCecVersion() + >= HdmiControlManager.HDMI_CEC_VERSION_2_0 + && localDevice.mService.getHdmiCecNetwork().getCecDeviceInfo( + targetAddress).getCecVersion() >= HdmiControlManager.HDMI_CEC_VERSION_2_0); + } + + @VisibleForTesting + OneTouchPlayAction(HdmiCecLocalDevice localDevice, int targetAddress, + IHdmiControlCallback callback, boolean isCec20) { super(localDevice, callback); mTargetAddress = targetAddress; + mIsCec20 = isCec20; } @Override @@ -74,6 +88,9 @@ final class OneTouchPlayAction extends HdmiCecFeatureAction { // Because only source device can create this action, it's safe to cast. mSource = source(); sendCommand(HdmiCecMessageBuilder.buildTextViewOn(getSourceAddress(), mTargetAddress)); + boolean targetOnBefore = localDevice().mService.getHdmiCecNetwork() + .getCecDeviceInfo(mTargetAddress).getDevicePowerStatus() + == HdmiControlManager.POWER_STATUS_ON; broadcastActiveSource(); // If the device is not an audio system itself, request the connected audio system to // turn on. @@ -81,7 +98,20 @@ final class OneTouchPlayAction extends HdmiCecFeatureAction { sendCommand(HdmiCecMessageBuilder.buildSystemAudioModeRequest(getSourceAddress(), Constants.ADDR_AUDIO_SYSTEM, getSourcePath(), true)); } - queryDevicePowerStatus(); + int targetPowerStatus = localDevice().mService.getHdmiCecNetwork() + .getCecDeviceInfo(mTargetAddress).getDevicePowerStatus(); + if (!mIsCec20 || targetPowerStatus == HdmiControlManager.POWER_STATUS_UNKNOWN) { + queryDevicePowerStatus(); + } else if (targetPowerStatus == HdmiControlManager.POWER_STATUS_ON) { + if (!targetOnBefore) { + // Suppress 2nd <Active Source> message if the target device was already on when + // the 1st one was sent. + broadcastActiveSource(); + } + finishWithCallback(HdmiControlManager.RESULT_SUCCESS); + return true; + } + mState = STATE_WAITING_FOR_REPORT_POWER_STATUS; addTimer(mState, HdmiConfig.TIMEOUT_MS); return true; } @@ -101,7 +131,6 @@ final class OneTouchPlayAction extends HdmiCecFeatureAction { } private void queryDevicePowerStatus() { - mState = STATE_WAITING_FOR_REPORT_POWER_STATUS; sendCommand(HdmiCecMessageBuilder.buildGiveDevicePowerStatus(getSourceAddress(), mTargetAddress)); } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java index 915392e6eb80..1a6bad8b29cf 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java @@ -61,6 +61,12 @@ import java.util.concurrent.TimeUnit; /** Tests for {@link HdmiCecLocalDevicePlayback} class. */ public class HdmiCecLocalDevicePlaybackTest { + private static final int PORT_1 = 1; + private static final HdmiDeviceInfo INFO_TV = new HdmiDeviceInfo( + ADDR_TV, 0x0000, PORT_1, HdmiDeviceInfo.DEVICE_TV, + 0x1234, "TV", + HdmiControlManager.POWER_STATUS_ON, HdmiControlManager.HDMI_CEC_VERSION_1_4_B); + private HdmiControlService mHdmiControlService; private HdmiCecController mHdmiCecController; private HdmiCecLocalDevicePlayback mHdmiCecLocalDevicePlayback; @@ -159,6 +165,7 @@ public class HdmiCecLocalDevicePlaybackTest { mNativeWrapper.setPhysicalAddress(mPlaybackPhysicalAddress); mTestLooper.dispatchAll(); mPlaybackLogicalAddress = mHdmiCecLocalDevicePlayback.getDeviceInfo().getLogicalAddress(); + mHdmiControlService.getHdmiCecNetwork().addCecDevice(INFO_TV); mNativeWrapper.clearResultMessages(); } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/OneTouchPlayActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/OneTouchPlayActionTest.java new file mode 100644 index 000000000000..907cf3eb1f70 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/hdmi/OneTouchPlayActionTest.java @@ -0,0 +1,420 @@ +/* + * Copyright (C) 2021 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.Constants.ADDR_TV; +import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC; +import static com.android.server.hdmi.OneTouchPlayAction.STATE_WAITING_FOR_REPORT_POWER_STATUS; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.ContextWrapper; +import android.hardware.hdmi.HdmiControlManager; +import android.hardware.hdmi.HdmiDeviceInfo; +import android.hardware.hdmi.IHdmiControlCallback; +import android.media.AudioManager; +import android.os.Handler; +import android.os.IPowerManager; +import android.os.IThermalService; +import android.os.Looper; +import android.os.PowerManager; +import android.os.test.TestLooper; + +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; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.ArrayList; + +/** Tests for {@link OneTouchPlayAction} */ +@SmallTest +@RunWith(JUnit4.class) +public class OneTouchPlayActionTest { + private static final byte[] POWER_ON = new byte[]{HdmiControlManager.POWER_STATUS_ON}; + private static final byte[] POWER_TRANSIENT_TO_ON = + new byte[]{HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON}; + + private static final int PORT_1 = 1; + private static final HdmiDeviceInfo INFO_TV = new HdmiDeviceInfo( + ADDR_TV, 0x0000, PORT_1, HdmiDeviceInfo.DEVICE_TV, + 0x1234, "TV", + HdmiControlManager.POWER_STATUS_ON, HdmiControlManager.HDMI_CEC_VERSION_1_4_B); + + private Context mContextSpy; + private HdmiControlService mHdmiControlService; + private FakeNativeWrapper mNativeWrapper; + + private TestLooper mTestLooper = new TestLooper(); + private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>(); + private int mPhysicalAddress; + + @Mock + private IPowerManager mIPowerManagerMock; + @Mock + private IThermalService mIThermalServiceMock; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + + mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext())); + + PowerManager powerManager = new PowerManager(mContextSpy, mIPowerManagerMock, + mIThermalServiceMock, new Handler(mTestLooper.getLooper())); + when(mContextSpy.getSystemService(Context.POWER_SERVICE)).thenReturn(powerManager); + when(mContextSpy.getSystemService(PowerManager.class)).thenReturn(powerManager); + when(mIPowerManagerMock.isInteractive()).thenReturn(true); + + mHdmiControlService = new HdmiControlService(mContextSpy) { + @Override + AudioManager getAudioManager() { + return new AudioManager() { + @Override + public void setWiredDeviceConnectionState( + int type, int state, String address, String name) { + // Do nothing. + } + }; + } + + @Override + void wakeUp() { + } + + @Override + boolean isPowerStandby() { + return false; + } + + @Override + protected PowerManager getPowerManager() { + return powerManager; + } + + @Override + protected void writeStringSystemProperty(String key, String value) { + // do nothing + } + }; + + Looper looper = mTestLooper.getLooper(); + mHdmiControlService.setIoLooper(looper); + mHdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(mContextSpy)); + mNativeWrapper = new FakeNativeWrapper(); + HdmiCecController hdmiCecController = HdmiCecController.createWithNativeWrapper( + this.mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter()); + mHdmiControlService.setCecController(hdmiCecController); + mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService)); + mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService)); + mHdmiControlService.initService(); + mPhysicalAddress = 0x2000; + mNativeWrapper.setPhysicalAddress(mPhysicalAddress); + mTestLooper.dispatchAll(); + mHdmiControlService.getHdmiCecNetwork().addCecDevice(INFO_TV); + } + + private OneTouchPlayAction createOneTouchPlayAction(HdmiCecLocalDevicePlayback device, + TestActionTimer actionTimer, TestCallback callback, boolean isCec20) { + OneTouchPlayAction action = new OneTouchPlayAction(device, ADDR_TV, callback, isCec20); + action.setActionTimer(actionTimer); + return action; + } + + @Test + public void succeedAfterGettingPowerStatusOn_Cec14b() { + HdmiCecLocalDevicePlayback playbackDevice = new HdmiCecLocalDevicePlayback( + mHdmiControlService); + playbackDevice.init(); + mLocalDevices.add(playbackDevice); + mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); + mTestLooper.dispatchAll(); + + TestActionTimer actionTimer = new TestActionTimer(); + TestCallback callback = new TestCallback(); + OneTouchPlayAction action = createOneTouchPlayAction(playbackDevice, actionTimer, callback, + false); + playbackDevice.addAndStartAction(action); + mTestLooper.dispatchAll(); + + HdmiCecMessage activeSource = HdmiCecMessageBuilder.buildActiveSource( + playbackDevice.mAddress, mPhysicalAddress); + HdmiCecMessage textViewOn = HdmiCecMessageBuilder.buildTextViewOn(playbackDevice.mAddress, + ADDR_TV); + HdmiCecMessage giveDevicePowerStatus = HdmiCecMessageBuilder + .buildGiveDevicePowerStatus(playbackDevice.mAddress, ADDR_TV); + + assertThat(mNativeWrapper.getResultMessages()).contains(textViewOn); + assertThat(mNativeWrapper.getResultMessages()).contains(activeSource); + assertThat(mNativeWrapper.getResultMessages()).contains(giveDevicePowerStatus); + mNativeWrapper.clearResultMessages(); + assertThat(actionTimer.getState()).isEqualTo(STATE_WAITING_FOR_REPORT_POWER_STATUS); + HdmiCecMessage reportPowerStatusOn = new HdmiCecMessage( + ADDR_TV, playbackDevice.mAddress, Constants.MESSAGE_REPORT_POWER_STATUS, POWER_ON); + action.processCommand(reportPowerStatusOn); + mTestLooper.dispatchAll(); + + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(textViewOn); + assertThat(mNativeWrapper.getResultMessages()).contains(activeSource); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(giveDevicePowerStatus); + assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS); + } + + @Test + public void succeedAfterGettingTransientPowerStatus_Cec14b() { + HdmiCecLocalDevicePlayback playbackDevice = new HdmiCecLocalDevicePlayback( + mHdmiControlService); + playbackDevice.init(); + mLocalDevices.add(playbackDevice); + mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); + mTestLooper.dispatchAll(); + + TestActionTimer actionTimer = new TestActionTimer(); + TestCallback callback = new TestCallback(); + OneTouchPlayAction action = createOneTouchPlayAction(playbackDevice, actionTimer, callback, + false); + playbackDevice.addAndStartAction(action); + mTestLooper.dispatchAll(); + + HdmiCecMessage activeSource = HdmiCecMessageBuilder.buildActiveSource( + playbackDevice.mAddress, mPhysicalAddress); + HdmiCecMessage textViewOn = HdmiCecMessageBuilder.buildTextViewOn(playbackDevice.mAddress, + ADDR_TV); + HdmiCecMessage giveDevicePowerStatus = HdmiCecMessageBuilder + .buildGiveDevicePowerStatus(playbackDevice.mAddress, ADDR_TV); + + assertThat(mNativeWrapper.getResultMessages()).contains(textViewOn); + assertThat(mNativeWrapper.getResultMessages()).contains(activeSource); + assertThat(mNativeWrapper.getResultMessages()).contains(giveDevicePowerStatus); + mNativeWrapper.clearResultMessages(); + assertThat(actionTimer.getState()).isEqualTo(STATE_WAITING_FOR_REPORT_POWER_STATUS); + HdmiCecMessage reportPowerStatusTransientToOn = new HdmiCecMessage( + ADDR_TV, playbackDevice.mAddress, Constants.MESSAGE_REPORT_POWER_STATUS, + POWER_TRANSIENT_TO_ON); + action.processCommand(reportPowerStatusTransientToOn); + action.handleTimerEvent(STATE_WAITING_FOR_REPORT_POWER_STATUS); + mTestLooper.dispatchAll(); + + assertThat(mNativeWrapper.getResultMessages()).contains(giveDevicePowerStatus); + mNativeWrapper.clearResultMessages(); + + HdmiCecMessage reportPowerStatusOn = new HdmiCecMessage( + ADDR_TV, playbackDevice.mAddress, Constants.MESSAGE_REPORT_POWER_STATUS, POWER_ON); + action.processCommand(reportPowerStatusOn); + mTestLooper.dispatchAll(); + + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(textViewOn); + assertThat(mNativeWrapper.getResultMessages()).contains(activeSource); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(giveDevicePowerStatus); + assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS); + } + + @Test + public void timeOut_Cec14b() { + HdmiCecLocalDevicePlayback playbackDevice = new HdmiCecLocalDevicePlayback( + mHdmiControlService); + playbackDevice.init(); + mLocalDevices.add(playbackDevice); + mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); + mTestLooper.dispatchAll(); + + TestActionTimer actionTimer = new TestActionTimer(); + TestCallback callback = new TestCallback(); + OneTouchPlayAction action = createOneTouchPlayAction(playbackDevice, actionTimer, callback, + false); + playbackDevice.addAndStartAction(action); + mTestLooper.dispatchAll(); + + HdmiCecMessage activeSource = HdmiCecMessageBuilder.buildActiveSource( + playbackDevice.mAddress, mPhysicalAddress); + HdmiCecMessage textViewOn = HdmiCecMessageBuilder.buildTextViewOn(playbackDevice.mAddress, + ADDR_TV); + HdmiCecMessage giveDevicePowerStatus = HdmiCecMessageBuilder + .buildGiveDevicePowerStatus(playbackDevice.mAddress, ADDR_TV); + + assertThat(mNativeWrapper.getResultMessages()).contains(textViewOn); + assertThat(mNativeWrapper.getResultMessages()).contains(activeSource); + assertThat(mNativeWrapper.getResultMessages()).contains(giveDevicePowerStatus); + mNativeWrapper.clearResultMessages(); + assertThat(actionTimer.getState()).isEqualTo(STATE_WAITING_FOR_REPORT_POWER_STATUS); + for (int i = 0; i < 10; ++i) { + action.handleTimerEvent(STATE_WAITING_FOR_REPORT_POWER_STATUS); + mTestLooper.dispatchAll(); + } + + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(textViewOn); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(activeSource); + assertThat(mNativeWrapper.getResultMessages()).contains(giveDevicePowerStatus); + action.handleTimerEvent(STATE_WAITING_FOR_REPORT_POWER_STATUS); + assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_TIMEOUT); + } + + @Test + public void succeedIfPowerStatusOn_Cec20() { + HdmiCecLocalDevicePlayback playbackDevice = new HdmiCecLocalDevicePlayback( + mHdmiControlService); + playbackDevice.init(); + mLocalDevices.add(playbackDevice); + mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); + mHdmiControlService.getHdmiCecNetwork().updateDevicePowerStatus(ADDR_TV, + HdmiControlManager.POWER_STATUS_ON); + mTestLooper.dispatchAll(); + + TestActionTimer actionTimer = new TestActionTimer(); + TestCallback callback = new TestCallback(); + OneTouchPlayAction action = createOneTouchPlayAction(playbackDevice, actionTimer, callback, + true); + playbackDevice.addAndStartAction(action); + mTestLooper.dispatchAll(); + + HdmiCecMessage activeSource = HdmiCecMessageBuilder.buildActiveSource( + playbackDevice.mAddress, mPhysicalAddress); + HdmiCecMessage textViewOn = HdmiCecMessageBuilder.buildTextViewOn(playbackDevice.mAddress, + ADDR_TV); + HdmiCecMessage giveDevicePowerStatus = HdmiCecMessageBuilder + .buildGiveDevicePowerStatus(playbackDevice.mAddress, ADDR_TV); + + assertThat(mNativeWrapper.getResultMessages()).contains(textViewOn); + assertThat(mNativeWrapper.getResultMessages()).contains(activeSource); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(giveDevicePowerStatus); + assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS); + } + + @Test + public void succeedIfPowerStatusUnknown_Cec20() { + HdmiCecLocalDevicePlayback playbackDevice = new HdmiCecLocalDevicePlayback( + mHdmiControlService); + playbackDevice.init(); + mLocalDevices.add(playbackDevice); + mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); + mHdmiControlService.getHdmiCecNetwork().updateDevicePowerStatus(ADDR_TV, + HdmiControlManager.POWER_STATUS_UNKNOWN); + mTestLooper.dispatchAll(); + + TestActionTimer actionTimer = new TestActionTimer(); + TestCallback callback = new TestCallback(); + OneTouchPlayAction action = createOneTouchPlayAction(playbackDevice, actionTimer, callback, + true); + playbackDevice.addAndStartAction(action); + mTestLooper.dispatchAll(); + + HdmiCecMessage activeSource = HdmiCecMessageBuilder.buildActiveSource( + playbackDevice.mAddress, mPhysicalAddress); + HdmiCecMessage textViewOn = HdmiCecMessageBuilder.buildTextViewOn(playbackDevice.mAddress, + ADDR_TV); + HdmiCecMessage giveDevicePowerStatus = HdmiCecMessageBuilder + .buildGiveDevicePowerStatus(playbackDevice.mAddress, ADDR_TV); + + assertThat(mNativeWrapper.getResultMessages()).contains(textViewOn); + assertThat(mNativeWrapper.getResultMessages()).contains(activeSource); + assertThat(mNativeWrapper.getResultMessages()).contains(giveDevicePowerStatus); + mNativeWrapper.clearResultMessages(); + assertThat(actionTimer.getState()).isEqualTo(STATE_WAITING_FOR_REPORT_POWER_STATUS); + HdmiCecMessage reportPowerStatusOn = new HdmiCecMessage( + ADDR_TV, playbackDevice.mAddress, Constants.MESSAGE_REPORT_POWER_STATUS, POWER_ON); + action.processCommand(reportPowerStatusOn); + mTestLooper.dispatchAll(); + + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(textViewOn); + assertThat(mNativeWrapper.getResultMessages()).contains(activeSource); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(giveDevicePowerStatus); + assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS); + } + + @Test + public void succeedIfPowerStatusStandby_Cec20() { + HdmiCecLocalDevicePlayback playbackDevice = new HdmiCecLocalDevicePlayback( + mHdmiControlService); + playbackDevice.init(); + mLocalDevices.add(playbackDevice); + mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); + mHdmiControlService.getHdmiCecNetwork().updateDevicePowerStatus(ADDR_TV, + HdmiControlManager.POWER_STATUS_STANDBY); + mTestLooper.dispatchAll(); + + TestActionTimer actionTimer = new TestActionTimer(); + TestCallback callback = new TestCallback(); + OneTouchPlayAction action = createOneTouchPlayAction(playbackDevice, actionTimer, callback, + true); + playbackDevice.addAndStartAction(action); + mTestLooper.dispatchAll(); + + HdmiCecMessage activeSource = HdmiCecMessageBuilder.buildActiveSource( + playbackDevice.mAddress, mPhysicalAddress); + HdmiCecMessage textViewOn = HdmiCecMessageBuilder.buildTextViewOn(playbackDevice.mAddress, + ADDR_TV); + HdmiCecMessage giveDevicePowerStatus = HdmiCecMessageBuilder + .buildGiveDevicePowerStatus(playbackDevice.mAddress, ADDR_TV); + + assertThat(mNativeWrapper.getResultMessages()).contains(textViewOn); + assertThat(mNativeWrapper.getResultMessages()).contains(activeSource); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(giveDevicePowerStatus); + mNativeWrapper.clearResultMessages(); + assertThat(actionTimer.getState()).isEqualTo(STATE_WAITING_FOR_REPORT_POWER_STATUS); + HdmiCecMessage reportPowerStatusOn = new HdmiCecMessage( + ADDR_TV, playbackDevice.mAddress, Constants.MESSAGE_REPORT_POWER_STATUS, POWER_ON); + action.processCommand(reportPowerStatusOn); + mTestLooper.dispatchAll(); + + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(textViewOn); + assertThat(mNativeWrapper.getResultMessages()).contains(activeSource); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(giveDevicePowerStatus); + assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS); + } + + private static class TestActionTimer implements ActionTimer { + private int mState; + + @Override + public void sendTimerMessage(int state, long delayMillis) { + mState = state; + } + + @Override + public void clearTimerMessage() { + } + + private int getState() { + return mState; + } + } + + 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); + } + } +} |