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_AUDIO_SYSTEM; 19 import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_PLAYBACK; 20 import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_TV; 21 22 import static com.android.server.SystemService.PHASE_BOOT_COMPLETED; 23 import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY; 24 import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC; 25 import static com.android.server.hdmi.HdmiControlService.WAKE_UP_SCREEN_ON; 26 27 import static com.google.common.truth.Truth.assertThat; 28 29 import static junit.framework.Assert.assertFalse; 30 import static junit.framework.Assert.assertTrue; 31 import static junit.framework.TestCase.assertEquals; 32 33 import static org.mockito.ArgumentMatchers.any; 34 import static org.mockito.ArgumentMatchers.anyBoolean; 35 import static org.mockito.ArgumentMatchers.anyInt; 36 import static org.mockito.ArgumentMatchers.anyString; 37 import static org.mockito.ArgumentMatchers.eq; 38 import static org.mockito.Mockito.doNothing; 39 import static org.mockito.Mockito.doReturn; 40 import static org.mockito.Mockito.spy; 41 import static org.mockito.Mockito.times; 42 import static org.mockito.Mockito.verify; 43 44 import android.content.Context; 45 import android.content.ContextWrapper; 46 import android.hardware.hdmi.HdmiControlManager; 47 import android.hardware.hdmi.HdmiDeviceInfo; 48 import android.hardware.hdmi.HdmiPortInfo; 49 import android.hardware.hdmi.IHdmiCecVolumeControlFeatureListener; 50 import android.hardware.hdmi.IHdmiControlStatusChangeListener; 51 import android.hardware.hdmi.IHdmiVendorCommandListener; 52 import android.os.Binder; 53 import android.os.Looper; 54 import android.os.RemoteException; 55 import android.os.test.TestLooper; 56 import android.platform.test.annotations.Presubmit; 57 import android.sysprop.HdmiProperties; 58 59 import androidx.test.InstrumentationRegistry; 60 import androidx.test.filters.SmallTest; 61 62 import org.junit.Before; 63 import org.junit.Test; 64 import org.junit.runner.RunWith; 65 import org.junit.runners.JUnit4; 66 import org.mockito.Mockito; 67 68 import java.util.ArrayList; 69 import java.util.Arrays; 70 import java.util.Optional; 71 72 /** 73 * Tests for {@link HdmiControlService} class. 74 */ 75 @SmallTest 76 @Presubmit 77 @RunWith(JUnit4.class) 78 public class HdmiControlServiceTest { 79 80 private static final String TAG = "HdmiControlServiceTest"; 81 private Context mContextSpy; 82 private HdmiControlService mHdmiControlServiceSpy; 83 private HdmiCecController mHdmiCecController; 84 private MockAudioSystemDevice mAudioSystemDeviceSpy; 85 private MockPlaybackDevice mPlaybackDeviceSpy; 86 private FakeNativeWrapper mNativeWrapper; 87 private HdmiEarcController mHdmiEarcController; 88 private FakeEarcNativeWrapper mEarcNativeWrapper; 89 private FakePowerManagerWrapper mPowerManager; 90 private Looper mMyLooper; 91 private TestLooper mTestLooper = new TestLooper(); 92 private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>(); 93 private HdmiPortInfo[] mHdmiPortInfo; 94 private ArrayList<Integer> mLocalDeviceTypes = new ArrayList<>(); 95 private static final int PORT_ID_EARC_SUPPORTED = 3; 96 97 @Before setUp()98 public void setUp() throws Exception { 99 mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext())); 100 101 HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(mContextSpy); 102 mLocalDeviceTypes.add(HdmiDeviceInfo.DEVICE_PLAYBACK); 103 104 FakeAudioFramework audioFramework = new FakeAudioFramework(); 105 106 mHdmiControlServiceSpy = spy(new HdmiControlService(mContextSpy, mLocalDeviceTypes, 107 audioFramework.getAudioManager(), audioFramework.getAudioDeviceVolumeManager())); 108 doNothing().when(mHdmiControlServiceSpy) 109 .writeStringSystemProperty(anyString(), anyString()); 110 111 mMyLooper = mTestLooper.getLooper(); 112 113 mAudioSystemDeviceSpy = spy(new MockAudioSystemDevice(mHdmiControlServiceSpy)); 114 mPlaybackDeviceSpy = spy(new MockPlaybackDevice(mHdmiControlServiceSpy)); 115 mAudioSystemDeviceSpy.init(); 116 mPlaybackDeviceSpy.init(); 117 118 mHdmiControlServiceSpy.setIoLooper(mMyLooper); 119 mHdmiControlServiceSpy.setHdmiCecConfig(hdmiCecConfig); 120 mHdmiControlServiceSpy.setDeviceConfig(new FakeDeviceConfigWrapper()); 121 mHdmiControlServiceSpy.onBootPhase(PHASE_SYSTEM_SERVICES_READY); 122 123 mNativeWrapper = new FakeNativeWrapper(); 124 mHdmiCecController = HdmiCecController.createWithNativeWrapper( 125 mHdmiControlServiceSpy, mNativeWrapper, mHdmiControlServiceSpy.getAtomWriter()); 126 mHdmiControlServiceSpy.setCecController(mHdmiCecController); 127 mEarcNativeWrapper = new FakeEarcNativeWrapper(); 128 mHdmiEarcController = HdmiEarcController.createWithNativeWrapper( 129 mHdmiControlServiceSpy, mEarcNativeWrapper); 130 mHdmiControlServiceSpy.setEarcController(mHdmiEarcController); 131 mHdmiControlServiceSpy.setHdmiMhlController(HdmiMhlControllerStub.create( 132 mHdmiControlServiceSpy)); 133 134 mLocalDevices.add(mAudioSystemDeviceSpy); 135 mLocalDevices.add(mPlaybackDeviceSpy); 136 mHdmiPortInfo = new HdmiPortInfo[4]; 137 mHdmiPortInfo[0] = 138 new HdmiPortInfo.Builder(1, HdmiPortInfo.PORT_INPUT, 0x2100) 139 .setCecSupported(true) 140 .setMhlSupported(false) 141 .setArcSupported(false) 142 .setEarcSupported(false) 143 .build(); 144 mHdmiPortInfo[1] = 145 new HdmiPortInfo.Builder(2, HdmiPortInfo.PORT_INPUT, 0x2200) 146 .setCecSupported(true) 147 .setMhlSupported(false) 148 .setArcSupported(false) 149 .setEarcSupported(false) 150 .build(); 151 mHdmiPortInfo[2] = 152 new HdmiPortInfo.Builder(PORT_ID_EARC_SUPPORTED, HdmiPortInfo.PORT_INPUT, 0x2000) 153 .setCecSupported(true) 154 .setMhlSupported(false) 155 .setArcSupported(true) 156 .setEarcSupported(true) 157 .build(); 158 mHdmiPortInfo[3] = 159 new HdmiPortInfo.Builder(4, HdmiPortInfo.PORT_INPUT, 0x3000) 160 .setCecSupported(true) 161 .setMhlSupported(false) 162 .setArcSupported(false) 163 .setEarcSupported(false) 164 .build(); 165 mNativeWrapper.setPortInfo(mHdmiPortInfo); 166 mHdmiControlServiceSpy.initService(); 167 mPowerManager = new FakePowerManagerWrapper(mContextSpy); 168 mHdmiControlServiceSpy.setPowerManager(mPowerManager); 169 mHdmiControlServiceSpy.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); 170 mHdmiControlServiceSpy.setEarcSupported(true); 171 172 mTestLooper.dispatchAll(); 173 } 174 175 @Test onStandby_notByCec_cannotGoToStandby()176 public void onStandby_notByCec_cannotGoToStandby() { 177 doReturn(false).when(mHdmiControlServiceSpy).isStandbyMessageReceived(); 178 179 mPlaybackDeviceSpy.setCanGoToStandby(false); 180 181 mHdmiControlServiceSpy.onStandby(HdmiControlService.STANDBY_SCREEN_OFF); 182 assertTrue(mPlaybackDeviceSpy.isStandby()); 183 assertTrue(mAudioSystemDeviceSpy.isStandby()); 184 assertFalse(mPlaybackDeviceSpy.isDisabled()); 185 assertFalse(mAudioSystemDeviceSpy.isDisabled()); 186 } 187 188 @Test onStandby_byCec()189 public void onStandby_byCec() { 190 doReturn(true).when(mHdmiControlServiceSpy).isStandbyMessageReceived(); 191 192 mHdmiControlServiceSpy.onStandby(HdmiControlService.STANDBY_SCREEN_OFF); 193 assertTrue(mPlaybackDeviceSpy.isStandby()); 194 assertTrue(mAudioSystemDeviceSpy.isStandby()); 195 assertTrue(mPlaybackDeviceSpy.isDisabled()); 196 assertTrue(mAudioSystemDeviceSpy.isDisabled()); 197 } 198 199 @Test initialPowerStatus_normalBoot_isTransientToStandby()200 public void initialPowerStatus_normalBoot_isTransientToStandby() { 201 assertThat(mHdmiControlServiceSpy.getInitialPowerStatus()).isEqualTo( 202 HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY); 203 } 204 205 @Test initialPowerStatus_quiescentBoot_isTransientToStandby()206 public void initialPowerStatus_quiescentBoot_isTransientToStandby() throws RemoteException { 207 mPowerManager.setInteractive(false); 208 assertThat(mHdmiControlServiceSpy.getInitialPowerStatus()).isEqualTo( 209 HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY); 210 } 211 212 @Test powerStatusAfterBootComplete_normalBoot_isOn()213 public void powerStatusAfterBootComplete_normalBoot_isOn() { 214 mHdmiControlServiceSpy.setPowerStatus(HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON); 215 mHdmiControlServiceSpy.onBootPhase(PHASE_BOOT_COMPLETED); 216 assertThat(mHdmiControlServiceSpy.getPowerStatus()).isEqualTo( 217 HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON); 218 } 219 220 @Test powerStatusAfterBootComplete_quiescentBoot_isStandby()221 public void powerStatusAfterBootComplete_quiescentBoot_isStandby() throws RemoteException { 222 mPowerManager.setInteractive(false); 223 mHdmiControlServiceSpy.onBootPhase(PHASE_BOOT_COMPLETED); 224 assertThat(mHdmiControlServiceSpy.getPowerStatus()).isEqualTo( 225 HdmiControlManager.POWER_STATUS_STANDBY); 226 } 227 228 @Test initialPowerStatus_normalBoot_goToStandby_doesNotBroadcastsPowerStatus_1_4()229 public void initialPowerStatus_normalBoot_goToStandby_doesNotBroadcastsPowerStatus_1_4() { 230 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 231 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION, 232 HdmiControlManager.HDMI_CEC_VERSION_1_4_B); 233 234 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); 235 mNativeWrapper.clearResultMessages(); 236 237 assertThat(mHdmiControlServiceSpy.getInitialPowerStatus()).isEqualTo( 238 HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY); 239 240 mHdmiControlServiceSpy.onStandby(HdmiControlService.STANDBY_SCREEN_OFF); 241 242 HdmiCecMessage reportPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus( 243 Constants.ADDR_PLAYBACK_1, Constants.ADDR_BROADCAST, 244 HdmiControlManager.POWER_STATUS_STANDBY); 245 assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportPowerStatus); 246 } 247 248 @Test normalBoot_queuedActionsStartedAfterBoot()249 public void normalBoot_queuedActionsStartedAfterBoot() { 250 Mockito.clearInvocations(mAudioSystemDeviceSpy); 251 Mockito.clearInvocations(mPlaybackDeviceSpy); 252 253 mHdmiControlServiceSpy.onBootPhase(PHASE_BOOT_COMPLETED); 254 mTestLooper.dispatchAll(); 255 256 verify(mAudioSystemDeviceSpy, times(1)).startQueuedActions(); 257 verify(mPlaybackDeviceSpy, times(1)).startQueuedActions(); 258 } 259 260 @Test initialPowerStatus_normalBoot_goToStandby_broadcastsPowerStatus_2_0()261 public void initialPowerStatus_normalBoot_goToStandby_broadcastsPowerStatus_2_0() { 262 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 263 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION, 264 HdmiControlManager.HDMI_CEC_VERSION_2_0); 265 mTestLooper.dispatchAll(); 266 267 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); 268 mNativeWrapper.clearResultMessages(); 269 mTestLooper.dispatchAll(); 270 271 assertThat(mHdmiControlServiceSpy.getInitialPowerStatus()).isEqualTo( 272 HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY); 273 274 mHdmiControlServiceSpy.onStandby(HdmiControlService.STANDBY_SCREEN_OFF); 275 mTestLooper.dispatchAll(); 276 277 HdmiCecMessage reportPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus( 278 Constants.ADDR_PLAYBACK_1, Constants.ADDR_BROADCAST, 279 HdmiControlManager.POWER_STATUS_STANDBY); 280 assertThat(mNativeWrapper.getResultMessages()).contains(reportPowerStatus); 281 } 282 283 @Test setAndGetCecVolumeControlEnabled_isApi()284 public void setAndGetCecVolumeControlEnabled_isApi() { 285 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 286 HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE, 287 HdmiControlManager.VOLUME_CONTROL_DISABLED); 288 assertThat(mHdmiControlServiceSpy.getHdmiCecConfig().getIntValue( 289 HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE)).isEqualTo( 290 HdmiControlManager.VOLUME_CONTROL_DISABLED); 291 292 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 293 HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE, 294 HdmiControlManager.VOLUME_CONTROL_ENABLED); 295 assertThat(mHdmiControlServiceSpy.getHdmiCecConfig().getIntValue( 296 HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE)).isEqualTo( 297 HdmiControlManager.VOLUME_CONTROL_ENABLED); 298 } 299 300 @Test setAndGetCecVolumeControlEnabledInternal_doesNotChangeSetting()301 public void setAndGetCecVolumeControlEnabledInternal_doesNotChangeSetting() { 302 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 303 HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE, 304 HdmiControlManager.VOLUME_CONTROL_ENABLED); 305 306 mHdmiControlServiceSpy.setHdmiCecVolumeControlEnabledInternal( 307 HdmiControlManager.VOLUME_CONTROL_DISABLED); 308 assertThat(mHdmiControlServiceSpy.getHdmiCecConfig().getIntValue( 309 HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE)).isEqualTo( 310 HdmiControlManager.VOLUME_CONTROL_ENABLED); 311 312 mHdmiControlServiceSpy.setHdmiCecVolumeControlEnabledInternal( 313 HdmiControlManager.VOLUME_CONTROL_ENABLED); 314 assertThat(mHdmiControlServiceSpy.getHdmiCecConfig().getIntValue( 315 HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE)).isEqualTo( 316 HdmiControlManager.VOLUME_CONTROL_ENABLED); 317 } 318 319 @Test disableAndReenableCec_volumeControlReturnsToOriginalValue_enabled()320 public void disableAndReenableCec_volumeControlReturnsToOriginalValue_enabled() { 321 int volumeControlEnabled = HdmiControlManager.VOLUME_CONTROL_ENABLED; 322 mHdmiControlServiceSpy.setHdmiCecVolumeControlEnabledInternal(volumeControlEnabled); 323 324 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_DISABLED); 325 assertThat(mHdmiControlServiceSpy.getHdmiCecVolumeControl()).isEqualTo( 326 HdmiControlManager.VOLUME_CONTROL_DISABLED); 327 328 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); 329 assertThat(mHdmiControlServiceSpy.getHdmiCecVolumeControl()) 330 .isEqualTo(volumeControlEnabled); 331 } 332 333 @Test disableAndReenableCec_volumeControlReturnsToOriginalValue_disabled()334 public void disableAndReenableCec_volumeControlReturnsToOriginalValue_disabled() { 335 int volumeControlEnabled = HdmiControlManager.VOLUME_CONTROL_DISABLED; 336 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 337 HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE, volumeControlEnabled); 338 339 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_DISABLED); 340 assertThat(mHdmiControlServiceSpy.getHdmiCecConfig().getIntValue( 341 HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE)).isEqualTo( 342 volumeControlEnabled); 343 344 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); 345 assertThat(mHdmiControlServiceSpy.getHdmiCecConfig().getIntValue( 346 HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE)).isEqualTo( 347 volumeControlEnabled); 348 } 349 350 @Test disableAndReenableCec_volumeControlFeatureListenersNotified()351 public void disableAndReenableCec_volumeControlFeatureListenersNotified() { 352 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 353 HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE, 354 HdmiControlManager.VOLUME_CONTROL_ENABLED); 355 356 VolumeControlFeatureCallback callback = new VolumeControlFeatureCallback(); 357 mHdmiControlServiceSpy.addHdmiCecVolumeControlFeatureListener(callback); 358 359 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_DISABLED); 360 assertThat(callback.mCallbackReceived).isTrue(); 361 assertThat(callback.mVolumeControlEnabled).isEqualTo( 362 HdmiControlManager.VOLUME_CONTROL_DISABLED); 363 364 365 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); 366 assertThat(callback.mVolumeControlEnabled).isEqualTo( 367 HdmiControlManager.VOLUME_CONTROL_ENABLED); 368 } 369 370 @Test addHdmiCecVolumeControlFeatureListener_emitsCurrentState_enabled()371 public void addHdmiCecVolumeControlFeatureListener_emitsCurrentState_enabled() { 372 mHdmiControlServiceSpy.setHdmiCecVolumeControlEnabledInternal( 373 HdmiControlManager.VOLUME_CONTROL_ENABLED); 374 VolumeControlFeatureCallback callback = new VolumeControlFeatureCallback(); 375 376 mHdmiControlServiceSpy.addHdmiCecVolumeControlFeatureListener(callback); 377 mTestLooper.dispatchAll(); 378 379 assertThat(callback.mCallbackReceived).isTrue(); 380 assertThat(callback.mVolumeControlEnabled).isEqualTo( 381 HdmiControlManager.VOLUME_CONTROL_ENABLED); 382 } 383 384 @Test addHdmiCecVolumeControlFeatureListener_emitsCurrentState_disabled()385 public void addHdmiCecVolumeControlFeatureListener_emitsCurrentState_disabled() { 386 mHdmiControlServiceSpy.setHdmiCecVolumeControlEnabledInternal( 387 HdmiControlManager.VOLUME_CONTROL_DISABLED); 388 VolumeControlFeatureCallback callback = new VolumeControlFeatureCallback(); 389 390 mHdmiControlServiceSpy.addHdmiCecVolumeControlFeatureListener(callback); 391 mTestLooper.dispatchAll(); 392 393 assertThat(callback.mCallbackReceived).isTrue(); 394 assertThat(callback.mVolumeControlEnabled).isEqualTo( 395 HdmiControlManager.VOLUME_CONTROL_DISABLED); 396 } 397 398 @Test addHdmiCecVolumeControlFeatureListener_notifiesStateUpdate()399 public void addHdmiCecVolumeControlFeatureListener_notifiesStateUpdate() { 400 mHdmiControlServiceSpy.setHdmiCecVolumeControlEnabledInternal( 401 HdmiControlManager.VOLUME_CONTROL_DISABLED); 402 VolumeControlFeatureCallback callback = new VolumeControlFeatureCallback(); 403 404 mHdmiControlServiceSpy.addHdmiCecVolumeControlFeatureListener(callback); 405 406 mHdmiControlServiceSpy.setHdmiCecVolumeControlEnabledInternal( 407 HdmiControlManager.VOLUME_CONTROL_ENABLED); 408 mTestLooper.dispatchAll(); 409 410 assertThat(callback.mCallbackReceived).isTrue(); 411 assertThat(callback.mVolumeControlEnabled).isEqualTo( 412 HdmiControlManager.VOLUME_CONTROL_ENABLED); 413 } 414 415 @Test addHdmiCecVolumeControlFeatureListener_honorsUnregistration()416 public void addHdmiCecVolumeControlFeatureListener_honorsUnregistration() { 417 mHdmiControlServiceSpy.setHdmiCecVolumeControlEnabledInternal( 418 HdmiControlManager.VOLUME_CONTROL_DISABLED); 419 VolumeControlFeatureCallback callback = new VolumeControlFeatureCallback(); 420 421 mHdmiControlServiceSpy.addHdmiCecVolumeControlFeatureListener(callback); 422 mTestLooper.dispatchAll(); 423 424 mHdmiControlServiceSpy.removeHdmiControlVolumeControlStatusChangeListener(callback); 425 mHdmiControlServiceSpy.setHdmiCecVolumeControlEnabledInternal( 426 HdmiControlManager.VOLUME_CONTROL_ENABLED); 427 mTestLooper.dispatchAll(); 428 429 assertThat(callback.mCallbackReceived).isTrue(); 430 assertThat(callback.mVolumeControlEnabled).isEqualTo( 431 HdmiControlManager.VOLUME_CONTROL_DISABLED); 432 } 433 434 @Test addHdmiCecVolumeControlFeatureListener_notifiesStateUpdate_multiple()435 public void addHdmiCecVolumeControlFeatureListener_notifiesStateUpdate_multiple() { 436 mHdmiControlServiceSpy.setHdmiCecVolumeControlEnabledInternal( 437 HdmiControlManager.VOLUME_CONTROL_DISABLED); 438 VolumeControlFeatureCallback callback1 = new VolumeControlFeatureCallback(); 439 VolumeControlFeatureCallback callback2 = new VolumeControlFeatureCallback(); 440 441 mHdmiControlServiceSpy.addHdmiCecVolumeControlFeatureListener(callback1); 442 mHdmiControlServiceSpy.addHdmiCecVolumeControlFeatureListener(callback2); 443 444 445 mHdmiControlServiceSpy.setHdmiCecVolumeControlEnabledInternal( 446 HdmiControlManager.VOLUME_CONTROL_ENABLED); 447 mTestLooper.dispatchAll(); 448 449 assertThat(callback1.mCallbackReceived).isTrue(); 450 assertThat(callback2.mCallbackReceived).isTrue(); 451 assertThat(callback1.mVolumeControlEnabled).isEqualTo( 452 HdmiControlManager.VOLUME_CONTROL_ENABLED); 453 assertThat(callback2.mVolumeControlEnabled).isEqualTo( 454 HdmiControlManager.VOLUME_CONTROL_ENABLED); 455 } 456 457 @Test getCecVersion_1_4()458 public void getCecVersion_1_4() { 459 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 460 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION, 461 HdmiControlManager.HDMI_CEC_VERSION_1_4_B); 462 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); 463 assertThat(mHdmiControlServiceSpy.getCecVersion()).isEqualTo( 464 HdmiControlManager.HDMI_CEC_VERSION_1_4_B); 465 } 466 467 @Test getCecVersion_2_0()468 public void getCecVersion_2_0() { 469 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 470 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION, 471 HdmiControlManager.HDMI_CEC_VERSION_2_0); 472 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); 473 assertThat(mHdmiControlServiceSpy.getCecVersion()).isEqualTo( 474 HdmiControlManager.HDMI_CEC_VERSION_2_0); 475 } 476 477 @Test getCecVersion_change()478 public void getCecVersion_change() { 479 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 480 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION, 481 HdmiControlManager.HDMI_CEC_VERSION_1_4_B); 482 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); 483 assertThat(mHdmiControlServiceSpy.getCecVersion()).isEqualTo( 484 HdmiControlManager.HDMI_CEC_VERSION_1_4_B); 485 486 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 487 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION, 488 HdmiControlManager.HDMI_CEC_VERSION_2_0); 489 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); 490 assertThat(mHdmiControlServiceSpy.getCecVersion()).isEqualTo( 491 HdmiControlManager.HDMI_CEC_VERSION_2_0); 492 } 493 494 @Test handleGiveFeatures_cec14_featureAbort()495 public void handleGiveFeatures_cec14_featureAbort() { 496 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 497 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION, 498 HdmiControlManager.HDMI_CEC_VERSION_1_4_B); 499 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); 500 mTestLooper.dispatchAll(); 501 502 mNativeWrapper.onCecMessage(HdmiCecMessageBuilder.buildGiveFeatures(Constants.ADDR_TV, 503 Constants.ADDR_PLAYBACK_1)); 504 mTestLooper.dispatchAll(); 505 506 HdmiCecMessage featureAbort = HdmiCecMessageBuilder.buildFeatureAbortCommand( 507 Constants.ADDR_PLAYBACK_1, Constants.ADDR_TV, Constants.MESSAGE_GIVE_FEATURES, 508 Constants.ABORT_UNRECOGNIZED_OPCODE); 509 assertThat(mNativeWrapper.getResultMessages()).contains(featureAbort); 510 } 511 512 @Test handleGiveFeatures_cec20_reportsFeatures()513 public void handleGiveFeatures_cec20_reportsFeatures() { 514 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 515 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION, 516 HdmiControlManager.HDMI_CEC_VERSION_2_0); 517 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); 518 mHdmiControlServiceSpy.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); 519 mTestLooper.dispatchAll(); 520 521 mNativeWrapper.onCecMessage(HdmiCecMessageBuilder.buildGiveFeatures(Constants.ADDR_TV, 522 Constants.ADDR_PLAYBACK_1)); 523 mTestLooper.dispatchAll(); 524 525 HdmiCecMessage reportFeatures = ReportFeaturesMessage.build( 526 Constants.ADDR_PLAYBACK_1, HdmiControlManager.HDMI_CEC_VERSION_2_0, 527 Arrays.asList(DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM), 528 mPlaybackDeviceSpy.getRcProfile(), mPlaybackDeviceSpy.getRcFeatures(), 529 mPlaybackDeviceSpy.getDeviceFeatures()); 530 assertThat(mNativeWrapper.getResultMessages()).contains(reportFeatures); 531 } 532 533 @Test initializeCec_14_doesNotBroadcastReportFeatures()534 public void initializeCec_14_doesNotBroadcastReportFeatures() { 535 mNativeWrapper.clearResultMessages(); 536 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 537 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION, 538 HdmiControlManager.HDMI_CEC_VERSION_1_4_B); 539 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); 540 mHdmiControlServiceSpy.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); 541 mTestLooper.dispatchAll(); 542 543 HdmiCecMessage reportFeatures = ReportFeaturesMessage.build( 544 Constants.ADDR_PLAYBACK_1, HdmiControlManager.HDMI_CEC_VERSION_2_0, 545 Arrays.asList(DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM), 546 mPlaybackDeviceSpy.getRcProfile(), mPlaybackDeviceSpy.getRcFeatures(), 547 mPlaybackDeviceSpy.getDeviceFeatures()); 548 assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportFeatures); 549 } 550 551 @Test initializeCec_20_reportsFeaturesBroadcast()552 public void initializeCec_20_reportsFeaturesBroadcast() { 553 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 554 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION, 555 HdmiControlManager.HDMI_CEC_VERSION_2_0); 556 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); 557 mHdmiControlServiceSpy.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); 558 mTestLooper.dispatchAll(); 559 560 HdmiCecMessage reportFeatures = ReportFeaturesMessage.build( 561 Constants.ADDR_PLAYBACK_1, HdmiControlManager.HDMI_CEC_VERSION_2_0, 562 Arrays.asList(DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM), 563 mPlaybackDeviceSpy.getRcProfile(), mPlaybackDeviceSpy.getRcFeatures(), 564 mPlaybackDeviceSpy.getDeviceFeatures()); 565 assertThat(mNativeWrapper.getResultMessages()).contains(reportFeatures); 566 } 567 568 @Test runOnServiceThread_preservesAndRestoresWorkSourceUid()569 public void runOnServiceThread_preservesAndRestoresWorkSourceUid() { 570 int callerUid = 1234; 571 int runnerUid = 5678; 572 573 Binder.setCallingWorkSourceUid(callerUid); 574 WorkSourceUidReadingRunnable uidReadingRunnable = new WorkSourceUidReadingRunnable(); 575 mHdmiControlServiceSpy.runOnServiceThread(uidReadingRunnable); 576 577 Binder.setCallingWorkSourceUid(runnerUid); 578 579 mTestLooper.dispatchAll(); 580 581 assertEquals(Optional.of(callerUid), uidReadingRunnable.getWorkSourceUid()); 582 assertEquals(runnerUid, Binder.getCallingWorkSourceUid()); 583 } 584 585 @Test initCecVersion_limitToMinimumSupportedVersion()586 public void initCecVersion_limitToMinimumSupportedVersion() { 587 mNativeWrapper.setCecVersion(HdmiControlManager.HDMI_CEC_VERSION_1_4_B); 588 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 589 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION, 590 HdmiControlManager.HDMI_CEC_VERSION_2_0); 591 592 mTestLooper.dispatchAll(); 593 assertThat(mHdmiControlServiceSpy.getCecVersion()).isEqualTo( 594 HdmiControlManager.HDMI_CEC_VERSION_1_4_B); 595 } 596 597 @Test initCecVersion_limitToAtLeast1_4()598 public void initCecVersion_limitToAtLeast1_4() { 599 mNativeWrapper.setCecVersion(0x0); 600 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 601 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION, 602 HdmiControlManager.HDMI_CEC_VERSION_2_0); 603 604 mTestLooper.dispatchAll(); 605 assertThat(mHdmiControlServiceSpy.getCecVersion()).isEqualTo( 606 HdmiControlManager.HDMI_CEC_VERSION_1_4_B); 607 } 608 609 @Test initCecVersion_useHighestMatchingVersion()610 public void initCecVersion_useHighestMatchingVersion() { 611 mNativeWrapper.setCecVersion(HdmiControlManager.HDMI_CEC_VERSION_2_0); 612 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 613 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION, 614 HdmiControlManager.HDMI_CEC_VERSION_2_0); 615 616 mTestLooper.dispatchAll(); 617 assertThat(mHdmiControlServiceSpy.getCecVersion()).isEqualTo( 618 HdmiControlManager.HDMI_CEC_VERSION_2_0); 619 } 620 621 @Test initCec_statusListener_CecDisabled()622 public void initCec_statusListener_CecDisabled() { 623 HdmiControlStatusCallback hdmiControlStatusCallback = new HdmiControlStatusCallback(); 624 625 mHdmiControlServiceSpy.addHdmiControlStatusChangeListener(hdmiControlStatusCallback); 626 627 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 628 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED, 629 HdmiControlManager.HDMI_CEC_CONTROL_DISABLED); 630 mTestLooper.dispatchAll(); 631 632 assertThat(hdmiControlStatusCallback.mCecEnabled).isFalse(); 633 assertThat(hdmiControlStatusCallback.mCecAvailable).isFalse(); 634 } 635 636 @Test initCec_statusListener_CecEnabled_NoCecResponse()637 public void initCec_statusListener_CecEnabled_NoCecResponse() { 638 HdmiControlStatusCallback hdmiControlStatusCallback = new HdmiControlStatusCallback(); 639 640 mHdmiControlServiceSpy.addHdmiControlStatusChangeListener(hdmiControlStatusCallback); 641 642 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 643 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED, 644 HdmiControlManager.HDMI_CEC_CONTROL_DISABLED); 645 mTestLooper.dispatchAll(); 646 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 647 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED, 648 HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); 649 mTestLooper.dispatchAll(); 650 // Hit timeout twice due to retries 651 mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS); 652 mTestLooper.dispatchAll(); 653 mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS); 654 mTestLooper.dispatchAll(); 655 656 assertThat(hdmiControlStatusCallback.mCecEnabled).isTrue(); 657 assertThat(hdmiControlStatusCallback.mCecAvailable).isFalse(); 658 } 659 660 @Test initCec_statusListener_CecEnabled_CecAvailable_TvOn()661 public void initCec_statusListener_CecEnabled_CecAvailable_TvOn() { 662 HdmiControlStatusCallback hdmiControlStatusCallback = new HdmiControlStatusCallback(); 663 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_DISABLED); 664 mTestLooper.dispatchAll(); 665 666 mHdmiControlServiceSpy.addHdmiControlStatusChangeListener(hdmiControlStatusCallback); 667 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); 668 mHdmiControlServiceSpy.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); 669 mTestLooper.dispatchAll(); 670 671 HdmiCecMessage reportPowerStatus = 672 HdmiCecMessageBuilder.buildReportPowerStatus( 673 Constants.ADDR_TV, 674 mHdmiControlServiceSpy.playback().getDeviceInfo().getLogicalAddress(), 675 HdmiControlManager.POWER_STATUS_ON); 676 mNativeWrapper.onCecMessage(reportPowerStatus); 677 mTestLooper.dispatchAll(); 678 679 assertThat(hdmiControlStatusCallback.mCecEnabled).isTrue(); 680 assertThat(hdmiControlStatusCallback.mCecAvailable).isTrue(); 681 } 682 683 @Test initCec_statusListener_CecEnabled_CecAvailable_TvStandby()684 public void initCec_statusListener_CecEnabled_CecAvailable_TvStandby() { 685 HdmiControlStatusCallback hdmiControlStatusCallback = new HdmiControlStatusCallback(); 686 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_DISABLED); 687 mTestLooper.dispatchAll(); 688 689 mHdmiControlServiceSpy.addHdmiControlStatusChangeListener(hdmiControlStatusCallback); 690 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); 691 mHdmiControlServiceSpy.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); 692 mTestLooper.dispatchAll(); 693 694 HdmiCecMessage reportPowerStatus = 695 HdmiCecMessageBuilder.buildReportPowerStatus( 696 Constants.ADDR_TV, 697 mHdmiControlServiceSpy.playback().getDeviceInfo().getLogicalAddress(), 698 HdmiControlManager.POWER_STATUS_STANDBY); 699 mNativeWrapper.onCecMessage(reportPowerStatus); 700 mTestLooper.dispatchAll(); 701 702 assertThat(hdmiControlStatusCallback.mCecEnabled).isTrue(); 703 assertThat(hdmiControlStatusCallback.mCecAvailable).isTrue(); 704 } 705 706 @Test initCec_statusListener_CecEnabled_CecAvailable_TvTransientToOn()707 public void initCec_statusListener_CecEnabled_CecAvailable_TvTransientToOn() { 708 HdmiControlStatusCallback hdmiControlStatusCallback = new HdmiControlStatusCallback(); 709 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_DISABLED); 710 mTestLooper.dispatchAll(); 711 712 mHdmiControlServiceSpy.addHdmiControlStatusChangeListener(hdmiControlStatusCallback); 713 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); 714 mHdmiControlServiceSpy.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); 715 mTestLooper.dispatchAll(); 716 717 HdmiCecMessage reportPowerStatus = 718 HdmiCecMessageBuilder.buildReportPowerStatus( 719 Constants.ADDR_TV, 720 mHdmiControlServiceSpy.playback().getDeviceInfo().getLogicalAddress(), 721 HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON); 722 mNativeWrapper.onCecMessage(reportPowerStatus); 723 mTestLooper.dispatchAll(); 724 725 assertThat(hdmiControlStatusCallback.mCecEnabled).isTrue(); 726 assertThat(hdmiControlStatusCallback.mCecAvailable).isTrue(); 727 } 728 729 @Test initCec_statusListener_CecEnabled_CecAvailable_TvTransientToStandby()730 public void initCec_statusListener_CecEnabled_CecAvailable_TvTransientToStandby() { 731 HdmiControlStatusCallback hdmiControlStatusCallback = new HdmiControlStatusCallback(); 732 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_DISABLED); 733 mTestLooper.dispatchAll(); 734 735 mHdmiControlServiceSpy.addHdmiControlStatusChangeListener(hdmiControlStatusCallback); 736 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); 737 mHdmiControlServiceSpy.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); 738 mTestLooper.dispatchAll(); 739 740 HdmiCecMessage reportPowerStatus = 741 HdmiCecMessageBuilder.buildReportPowerStatus( 742 Constants.ADDR_TV, 743 mHdmiControlServiceSpy.playback().getDeviceInfo().getLogicalAddress(), 744 HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY); 745 mNativeWrapper.onCecMessage(reportPowerStatus); 746 mTestLooper.dispatchAll(); 747 748 assertThat(hdmiControlStatusCallback.mCecEnabled).isTrue(); 749 assertThat(hdmiControlStatusCallback.mCecAvailable).isTrue(); 750 } 751 752 @Test handleCecCommand_errorParameter_returnsAbortInvalidOperand()753 public void handleCecCommand_errorParameter_returnsAbortInvalidOperand() { 754 // Validity ERROR_PARAMETER. Taken from HdmiCecMessageValidatorTest#isValid_menuStatus 755 HdmiCecMessage message = HdmiUtils.buildMessage("80:8D:03"); 756 757 assertThat(mHdmiControlServiceSpy.handleCecCommand(message)) 758 .isEqualTo(Constants.ABORT_INVALID_OPERAND); 759 760 // Validating ERROR_PARAMETER_LONG will generate ABORT_INVALID_OPERAND. 761 // Taken from HdmiCecMessageValidatorTest#isValid_systemAudioModeStatus 762 HdmiCecMessage systemAudioModeStatus = HdmiUtils.buildMessage("40:7E:01:1F:28"); 763 764 assertThat(mHdmiControlServiceSpy.handleCecCommand(systemAudioModeStatus)) 765 .isEqualTo(Constants.ABORT_INVALID_OPERAND); 766 } 767 768 @Test handleCecCommand_errorSource_returnsHandled()769 public void handleCecCommand_errorSource_returnsHandled() { 770 // Validity ERROR_SOURCE. Taken from HdmiCecMessageValidatorTest#isValid_menuStatus 771 HdmiCecMessage message = HdmiUtils.buildMessage("F0:8E"); 772 773 assertThat(mHdmiControlServiceSpy.handleCecCommand(message)) 774 .isEqualTo(Constants.HANDLED); 775 776 } 777 778 @Test handleCecCommand_errorDestination_returnsHandled()779 public void handleCecCommand_errorDestination_returnsHandled() { 780 // Validity ERROR_DESTINATION. Taken from HdmiCecMessageValidatorTest#isValid_menuStatus 781 HdmiCecMessage message = HdmiUtils.buildMessage("0F:8E:00"); 782 783 assertThat(mHdmiControlServiceSpy.handleCecCommand(message)) 784 .isEqualTo(Constants.HANDLED); 785 } 786 787 @Test handleCecCommand_errorParameterShort_returnsHandled()788 public void handleCecCommand_errorParameterShort_returnsHandled() { 789 // Validity ERROR_PARAMETER_SHORT 790 // Taken from HdmiCecMessageValidatorTest#isValid_menuStatus 791 HdmiCecMessage message = HdmiUtils.buildMessage("40:8E"); 792 793 assertThat(mHdmiControlServiceSpy.handleCecCommand(message)) 794 .isEqualTo(Constants.HANDLED); 795 } 796 797 @Test handleCecCommand_notHandledByLocalDevice_returnsNotHandled()798 public void handleCecCommand_notHandledByLocalDevice_returnsNotHandled() { 799 HdmiCecMessage message = HdmiCecMessageBuilder.buildReportPowerStatus( 800 Constants.ADDR_TV, 801 Constants.ADDR_PLAYBACK_1, 802 HdmiControlManager.POWER_STATUS_ON); 803 804 doReturn(Constants.NOT_HANDLED).when(mHdmiControlServiceSpy) 805 .dispatchMessageToLocalDevice(message); 806 807 assertThat(mHdmiControlServiceSpy.handleCecCommand(message)) 808 .isEqualTo(Constants.NOT_HANDLED); 809 } 810 811 @Test handleCecCommand_handledByLocalDevice_returnsHandled()812 public void handleCecCommand_handledByLocalDevice_returnsHandled() { 813 HdmiCecMessage message = HdmiCecMessageBuilder.buildReportPowerStatus( 814 Constants.ADDR_TV, 815 Constants.ADDR_PLAYBACK_1, 816 HdmiControlManager.POWER_STATUS_ON); 817 818 doReturn(Constants.HANDLED).when(mHdmiControlServiceSpy) 819 .dispatchMessageToLocalDevice(message); 820 821 assertThat(mHdmiControlServiceSpy.handleCecCommand(message)) 822 .isEqualTo(Constants.HANDLED); 823 } 824 825 @Test handleCecCommand_localDeviceReturnsFeatureAbort_returnsFeatureAbort()826 public void handleCecCommand_localDeviceReturnsFeatureAbort_returnsFeatureAbort() { 827 HdmiCecMessage message = HdmiCecMessageBuilder.buildReportPowerStatus( 828 Constants.ADDR_TV, 829 Constants.ADDR_PLAYBACK_1, 830 HdmiControlManager.POWER_STATUS_ON); 831 832 doReturn(Constants.ABORT_REFUSED).when(mHdmiControlServiceSpy) 833 .dispatchMessageToLocalDevice(message); 834 835 assertThat(mHdmiControlServiceSpy.handleCecCommand(message)) 836 .isEqualTo(Constants.ABORT_REFUSED); 837 } 838 839 @Test addVendorCommandListener_receiveCallback_VendorCmdNoIdTest()840 public void addVendorCommandListener_receiveCallback_VendorCmdNoIdTest() { 841 int destAddress = mHdmiControlServiceSpy.playback().getDeviceInfo().getLogicalAddress(); 842 int sourceAddress = Constants.ADDR_TV; 843 byte[] params = {0x00, 0x01, 0x02, 0x03}; 844 int vendorId = 0x123456; 845 mHdmiControlServiceSpy.setPowerStatus(HdmiControlManager.POWER_STATUS_ON); 846 847 VendorCommandListener vendorCmdListener = 848 new VendorCommandListener(sourceAddress, destAddress, params, vendorId); 849 mHdmiControlServiceSpy.addVendorCommandListener(vendorCmdListener, vendorId); 850 mTestLooper.dispatchAll(); 851 852 HdmiCecMessage vendorCommandNoId = 853 HdmiCecMessageBuilder.buildVendorCommand(sourceAddress, destAddress, params); 854 mNativeWrapper.onCecMessage(vendorCommandNoId); 855 mTestLooper.dispatchAll(); 856 assertThat(vendorCmdListener.mVendorCommandCallbackReceived).isTrue(); 857 assertThat(vendorCmdListener.mParamsCorrect).isTrue(); 858 assertThat(vendorCmdListener.mHasVendorId).isFalse(); 859 } 860 861 @Test addVendorCommandListener_receiveCallback_VendorCmdWithIdTest()862 public void addVendorCommandListener_receiveCallback_VendorCmdWithIdTest() { 863 int destAddress = mHdmiControlServiceSpy.playback().getDeviceInfo().getLogicalAddress(); 864 int sourceAddress = Constants.ADDR_TV; 865 byte[] params = {0x00, 0x01, 0x02, 0x03}; 866 int vendorId = 0x123456; 867 mHdmiControlServiceSpy.setPowerStatus(HdmiControlManager.POWER_STATUS_ON); 868 869 VendorCommandListener vendorCmdListener = 870 new VendorCommandListener(sourceAddress, destAddress, params, vendorId); 871 mHdmiControlServiceSpy.addVendorCommandListener(vendorCmdListener, vendorId); 872 mTestLooper.dispatchAll(); 873 874 HdmiCecMessage vendorCommandWithId = 875 HdmiCecMessageBuilder.buildVendorCommandWithId( 876 sourceAddress, destAddress, vendorId, params); 877 mNativeWrapper.onCecMessage(vendorCommandWithId); 878 mTestLooper.dispatchAll(); 879 assertThat(vendorCmdListener.mVendorCommandCallbackReceived).isTrue(); 880 assertThat(vendorCmdListener.mParamsCorrect).isTrue(); 881 assertThat(vendorCmdListener.mHasVendorId).isTrue(); 882 } 883 884 @Test addVendorCommandListener_noCallback_VendorCmdDiffIdTest()885 public void addVendorCommandListener_noCallback_VendorCmdDiffIdTest() { 886 int destAddress = mHdmiControlServiceSpy.playback().getDeviceInfo().getLogicalAddress(); 887 int sourceAddress = Constants.ADDR_TV; 888 byte[] params = {0x00, 0x01, 0x02, 0x03}; 889 int vendorId = 0x123456; 890 int diffVendorId = 0x345678; 891 mHdmiControlServiceSpy.setPowerStatus(HdmiControlManager.POWER_STATUS_ON); 892 893 VendorCommandListener vendorCmdListener = 894 new VendorCommandListener(sourceAddress, destAddress, params, vendorId); 895 mHdmiControlServiceSpy.addVendorCommandListener(vendorCmdListener, vendorId); 896 mTestLooper.dispatchAll(); 897 898 HdmiCecMessage vendorCommandWithDiffId = 899 HdmiCecMessageBuilder.buildVendorCommandWithId( 900 sourceAddress, destAddress, diffVendorId, params); 901 mNativeWrapper.onCecMessage(vendorCommandWithDiffId); 902 mTestLooper.dispatchAll(); 903 assertThat(vendorCmdListener.mVendorCommandCallbackReceived).isFalse(); 904 } 905 906 private static class VendorCommandListener extends IHdmiVendorCommandListener.Stub { 907 boolean mVendorCommandCallbackReceived = false; 908 boolean mParamsCorrect = false; 909 boolean mHasVendorId = false; 910 911 int mSourceAddress; 912 int mDestAddress; 913 byte[] mParams; 914 int mVendorId; 915 VendorCommandListener(int sourceAddress, int destAddress, byte[] params, int vendorId)916 VendorCommandListener(int sourceAddress, int destAddress, byte[] params, int vendorId) { 917 this.mSourceAddress = sourceAddress; 918 this.mDestAddress = destAddress; 919 this.mParams = params.clone(); 920 this.mVendorId = vendorId; 921 } 922 923 @Override onReceived( int sourceAddress, int destAddress, byte[] params, boolean hasVendorId)924 public void onReceived( 925 int sourceAddress, int destAddress, byte[] params, boolean hasVendorId) { 926 mVendorCommandCallbackReceived = true; 927 if (mSourceAddress == sourceAddress && mDestAddress == destAddress) { 928 byte[] expectedParams; 929 if (hasVendorId) { 930 // If the command has vendor ID, we have to add it to mParams. 931 expectedParams = new byte[params.length]; 932 expectedParams[0] = (byte) ((mVendorId >> 16) & 0xFF); 933 expectedParams[1] = (byte) ((mVendorId >> 8) & 0xFF); 934 expectedParams[2] = (byte) (mVendorId & 0xFF); 935 System.arraycopy(mParams, 0, expectedParams, 3, mParams.length); 936 } else { 937 expectedParams = params.clone(); 938 } 939 if (Arrays.equals(expectedParams, params)) { 940 mParamsCorrect = true; 941 } 942 } 943 mHasVendorId = hasVendorId; 944 } 945 946 @Override onControlStateChanged(boolean enabled, int reason)947 public void onControlStateChanged(boolean enabled, int reason) {} 948 } 949 950 @Test dispatchMessageToLocalDevice_broadcastMessage_returnsHandled()951 public void dispatchMessageToLocalDevice_broadcastMessage_returnsHandled() { 952 HdmiCecMessage message = HdmiCecMessageBuilder.buildStandby( 953 Constants.ADDR_TV, 954 Constants.ADDR_BROADCAST); 955 956 doReturn(Constants.ABORT_REFUSED).when(mPlaybackDeviceSpy).dispatchMessage(message); 957 doReturn(Constants.ABORT_NOT_IN_CORRECT_MODE) 958 .when(mAudioSystemDeviceSpy).dispatchMessage(message); 959 960 assertThat(mHdmiControlServiceSpy.dispatchMessageToLocalDevice(message)) 961 .isEqualTo(Constants.HANDLED); 962 } 963 964 @Test dispatchMessageToLocalDevice_localDevicesDoNotHandleMessage_returnsUnhandled()965 public void dispatchMessageToLocalDevice_localDevicesDoNotHandleMessage_returnsUnhandled() { 966 HdmiCecMessage message = HdmiCecMessageBuilder.buildStandby( 967 Constants.ADDR_TV, 968 Constants.ADDR_PLAYBACK_1); 969 970 doReturn(Constants.NOT_HANDLED).when(mPlaybackDeviceSpy).dispatchMessage(message); 971 doReturn(Constants.NOT_HANDLED) 972 .when(mAudioSystemDeviceSpy).dispatchMessage(message); 973 974 assertThat(mHdmiControlServiceSpy.dispatchMessageToLocalDevice(message)) 975 .isEqualTo(Constants.NOT_HANDLED); 976 } 977 978 @Test dispatchMessageToLocalDevice_localDeviceHandlesMessage_returnsHandled()979 public void dispatchMessageToLocalDevice_localDeviceHandlesMessage_returnsHandled() { 980 HdmiCecMessage message = HdmiCecMessageBuilder.buildStandby( 981 Constants.ADDR_TV, 982 Constants.ADDR_PLAYBACK_1); 983 984 doReturn(Constants.NOT_HANDLED).when(mPlaybackDeviceSpy).dispatchMessage(message); 985 doReturn(Constants.HANDLED) 986 .when(mAudioSystemDeviceSpy).dispatchMessage(message); 987 988 assertThat(mHdmiControlServiceSpy.dispatchMessageToLocalDevice(message)) 989 .isEqualTo(Constants.HANDLED); 990 } 991 992 @Test dispatchMessageToLocalDevice_localDeviceReturnsFeatureAbort_returnsFeatureAbort()993 public void dispatchMessageToLocalDevice_localDeviceReturnsFeatureAbort_returnsFeatureAbort() { 994 HdmiCecMessage message = HdmiCecMessageBuilder.buildStandby( 995 Constants.ADDR_TV, 996 Constants.ADDR_PLAYBACK_1); 997 998 doReturn(Constants.NOT_HANDLED).when(mPlaybackDeviceSpy).dispatchMessage(message); 999 doReturn(Constants.ABORT_REFUSED) 1000 .when(mAudioSystemDeviceSpy).dispatchMessage(message); 1001 1002 assertThat(mHdmiControlServiceSpy.dispatchMessageToLocalDevice(message)) 1003 .isEqualTo(Constants.ABORT_REFUSED); 1004 } 1005 1006 @Test readDeviceTypes_readsIntegerDeviceTypes()1007 public void readDeviceTypes_readsIntegerDeviceTypes() { 1008 doReturn(Arrays.asList(new Integer[]{DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM})) 1009 .when(mHdmiControlServiceSpy).getDeviceTypes(); 1010 doReturn(Arrays.asList(new HdmiProperties.cec_device_types_values[]{})) 1011 .when(mHdmiControlServiceSpy).getCecDeviceTypes(); 1012 1013 assertThat(mHdmiControlServiceSpy.readDeviceTypes()) 1014 .containsExactly(DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM); 1015 } 1016 1017 @Test readDeviceTypes_readsEnumDeviceTypes()1018 public void readDeviceTypes_readsEnumDeviceTypes() { 1019 doReturn(Arrays.asList(new Integer[]{})).when(mHdmiControlServiceSpy).getDeviceTypes(); 1020 doReturn(Arrays.asList( 1021 new HdmiProperties.cec_device_types_values[]{ 1022 HdmiProperties.cec_device_types_values.PLAYBACK_DEVICE, 1023 HdmiProperties.cec_device_types_values.AUDIO_SYSTEM 1024 })) 1025 .when(mHdmiControlServiceSpy).getCecDeviceTypes(); 1026 1027 assertThat(mHdmiControlServiceSpy.readDeviceTypes()) 1028 .containsExactly(DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM); 1029 } 1030 1031 @Test readDeviceTypes_readsEnumOverIntegerDeviceTypes()1032 public void readDeviceTypes_readsEnumOverIntegerDeviceTypes() { 1033 doReturn(Arrays.asList(new Integer[]{DEVICE_TV})) 1034 .when(mHdmiControlServiceSpy).getDeviceTypes(); 1035 doReturn(Arrays.asList( 1036 new HdmiProperties.cec_device_types_values[]{ 1037 HdmiProperties.cec_device_types_values.PLAYBACK_DEVICE, 1038 HdmiProperties.cec_device_types_values.AUDIO_SYSTEM 1039 })) 1040 .when(mHdmiControlServiceSpy).getCecDeviceTypes(); 1041 1042 assertThat(mHdmiControlServiceSpy.readDeviceTypes()) 1043 .containsExactly(DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM); 1044 } 1045 1046 @Test readDeviceTypes_doesNotReadNullEnumDeviceType()1047 public void readDeviceTypes_doesNotReadNullEnumDeviceType() { 1048 doReturn(Arrays.asList(new Integer[]{})).when(mHdmiControlServiceSpy).getDeviceTypes(); 1049 doReturn(Arrays.asList( 1050 new HdmiProperties.cec_device_types_values[]{ 1051 HdmiProperties.cec_device_types_values.PLAYBACK_DEVICE, 1052 HdmiProperties.cec_device_types_values.AUDIO_SYSTEM, 1053 null 1054 })) 1055 .when(mHdmiControlServiceSpy).getCecDeviceTypes(); 1056 1057 assertThat(mHdmiControlServiceSpy.readDeviceTypes()) 1058 .containsExactly(DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM); 1059 } 1060 1061 @Test readDeviceTypes_doesNotReadNullIntegerDeviceType()1062 public void readDeviceTypes_doesNotReadNullIntegerDeviceType() { 1063 doReturn(Arrays.asList(new Integer[]{DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM, null})) 1064 .when(mHdmiControlServiceSpy).getDeviceTypes(); 1065 doReturn(Arrays.asList(new HdmiProperties.cec_device_types_values[]{})) 1066 .when(mHdmiControlServiceSpy).getCecDeviceTypes(); 1067 1068 assertThat(mHdmiControlServiceSpy.readDeviceTypes()) 1069 .containsExactly(DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM); 1070 } 1071 1072 @Test setSoundbarMode_enabled_addAudioSystemLocalDevice()1073 public void setSoundbarMode_enabled_addAudioSystemLocalDevice() { 1074 mHdmiControlServiceSpy.setPowerStatus(HdmiControlManager.POWER_STATUS_ON); 1075 // Initialize the local devices excluding the audio system. 1076 mHdmiControlServiceSpy.clearCecLocalDevices(); 1077 mLocalDevices.remove(mAudioSystemDeviceSpy); 1078 mHdmiControlServiceSpy.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); 1079 mTestLooper.dispatchAll(); 1080 assertThat(mHdmiControlServiceSpy.audioSystem()).isNull(); 1081 1082 // Enable the setting and check if the audio system local device is found in the network. 1083 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 1084 HdmiControlManager.CEC_SETTING_NAME_SOUNDBAR_MODE, 1085 HdmiControlManager.SOUNDBAR_MODE_ENABLED); 1086 mTestLooper.dispatchAll(); 1087 assertThat(mHdmiControlServiceSpy.audioSystem()).isNotNull(); 1088 } 1089 1090 @Test setSoundbarMode_disabled_removeAudioSystemLocalDevice()1091 public void setSoundbarMode_disabled_removeAudioSystemLocalDevice() { 1092 mHdmiControlServiceSpy.setPowerStatus(HdmiControlManager.POWER_STATUS_ON); 1093 // Initialize the local devices excluding the audio system. 1094 mHdmiControlServiceSpy.clearCecLocalDevices(); 1095 mLocalDevices.remove(mAudioSystemDeviceSpy); 1096 mHdmiControlServiceSpy.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); 1097 mTestLooper.dispatchAll(); 1098 assertThat(mHdmiControlServiceSpy.audioSystem()).isNull(); 1099 1100 // Enable the setting and check if the audio system local device is found in the network. 1101 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 1102 HdmiControlManager.CEC_SETTING_NAME_SOUNDBAR_MODE, 1103 HdmiControlManager.SOUNDBAR_MODE_ENABLED); 1104 mTestLooper.dispatchAll(); 1105 assertThat(mHdmiControlServiceSpy.audioSystem()).isNotNull(); 1106 1107 // Disable the setting and check if the audio system local device is removed from the 1108 // network. 1109 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 1110 HdmiControlManager.CEC_SETTING_NAME_SOUNDBAR_MODE, 1111 HdmiControlManager.SOUNDBAR_MODE_DISABLED); 1112 mTestLooper.dispatchAll(); 1113 1114 // Wait for ArcTerminationActionFromAvr timeout for the logical address allocation to start. 1115 mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS); 1116 mTestLooper.dispatchAll(); 1117 assertThat(mHdmiControlServiceSpy.audioSystem()).isNull(); 1118 } 1119 1120 @Test disableEarc_clearEarcLocalDevice()1121 public void disableEarc_clearEarcLocalDevice() { 1122 mHdmiControlServiceSpy.clearEarcLocalDevice(); 1123 mHdmiControlServiceSpy.addEarcLocalDevice( 1124 new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy)); 1125 assertThat(mHdmiControlServiceSpy.getEarcLocalDevice()).isNotNull(); 1126 1127 mHdmiControlServiceSpy.setEarcEnabled(HdmiControlManager.EARC_FEATURE_DISABLED); 1128 mTestLooper.dispatchAll(); 1129 assertThat(mHdmiControlServiceSpy.getEarcLocalDevice()).isNull(); 1130 } 1131 1132 @Test disableEarc_noEarcLocalDevice_enableArc()1133 public void disableEarc_noEarcLocalDevice_enableArc() { 1134 mHdmiControlServiceSpy.clearEarcLocalDevice(); 1135 mHdmiControlServiceSpy.addEarcLocalDevice( 1136 new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy)); 1137 mHdmiControlServiceSpy.setEarcEnabled(HdmiControlManager.EARC_FEATURE_DISABLED); 1138 mTestLooper.dispatchAll(); 1139 assertThat(mHdmiControlServiceSpy.getEarcLocalDevice()).isNull(); 1140 1141 Mockito.clearInvocations(mHdmiControlServiceSpy); 1142 mHdmiControlServiceSpy.handleEarcStateChange(Constants.HDMI_EARC_STATUS_ARC_PENDING, 1143 PORT_ID_EARC_SUPPORTED); 1144 verify(mHdmiControlServiceSpy, times(1)) 1145 .notifyEarcStatusToAudioService(eq(false), eq(new ArrayList<>())); 1146 verify(mHdmiControlServiceSpy, times(1)).startArcAction(eq(true), any()); 1147 } 1148 1149 @Test disableCec_doNotClearEarcLocalDevice()1150 public void disableCec_doNotClearEarcLocalDevice() { 1151 mHdmiControlServiceSpy.clearEarcLocalDevice(); 1152 mHdmiControlServiceSpy.addEarcLocalDevice( 1153 new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy)); 1154 assertThat(mHdmiControlServiceSpy.getEarcLocalDevice()).isNotNull(); 1155 1156 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_DISABLED); 1157 mTestLooper.dispatchAll(); 1158 assertThat(mHdmiControlServiceSpy.getEarcLocalDevice()).isNotNull(); 1159 } 1160 1161 @Test enableCec_initializeCecLocalDevices()1162 public void enableCec_initializeCecLocalDevices() { 1163 Mockito.clearInvocations(mHdmiControlServiceSpy); 1164 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_DISABLED); 1165 mTestLooper.dispatchAll(); 1166 mHdmiControlServiceSpy.setCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); 1167 mTestLooper.dispatchAll(); 1168 verify(mHdmiControlServiceSpy, times(1)).initializeCecLocalDevices(anyInt()); 1169 verify(mHdmiControlServiceSpy, times(0)).initializeEarcLocalDevice(anyInt()); 1170 } 1171 1172 @Test enableEarc_initializeEarcLocalDevices()1173 public void enableEarc_initializeEarcLocalDevices() { 1174 Mockito.clearInvocations(mHdmiControlServiceSpy); 1175 mHdmiControlServiceSpy.setEarcEnabled(HdmiControlManager.EARC_FEATURE_DISABLED); 1176 mTestLooper.dispatchAll(); 1177 mHdmiControlServiceSpy.setEarcEnabled(HdmiControlManager.EARC_FEATURE_ENABLED); 1178 mTestLooper.dispatchAll(); 1179 verify(mHdmiControlServiceSpy, times(0)).initializeCecLocalDevices(anyInt()); 1180 verify(mHdmiControlServiceSpy, times(1)).initializeEarcLocalDevice(anyInt()); 1181 } 1182 1183 @Test disableCec_DoNotInformHalAboutEarc()1184 public void disableCec_DoNotInformHalAboutEarc() { 1185 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 1186 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED, 1187 HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); 1188 mTestLooper.dispatchAll(); 1189 Mockito.clearInvocations(mHdmiControlServiceSpy); 1190 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 1191 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED, 1192 HdmiControlManager.HDMI_CEC_CONTROL_DISABLED); 1193 mTestLooper.dispatchAll(); 1194 verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(anyBoolean(), anyBoolean()); 1195 } 1196 1197 @Test disableEarc_informHalAboutEarc()1198 public void disableEarc_informHalAboutEarc() { 1199 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 1200 HdmiControlManager.SETTING_NAME_EARC_ENABLED, 1201 HdmiControlManager.EARC_FEATURE_ENABLED); 1202 mTestLooper.dispatchAll(); 1203 Mockito.clearInvocations(mHdmiControlServiceSpy); 1204 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 1205 HdmiControlManager.SETTING_NAME_EARC_ENABLED, 1206 HdmiControlManager.EARC_FEATURE_DISABLED); 1207 mTestLooper.dispatchAll(); 1208 verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(false, false); 1209 verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(eq(true), anyBoolean()); 1210 } 1211 1212 @Test enableCec_DoNotInformHalAboutEarc()1213 public void enableCec_DoNotInformHalAboutEarc() { 1214 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 1215 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED, 1216 HdmiControlManager.HDMI_CEC_CONTROL_DISABLED); 1217 mTestLooper.dispatchAll(); 1218 Mockito.clearInvocations(mHdmiControlServiceSpy); 1219 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 1220 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED, 1221 HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); 1222 mTestLooper.dispatchAll(); 1223 verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(anyBoolean(), anyBoolean()); 1224 } 1225 1226 @Test enableEarc_informHalAboutEarc()1227 public void enableEarc_informHalAboutEarc() { 1228 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 1229 HdmiControlManager.SETTING_NAME_EARC_ENABLED, 1230 HdmiControlManager.EARC_FEATURE_DISABLED); 1231 mTestLooper.dispatchAll(); 1232 Mockito.clearInvocations(mHdmiControlServiceSpy); 1233 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 1234 HdmiControlManager.SETTING_NAME_EARC_ENABLED, 1235 HdmiControlManager.EARC_FEATURE_ENABLED); 1236 mTestLooper.dispatchAll(); 1237 verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(true, true); 1238 verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(eq(false), anyBoolean()); 1239 } 1240 1241 @Test bootWithEarcEnabled_informHalAboutEarc()1242 public void bootWithEarcEnabled_informHalAboutEarc() { 1243 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 1244 HdmiControlManager.SETTING_NAME_EARC_ENABLED, 1245 HdmiControlManager.EARC_FEATURE_ENABLED); 1246 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 1247 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED, 1248 HdmiControlManager.HDMI_CEC_CONTROL_DISABLED); 1249 mTestLooper.dispatchAll(); 1250 Mockito.clearInvocations(mHdmiControlServiceSpy); 1251 mHdmiControlServiceSpy.initService(); 1252 mTestLooper.dispatchAll(); 1253 verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(true, false); 1254 verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(eq(false), anyBoolean()); 1255 } 1256 1257 @Test bootWithEarcDisabled_informHalAboutEarc()1258 public void bootWithEarcDisabled_informHalAboutEarc() { 1259 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 1260 HdmiControlManager.SETTING_NAME_EARC_ENABLED, 1261 HdmiControlManager.EARC_FEATURE_DISABLED); 1262 mTestLooper.dispatchAll(); 1263 Mockito.clearInvocations(mHdmiControlServiceSpy); 1264 mHdmiControlServiceSpy.initService(); 1265 mTestLooper.dispatchAll(); 1266 verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(false, false); 1267 verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(eq(true), anyBoolean()); 1268 } 1269 1270 @Test wakeUpWithEarcEnabled_informHalAboutEarc()1271 public void wakeUpWithEarcEnabled_informHalAboutEarc() { 1272 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 1273 HdmiControlManager.SETTING_NAME_EARC_ENABLED, 1274 HdmiControlManager.EARC_FEATURE_ENABLED); 1275 mTestLooper.dispatchAll(); 1276 Mockito.clearInvocations(mHdmiControlServiceSpy); 1277 mHdmiControlServiceSpy.onWakeUp(WAKE_UP_SCREEN_ON); 1278 mTestLooper.dispatchAll(); 1279 verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(true, false); 1280 verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(eq(false), anyBoolean()); 1281 } 1282 1283 @Test wakeUpWithEarcDisabled_informHalAboutEarc()1284 public void wakeUpWithEarcDisabled_informHalAboutEarc() { 1285 mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue( 1286 HdmiControlManager.SETTING_NAME_EARC_ENABLED, 1287 HdmiControlManager.EARC_FEATURE_DISABLED); 1288 mTestLooper.dispatchAll(); 1289 Mockito.clearInvocations(mHdmiControlServiceSpy); 1290 mHdmiControlServiceSpy.onWakeUp(WAKE_UP_SCREEN_ON); 1291 mTestLooper.dispatchAll(); 1292 verify(mHdmiControlServiceSpy, times(1)).setEarcEnabledInHal(false, false); 1293 verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(eq(true), anyBoolean()); 1294 } 1295 1296 @Test earcIdle_blocksArcConnection()1297 public void earcIdle_blocksArcConnection() { 1298 mHdmiControlServiceSpy.clearEarcLocalDevice(); 1299 HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy); 1300 localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_IDLE); 1301 mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx); 1302 assertThat(mHdmiControlServiceSpy.earcBlocksArcConnection()).isTrue(); 1303 } 1304 1305 @Test earcPending_blocksArcConnection()1306 public void earcPending_blocksArcConnection() { 1307 mHdmiControlServiceSpy.clearEarcLocalDevice(); 1308 HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy); 1309 localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_EARC_PENDING); 1310 mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx); 1311 assertThat(mHdmiControlServiceSpy.earcBlocksArcConnection()).isTrue(); 1312 } 1313 1314 @Test earcEnabled_blocksArcConnection()1315 public void earcEnabled_blocksArcConnection() { 1316 mHdmiControlServiceSpy.clearEarcLocalDevice(); 1317 HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy); 1318 localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_EARC_CONNECTED); 1319 mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx); 1320 assertThat(mHdmiControlServiceSpy.earcBlocksArcConnection()).isTrue(); 1321 } 1322 1323 @Test arcPending_doesNotBlockArcConnection()1324 public void arcPending_doesNotBlockArcConnection() { 1325 mHdmiControlServiceSpy.clearEarcLocalDevice(); 1326 HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy); 1327 localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_ARC_PENDING); 1328 mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx); 1329 assertThat(mHdmiControlServiceSpy.earcBlocksArcConnection()).isFalse(); 1330 } 1331 1332 @Test earcStatusBecomesIdle_terminateArc()1333 public void earcStatusBecomesIdle_terminateArc() { 1334 mHdmiControlServiceSpy.clearEarcLocalDevice(); 1335 HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy); 1336 mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx); 1337 localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_IDLE); 1338 verify(mHdmiControlServiceSpy, times(1)).startArcAction(eq(false), any()); 1339 } 1340 1341 @Test earcStatusBecomesEnabled_doNothing()1342 public void earcStatusBecomesEnabled_doNothing() { 1343 mHdmiControlServiceSpy.clearEarcLocalDevice(); 1344 HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy); 1345 mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx); 1346 localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_EARC_CONNECTED); 1347 verify(mHdmiControlServiceSpy, times(0)).startArcAction(anyBoolean(), any()); 1348 } 1349 1350 @Test earcStatusBecomesPending_doNothing()1351 public void earcStatusBecomesPending_doNothing() { 1352 mHdmiControlServiceSpy.clearEarcLocalDevice(); 1353 HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy); 1354 mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx); 1355 localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_EARC_PENDING); 1356 verify(mHdmiControlServiceSpy, times(0)).startArcAction(anyBoolean(), any()); 1357 } 1358 1359 @Test earcStatusBecomesNotEnabled_initiateArc()1360 public void earcStatusBecomesNotEnabled_initiateArc() { 1361 mHdmiControlServiceSpy.clearEarcLocalDevice(); 1362 HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy); 1363 mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx); 1364 localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_ARC_PENDING); 1365 verify(mHdmiControlServiceSpy, times(1)).startArcAction(eq(true), any()); 1366 } 1367 1368 @Test earcStateWasArcPending_becomesEarcPending_terminateArc()1369 public void earcStateWasArcPending_becomesEarcPending_terminateArc() { 1370 mHdmiControlServiceSpy.clearEarcLocalDevice(); 1371 HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy); 1372 mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx); 1373 localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_ARC_PENDING); 1374 mTestLooper.dispatchAll(); 1375 localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_EARC_PENDING); 1376 verify(mHdmiControlServiceSpy, times(1)).startArcAction(eq(false), any()); 1377 } 1378 1379 @Test earcStateWasArcPending_becomesEarcEnabled_terminateArc()1380 public void earcStateWasArcPending_becomesEarcEnabled_terminateArc() { 1381 mHdmiControlServiceSpy.clearEarcLocalDevice(); 1382 HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy); 1383 mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx); 1384 localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_ARC_PENDING); 1385 mTestLooper.dispatchAll(); 1386 localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_EARC_CONNECTED); 1387 verify(mHdmiControlServiceSpy, times(1)).startArcAction(eq(false), any()); 1388 } 1389 1390 protected static class MockPlaybackDevice extends HdmiCecLocalDevicePlayback { 1391 1392 private boolean mCanGoToStandby; 1393 private boolean mIsStandby; 1394 private boolean mIsDisabled; 1395 MockPlaybackDevice(HdmiControlService service)1396 MockPlaybackDevice(HdmiControlService service) { 1397 super(service); 1398 } 1399 1400 @Override onAddressAllocated(int logicalAddress, int reason)1401 protected void onAddressAllocated(int logicalAddress, int reason) { 1402 } 1403 1404 @Override getPreferredAddress()1405 protected int getPreferredAddress() { 1406 return 0; 1407 } 1408 1409 @Override setPreferredAddress(int addr)1410 protected void setPreferredAddress(int addr) { 1411 } 1412 1413 @Override canGoToStandby()1414 protected boolean canGoToStandby() { 1415 return mCanGoToStandby; 1416 } 1417 1418 @Override disableDevice( boolean initiatedByCec, final PendingActionClearedCallback originalCallback)1419 protected void disableDevice( 1420 boolean initiatedByCec, final PendingActionClearedCallback originalCallback) { 1421 mIsDisabled = true; 1422 originalCallback.onCleared(this); 1423 } 1424 1425 @Override onStandby(boolean initiatedByCec, int standbyAction)1426 protected void onStandby(boolean initiatedByCec, int standbyAction) { 1427 mIsStandby = true; 1428 } 1429 isStandby()1430 protected boolean isStandby() { 1431 return mIsStandby; 1432 } 1433 isDisabled()1434 protected boolean isDisabled() { 1435 return mIsDisabled; 1436 } 1437 setCanGoToStandby(boolean canGoToStandby)1438 protected void setCanGoToStandby(boolean canGoToStandby) { 1439 mCanGoToStandby = canGoToStandby; 1440 } 1441 } 1442 1443 protected static class MockAudioSystemDevice extends HdmiCecLocalDeviceAudioSystem { 1444 1445 private boolean mCanGoToStandby; 1446 private boolean mIsStandby; 1447 private boolean mIsDisabled; 1448 MockAudioSystemDevice(HdmiControlService service)1449 MockAudioSystemDevice(HdmiControlService service) { 1450 super(service); 1451 } 1452 1453 @Override onAddressAllocated(int logicalAddress, int reason)1454 protected void onAddressAllocated(int logicalAddress, int reason) { 1455 } 1456 1457 @Override getPreferredAddress()1458 protected int getPreferredAddress() { 1459 return 0; 1460 } 1461 1462 @Override setPreferredAddress(int addr)1463 protected void setPreferredAddress(int addr) { 1464 } 1465 1466 @Override canGoToStandby()1467 protected boolean canGoToStandby() { 1468 return mCanGoToStandby; 1469 } 1470 1471 @Override disableDevice( boolean initiatedByCec, final PendingActionClearedCallback originalCallback)1472 protected void disableDevice( 1473 boolean initiatedByCec, final PendingActionClearedCallback originalCallback) { 1474 mIsDisabled = true; 1475 originalCallback.onCleared(this); 1476 } 1477 1478 @Override onStandby(boolean initiatedByCec, int standbyAction)1479 protected void onStandby(boolean initiatedByCec, int standbyAction) { 1480 mIsStandby = true; 1481 } 1482 isStandby()1483 protected boolean isStandby() { 1484 return mIsStandby; 1485 } 1486 isDisabled()1487 protected boolean isDisabled() { 1488 return mIsDisabled; 1489 } 1490 setCanGoToStandby(boolean canGoToStandby)1491 protected void setCanGoToStandby(boolean canGoToStandby) { 1492 mCanGoToStandby = canGoToStandby; 1493 } 1494 } 1495 1496 private static class HdmiControlStatusCallback extends IHdmiControlStatusChangeListener.Stub { 1497 boolean mCecEnabled = false; 1498 boolean mCecAvailable = false; 1499 1500 @Override onStatusChange(int isCecEnabled, boolean isCecAvailable)1501 public void onStatusChange(int isCecEnabled, boolean isCecAvailable) 1502 throws RemoteException { 1503 mCecEnabled = isCecEnabled == HdmiControlManager.HDMI_CEC_CONTROL_ENABLED; 1504 mCecAvailable = isCecAvailable; 1505 } 1506 } 1507 1508 private static class VolumeControlFeatureCallback extends 1509 IHdmiCecVolumeControlFeatureListener.Stub { 1510 boolean mCallbackReceived = false; 1511 int mVolumeControlEnabled = -1; 1512 1513 @Override onHdmiCecVolumeControlFeature(int enabled)1514 public void onHdmiCecVolumeControlFeature(int enabled) throws RemoteException { 1515 this.mCallbackReceived = true; 1516 this.mVolumeControlEnabled = enabled; 1517 } 1518 } 1519 1520 } 1521