1 /*
2  * Copyright (C) 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 import android.hdmicec.cts.error.CecClientWrapperException;
28 import android.hdmicec.cts.error.ErrorCodes;
29 
30 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
31 
32 import org.junit.Before;
33 import org.junit.Rule;
34 import org.junit.Test;
35 import org.junit.rules.RuleChain;
36 import org.junit.runner.RunWith;
37 
38 import java.util.concurrent.TimeUnit;
39 
40 /** HDMI CEC Routing control tests (Section 11.1.2) */
41 @RunWith(DeviceJUnit4ClassRunner.class)
42 public final class HdmiCecRoutingControlTest extends BaseHdmiCecCtsTest {
43 
44     private static final int WAIT_TIME_MS = 1000;
45 
46     @Rule
47     public RuleChain ruleChain =
48             RuleChain.outerRule(CecRules.requiresCec(this))
49                     .around(CecRules.requiresLeanback(this))
50                     .around(CecRules.requiresPhysicalDevice(this))
51                     .around(CecRules.requiresDeviceType(this, HdmiCecConstants.CEC_DEVICE_TYPE_TV))
52                     .around(hdmiCecClient);
53 
HdmiCecRoutingControlTest()54     public HdmiCecRoutingControlTest() {
55         super(HdmiCecConstants.CEC_DEVICE_TYPE_TV, "-t", "r", "-t", "t", "-t", "p");
56     }
57 
58     @Before
checkForInitialActiveSourceMessage()59     public void checkForInitialActiveSourceMessage() throws CecClientWrapperException {
60         try {
61             /*
62              * Check for the broadcasted <ACTIVE_SOURCE> message from Recorder_1, which was sent as
63              * a response to <SET_STREAM_PATH> message from the TV.
64              */
65             String message =
66                     hdmiCecClient.checkExpectedMessageFromClient(
67                             LogicalAddress.RECORDER_1, CecOperand.ACTIVE_SOURCE);
68         } catch (CecClientWrapperException e) {
69             if (e.getErrorCode() != ErrorCodes.CecMessageNotFound) {
70                 throw e;
71             } else {
72                 /*
73                  * In case the TV does not send <Set Stream Path> to CEC adapter, or the client does
74                  * not make recorder active source, broadcast an <Active Source> message from the
75                  * adapter.
76                  */
77                 hdmiCecClient.broadcastActiveSource(
78                         hdmiCecClient.getSelfDevice(), hdmiCecClient.getPhysicalAddress());
79                 try {
80                     TimeUnit.MILLISECONDS.sleep(WAIT_TIME_MS);
81                 } catch (InterruptedException ex) {
82                     // Do nothing
83                 }
84             }
85         }
86     }
87 
88     /**
89      * Test 11.1.2-1
90      *
91      * <p>Tests that the device sends a {@code <Set Stream Path>} message if the user selects
92      * another source device.
93      */
94     @Test
cect_11_1_2_1_DutSendsSetStreamPathMessage()95     public void cect_11_1_2_1_DutSendsSetStreamPathMessage() throws Exception {
96         // Broadcast a <Report Physical Address> [2.1.0.0] message from Logical Address 3.
97         hdmiCecClient.broadcastReportPhysicalAddress(LogicalAddress.TUNER_1, 0x2100);
98         // Broadcast a <Report Physical Address> [2.2.0.0] message from Logical Address 4.
99         hdmiCecClient.broadcastReportPhysicalAddress(LogicalAddress.PLAYBACK_1, 0x2200);
100         TimeUnit.SECONDS.sleep(2);
101         // Make the device with LA 4 as the active source.
102         HdmiControlManagerUtility.selectDevice(
103                 this, getDevice(), LogicalAddress.PLAYBACK_1.toString());
104         String message = hdmiCecClient.checkExpectedOutput(CecOperand.SET_STREAM_PATH);
105         assertWithMessage("Device has not sent a Set Stream Path message to the selected device")
106                 .that(CecMessage.getParams(message))
107                 .isEqualTo(0x2200);
108     }
109 
110     /**
111      * Test 11.1.2-2
112      *
113      * <p>Tests that the device doesn't respond to a {@code <Request Active Source>} message when it
114      * is not the current active source.
115      */
116     @Test
cect_11_1_2_2_DutDoesNotRespondToRequestActiveSourceMessage()117     public void cect_11_1_2_2_DutDoesNotRespondToRequestActiveSourceMessage() throws Exception {
118         // Ensure that DUT is the active source.
119         HdmiControlManagerUtility.selectDevice(this, getDevice(), LogicalAddress.TV.toString());
120         hdmiCecClient.checkExpectedOutput(CecOperand.ACTIVE_SOURCE);
121         // Broadcast an active source from the client device.
122         hdmiCecClient.broadcastActiveSource(hdmiCecClient.getSelfDevice());
123         hdmiCecClient.sendCecMessage(
124                 hdmiCecClient.getSelfDevice(),
125                 LogicalAddress.BROADCAST,
126                 CecOperand.REQUEST_ACTIVE_SOURCE);
127         hdmiCecClient.checkOutputDoesNotContainMessage(
128                 LogicalAddress.BROADCAST, CecOperand.ACTIVE_SOURCE);
129     }
130 
131     /**
132      * Test 11.1.2-3
133      *
134      * <p>Tests that the device responds correctly to a {@code <Request Active Source>} message when
135      * it is the current active source.
136      */
137     @Test
cect_11_1_2_3_DutDoesRespondToRequestActiveSourceMessage()138     public void cect_11_1_2_3_DutDoesRespondToRequestActiveSourceMessage() throws Exception {
139         // Make the TV device the active source.
140         HdmiControlManagerUtility.selectDevice(this, getDevice(), LogicalAddress.TV.toString());
141         hdmiCecClient.sendCecMessage(
142                 hdmiCecClient.getSelfDevice(),
143                 LogicalAddress.BROADCAST,
144                 CecOperand.REQUEST_ACTIVE_SOURCE);
145         hdmiCecClient.checkExpectedOutput(CecOperand.ACTIVE_SOURCE);
146     }
147 
148     /**
149      * Test 11.1.2-4
150      *
151      * <p>Tests that the device accepts {@code <Inactive Source>} message.
152      */
153     @Test
cect_11_1_2_4_DutAcceptsInactiveSourceMessage()154     public void cect_11_1_2_4_DutAcceptsInactiveSourceMessage() throws Exception {
155         hdmiCecClient.sendCecMessage(
156                 hdmiCecClient.getSelfDevice(),
157                 LogicalAddress.TV,
158                 CecOperand.INACTIVE_SOURCE,
159                 CecMessage.formatParams(hdmiCecClient.getPhysicalAddress()));
160         hdmiCecClient.checkOutputDoesNotContainMessage(
161                 hdmiCecClient.getSelfDevice(),
162                 CecOperand.FEATURE_ABORT,
163                 CecMessage.formatParams(CecOperand.INACTIVE_SOURCE.toString()));
164     }
165 }
166