1 /* 2 * Copyright 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.hdmicec.cts.tv; 18 19 import static com.google.common.truth.Truth.assertWithMessage; 20 21 import android.hdmicec.cts.BaseHdmiCecCtsTest; 22 import android.hdmicec.cts.CecMessage; 23 import android.hdmicec.cts.CecOperand; 24 import android.hdmicec.cts.HdmiCecConstants; 25 import android.hdmicec.cts.HdmiControlManagerUtility; 26 import android.hdmicec.cts.LogicalAddress; 27 28 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; 29 30 import org.junit.Rule; 31 import org.junit.Test; 32 import org.junit.rules.RuleChain; 33 import org.junit.runner.RunWith; 34 35 import java.util.ArrayList; 36 import java.util.List; 37 import java.util.concurrent.TimeUnit; 38 39 /** HDMI CEC test to test One Touch Play features (Section 11.1.1) */ 40 @RunWith(DeviceJUnit4ClassRunner.class) 41 public class HdmiCecTvOneTouchPlayTest extends BaseHdmiCecCtsTest { 42 43 private static final int WAIT_TIME_MS = 1000; 44 45 private static final int SLEEP_TIMESTEP_SECONDS = 1; 46 private static final int POWER_TRANSITION_WAIT_TIME = 10; 47 private static final int MAX_POWER_TRANSITION_WAIT_TIME = 15; 48 49 List<LogicalAddress> testDevices = new ArrayList<>(); 50 HdmiCecTvOneTouchPlayTest()51 public HdmiCecTvOneTouchPlayTest() { 52 /* Start the client as recorder, tuner and playback devices */ 53 super(HdmiCecConstants.CEC_DEVICE_TYPE_TV, "-t", "r", "-t", "t", "-t", "p"); 54 testDevices.add(LogicalAddress.RECORDER_1); 55 testDevices.add(LogicalAddress.TUNER_1); 56 testDevices.add(LogicalAddress.PLAYBACK_1); 57 } 58 59 @Rule 60 public RuleChain ruleChain = 61 RuleChain.outerRule(CecRules.requiresCec(this)) 62 .around(CecRules.requiresLeanback(this)) 63 .around(CecRules.requiresPhysicalDevice(this)) 64 .around(CecRules.requiresDeviceType(this, HdmiCecConstants.CEC_DEVICE_TYPE_TV)) 65 .around(hdmiCecClient); 66 67 /** 68 * Test 11.1.1-1 69 * 70 * <p>Tests that the DUT responds to {@code <Image View On>} message correctly when the message 71 * is sent from logical addresses 0x1, 0x3 and 0x4 72 */ 73 @Test cect_11_1_1_1_RespondToImageViewOn()74 public void cect_11_1_1_1_RespondToImageViewOn() throws Exception { 75 for (LogicalAddress testDevice : testDevices) { 76 hdmiCecClient.sendCecMessage(testDevice, LogicalAddress.TV, CecOperand.IMAGE_VIEW_ON); 77 TimeUnit.MILLISECONDS.sleep(WAIT_TIME_MS); 78 hdmiCecClient.broadcastActiveSource(testDevice, hdmiCecClient.getPhysicalAddress()); 79 hdmiCecClient.checkOutputDoesNotContainMessage(testDevice, CecOperand.FEATURE_ABORT); 80 assertWithMessage( 81 "Device has not registered expected logical address as active source.") 82 .that(getDumpsysActiveSourceLogicalAddress()) 83 .isEqualTo(testDevice); 84 } 85 } 86 87 /** 88 * Test 11.1.1-2 89 * 90 * <p>Tests that the DUT responds to {@code <Text View On>} message correctly when the message 91 * is sent from logical addresses 0x1, 0x3 and 0x4 92 */ 93 @Test cect_11_1_1_2_RespondToTextViewOn()94 public void cect_11_1_1_2_RespondToTextViewOn() throws Exception { 95 for (LogicalAddress testDevice : testDevices) { 96 hdmiCecClient.sendCecMessage(testDevice, LogicalAddress.TV, CecOperand.TEXT_VIEW_ON); 97 TimeUnit.MILLISECONDS.sleep(WAIT_TIME_MS); 98 hdmiCecClient.broadcastActiveSource(testDevice, hdmiCecClient.getPhysicalAddress()); 99 hdmiCecClient.checkOutputDoesNotContainMessage(testDevice, CecOperand.FEATURE_ABORT); 100 assertWithMessage( 101 "Device has not registered expected logical address as active source.") 102 .that(getDumpsysActiveSourceLogicalAddress()) 103 .isEqualTo(testDevice); 104 } 105 } 106 107 /** 108 * Test 11.1.1-5 109 * 110 * <p>Tests that the DUT broadcasts an {@code <Active Source>} message when changing to an 111 * internal source from previously displaying an external source. 112 */ 113 @Test cect_11_1_1_5_DutBroadcastsActiveSourceWhenChangingToInternal()114 public void cect_11_1_1_5_DutBroadcastsActiveSourceWhenChangingToInternal() throws Exception { 115 // Ensure that an external source is the active source. 116 try { 117 /* 118 * Check for the broadcasted <ACTIVE_SOURCE> message from Recorder_1, which was sent as 119 * a response to <SET_STREAM_PATH> message from the TV. 120 */ 121 String message = 122 hdmiCecClient.checkExpectedMessageFromClient( 123 LogicalAddress.RECORDER_1, CecOperand.ACTIVE_SOURCE); 124 } catch (Exception e) { 125 /* 126 * In case the TV does not send <Set Stream Path> to CEC adapter, or the client does 127 * not make recorder active source, broadcast an <Active Source> message from the 128 * adapter. 129 */ 130 hdmiCecClient.broadcastActiveSource( 131 LogicalAddress.RECORDER_1, hdmiCecClient.getPhysicalAddress()); 132 TimeUnit.MILLISECONDS.sleep(WAIT_TIME_MS); 133 } 134 // Make the TV device the active source. 135 HdmiControlManagerUtility.selectDevice(this, getDevice(), LogicalAddress.TV.toString()); 136 hdmiCecClient.checkExpectedOutput(LogicalAddress.BROADCAST, CecOperand.ACTIVE_SOURCE); 137 } 138 139 /** 140 * Test 11.1.1-3 141 * 142 * <p>Tests that the DUT powers on in response to an {@code <Image View On>} message when in 143 * standby 144 */ 145 @Test cect_11_1_1_3_ImageViewOnWhenInStandby()146 public void cect_11_1_1_3_ImageViewOnWhenInStandby() throws Exception { 147 try { 148 getDevice().reboot(); 149 sendDeviceToSleep(); 150 assertDevicePowerStatus(HdmiCecConstants.CEC_POWER_STATUS_STANDBY); 151 /* Get the first device the client has started as */ 152 LogicalAddress testDevice = testDevices.get(0); 153 hdmiCecClient.sendCecMessage(testDevice, LogicalAddress.TV, CecOperand.IMAGE_VIEW_ON); 154 assertDevicePowerStatus(HdmiCecConstants.CEC_POWER_STATUS_ON); 155 } finally { 156 wakeUpDevice(); 157 } 158 } 159 160 /** 161 * Test 11.1.1-4 162 * 163 * <p>Tests that the DUT powers on in response to an {@code <Text View On>} message when in 164 * standby 165 */ 166 @Test cect_11_1_1_4_TextViewOnWhenInStandby()167 public void cect_11_1_1_4_TextViewOnWhenInStandby() throws Exception { 168 try { 169 getDevice().reboot(); 170 sendDeviceToSleep(); 171 assertDevicePowerStatus(HdmiCecConstants.CEC_POWER_STATUS_STANDBY); 172 /* Get the first device the client has started as */ 173 LogicalAddress testDevice = testDevices.get(0); 174 hdmiCecClient.sendCecMessage(testDevice, LogicalAddress.TV, CecOperand.TEXT_VIEW_ON); 175 assertDevicePowerStatus(HdmiCecConstants.CEC_POWER_STATUS_ON); 176 } finally { 177 wakeUpDevice(); 178 } 179 } 180 assertDevicePowerStatus(int powerStatus)181 private void assertDevicePowerStatus(int powerStatus) throws Exception { 182 String[] powerStatusNames = {"ON", "OFF", "IN_TRANSITION_TO_ON", "IN_TRANSITION_TO_OFF"}; 183 LogicalAddress cecClientDevice = hdmiCecClient.getSelfDevice(); 184 int actualPowerStatus; 185 int waitTimeSeconds = POWER_TRANSITION_WAIT_TIME; 186 187 /* Wait for the device to transition */ 188 TimeUnit.SECONDS.sleep(waitTimeSeconds); 189 190 do { 191 TimeUnit.SECONDS.sleep(SLEEP_TIMESTEP_SECONDS); 192 waitTimeSeconds += SLEEP_TIMESTEP_SECONDS; 193 hdmiCecClient.sendCecMessage(cecClientDevice, CecOperand.GIVE_POWER_STATUS); 194 actualPowerStatus = 195 CecMessage.getParams( 196 hdmiCecClient.checkExpectedOutput( 197 cecClientDevice, CecOperand.REPORT_POWER_STATUS)); 198 /* Compare with (powerStatus + 2) to check if it is transitioning to the expected power 199 * status. 200 */ 201 } while (actualPowerStatus == (powerStatus + 2) 202 && waitTimeSeconds <= MAX_POWER_TRANSITION_WAIT_TIME); 203 assertWithMessage( 204 "Device power status is " 205 + powerStatusNames[actualPowerStatus] 206 + " but expected to be " 207 + powerStatusNames[powerStatus]) 208 .that(actualPowerStatus) 209 .isEqualTo(powerStatus); 210 } 211 } 212