1 /*
2  * Copyright (C) 2018 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 package com.android.server.hdmi;
17 
18 import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
19 
20 import static com.google.common.truth.Truth.assertThat;
21 
22 import static org.mockito.Mockito.spy;
23 
24 import android.content.Context;
25 import android.content.ContextWrapper;
26 import android.hardware.hdmi.HdmiControlManager;
27 import android.hardware.hdmi.HdmiDeviceInfo;
28 import android.hardware.hdmi.HdmiPortInfo;
29 import android.os.Looper;
30 import android.os.test.TestLooper;
31 import android.platform.test.annotations.Presubmit;
32 
33 import androidx.test.InstrumentationRegistry;
34 import androidx.test.filters.SmallTest;
35 
36 import com.android.server.SystemService;
37 
38 import org.junit.Before;
39 import org.junit.Test;
40 import org.junit.runner.RunWith;
41 import org.junit.runners.JUnit4;
42 
43 import java.util.Collections;
44 
45 @SmallTest
46 @Presubmit
47 @RunWith(JUnit4.class)
48 /** Tests for {@link HdmiCecPowerStatusController} class. */
49 public class HdmiCecPowerStatusControllerTest {
50 
51     public static final int[] ARRAY_POWER_STATUS = new int[]{HdmiControlManager.POWER_STATUS_ON,
52             HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON,
53             HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY,
54             HdmiControlManager.POWER_STATUS_STANDBY};
55     private HdmiCecPowerStatusController mHdmiCecPowerStatusController;
56     private FakeNativeWrapper mNativeWrapper;
57     private FakePowerManagerWrapper mPowerManager;
58     private TestLooper mTestLooper = new TestLooper();
59     private HdmiControlService mHdmiControlService;
60     private HdmiCecLocalDevicePlayback mHdmiCecLocalDevicePlayback;
61 
62     @Before
setUp()63     public void setUp() throws Exception {
64         Context contextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
65         Looper myLooper = mTestLooper.getLooper();
66 
67         FakeAudioFramework audioFramework = new FakeAudioFramework();
68 
69         mHdmiControlService = new HdmiControlService(contextSpy,
70                 Collections.singletonList(HdmiDeviceInfo.DEVICE_PLAYBACK),
71                 audioFramework.getAudioManager(), audioFramework.getAudioDeviceVolumeManager()) {
72             @Override
73             boolean isCecControlEnabled() {
74                 return true;
75             }
76 
77             @Override
78             boolean isPlaybackDevice() {
79                 return true;
80             }
81 
82             @Override
83             protected void writeStringSystemProperty(String key, String value) {
84                 // do nothing
85             }
86 
87             @Override
88             boolean isPowerStandby() {
89                 return false;
90             }
91         };
92         mHdmiControlService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
93 
94         mHdmiControlService.setIoLooper(myLooper);
95         mHdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(contextSpy));
96         mHdmiControlService.setDeviceConfig(new FakeDeviceConfigWrapper());
97         mNativeWrapper = new FakeNativeWrapper();
98         HdmiCecController hdmiCecController = HdmiCecController.createWithNativeWrapper(
99                 mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
100         mHdmiControlService.setCecController(hdmiCecController);
101         mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
102         HdmiPortInfo[] hdmiPortInfos = new HdmiPortInfo[1];
103         hdmiPortInfos[0] =
104                 new HdmiPortInfo.Builder(1, HdmiPortInfo.PORT_OUTPUT, 0x0000)
105                         .setCecSupported(true)
106                         .setMhlSupported(false)
107                         .setArcSupported(false)
108                         .build();
109         mNativeWrapper.setPortInfo(hdmiPortInfos);
110         mNativeWrapper.setPortConnectionStatus(1, true);
111         mHdmiControlService.initService();
112         mHdmiControlService.onBootPhase(PHASE_SYSTEM_SERVICES_READY);
113         mPowerManager = new FakePowerManagerWrapper(contextSpy);
114         mHdmiControlService.setPowerManager(mPowerManager);
115         mHdmiControlService.getHdmiCecNetwork().initPortInfo();
116         mNativeWrapper.setPhysicalAddress(0x2000);
117         mTestLooper.dispatchAll();
118         mHdmiCecLocalDevicePlayback = mHdmiControlService.playback();
119         mHdmiCecPowerStatusController = new HdmiCecPowerStatusController(mHdmiControlService);
120         mNativeWrapper.clearResultMessages();
121     }
122 
123     @Test
setPowerStatus()124     public void setPowerStatus() {
125         for (int status : ARRAY_POWER_STATUS) {
126             mHdmiCecPowerStatusController.setPowerStatus(status);
127             assertThat(mHdmiCecPowerStatusController.getPowerStatus()).isEqualTo(status);
128         }
129     }
130 
131     @Test
isPowerStatusOn()132     public void isPowerStatusOn() {
133         for (int status : ARRAY_POWER_STATUS) {
134             mHdmiCecPowerStatusController.setPowerStatus(status);
135             assertThat(mHdmiCecPowerStatusController.isPowerStatusOn()).isEqualTo(
136                     HdmiControlManager.POWER_STATUS_ON == status);
137         }
138     }
139 
140     @Test
isPowerStatusStandby()141     public void isPowerStatusStandby() {
142         for (int status : ARRAY_POWER_STATUS) {
143             mHdmiCecPowerStatusController.setPowerStatus(status);
144             assertThat(mHdmiCecPowerStatusController.isPowerStatusStandby()).isEqualTo(
145                     HdmiControlManager.POWER_STATUS_STANDBY == status);
146         }
147     }
148 
149     @Test
isPowerStatusTransientToOn()150     public void isPowerStatusTransientToOn() {
151         for (int status : ARRAY_POWER_STATUS) {
152             mHdmiCecPowerStatusController.setPowerStatus(status);
153             assertThat(mHdmiCecPowerStatusController.isPowerStatusTransientToOn()).isEqualTo(
154                     HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON == status);
155         }
156     }
157 
158     @Test
isPowerStatusTransientToStandby()159     public void isPowerStatusTransientToStandby() {
160         for (int status : ARRAY_POWER_STATUS) {
161             mHdmiCecPowerStatusController.setPowerStatus(status);
162             assertThat(mHdmiCecPowerStatusController.isPowerStatusTransientToStandby()).isEqualTo(
163                     HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY == status);
164         }
165     }
166 
167     @Test
setPowerStatus_doesntSendBroadcast_1_4()168     public void setPowerStatus_doesntSendBroadcast_1_4() {
169         setCecVersion(HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
170         mHdmiCecPowerStatusController.setPowerStatus(HdmiControlManager.POWER_STATUS_ON);
171         mTestLooper.dispatchAll();
172 
173         HdmiCecMessage reportPowerStatus =
174                 HdmiCecMessageBuilder.buildReportPowerStatus(
175                         mHdmiCecLocalDevicePlayback.getDeviceInfo().getLogicalAddress(),
176                         Constants.ADDR_BROADCAST,
177                         HdmiControlManager.POWER_STATUS_ON);
178         assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportPowerStatus);
179     }
180 
181     @Test
setPowerStatus_transient_doesntSendBroadcast_1_4()182     public void setPowerStatus_transient_doesntSendBroadcast_1_4() {
183         setCecVersion(HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
184         mHdmiCecPowerStatusController.setPowerStatus(
185                 HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON);
186         mTestLooper.dispatchAll();
187 
188         HdmiCecMessage reportPowerStatus =
189                 HdmiCecMessageBuilder.buildReportPowerStatus(
190                         mHdmiCecLocalDevicePlayback.getDeviceInfo().getLogicalAddress(),
191                         Constants.ADDR_BROADCAST,
192                         HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON);
193         assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportPowerStatus);
194     }
195 
196     @Test
setPowerStatus_fast_transient_doesntSendBroadcast_1_4()197     public void setPowerStatus_fast_transient_doesntSendBroadcast_1_4() {
198         setCecVersion(HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
199         mHdmiCecPowerStatusController.setPowerStatus(
200                 HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON, false);
201         mTestLooper.dispatchAll();
202 
203         HdmiCecMessage reportPowerStatus =
204                 HdmiCecMessageBuilder.buildReportPowerStatus(
205                         mHdmiCecLocalDevicePlayback.getDeviceInfo().getLogicalAddress(),
206                         Constants.ADDR_BROADCAST,
207                         HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON);
208         assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportPowerStatus);
209     }
210 
211     @Test
setPowerStatus_sendsBroadcast_2_0()212     public void setPowerStatus_sendsBroadcast_2_0() {
213         setCecVersion(HdmiControlManager.HDMI_CEC_VERSION_2_0);
214         mHdmiCecPowerStatusController.setPowerStatus(HdmiControlManager.POWER_STATUS_ON);
215         mTestLooper.dispatchAll();
216 
217         HdmiCecMessage reportPowerStatus =
218                 HdmiCecMessageBuilder.buildReportPowerStatus(
219                         mHdmiCecLocalDevicePlayback.getDeviceInfo().getLogicalAddress(),
220                         Constants.ADDR_BROADCAST,
221                         HdmiControlManager.POWER_STATUS_ON);
222         assertThat(mNativeWrapper.getResultMessages()).contains(reportPowerStatus);
223     }
224 
225     @Test
setPowerStatus_transient_sendsBroadcast_2_0()226     public void setPowerStatus_transient_sendsBroadcast_2_0() {
227         setCecVersion(HdmiControlManager.HDMI_CEC_VERSION_2_0);
228         mHdmiCecPowerStatusController.setPowerStatus(
229                 HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON);
230         mTestLooper.dispatchAll();
231 
232         HdmiCecMessage reportPowerStatus =
233                 HdmiCecMessageBuilder.buildReportPowerStatus(
234                         mHdmiCecLocalDevicePlayback.getDeviceInfo().getLogicalAddress(),
235                         Constants.ADDR_BROADCAST,
236                         HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON);
237         assertThat(mNativeWrapper.getResultMessages()).contains(reportPowerStatus);
238     }
239 
240     @Test
setPowerStatus_fast_transient_doesntSendBroadcast_2_0()241     public void setPowerStatus_fast_transient_doesntSendBroadcast_2_0() {
242         setCecVersion(HdmiControlManager.HDMI_CEC_VERSION_2_0);
243         mHdmiCecPowerStatusController.setPowerStatus(
244                 HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON, false);
245         mTestLooper.dispatchAll();
246 
247         HdmiCecMessage reportPowerStatus =
248                 HdmiCecMessageBuilder.buildReportPowerStatus(
249                         mHdmiCecLocalDevicePlayback.getDeviceInfo().getLogicalAddress(),
250                         Constants.ADDR_BROADCAST,
251                         HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON);
252         assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportPowerStatus);
253     }
254 
setCecVersion(int version)255     private void setCecVersion(int version) {
256         mHdmiControlService.getHdmiCecConfig().setIntValue(
257                 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION, version);
258         mTestLooper.dispatchAll();
259     }
260 }
261