[2.0] Disable sending <User Control Pressed> in attempts to change the active source to a 2.0 device

Bug: 169121092
Test: atest DeviceSelectActionTest
Change-Id: I41a590819fa8ac4efe307932bec59881f975c715
This commit is contained in:
Michal Olech
2021-01-07 12:59:10 +01:00
parent e656e5cbe1
commit b695454d8a
2 changed files with 436 additions and 47 deletions

View File

@@ -23,6 +23,8 @@ import android.hardware.hdmi.IHdmiControlCallback;
import android.hardware.tv.cec.V1_0.SendMessageResult;
import android.os.RemoteException;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
/**
@@ -47,7 +49,8 @@ final class DeviceSelectAction extends HdmiCecFeatureAction {
// State in which we wait for <Report Power Status> to come in response to the command
// <Give Device Power Status> we have sent.
private static final int STATE_WAIT_FOR_REPORT_POWER_STATUS = 1;
@VisibleForTesting
static final int STATE_WAIT_FOR_REPORT_POWER_STATUS = 1;
// State in which we wait for the device power status to switch to 'Standby'.
// We wait till the status becomes 'Standby' before we send <Set Stream Path>
@@ -56,11 +59,13 @@ final class DeviceSelectAction extends HdmiCecFeatureAction {
// State in which we wait for the device power status to switch to 'on'. We wait
// maximum 100 seconds (20 * 5) before we give up and just send <Set Stream Path>.
private static final int STATE_WAIT_FOR_DEVICE_POWER_ON = 3;
@VisibleForTesting
static final int STATE_WAIT_FOR_DEVICE_POWER_ON = 3;
private final HdmiDeviceInfo mTarget;
private final IHdmiControlCallback mCallback;
private final HdmiCecMessage mGivePowerStatus;
private final boolean mIsCec20;
private int mPowerStatusCounter = 0;
@@ -71,13 +76,22 @@ final class DeviceSelectAction extends HdmiCecFeatureAction {
* @param target target logical device that will be a new active source
* @param callback callback object
*/
public DeviceSelectAction(HdmiCecLocalDeviceTv source,
HdmiDeviceInfo target, IHdmiControlCallback callback) {
DeviceSelectAction(HdmiCecLocalDeviceTv source, HdmiDeviceInfo target,
IHdmiControlCallback callback) {
this(source, target, callback,
source.getDeviceInfo().getCecVersion() >= HdmiControlManager.HDMI_CEC_VERSION_2_0
&& target.getCecVersion() >= HdmiControlManager.HDMI_CEC_VERSION_2_0);
}
@VisibleForTesting
DeviceSelectAction(HdmiCecLocalDeviceTv source, HdmiDeviceInfo target,
IHdmiControlCallback callback, boolean isCec20) {
super(source);
mCallback = callback;
mTarget = target;
mGivePowerStatus = HdmiCecMessageBuilder.buildGiveDevicePowerStatus(
getSourceAddress(), getTargetAddress());
mIsCec20 = isCec20;
}
int getTargetAddress() {
@@ -86,8 +100,18 @@ final class DeviceSelectAction extends HdmiCecFeatureAction {
@Override
public boolean start() {
// Seq #9
queryDevicePowerStatus();
if (mIsCec20) {
sendSetStreamPath();
}
if (!mIsCec20 || mTarget.getDevicePowerStatus()
== HdmiControlManager.POWER_STATUS_UNKNOWN) {
queryDevicePowerStatus();
} else if (mTarget.getDevicePowerStatus() == HdmiControlManager.POWER_STATUS_ON) {
invokeCallbackAndFinish(HdmiControlManager.RESULT_SUCCESS);
return true;
}
mState = STATE_WAIT_FOR_REPORT_POWER_STATUS;
addTimer(mState, HdmiConfig.TIMEOUT_MS);
return true;
}
@@ -96,14 +120,10 @@ final class DeviceSelectAction extends HdmiCecFeatureAction {
@Override
public void onSendCompleted(int error) {
if (error != SendMessageResult.SUCCESS) {
invokeCallback(HdmiControlManager.RESULT_COMMUNICATION_FAILED);
finish();
return;
invokeCallbackAndFinish(HdmiControlManager.RESULT_COMMUNICATION_FAILED);
}
}
});
mState = STATE_WAIT_FOR_REPORT_POWER_STATUS;
addTimer(mState, HdmiConfig.TIMEOUT_MS);
}
@Override
@@ -113,7 +133,6 @@ final class DeviceSelectAction extends HdmiCecFeatureAction {
}
int opcode = cmd.getOpcode();
byte[] params = cmd.getParams();
switch (mState) {
case STATE_WAIT_FOR_REPORT_POWER_STATUS:
if (opcode == Constants.MESSAGE_REPORT_POWER_STATUS) {
@@ -129,21 +148,23 @@ final class DeviceSelectAction extends HdmiCecFeatureAction {
private boolean handleReportPowerStatus(int powerStatus) {
switch (powerStatus) {
case HdmiControlManager.POWER_STATUS_ON:
sendSetStreamPath();
selectDevice();
return true;
case HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY:
if (mPowerStatusCounter < 4) {
mState = STATE_WAIT_FOR_DEVICE_TO_TRANSIT_TO_STANDBY;
addTimer(mState, TIMEOUT_TRANSIT_TO_STANDBY_MS);
} else {
sendSetStreamPath();
selectDevice();
}
return true;
case HdmiControlManager.POWER_STATUS_STANDBY:
if (mPowerStatusCounter == 0) {
turnOnDevice();
mState = STATE_WAIT_FOR_DEVICE_POWER_ON;
addTimer(mState, TIMEOUT_POWER_ON_MS);
} else {
sendSetStreamPath();
selectDevice();
}
return true;
case HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON:
@@ -151,33 +172,13 @@ final class DeviceSelectAction extends HdmiCecFeatureAction {
mState = STATE_WAIT_FOR_DEVICE_POWER_ON;
addTimer(mState, TIMEOUT_POWER_ON_MS);
} else {
sendSetStreamPath();
selectDevice();
}
return true;
}
return false;
}
private void turnOnDevice() {
sendUserControlPressedAndReleased(mTarget.getLogicalAddress(),
HdmiCecKeycode.CEC_KEYCODE_POWER);
sendUserControlPressedAndReleased(mTarget.getLogicalAddress(),
HdmiCecKeycode.CEC_KEYCODE_POWER_ON_FUNCTION);
mState = STATE_WAIT_FOR_DEVICE_POWER_ON;
addTimer(mState, TIMEOUT_POWER_ON_MS);
}
private void sendSetStreamPath() {
// Turn the active source invalidated, which remains so till <Active Source> comes from
// the selected device.
tv().getActiveSource().invalidate();
tv().setActivePath(mTarget.getPhysicalAddress());
sendCommand(HdmiCecMessageBuilder.buildSetStreamPath(
getSourceAddress(), mTarget.getPhysicalAddress()));
invokeCallback(HdmiControlManager.RESULT_SUCCESS);
finish();
}
@Override
public void handleTimerEvent(int timeoutState) {
if (mState != timeoutState) {
@@ -187,28 +188,54 @@ final class DeviceSelectAction extends HdmiCecFeatureAction {
switch (mState) {
case STATE_WAIT_FOR_REPORT_POWER_STATUS:
if (tv().isPowerStandbyOrTransient()) {
invokeCallback(HdmiControlManager.RESULT_INCORRECT_MODE);
finish();
invokeCallbackAndFinish(HdmiControlManager.RESULT_INCORRECT_MODE);
return;
}
sendSetStreamPath();
selectDevice();
break;
case STATE_WAIT_FOR_DEVICE_TO_TRANSIT_TO_STANDBY:
case STATE_WAIT_FOR_DEVICE_POWER_ON:
mPowerStatusCounter++;
queryDevicePowerStatus();
mState = STATE_WAIT_FOR_REPORT_POWER_STATUS;
addTimer(mState, HdmiConfig.TIMEOUT_MS);
break;
}
}
private void invokeCallback(int result) {
if (mCallback == null) {
return;
}
try {
mCallback.onComplete(result);
} catch (RemoteException e) {
Slog.e(TAG, "Callback failed:" + e);
private void turnOnDevice() {
if (!mIsCec20) {
sendUserControlPressedAndReleased(mTarget.getLogicalAddress(),
HdmiCecKeycode.CEC_KEYCODE_POWER);
sendUserControlPressedAndReleased(mTarget.getLogicalAddress(),
HdmiCecKeycode.CEC_KEYCODE_POWER_ON_FUNCTION);
}
}
private void selectDevice() {
if (!mIsCec20) {
sendSetStreamPath();
}
invokeCallbackAndFinish(HdmiControlManager.RESULT_SUCCESS);
}
private void sendSetStreamPath() {
// Turn the active source invalidated, which remains so till <Active Source> comes from
// the selected device.
tv().getActiveSource().invalidate();
tv().setActivePath(mTarget.getPhysicalAddress());
sendCommand(HdmiCecMessageBuilder.buildSetStreamPath(
getSourceAddress(), mTarget.getPhysicalAddress()));
}
private void invokeCallbackAndFinish(int result) {
if (mCallback != null) {
try {
mCallback.onComplete(result);
} catch (RemoteException e) {
Slog.e(TAG, "Callback failed:" + e);
}
}
finish();
}
}

View File

@@ -0,0 +1,362 @@
/*
* Copyright (C) 2014 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 android.hardware.hdmi.HdmiControlManager.POWER_STATUS_ON;
import static android.hardware.hdmi.HdmiControlManager.POWER_STATUS_STANDBY;
import static android.hardware.hdmi.HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON;
import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_1;
import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_2;
import static com.android.server.hdmi.Constants.ADDR_TV;
import static com.android.server.hdmi.DeviceSelectAction.STATE_WAIT_FOR_DEVICE_POWER_ON;
import static com.android.server.hdmi.DeviceSelectAction.STATE_WAIT_FOR_REPORT_POWER_STATUS;
import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.hdmi.HdmiPortInfo;
import android.hardware.hdmi.IHdmiControlCallback;
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;
@SmallTest
@RunWith(JUnit4.class)
public class DeviceSelectActionTest {
private static final int PORT_1 = 1;
private static final int PORT_2 = 1;
private static final int PHYSICAL_ADDRESS_PLAYBACK_1 = 0x1000;
private static final int PHYSICAL_ADDRESS_PLAYBACK_2 = 0x2000;
private static final byte[] POWER_ON = new byte[] { POWER_STATUS_ON };
private static final byte[] POWER_STANDBY = new byte[] { POWER_STATUS_STANDBY };
private static final byte[] POWER_TRANSIENT_TO_ON = new byte[] { POWER_STATUS_TRANSIENT_TO_ON };
private static final HdmiCecMessage REPORT_POWER_STATUS_ON = new HdmiCecMessage(
ADDR_PLAYBACK_1, ADDR_TV, Constants.MESSAGE_REPORT_POWER_STATUS, POWER_ON);
private static final HdmiCecMessage REPORT_POWER_STATUS_STANDBY = new HdmiCecMessage(
ADDR_PLAYBACK_1, ADDR_TV, Constants.MESSAGE_REPORT_POWER_STATUS, POWER_STANDBY);
private static final HdmiCecMessage REPORT_POWER_STATUS_TRANSIENT_TO_ON = new HdmiCecMessage(
ADDR_PLAYBACK_1, ADDR_TV, Constants.MESSAGE_REPORT_POWER_STATUS, POWER_TRANSIENT_TO_ON);
private static final HdmiCecMessage SET_STREAM_PATH = HdmiCecMessageBuilder.buildSetStreamPath(
ADDR_TV, PHYSICAL_ADDRESS_PLAYBACK_1);
private static final HdmiDeviceInfo INFO_PLAYBACK_1 = new HdmiDeviceInfo(
ADDR_PLAYBACK_1, PHYSICAL_ADDRESS_PLAYBACK_1, PORT_1, HdmiDeviceInfo.DEVICE_PLAYBACK,
0x1234, "Playback 1",
HdmiControlManager.POWER_STATUS_ON, HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
private static final HdmiDeviceInfo INFO_PLAYBACK_2 = new HdmiDeviceInfo(
ADDR_PLAYBACK_2, PHYSICAL_ADDRESS_PLAYBACK_2, PORT_2, HdmiDeviceInfo.DEVICE_PLAYBACK,
0x1234, "Playback 2",
HdmiControlManager.POWER_STATUS_ON, HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
private HdmiControlService mHdmiControlService;
private HdmiCecController mHdmiCecController;
private HdmiCecLocalDeviceTv mHdmiCecLocalDeviceTv;
private FakeNativeWrapper mNativeWrapper;
private Looper mMyLooper;
private TestLooper mTestLooper = new TestLooper();
private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
@Mock
private IPowerManager mIPowerManagerMock;
@Mock
private IThermalService mIThermalServiceMock;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
Context context = InstrumentationRegistry.getTargetContext();
mMyLooper = mTestLooper.getLooper();
PowerManager powerManager = new PowerManager(context, mIPowerManagerMock,
mIThermalServiceMock, new Handler(mMyLooper));
HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(context);
mHdmiControlService =
new HdmiControlService(InstrumentationRegistry.getTargetContext()) {
@Override
boolean isControlEnabled() {
return true;
}
@Override
void wakeUp() {
}
@Override
protected void writeStringSystemProperty(String key, String value) {
// do nothing
}
@Override
boolean isPowerStandbyOrTransient() {
return false;
}
@Override
protected PowerManager getPowerManager() {
return powerManager;
}
@Override
protected HdmiCecConfig getHdmiCecConfig() {
return hdmiCecConfig;
}
};
mHdmiCecLocalDeviceTv = new HdmiCecLocalDeviceTv(mHdmiControlService);
mHdmiCecLocalDeviceTv.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(mHdmiCecLocalDeviceTv);
HdmiPortInfo[] hdmiPortInfos = new HdmiPortInfo[2];
hdmiPortInfos[0] =
new HdmiPortInfo(1, HdmiPortInfo.PORT_INPUT, PHYSICAL_ADDRESS_PLAYBACK_1,
true, false, false);
hdmiPortInfos[1] =
new HdmiPortInfo(2, HdmiPortInfo.PORT_INPUT, PHYSICAL_ADDRESS_PLAYBACK_2,
true, false, false);
mNativeWrapper.setPortInfo(hdmiPortInfos);
mHdmiControlService.initService();
mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
mNativeWrapper.setPhysicalAddress(0x0000);
mTestLooper.dispatchAll();
mNativeWrapper.clearResultMessages();
mHdmiControlService.getHdmiCecNetwork().addCecDevice(INFO_PLAYBACK_1);
mHdmiControlService.getHdmiCecNetwork().addCecDevice(INFO_PLAYBACK_2);
}
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);
}
}
private DeviceSelectAction createDeviceSelectAction(TestActionTimer actionTimer,
TestCallback callback,
boolean isCec20) {
HdmiDeviceInfo hdmiDeviceInfo =
mHdmiControlService.getHdmiCecNetwork().getCecDeviceInfo(ADDR_PLAYBACK_1);
DeviceSelectAction action = new DeviceSelectAction(mHdmiCecLocalDeviceTv,
hdmiDeviceInfo, callback, isCec20);
action.setActionTimer(actionTimer);
return action;
}
@Test
public void testDeviceSelect_DeviceInPowerOnStatus_Cec14b() {
// TV was watching playback2 device connected at port 2, and wants to select
// playback1.
TestActionTimer actionTimer = new TestActionTimer();
TestCallback callback = new TestCallback();
DeviceSelectAction action = createDeviceSelectAction(actionTimer, callback,
/*isCec20=*/false);
mHdmiCecLocalDeviceTv.updateActiveSource(ADDR_PLAYBACK_2, PHYSICAL_ADDRESS_PLAYBACK_2,
"testDeviceSelect");
action.start();
mTestLooper.dispatchAll();
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(SET_STREAM_PATH);
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
action.processCommand(REPORT_POWER_STATUS_ON);
mTestLooper.dispatchAll();
assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
}
@Test
public void testDeviceSelect_DeviceInStandbyStatus_Cec14b() {
mHdmiCecLocalDeviceTv.updateActiveSource(ADDR_PLAYBACK_2, PHYSICAL_ADDRESS_PLAYBACK_2,
"testDeviceSelect");
TestActionTimer actionTimer = new TestActionTimer();
TestCallback callback = new TestCallback();
DeviceSelectAction action = createDeviceSelectAction(actionTimer, callback,
/*isCec20=*/false);
action.start();
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
action.processCommand(REPORT_POWER_STATUS_STANDBY);
mTestLooper.dispatchAll();
HdmiCecMessage userControlPressed = HdmiCecMessageBuilder.buildUserControlPressed(
ADDR_TV, ADDR_PLAYBACK_1, HdmiCecKeycode.CEC_KEYCODE_POWER);
assertThat(mNativeWrapper.getResultMessages()).contains(userControlPressed);
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_DEVICE_POWER_ON);
action.handleTimerEvent(STATE_WAIT_FOR_DEVICE_POWER_ON);
action.processCommand(REPORT_POWER_STATUS_ON);
mTestLooper.dispatchAll();
assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
}
@Test
public void testDeviceSelect_DeviceInStandbyStatusWithSomeTimeouts_Cec14b() {
mHdmiCecLocalDeviceTv.updateActiveSource(ADDR_PLAYBACK_2, PHYSICAL_ADDRESS_PLAYBACK_2,
"testDeviceSelect");
TestActionTimer actionTimer = new TestActionTimer();
TestCallback callback = new TestCallback();
DeviceSelectAction action = createDeviceSelectAction(actionTimer, callback,
/*isCec20=*/false);
action.start();
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
action.processCommand(REPORT_POWER_STATUS_STANDBY);
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_DEVICE_POWER_ON);
action.handleTimerEvent(STATE_WAIT_FOR_DEVICE_POWER_ON);
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
action.processCommand(REPORT_POWER_STATUS_TRANSIENT_TO_ON);
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_DEVICE_POWER_ON);
action.handleTimerEvent(STATE_WAIT_FOR_DEVICE_POWER_ON);
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
action.processCommand(REPORT_POWER_STATUS_ON);
mTestLooper.dispatchAll();
assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
}
@Test
public void testDeviceSelect_DeviceInStandbyAfterTimeoutForReportPowerStatus_Cec14b() {
mHdmiCecLocalDeviceTv.updateActiveSource(ADDR_PLAYBACK_2, PHYSICAL_ADDRESS_PLAYBACK_2,
"testDeviceSelect");
TestActionTimer actionTimer = new TestActionTimer();
TestCallback callback = new TestCallback();
DeviceSelectAction action = createDeviceSelectAction(actionTimer, callback,
/*isCec20=*/false);
action.start();
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
action.processCommand(REPORT_POWER_STATUS_STANDBY);
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_DEVICE_POWER_ON);
action.handleTimerEvent(STATE_WAIT_FOR_DEVICE_POWER_ON);
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
action.processCommand(REPORT_POWER_STATUS_TRANSIENT_TO_ON);
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_DEVICE_POWER_ON);
action.handleTimerEvent(STATE_WAIT_FOR_DEVICE_POWER_ON);
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
action.handleTimerEvent(STATE_WAIT_FOR_REPORT_POWER_STATUS);
// Give up getting power status, and just send <Set Stream Path>
mTestLooper.dispatchAll();
assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
}
@Test
public void testDeviceSelect_DeviceInPowerOnStatus_Cec20() {
mHdmiControlService.getHdmiCecNetwork().updateDevicePowerStatus(ADDR_PLAYBACK_1,
HdmiControlManager.POWER_STATUS_ON);
TestActionTimer actionTimer = new TestActionTimer();
TestCallback callback = new TestCallback();
DeviceSelectAction action = createDeviceSelectAction(actionTimer, callback,
/*isCec20=*/true);
mHdmiCecLocalDeviceTv.updateActiveSource(ADDR_PLAYBACK_2, PHYSICAL_ADDRESS_PLAYBACK_2,
"testDeviceSelect");
action.start();
mTestLooper.dispatchAll();
assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
}
@Test
public void testDeviceSelect_DeviceInPowerUnknownStatus_Cec20() {
mHdmiControlService.getHdmiCecNetwork().updateDevicePowerStatus(ADDR_PLAYBACK_1,
HdmiControlManager.POWER_STATUS_UNKNOWN);
TestActionTimer actionTimer = new TestActionTimer();
TestCallback callback = new TestCallback();
DeviceSelectAction action = createDeviceSelectAction(actionTimer, callback,
/*isCec20=*/true);
mHdmiCecLocalDeviceTv.updateActiveSource(ADDR_PLAYBACK_2, PHYSICAL_ADDRESS_PLAYBACK_2,
"testDeviceSelect");
action.start();
mTestLooper.dispatchAll();
assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
action.processCommand(REPORT_POWER_STATUS_ON);
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
}
@Test
public void testDeviceSelect_DeviceInStandbyStatus_Cec20() {
mHdmiControlService.getHdmiCecNetwork().updateDevicePowerStatus(ADDR_PLAYBACK_1,
HdmiControlManager.POWER_STATUS_STANDBY);
mHdmiCecLocalDeviceTv.updateActiveSource(ADDR_PLAYBACK_2, PHYSICAL_ADDRESS_PLAYBACK_2,
"testDeviceSelect");
TestActionTimer actionTimer = new TestActionTimer();
TestCallback callback = new TestCallback();
DeviceSelectAction action = createDeviceSelectAction(actionTimer, callback,
/*isCec20=*/true);
action.start();
mTestLooper.dispatchAll();
assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
action.processCommand(REPORT_POWER_STATUS_STANDBY);
mTestLooper.dispatchAll();
HdmiCecMessage userControlPressed = HdmiCecMessageBuilder.buildUserControlPressed(
ADDR_TV, ADDR_PLAYBACK_1, HdmiCecKeycode.CEC_KEYCODE_POWER);
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(userControlPressed);
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_DEVICE_POWER_ON);
action.handleTimerEvent(STATE_WAIT_FOR_DEVICE_POWER_ON);
action.processCommand(REPORT_POWER_STATUS_ON);
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
}
}