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 android.hardware.hdmi.HdmiDeviceInfo.DEVICE_TV;
19 
20 import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
21 import static com.android.server.hdmi.Constants.ADDR_AUDIO_SYSTEM;
22 import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_1;
23 import static com.android.server.hdmi.Constants.ADDR_TV;
24 import static com.android.server.hdmi.Constants.MESSAGE_DEVICE_VENDOR_ID;
25 import static com.android.server.hdmi.Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS;
26 import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
27 
28 import static com.google.common.truth.Truth.assertThat;
29 
30 import static junit.framework.Assert.assertEquals;
31 import static junit.framework.Assert.assertFalse;
32 import static junit.framework.Assert.assertTrue;
33 
34 import static org.mockito.ArgumentMatchers.anyInt;
35 import static org.mockito.ArgumentMatchers.eq;
36 import static org.mockito.Mockito.spy;
37 import static org.mockito.Mockito.times;
38 import static org.mockito.Mockito.verify;
39 
40 import android.content.Context;
41 import android.hardware.hdmi.HdmiControlManager;
42 import android.hardware.hdmi.HdmiPortInfo;
43 import android.hardware.tv.cec.V1_0.Result;
44 import android.media.AudioManager;
45 import android.os.test.TestLooper;
46 import android.platform.test.annotations.Presubmit;
47 
48 import androidx.test.InstrumentationRegistry;
49 import androidx.test.filters.SmallTest;
50 
51 import com.google.common.testing.EqualsTester;
52 
53 import org.junit.Before;
54 import org.junit.Test;
55 import org.junit.runner.RunWith;
56 import org.junit.runners.JUnit4;
57 
58 import java.util.ArrayList;
59 import java.util.Arrays;
60 import java.util.Collections;
61 import java.util.List;
62 
63 @SmallTest
64 @Presubmit
65 @RunWith(JUnit4.class)
66 /** Tests for {@link HdmiCecLocalDevice} class. */
67 public class HdmiCecLocalDeviceTest {
68 
69     private FakeNativeWrapper mNativeWrapper;
70 
SendCecCommandFactory(int srcAddress, int dstAddress, byte[] body)71     private static int SendCecCommandFactory(int srcAddress, int dstAddress, byte[] body) {
72         switch (body[0] & 0xFF) {
73                 /** {@link Constants#MESSAGE_GIVE_PHYSICAL_ADDRESS} */
74             case MESSAGE_REPORT_PHYSICAL_ADDRESS:
75             case MESSAGE_DEVICE_VENDOR_ID:
76                 return srcAddress == mSrcAddr
77                                 && dstAddress == mDesAddr
78                                 && Arrays.equals(Arrays.copyOfRange(body, 1, body.length), param)
79                         ? 0
80                         : 1;
81             default:
82                 return 1;
83         }
84     }
85 
86     private class MyHdmiCecLocalDevice extends HdmiCecLocalDevice {
87 
MyHdmiCecLocalDevice(HdmiControlService service, int deviceType)88         protected MyHdmiCecLocalDevice(HdmiControlService service, int deviceType) {
89             super(service, deviceType);
90         }
91 
92         @Override
onAddressAllocated(int logicalAddress, int reason)93         protected void onAddressAllocated(int logicalAddress, int reason) {}
94 
95         @Override
getPreferredAddress()96         protected int getPreferredAddress() {
97             return 0;
98         }
99 
100         @Override
setPreferredAddress(int addr)101         protected void setPreferredAddress(int addr) {}
102 
103         @Override
getRcProfile()104         protected int getRcProfile() {
105             return 0;
106         }
107 
108         @Override
getRcFeatures()109         protected List<Integer> getRcFeatures() {
110             return Collections.emptyList();
111         }
112     }
113 
114     private MyHdmiCecLocalDevice mHdmiLocalDevice;
115     private HdmiControlService mHdmiControlService;
116     private HdmiCecController mHdmiCecController;
117     private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
118     private TestLooper mTestLooper = new TestLooper();
119     private static int mDesAddr = -1;
120     private static int mSrcAddr = -1;
121     private static int mPhysicalAddr = 2;
122     private int callbackResult;
123     private HdmiCecMessageValidator mMessageValidator;
124     private static byte[] param;
125     private boolean mStandbyMessageReceived;
126     private boolean mWakeupMessageReceived;
127     private boolean isControlEnabled;
128     private int mPowerStatus;
129 
130     private AudioManagerWrapper mAudioManager;
131 
132     @Before
SetUp()133     public void SetUp() {
134         Context context = InstrumentationRegistry.getTargetContext();
135 
136         FakeAudioFramework audioFramework = new FakeAudioFramework();
137         mAudioManager = spy(audioFramework.getAudioManager());
138         mHdmiControlService =
139                 new HdmiControlService(context, Collections.emptyList(),
140                         mAudioManager, audioFramework.getAudioDeviceVolumeManager()) {
141                     @Override
142                     boolean isCecControlEnabled() {
143                         return isControlEnabled;
144                     }
145 
146                     @Override
147                     boolean isPowerOnOrTransient() {
148                         return mPowerStatus == HdmiControlManager.POWER_STATUS_ON
149                                 || mPowerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON;
150                     }
151 
152                     @Override
153                     boolean isPowerStandbyOrTransient() {
154                         return mPowerStatus == HdmiControlManager.POWER_STATUS_STANDBY
155                                 || mPowerStatus
156                                 == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY;
157                     }
158 
159                     @Override
160                     protected void writeStringSystemProperty(String key, String value) {
161                     }
162 
163                     @Override
164                     void standby() {
165                         mStandbyMessageReceived = true;
166                     }
167 
168                     @Override
169                     void wakeUp() {
170                         mWakeupMessageReceived = true;
171                     }
172                 };
173         mHdmiControlService.setIoLooper(mTestLooper.getLooper());
174         mHdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(context));
175         mHdmiControlService.setDeviceConfig(new FakeDeviceConfigWrapper());
176         mNativeWrapper = new FakeNativeWrapper();
177         mHdmiCecController = HdmiCecController.createWithNativeWrapper(
178                 mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
179         mHdmiControlService.setCecController(mHdmiCecController);
180         mHdmiLocalDevice = new MyHdmiCecLocalDevice(mHdmiControlService, DEVICE_TV);
181 
182         mLocalDevices.add(mHdmiLocalDevice);
183         HdmiPortInfo[] hdmiPortInfos = new HdmiPortInfo[1];
184         hdmiPortInfos[0] =
185                 new HdmiPortInfo.Builder(1, HdmiPortInfo.PORT_OUTPUT, 0x0000)
186                         .setCecSupported(true)
187                         .setMhlSupported(false)
188                         .setArcSupported(false)
189                         .build();
190         mNativeWrapper.setPortInfo(hdmiPortInfos);
191         mNativeWrapper.setPortConnectionStatus(1, true);
192         mHdmiControlService.initService();
193         mHdmiControlService.onBootPhase(PHASE_SYSTEM_SERVICES_READY);
194         mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
195         mNativeWrapper.setPhysicalAddress(0x2000);
196         mTestLooper.dispatchAll();
197         mNativeWrapper.clearResultMessages();
198     }
199 
200     @Test
testEqualsActiveSource()201     public void testEqualsActiveSource() {
202         int logicalAddress = 0;
203         int physicalAddress = 0x0000;
204         new EqualsTester()
205                 .addEqualityGroup(
206                         new HdmiCecLocalDevice.ActiveSource(logicalAddress, physicalAddress),
207                         new HdmiCecLocalDevice.ActiveSource(logicalAddress, physicalAddress))
208                 .addEqualityGroup(
209                         new HdmiCecLocalDevice.ActiveSource(logicalAddress, physicalAddress + 1))
210                 .addEqualityGroup(
211                         new HdmiCecLocalDevice.ActiveSource(logicalAddress + 1, physicalAddress))
212                 .addEqualityGroup(
213                         new HdmiCecLocalDevice.ActiveSource(
214                                 logicalAddress + 1, physicalAddress + 1))
215                 .testEquals();
216     }
217 
218     @Test
dispatchMessage_logicalAddressDoesNotMatch()219     public void dispatchMessage_logicalAddressDoesNotMatch() {
220         HdmiCecMessage msg =
221                 HdmiCecMessage.build(
222                         ADDR_TV,
223                         ADDR_PLAYBACK_1,
224                         Constants.MESSAGE_CEC_VERSION,
225                         HdmiCecMessage.EMPTY_PARAM);
226         @Constants.HandleMessageResult int handleResult = mHdmiLocalDevice.dispatchMessage(msg);
227         assertEquals(Constants.NOT_HANDLED, handleResult);
228     }
229 
230     @Test
handleGivePhysicalAddress_success()231     public void handleGivePhysicalAddress_success() {
232         mNativeWrapper.setPhysicalAddress(0x0);
233         HdmiCecMessage expectedMessage =
234                 HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(ADDR_TV, 0, DEVICE_TV);
235         @Constants.HandleMessageResult
236         int handleResult =
237                 mHdmiLocalDevice.handleGivePhysicalAddress(
238                         HdmiCecMessageBuilder.buildGivePhysicalAddress(
239                                 ADDR_PLAYBACK_1, ADDR_TV));
240         mTestLooper.dispatchAll();
241         assertEquals(Constants.HANDLED, handleResult);
242         assertThat(mNativeWrapper.getOnlyResultMessage()).isEqualTo(expectedMessage);
243     }
244 
245     @Test
handleGivePhysicalAddress_failure()246     public void handleGivePhysicalAddress_failure() {
247         mNativeWrapper.setPhysicalAddress(Constants.INVALID_PHYSICAL_ADDRESS);
248         HdmiCecMessage expectedMessage =
249                 HdmiCecMessageBuilder.buildFeatureAbortCommand(
250                         ADDR_TV,
251                         ADDR_PLAYBACK_1,
252                         Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS,
253                         Constants.ABORT_UNABLE_TO_DETERMINE);
254         @Constants.HandleMessageResult
255         int handleResult =
256                 mHdmiLocalDevice.handleGivePhysicalAddress(
257                         HdmiCecMessageBuilder.buildGivePhysicalAddress(
258                                 ADDR_PLAYBACK_1, ADDR_TV));
259         mTestLooper.dispatchAll();
260         assertEquals(Constants.HANDLED, handleResult);
261         assertThat(mNativeWrapper.getOnlyResultMessage()).isEqualTo(expectedMessage);
262     }
263 
264     @Test
handleGiveDeviceVendorId_success()265     public void handleGiveDeviceVendorId_success() {
266         /** Set vendor id to 0 */
267         mNativeWrapper.setVendorId(0);
268         HdmiCecMessage expectedMessage =
269                 HdmiCecMessageBuilder.buildDeviceVendorIdCommand(ADDR_TV, 0);
270         @Constants.HandleMessageResult
271         int handleResult =
272                 mHdmiLocalDevice.handleGiveDeviceVendorId(
273                         HdmiCecMessageBuilder.buildGiveDeviceVendorIdCommand(
274                                 ADDR_PLAYBACK_1, ADDR_TV));
275         mTestLooper.dispatchAll();
276         assertEquals(Constants.HANDLED, handleResult);
277         assertThat(mNativeWrapper.getOnlyResultMessage()).isEqualTo(expectedMessage);
278     }
279 
280     @Test
handleGiveDeviceVendorId_failure()281     public void handleGiveDeviceVendorId_failure() {
282         mNativeWrapper.setVendorId(Result.FAILURE_UNKNOWN);
283         HdmiCecMessage expectedMessage =
284                 HdmiCecMessageBuilder.buildFeatureAbortCommand(
285                         ADDR_TV,
286                         ADDR_PLAYBACK_1,
287                         Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID,
288                         Constants.ABORT_UNABLE_TO_DETERMINE);
289         @Constants.HandleMessageResult
290         int handleResult =
291                 mHdmiLocalDevice.handleGiveDeviceVendorId(
292                         HdmiCecMessageBuilder.buildGiveDeviceVendorIdCommand(
293                                 ADDR_PLAYBACK_1, ADDR_TV));
294         mTestLooper.dispatchAll();
295         assertEquals(Constants.HANDLED, handleResult);
296         assertThat(mNativeWrapper.getOnlyResultMessage()).isEqualTo(expectedMessage);
297     }
298 
299     @Test
handleStandby_isPowerOn()300     public void handleStandby_isPowerOn() {
301         mPowerStatus = HdmiControlManager.POWER_STATUS_ON;
302         isControlEnabled = true;
303         assertFalse(mStandbyMessageReceived);
304         mHdmiLocalDevice.handleStandby(
305                 HdmiCecMessageBuilder.buildStandby(ADDR_TV, ADDR_AUDIO_SYSTEM));
306         assertTrue(mStandbyMessageReceived);
307     }
308 
309     @Test
handleUserControlPressed_volumeUp()310     public void handleUserControlPressed_volumeUp() {
311         mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
312                 HdmiControlManager.VOLUME_CONTROL_ENABLED);
313         @Constants.HandleMessageResult int result = mHdmiLocalDevice.handleUserControlPressed(
314                 HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
315                         HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP));
316 
317         assertEquals(Constants.HANDLED, result);
318     }
319 
320     @Test
handleUserControlPressed_volumeDown()321     public void handleUserControlPressed_volumeDown() {
322         mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
323                 HdmiControlManager.VOLUME_CONTROL_ENABLED);
324         @Constants.HandleMessageResult int result = mHdmiLocalDevice.handleUserControlPressed(
325                 HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
326                         HdmiCecKeycode.CEC_KEYCODE_VOLUME_DOWN));
327 
328         assertEquals(Constants.HANDLED, result);
329     }
330 
331     @Test
handleUserControlPressed_volumeMute()332     public void handleUserControlPressed_volumeMute() {
333         mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
334                 HdmiControlManager.VOLUME_CONTROL_ENABLED);
335         @Constants.HandleMessageResult int result = mHdmiLocalDevice.handleUserControlPressed(
336                 HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
337                         HdmiCecKeycode.CEC_KEYCODE_MUTE));
338 
339         assertEquals(Constants.HANDLED, result);
340     }
341 
342     @Test
handleUserControlPressed_volumeUp_disabled()343     public void handleUserControlPressed_volumeUp_disabled() {
344         mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
345                 HdmiControlManager.VOLUME_CONTROL_DISABLED);
346         @Constants.HandleMessageResult int result = mHdmiLocalDevice.handleUserControlPressed(
347                 HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
348                         HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP));
349 
350         assertThat(result).isEqualTo(Constants.ABORT_REFUSED);
351     }
352 
353     @Test
handleUserControlPressed_volumeDown_disabled()354     public void handleUserControlPressed_volumeDown_disabled() {
355         mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
356                 HdmiControlManager.VOLUME_CONTROL_DISABLED);
357         @Constants.HandleMessageResult int result = mHdmiLocalDevice.handleUserControlPressed(
358                 HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
359                         HdmiCecKeycode.CEC_KEYCODE_VOLUME_DOWN));
360 
361         assertThat(result).isEqualTo(Constants.ABORT_REFUSED);
362     }
363 
364     @Test
handleUserControlPressed_volumeMute_disabled()365     public void handleUserControlPressed_volumeMute_disabled() {
366         mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
367                 HdmiControlManager.VOLUME_CONTROL_DISABLED);
368         @Constants.HandleMessageResult int result = mHdmiLocalDevice.handleUserControlPressed(
369                 HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
370                         HdmiCecKeycode.CEC_KEYCODE_MUTE));
371 
372         assertThat(result).isEqualTo(Constants.ABORT_REFUSED);
373     }
374 
375     @Test
handleCecVersion_isHandled()376     public void handleCecVersion_isHandled() {
377         @Constants.HandleMessageResult
378         int result =
379                 mHdmiLocalDevice.onMessage(
380                         HdmiCecMessageBuilder.buildCecVersion(
381                                 ADDR_PLAYBACK_1,
382                                 mHdmiLocalDevice.getDeviceInfo().getLogicalAddress(),
383                                 HdmiControlManager.HDMI_CEC_VERSION_1_4_B));
384 
385         assertEquals(Constants.HANDLED, result);
386     }
387 
388     @Test
handleUserControlPressed_power_localDeviceInStandby_shouldTurnOn()389     public void handleUserControlPressed_power_localDeviceInStandby_shouldTurnOn() {
390         mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;
391         @Constants.HandleMessageResult int result = mHdmiLocalDevice.handleUserControlPressed(
392                 HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1,
393                         HdmiCecKeycode.CEC_KEYCODE_POWER));
394 
395         assertEquals(Constants.HANDLED, result);
396         assertThat(mWakeupMessageReceived).isTrue();
397         assertThat(mStandbyMessageReceived).isFalse();
398     }
399 
400     @Test
handleUserControlPressed_power_localDeviceOn_shouldNotChangePowerStatus()401     public void handleUserControlPressed_power_localDeviceOn_shouldNotChangePowerStatus() {
402         mPowerStatus = HdmiControlManager.POWER_STATUS_ON;
403         @Constants.HandleMessageResult int result = mHdmiLocalDevice.handleUserControlPressed(
404                 HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1,
405                         HdmiCecKeycode.CEC_KEYCODE_POWER));
406 
407         assertEquals(Constants.HANDLED, result);
408         assertThat(mWakeupMessageReceived).isFalse();
409         assertThat(mStandbyMessageReceived).isFalse();
410     }
411 
412     @Test
handleUserControlPressed_powerToggleFunction_localDeviceInStandby_shouldTurnOn()413     public void handleUserControlPressed_powerToggleFunction_localDeviceInStandby_shouldTurnOn() {
414         mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;
415         @Constants.HandleMessageResult int result = mHdmiLocalDevice.handleUserControlPressed(
416                 HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1,
417                         HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION));
418 
419         assertEquals(Constants.HANDLED, result);
420         assertThat(mWakeupMessageReceived).isTrue();
421         assertThat(mStandbyMessageReceived).isFalse();
422     }
423 
424     @Test
handleUserControlPressed_powerToggleFunction_localDeviceOn_shouldTurnOff()425     public void handleUserControlPressed_powerToggleFunction_localDeviceOn_shouldTurnOff() {
426         mPowerStatus = HdmiControlManager.POWER_STATUS_ON;
427         @Constants.HandleMessageResult int result = mHdmiLocalDevice.handleUserControlPressed(
428                 HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1,
429                         HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION));
430 
431         assertEquals(Constants.HANDLED, result);
432         assertThat(mWakeupMessageReceived).isFalse();
433         assertThat(mStandbyMessageReceived).isTrue();
434     }
435 
436     @Test
handleUserControlPressed_powerOnFunction_localDeviceInStandby_shouldTurnOn()437     public void handleUserControlPressed_powerOnFunction_localDeviceInStandby_shouldTurnOn() {
438         mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;
439         @Constants.HandleMessageResult int result = mHdmiLocalDevice.handleUserControlPressed(
440                 HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1,
441                         HdmiCecKeycode.CEC_KEYCODE_POWER_ON_FUNCTION));
442 
443         assertEquals(Constants.HANDLED, result);
444         assertThat(mWakeupMessageReceived).isTrue();
445         assertThat(mStandbyMessageReceived).isFalse();
446     }
447 
448     @Test
handleUserControlPressed_powerOnFunction_localDeviceOn_noPowerStatusChange()449     public void handleUserControlPressed_powerOnFunction_localDeviceOn_noPowerStatusChange() {
450         mPowerStatus = HdmiControlManager.POWER_STATUS_ON;
451         @Constants.HandleMessageResult int result = mHdmiLocalDevice.handleUserControlPressed(
452                 HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1,
453                         HdmiCecKeycode.CEC_KEYCODE_POWER_ON_FUNCTION));
454 
455         assertEquals(Constants.HANDLED, result);
456         assertThat(mWakeupMessageReceived).isFalse();
457         assertThat(mStandbyMessageReceived).isFalse();
458     }
459 
460     @Test
handleUserControlPressed_powerOffFunction_localDeviceStandby_noPowerStatusChange()461     public void handleUserControlPressed_powerOffFunction_localDeviceStandby_noPowerStatusChange() {
462         mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;
463         @Constants.HandleMessageResult int result = mHdmiLocalDevice.handleUserControlPressed(
464                 HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1,
465                         HdmiCecKeycode.CEC_KEYCODE_POWER_OFF_FUNCTION));
466 
467         assertEquals(Constants.HANDLED, result);
468         assertThat(mWakeupMessageReceived).isFalse();
469         assertThat(mStandbyMessageReceived).isFalse();
470     }
471 
472     @Test
handleUserControlPressed_powerOffFunction_localDeviceOn_shouldTurnOff()473     public void handleUserControlPressed_powerOffFunction_localDeviceOn_shouldTurnOff() {
474         mPowerStatus = HdmiControlManager.POWER_STATUS_ON;
475         @Constants.HandleMessageResult int result = mHdmiLocalDevice.handleUserControlPressed(
476                 HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1,
477                         HdmiCecKeycode.CEC_KEYCODE_POWER_OFF_FUNCTION));
478 
479         assertEquals(Constants.HANDLED, result);
480         assertThat(mWakeupMessageReceived).isFalse();
481         assertThat(mStandbyMessageReceived).isTrue();
482     }
483 
484     @Test
handleUserControlPressed_muteFunction()485     public void handleUserControlPressed_muteFunction() {
486         @Constants.HandleMessageResult int result = mHdmiLocalDevice.handleUserControlPressed(
487                 HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1,
488                         HdmiCecKeycode.CEC_KEYCODE_MUTE_FUNCTION));
489 
490         assertEquals(result, Constants.HANDLED);
491         verify(mAudioManager, times(1))
492                 .adjustStreamVolume(anyInt(), eq(AudioManager.ADJUST_MUTE), anyInt());
493     }
494 
495     @Test
handleUserControlPressed_restoreVolumeFunction()496     public void handleUserControlPressed_restoreVolumeFunction() {
497         @Constants.HandleMessageResult int result = mHdmiLocalDevice.handleUserControlPressed(
498                 HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1,
499                         HdmiCecKeycode.CEC_KEYCODE_RESTORE_VOLUME_FUNCTION));
500 
501         assertEquals(result, Constants.HANDLED);
502         verify(mAudioManager, times(1))
503                 .adjustStreamVolume(anyInt(), eq(AudioManager.ADJUST_UNMUTE), anyInt());
504     }
505 
506     @Test
handleVendorCommand_notHandled()507     public void handleVendorCommand_notHandled() {
508         HdmiCecMessage vendorCommand = HdmiCecMessageBuilder.buildVendorCommand(ADDR_TV,
509                 ADDR_PLAYBACK_1, new byte[]{0});
510         mNativeWrapper.onCecMessage(vendorCommand);
511         mTestLooper.dispatchAll();
512 
513         HdmiCecMessageBuilder.buildFeatureAbortCommand(ADDR_PLAYBACK_1, ADDR_TV,
514                 vendorCommand.getOpcode(), Constants.ABORT_REFUSED);
515     }
516 
517     @Test
handleVendorCommandWithId_notHandled_Cec14()518     public void handleVendorCommandWithId_notHandled_Cec14() {
519         HdmiCecMessage vendorCommand = HdmiCecMessageBuilder.buildVendorCommandWithId(ADDR_TV,
520                 ADDR_PLAYBACK_1, 0x1234, new byte[]{0});
521         mNativeWrapper.onCecMessage(vendorCommand);
522         mTestLooper.dispatchAll();
523 
524         HdmiCecMessageBuilder.buildFeatureAbortCommand(ADDR_PLAYBACK_1, ADDR_TV,
525                 vendorCommand.getOpcode(), Constants.ABORT_REFUSED);
526     }
527 }
528