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 import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
20 
21 import static com.google.common.truth.Truth.assertThat;
22 
23 import static org.mockito.Mockito.spy;
24 
25 import android.content.Context;
26 import android.content.ContextWrapper;
27 import android.hardware.hdmi.HdmiControlManager;
28 import android.hardware.hdmi.IHdmiControlCallback;
29 import android.hardware.tv.cec.V1_0.SendMessageResult;
30 import android.os.Looper;
31 import android.os.test.TestLooper;
32 import android.platform.test.annotations.Presubmit;
33 
34 import androidx.test.InstrumentationRegistry;
35 import androidx.test.filters.SmallTest;
36 
37 import org.junit.Before;
38 import org.junit.Test;
39 import org.junit.runner.RunWith;
40 import org.junit.runners.JUnit4;
41 import org.mockito.MockitoAnnotations;
42 
43 import java.util.ArrayList;
44 import java.util.Collections;
45 
46 /** Tests for {@link ArcTerminationActionFromAvr} */
47 @SmallTest
48 @Presubmit
49 @RunWith(JUnit4.class)
50 public class ArcTerminationActionFromAvrTest {
51 
52     private Context mContextSpy;
53     private HdmiCecLocalDeviceAudioSystem mHdmiCecLocalDeviceAudioSystem;
54     private FakePowerManagerWrapper mPowerManager;
55     private TestCallback mCallback;
56     private ArcTerminationActionFromAvr mAction;
57 
58     private FakeNativeWrapper mNativeWrapper;
59 
60     private TestLooper mTestLooper = new TestLooper();
61     private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
62 
63     @Before
setUp()64     public void setUp() throws Exception {
65         MockitoAnnotations.initMocks(this);
66 
67         mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
68 
69         FakeAudioFramework audioFramework = new FakeAudioFramework();
70 
71         HdmiControlService hdmiControlService =
72                 new HdmiControlService(mContextSpy, Collections.emptyList(),
73                         audioFramework.getAudioManager(),
74                         audioFramework.getAudioDeviceVolumeManager()) {
75                     @Override
76                     boolean isPowerStandby() {
77                         return false;
78                     }
79 
80                     @Override
81                     boolean isAddressAllocated() {
82                         return true;
83                     }
84 
85                     @Override
86                     protected void writeStringSystemProperty(String key, String value) {
87                     }
88 
89                     @Override
90                     protected Looper getServiceLooper() {
91                         return mTestLooper.getLooper();
92                     }
93                 };
94 
95         Looper looper = mTestLooper.getLooper();
96         hdmiControlService.setIoLooper(looper);
97         hdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(mContextSpy));
98         hdmiControlService.setDeviceConfig(new FakeDeviceConfigWrapper());
99         mNativeWrapper = new FakeNativeWrapper();
100         HdmiCecController hdmiCecController = HdmiCecController.createWithNativeWrapper(
101                 hdmiControlService, mNativeWrapper, hdmiControlService.getAtomWriter());
102         hdmiControlService.setCecController(hdmiCecController);
103         hdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(hdmiControlService));
104         hdmiControlService.initService();
105         mPowerManager = new FakePowerManagerWrapper(mContextSpy);
106         hdmiControlService.setPowerManager(mPowerManager);
107         mHdmiCecLocalDeviceAudioSystem = new HdmiCecLocalDeviceAudioSystem(hdmiControlService) {
108             @Override
109             protected void setPreferredAddress(int addr) {
110             }
111         };
112         mHdmiCecLocalDeviceAudioSystem.init();
113         mCallback = new TestCallback();
114         mAction = new ArcTerminationActionFromAvr(mHdmiCecLocalDeviceAudioSystem,
115                 mCallback);
116 
117         mLocalDevices.add(mHdmiCecLocalDeviceAudioSystem);
118         hdmiControlService.onBootPhase(PHASE_SYSTEM_SERVICES_READY);
119         hdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
120         mHdmiCecLocalDeviceAudioSystem.setArcStatus(true);
121         mTestLooper.dispatchAll();
122     }
123 
124     private static class TestCallback extends IHdmiControlCallback.Stub {
125         private final ArrayList<Integer> mCallbackResult = new ArrayList<Integer>();
126 
127         @Override
onComplete(int result)128         public void onComplete(int result) {
129             mCallbackResult.add(result);
130         }
131 
getResult()132         private int getResult() {
133             assertThat(mCallbackResult.size()).isEqualTo(1);
134             return mCallbackResult.get(0);
135         }
136     }
137 
138     @Test
testSendMessage_sendFailed()139     public void testSendMessage_sendFailed() {
140         mNativeWrapper.setMessageSendResult(Constants.MESSAGE_TERMINATE_ARC,
141                 SendMessageResult.NACK);
142         mHdmiCecLocalDeviceAudioSystem.addAndStartAction(mAction);
143         mTestLooper.dispatchAll();
144         HdmiCecMessage terminateArc = HdmiCecMessageBuilder.buildTerminateArc(
145                 Constants.ADDR_AUDIO_SYSTEM, Constants.ADDR_TV);
146 
147         assertThat(mNativeWrapper.getResultMessages()).contains(terminateArc);
148 
149         assertThat(mHdmiCecLocalDeviceAudioSystem.isArcEnabled()).isFalse();
150         assertThat(mCallback.getResult()).isEqualTo(HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
151     }
152 
153     @Test
testReportArcTerminated_timeout()154     public void testReportArcTerminated_timeout() {
155         mHdmiCecLocalDeviceAudioSystem.addAndStartAction(mAction);
156         mTestLooper.dispatchAll();
157         HdmiCecMessage terminateArc = HdmiCecMessageBuilder.buildTerminateArc(
158                 Constants.ADDR_AUDIO_SYSTEM, Constants.ADDR_TV);
159 
160         assertThat(mNativeWrapper.getResultMessages()).contains(terminateArc);
161         mTestLooper.dispatchAll();
162 
163         mTestLooper.moveTimeForward(ArcTerminationActionFromAvr.TIMEOUT_MS);
164         mTestLooper.dispatchAll();
165 
166         assertThat(mHdmiCecLocalDeviceAudioSystem.isArcEnabled()).isFalse();
167         assertThat(mCallback.getResult()).isEqualTo(HdmiControlManager.RESULT_TIMEOUT);
168     }
169 
170     @Test
testReportArcTerminated_received()171     public void testReportArcTerminated_received() {
172         mHdmiCecLocalDeviceAudioSystem.addAndStartAction(mAction);
173         mTestLooper.dispatchAll();
174         HdmiCecMessage terminateArc = HdmiCecMessageBuilder.buildTerminateArc(
175                 Constants.ADDR_AUDIO_SYSTEM, Constants.ADDR_TV);
176 
177         assertThat(mNativeWrapper.getResultMessages()).contains(terminateArc);
178 
179         HdmiCecMessage arcTerminatedResponse = HdmiCecMessageBuilder.buildReportArcTerminated(
180                 Constants.ADDR_TV, Constants.ADDR_AUDIO_SYSTEM);
181 
182         mNativeWrapper.onCecMessage(arcTerminatedResponse);
183         mTestLooper.dispatchAll();
184 
185         assertThat(mHdmiCecLocalDeviceAudioSystem.isArcEnabled()).isFalse();
186         assertThat(mCallback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
187     }
188 
189     @Test
testReportArcTerminated_featureAbort()190     public void testReportArcTerminated_featureAbort() {
191         mHdmiCecLocalDeviceAudioSystem.addAndStartAction(mAction);
192         mTestLooper.dispatchAll();
193         HdmiCecMessage terminateArc = HdmiCecMessageBuilder.buildTerminateArc(
194                 Constants.ADDR_AUDIO_SYSTEM, Constants.ADDR_TV);
195 
196         assertThat(mNativeWrapper.getResultMessages()).contains(terminateArc);
197 
198         HdmiCecMessage arcTerminatedResponse = HdmiCecMessageBuilder.buildFeatureAbortCommand(
199                 Constants.ADDR_TV,
200                 Constants.ADDR_AUDIO_SYSTEM,
201                 Constants.MESSAGE_TERMINATE_ARC,
202                 Constants.ABORT_REFUSED);
203 
204         mNativeWrapper.onCecMessage(arcTerminatedResponse);
205         mTestLooper.dispatchAll();
206 
207         assertThat(mHdmiCecLocalDeviceAudioSystem.isArcEnabled()).isFalse();
208         assertThat(mCallback.getResult()).isEqualTo(HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
209     }
210 }
211