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.google.common.truth.Truth.assertThat;
19 
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertTrue;
22 
23 import android.annotation.Nullable;
24 import android.content.Context;
25 import android.hardware.hdmi.HdmiDeviceInfo;
26 import android.hardware.tv.cec.V1_0.SendMessageResult;
27 import android.os.Looper;
28 import android.os.test.TestLooper;
29 import android.platform.test.annotations.Presubmit;
30 
31 import androidx.test.InstrumentationRegistry;
32 import androidx.test.filters.SmallTest;
33 
34 import org.junit.Before;
35 import org.junit.Ignore;
36 import org.junit.Test;
37 import org.junit.runner.RunWith;
38 import org.junit.runners.JUnit4;
39 
40 import java.util.Collections;
41 
42 /** Tests for {@link SystemAudioInitiationActionFromAvr} */
43 @SmallTest
44 @Presubmit
45 @RunWith(JUnit4.class)
46 public class SystemAudioInitiationActionFromAvrTest {
47 
48     private HdmiCecLocalDeviceAudioSystem mHdmiCecLocalDeviceAudioSystem;
49     private FakePowerManagerWrapper mPowerManager;
50     private TestLooper mTestLooper = new TestLooper();
51 
52     private boolean mShouldDispatchActiveSource;
53     private boolean mTvSystemAudioModeSupport;
54     private int mTryCountBeforeSucceed;
55     private HdmiDeviceInfo mDeviceInfoForTests;
56 
57     private int mMsgRequestActiveSourceCount;
58     private int mMsgSetSystemAudioModeCount;
59     private int mQueryTvSystemAudioModeSupportCount;
60     private boolean mArcEnabled;
61     private boolean mIsPlaybackDevice;
62     private boolean mBroadcastActiveSource;
63 
64     @Before
SetUp()65     public void SetUp() {
66         mDeviceInfoForTests = HdmiDeviceInfo.hardwarePort(1001, 1234);
67 
68         Context context = InstrumentationRegistry.getTargetContext();
69 
70         FakeAudioFramework audioFramework = new FakeAudioFramework();
71 
72         HdmiControlService hdmiControlService = new HdmiControlService(context,
73                 Collections.emptyList(), audioFramework.getAudioManager(),
74                 audioFramework.getAudioDeviceVolumeManager()) {
75                     @Override
76                     void sendCecCommand(
77                             HdmiCecMessage command, @Nullable SendMessageCallback callback) {
78                         switch (command.getOpcode()) {
79                             case Constants.MESSAGE_REQUEST_ACTIVE_SOURCE:
80                                 mMsgRequestActiveSourceCount++;
81                                 if (mTryCountBeforeSucceed >= mMsgRequestActiveSourceCount
82                                         && callback != null) {
83                                     callback.onSendCompleted(SendMessageResult.NACK);
84                                     break;
85                                 }
86                                 if (mShouldDispatchActiveSource) {
87                                     mHdmiCecLocalDeviceAudioSystem.dispatchMessage(
88                                             HdmiCecMessageBuilder.buildActiveSource(
89                                                     Constants.ADDR_TV, 1002));
90                                 }
91                                 break;
92                             case Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE:
93                                 mMsgSetSystemAudioModeCount++;
94                                 if (mTryCountBeforeSucceed >= mMsgSetSystemAudioModeCount
95                                         && callback != null) {
96                                     callback.onSendCompleted(SendMessageResult.NACK);
97                                 }
98                                 break;
99                             case Constants.MESSAGE_INITIATE_ARC:
100                                 break;
101                         }
102                     }
103 
104                     @Override
105                     boolean isPowerStandby() {
106                         return false;
107                     }
108 
109                     @Override
110                     boolean isAddressAllocated() {
111                         return true;
112                     }
113 
114                     @Override
115                     protected void writeStringSystemProperty(String key, String value) {
116                     }
117 
118                     @Override
119                     int getPhysicalAddress() {
120                         return 0;
121                     }
122 
123                     @Override
124                     boolean isPlaybackDevice() {
125                         return mIsPlaybackDevice;
126                     }
127 
128                     @Override
129                     public void setAndBroadcastActiveSourceFromOneDeviceType(
130                             int sourceAddress, int physicalAddress, String caller) {
131                         mBroadcastActiveSource = true;
132                     }
133 
134                     @Override
135                     int pathToPortId(int path) {
136                         return -1;
137                     }
138                 };
139 
140         Looper looper = mTestLooper.getLooper();
141         hdmiControlService.setIoLooper(looper);
142         hdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(context));
143         hdmiControlService.setDeviceConfig(new FakeDeviceConfigWrapper());
144         HdmiCecController.NativeWrapper nativeWrapper = new FakeNativeWrapper();
145         HdmiCecController hdmiCecController = HdmiCecController.createWithNativeWrapper(
146                 hdmiControlService, nativeWrapper, hdmiControlService.getAtomWriter());
147         hdmiControlService.setCecController(hdmiCecController);
148         hdmiControlService.initService();
149         mPowerManager = new FakePowerManagerWrapper(context);
150         hdmiControlService.setPowerManager(mPowerManager);
151         mHdmiCecLocalDeviceAudioSystem =
152                 new HdmiCecLocalDeviceAudioSystem(hdmiControlService) {
153                     @Override
154                     void queryTvSystemAudioModeSupport(
155                             TvSystemAudioModeSupportedCallback callback) {
156                         mQueryTvSystemAudioModeSupportCount++;
157                         if (callback != null) {
158                             callback.onResult(mTvSystemAudioModeSupport);
159                         }
160                     }
161 
162                     @Override
163                     HdmiDeviceInfo getDeviceInfo() {
164                         return mDeviceInfoForTests;
165                     }
166 
167                     @Override
168                     void setArcStatus(boolean enabled) {
169                         mArcEnabled = enabled;
170                     }
171                 };
172         mHdmiCecLocalDeviceAudioSystem.init();
173         mHdmiCecLocalDeviceAudioSystem.setDeviceInfo(mDeviceInfoForTests);
174     }
175 
176     @Test
testNoActiveSourceMessageReceived()177     public void testNoActiveSourceMessageReceived() {
178         resetTestVariables();
179         mShouldDispatchActiveSource = false;
180 
181         assertThat(mHdmiCecLocalDeviceAudioSystem.getActiveSource().physicalAddress)
182                 .isEqualTo(Constants.INVALID_PHYSICAL_ADDRESS);
183 
184         mHdmiCecLocalDeviceAudioSystem.addAndStartAction(
185                 new SystemAudioInitiationActionFromAvr(mHdmiCecLocalDeviceAudioSystem));
186         mTestLooper.dispatchAll();
187 
188         assertThat(mMsgRequestActiveSourceCount).isEqualTo(1);
189         assertThat(mMsgSetSystemAudioModeCount).isEqualTo(0);
190         assertThat(mQueryTvSystemAudioModeSupportCount).isEqualTo(0);
191         assertFalse(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated());
192 
193         assertThat(mHdmiCecLocalDeviceAudioSystem.getActiveSource().physicalAddress)
194                 .isEqualTo(Constants.INVALID_PHYSICAL_ADDRESS);
195     }
196 
197     @Test
testTvNotSupport()198     public void testTvNotSupport() {
199         resetTestVariables();
200         mShouldDispatchActiveSource = true;
201         mTvSystemAudioModeSupport = false;
202 
203         mHdmiCecLocalDeviceAudioSystem.addAndStartAction(
204                 new SystemAudioInitiationActionFromAvr(mHdmiCecLocalDeviceAudioSystem));
205         mTestLooper.dispatchAll();
206 
207         assertThat(mMsgRequestActiveSourceCount).isEqualTo(1);
208         assertThat(mMsgSetSystemAudioModeCount).isEqualTo(0);
209         assertThat(mQueryTvSystemAudioModeSupportCount).isEqualTo(1);
210         assertFalse(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated());
211     }
212 
213     @Test
214     @Ignore("b/120845532")
testTvSupport()215     public void testTvSupport() {
216         resetTestVariables();
217         mShouldDispatchActiveSource = true;
218         mTvSystemAudioModeSupport = true;
219 
220         mHdmiCecLocalDeviceAudioSystem.addAndStartAction(
221                 new SystemAudioInitiationActionFromAvr(mHdmiCecLocalDeviceAudioSystem));
222         mTestLooper.dispatchAll();
223 
224         assertThat(mMsgRequestActiveSourceCount).isEqualTo(1);
225         assertThat(mMsgSetSystemAudioModeCount).isEqualTo(1);
226         assertThat(mQueryTvSystemAudioModeSupportCount).isEqualTo(1);
227         assertTrue(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated());
228 
229         assertThat(mHdmiCecLocalDeviceAudioSystem.getActiveSource().physicalAddress)
230             .isEqualTo(1002);
231     }
232 
233     @Test
testKnownActiveSource()234     public void testKnownActiveSource() {
235         resetTestVariables();
236         mTvSystemAudioModeSupport = true;
237         mHdmiCecLocalDeviceAudioSystem.getActiveSource().physicalAddress = 1001;
238 
239         mHdmiCecLocalDeviceAudioSystem.addAndStartAction(
240                 new SystemAudioInitiationActionFromAvr(mHdmiCecLocalDeviceAudioSystem));
241         mTestLooper.dispatchAll();
242 
243         assertThat(mMsgRequestActiveSourceCount).isEqualTo(0);
244         assertThat(mMsgSetSystemAudioModeCount).isEqualTo(1);
245         assertThat(mQueryTvSystemAudioModeSupportCount).isEqualTo(1);
246         assertTrue(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated());
247     }
248 
249     @Test
testRetry()250     public void testRetry() {
251         resetTestVariables();
252         mTvSystemAudioModeSupport = true;
253         mShouldDispatchActiveSource = true;
254         mTryCountBeforeSucceed = 3;
255         assertThat(mTryCountBeforeSucceed)
256                 .isAtMost(SystemAudioInitiationActionFromAvr.MAX_RETRY_COUNT);
257         assertThat(mHdmiCecLocalDeviceAudioSystem.getActiveSource().physicalAddress)
258                 .isEqualTo(Constants.INVALID_PHYSICAL_ADDRESS);
259 
260         mHdmiCecLocalDeviceAudioSystem.addAndStartAction(
261                 new SystemAudioInitiationActionFromAvr(mHdmiCecLocalDeviceAudioSystem));
262         mTestLooper.dispatchAll();
263 
264         assertThat(mMsgRequestActiveSourceCount).isEqualTo(4);
265         assertThat(mMsgSetSystemAudioModeCount).isEqualTo(4);
266         assertThat(mQueryTvSystemAudioModeSupportCount).isEqualTo(1);
267         assertTrue(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated());
268     }
269 
270     @Ignore("b/120845532")
271     @Test
testIsPlaybackDevice_cannotReceiveActiveSource()272     public void testIsPlaybackDevice_cannotReceiveActiveSource() {
273         resetTestVariables();
274         mIsPlaybackDevice = true;
275         assertThat(mHdmiCecLocalDeviceAudioSystem.getActiveSource().physicalAddress)
276             .isEqualTo(Constants.INVALID_PHYSICAL_ADDRESS);
277 
278         mHdmiCecLocalDeviceAudioSystem.addAndStartAction(
279                 new SystemAudioInitiationActionFromAvr(mHdmiCecLocalDeviceAudioSystem));
280         mTestLooper.dispatchAll();
281 
282         assertThat(mMsgRequestActiveSourceCount).isEqualTo(1);
283         assertThat(mBroadcastActiveSource).isTrue();
284         assertThat(mQueryTvSystemAudioModeSupportCount).isEqualTo(1);
285         assertThat(mMsgSetSystemAudioModeCount).isEqualTo(1);
286         assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isTrue();
287     }
288 
resetTestVariables()289     private void resetTestVariables() {
290         mMsgRequestActiveSourceCount = 0;
291         mMsgSetSystemAudioModeCount = 0;
292         mQueryTvSystemAudioModeSupportCount = 0;
293         mTryCountBeforeSucceed = 0;
294         mIsPlaybackDevice = false;
295         mBroadcastActiveSource = false;
296         mHdmiCecLocalDeviceAudioSystem.getActiveSource().physicalAddress =
297                 Constants.INVALID_PHYSICAL_ADDRESS;
298     }
299 }
300