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 17 package com.android.settings.sound; 18 19 20 import static android.media.AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP; 21 import static android.media.AudioSystem.DEVICE_OUT_HEARING_AID; 22 import static android.media.AudioSystem.DEVICE_OUT_REMOTE_SUBMIX; 23 import static android.media.AudioSystem.DEVICE_OUT_USB_HEADSET; 24 25 import static com.google.common.truth.Truth.assertThat; 26 27 import static org.mockito.ArgumentMatchers.any; 28 import static org.mockito.Mockito.mock; 29 import static org.mockito.Mockito.spy; 30 import static org.mockito.Mockito.times; 31 import static org.mockito.Mockito.verify; 32 import static org.mockito.Mockito.when; 33 34 import android.bluetooth.BluetoothAdapter; 35 import android.bluetooth.BluetoothDevice; 36 import android.bluetooth.BluetoothManager; 37 import android.content.Context; 38 import android.media.AudioManager; 39 import android.support.v7.preference.ListPreference; 40 import android.support.v7.preference.PreferenceManager; 41 import android.support.v7.preference.PreferenceScreen; 42 43 import com.android.settings.R; 44 import com.android.settings.testutils.SettingsRobolectricTestRunner; 45 import com.android.settings.testutils.shadow.ShadowAudioManager; 46 import com.android.settings.testutils.shadow.ShadowBluetoothUtils; 47 import com.android.settings.testutils.shadow.ShadowMediaRouter; 48 import com.android.settingslib.bluetooth.A2dpProfile; 49 import com.android.settingslib.bluetooth.BluetoothEventManager; 50 import com.android.settingslib.bluetooth.HearingAidProfile; 51 import com.android.settingslib.bluetooth.LocalBluetoothManager; 52 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; 53 54 import org.junit.After; 55 import org.junit.Before; 56 import org.junit.Test; 57 import org.junit.runner.RunWith; 58 import org.mockito.Mock; 59 import org.mockito.MockitoAnnotations; 60 import org.robolectric.RuntimeEnvironment; 61 import org.robolectric.annotation.Config; 62 import org.robolectric.shadows.ShadowBluetoothDevice; 63 64 import java.util.ArrayList; 65 import java.util.List; 66 67 @RunWith(SettingsRobolectricTestRunner.class) 68 @Config(shadows = { 69 ShadowAudioManager.class, 70 ShadowMediaRouter.class, 71 ShadowBluetoothUtils.class, 72 ShadowBluetoothDevice.class} 73 ) 74 public class MediaOutputPreferenceControllerTest { 75 private static final String TEST_KEY = "Test_Key"; 76 private static final String TEST_DEVICE_NAME_1 = "Test_A2DP_BT_Device_NAME_1"; 77 private static final String TEST_DEVICE_NAME_2 = "Test_A2DP_BT_Device_NAME_2"; 78 private static final String TEST_HAP_DEVICE_NAME_1 = "Test_HAP_BT_Device_NAME_1"; 79 private static final String TEST_HAP_DEVICE_NAME_2 = "Test_HAP_BT_Device_NAME_2"; 80 private static final String TEST_DEVICE_ADDRESS_1 = "00:A1:A1:A1:A1:A1"; 81 private static final String TEST_DEVICE_ADDRESS_2 = "00:B2:B2:B2:B2:B2"; 82 private static final String TEST_DEVICE_ADDRESS_3 = "00:C3:C3:C3:C3:C3"; 83 private static final String TEST_DEVICE_ADDRESS_4 = "00:D4:D4:D4:D4:D4"; 84 private final static long HISYNCID1 = 10; 85 private final static long HISYNCID2 = 11; 86 87 @Mock 88 private LocalBluetoothManager mLocalManager; 89 @Mock 90 private BluetoothEventManager mBluetoothEventManager; 91 @Mock 92 private LocalBluetoothProfileManager mLocalBluetoothProfileManager; 93 @Mock 94 private A2dpProfile mA2dpProfile; 95 @Mock 96 private HearingAidProfile mHearingAidProfile; 97 @Mock 98 private AudioSwitchPreferenceController.AudioSwitchCallback mAudioSwitchPreferenceCallback; 99 100 private Context mContext; 101 private PreferenceScreen mScreen; 102 private ListPreference mPreference; 103 private ShadowAudioManager mShadowAudioManager; 104 private ShadowMediaRouter mShadowMediaRouter; 105 private BluetoothManager mBluetoothManager; 106 private BluetoothAdapter mBluetoothAdapter; 107 private BluetoothDevice mBluetoothDevice; 108 private BluetoothDevice mSecondBluetoothDevice; 109 private BluetoothDevice mLeftBluetoothHapDevice; 110 private BluetoothDevice mRightBluetoothHapDevice; 111 private LocalBluetoothManager mLocalBluetoothManager; 112 private AudioSwitchPreferenceController mController; 113 private List<BluetoothDevice> mProfileConnectedDevices; 114 private List<BluetoothDevice> mHearingAidActiveDevices; 115 116 @Before 117 public void setUp() { 118 MockitoAnnotations.initMocks(this); 119 mContext = spy(RuntimeEnvironment.application); 120 121 mShadowAudioManager = ShadowAudioManager.getShadow(); 122 mShadowMediaRouter = ShadowMediaRouter.getShadow(); 123 124 ShadowBluetoothUtils.sLocalBluetoothManager = mLocalManager; 125 mLocalBluetoothManager = ShadowBluetoothUtils.getLocalBtManager(mContext); 126 127 when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager); 128 when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager); 129 when(mLocalBluetoothProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile); 130 when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile); 131 132 mBluetoothManager = new BluetoothManager(mContext); 133 mBluetoothAdapter = mBluetoothManager.getAdapter(); 134 135 mBluetoothDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_1)); 136 when(mBluetoothDevice.getName()).thenReturn(TEST_DEVICE_NAME_1); 137 when(mBluetoothDevice.isConnected()).thenReturn(true); 138 139 mSecondBluetoothDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2)); 140 when(mSecondBluetoothDevice.getName()).thenReturn(TEST_DEVICE_NAME_2); 141 when(mSecondBluetoothDevice.isConnected()).thenReturn(true); 142 143 mLeftBluetoothHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_3)); 144 when(mLeftBluetoothHapDevice.getName()).thenReturn(TEST_HAP_DEVICE_NAME_1); 145 when(mLeftBluetoothHapDevice.isConnected()).thenReturn(true); 146 147 mRightBluetoothHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_4)); 148 when(mRightBluetoothHapDevice.getName()).thenReturn(TEST_HAP_DEVICE_NAME_2); 149 when(mRightBluetoothHapDevice.isConnected()).thenReturn(true); 150 151 mController = new MediaOutputPreferenceController(mContext, TEST_KEY); 152 mScreen = spy(new PreferenceScreen(mContext, null)); 153 mPreference = new ListPreference(mContext); 154 mProfileConnectedDevices = new ArrayList<>(); 155 mHearingAidActiveDevices = new ArrayList<>(2); 156 157 when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); 158 when(mScreen.getContext()).thenReturn(mContext); 159 when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference); 160 mScreen.addPreference(mPreference); 161 mController.displayPreference(mScreen); 162 mController.setCallback(mAudioSwitchPreferenceCallback); 163 } 164 165 @After 166 public void tearDown() { 167 mShadowAudioManager.reset(); 168 mShadowMediaRouter.reset(); 169 ShadowBluetoothUtils.reset(); 170 } 171 172 /** 173 * In normal mode, bluetooth device with HisyncId. 174 * HearingAidProfile should set active device to this device. 175 */ 176 @Test 177 public void setActiveBluetoothDevice_btDeviceWithHisyncId_shouldSetBtDeviceActive() { 178 mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); 179 when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); 180 181 mController.setActiveBluetoothDevice(mLeftBluetoothHapDevice); 182 183 verify(mHearingAidProfile).setActiveDevice(mLeftBluetoothHapDevice); 184 } 185 186 /** 187 * In normal mode, bluetooth device without HisyncId. 188 * A2dpProfile should set active device to this device. 189 */ 190 @Test 191 public void setActiveBluetoothDevice_btDeviceWithoutHisyncId_shouldSetBtDeviceActive() { 192 mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); 193 194 mController.setActiveBluetoothDevice(mBluetoothDevice); 195 196 verify(mA2dpProfile).setActiveDevice(mBluetoothDevice); 197 } 198 199 /** 200 * In normal mode, set active device to "this device". 201 * A2dpProfile should set to null. 202 * HearingAidProfile should set to null. 203 */ 204 @Test 205 public void setActiveBluetoothDevice_setNull_shouldSetNullToBothProfiles() { 206 mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); 207 208 mController.setActiveBluetoothDevice(null); 209 210 verify(mA2dpProfile).setActiveDevice(null); 211 verify(mHearingAidProfile).setActiveDevice(null); 212 } 213 214 /** 215 * During a call 216 * A2dpProfile should not set active device. 217 */ 218 @Test 219 public void setActiveBluetoothDevice_duringACall_shouldNotSetActiveDeviceToA2dpProfile() { 220 mShadowAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); 221 222 mController.setActiveBluetoothDevice(mBluetoothDevice); 223 224 verify(mA2dpProfile, times(0)).setActiveDevice(any(BluetoothDevice.class)); 225 } 226 227 /** 228 * Default status 229 * Preference should be invisible 230 * Summary should be default summary 231 */ 232 @Test 233 public void updateState_shouldSetSummary() { 234 mController.updateState(mPreference); 235 236 assertThat(mPreference.isVisible()).isFalse(); 237 assertThat(mPreference.getSummary()).isEqualTo( 238 mContext.getText(R.string.media_output_default_summary)); 239 } 240 241 /** 242 * During a call 243 * Preference should be invisible 244 * Default string should be "Unavailable during calls" 245 */ 246 @Test 247 public void updateState_duringACall_shouldSetDefaultSummary() { 248 mShadowAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); 249 250 mController.updateState(mPreference); 251 252 assertThat(mPreference.isVisible()).isFalse(); 253 assertThat(mPreference.getSummary()).isEqualTo( 254 mContext.getText(R.string.media_out_summary_ongoing_call_state)); 255 } 256 257 /** 258 * No available A2dp BT devices: 259 * Preference should be invisible 260 * Preference summary should be "This device" 261 */ 262 @Test 263 public void updateState_noAvailableA2dpBtDevices_shouldDisableAndSetDefaultSummary() { 264 mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); 265 List<BluetoothDevice> emptyDeviceList = new ArrayList<>(); 266 when(mA2dpProfile.getConnectedDevices()).thenReturn(emptyDeviceList); 267 268 mController.updateState(mPreference); 269 270 assertThat(mPreference.isVisible()).isFalse(); 271 String defaultString = mContext.getString(R.string.media_output_default_summary); 272 assertThat(mPreference.getSummary()).isEqualTo(defaultString); 273 } 274 275 /** 276 * Media stream is captured by something else (cast device): 277 * Preference should be invisible 278 * Preference summary should be "unavailable" 279 */ 280 @Test 281 public void updateState_mediaStreamIsCapturedByCast_shouldDisableAndSetDefaultSummary() { 282 mShadowAudioManager.setOutputDevice(DEVICE_OUT_REMOTE_SUBMIX); 283 284 mController.updateState(mPreference); 285 286 assertThat(mPreference.isVisible()).isFalse(); 287 String defaultString = mContext.getString(R.string.media_output_summary_unavailable); 288 assertThat(mPreference.getSummary()).isEqualTo(defaultString); 289 } 290 291 /** 292 * One A2DP Bluetooth device is available and active. 293 * Preference should be visible 294 * Preference summary should be the activated device name 295 */ 296 @Test 297 public void updateState_oneA2dpBtDeviceAreAvailable_shouldSetActivatedDeviceName() { 298 mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); 299 mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_A2DP); 300 mProfileConnectedDevices.clear(); 301 mProfileConnectedDevices.add(mBluetoothDevice); 302 when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 303 when(mA2dpProfile.getActiveDevice()).thenReturn(mBluetoothDevice); 304 305 mController.updateState(mPreference); 306 307 assertThat(mPreference.isVisible()).isTrue(); 308 assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_1); 309 } 310 311 /** 312 * More than one A2DP Bluetooth devices are available, and second device is active. 313 * Preference should be visible 314 * Preference summary should be the activated device name 315 */ 316 @Test 317 public void updateState_moreThanOneA2DpBtDevicesAreAvailable_shouldSetActivatedDeviceName() { 318 mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); 319 mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_A2DP); 320 mProfileConnectedDevices.clear(); 321 mProfileConnectedDevices.add(mBluetoothDevice); 322 mProfileConnectedDevices.add(mSecondBluetoothDevice); 323 when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 324 when(mA2dpProfile.getActiveDevice()).thenReturn(mSecondBluetoothDevice); 325 326 mController.updateState(mPreference); 327 328 assertThat(mPreference.isVisible()).isTrue(); 329 assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_2); 330 } 331 332 /** 333 * A2DP Bluetooth device(s) are available, but wired headset is plugged in and activated 334 * Preference should be visible 335 * Preference summary should be "This device" 336 */ 337 @Test 338 public void updateState_a2dpDevicesAvailableWiredHeadsetIsActivated_shouldSetDefaultSummary() { 339 mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); 340 mShadowAudioManager.setOutputDevice(DEVICE_OUT_USB_HEADSET); 341 mProfileConnectedDevices.clear(); 342 mProfileConnectedDevices.add(mBluetoothDevice); 343 when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 344 when(mA2dpProfile.getActiveDevice()).thenReturn( 345 mBluetoothDevice); // BT device is still activated in this case 346 347 mController.updateState(mPreference); 348 349 assertThat(mPreference.isVisible()).isTrue(); 350 assertThat(mPreference.getSummary()).isEqualTo( 351 mContext.getString(R.string.media_output_default_summary)); 352 } 353 354 355 /** 356 * A2DP Bluetooth device(s) are available, but current device speaker is activated 357 * Preference should be visible 358 * Preference summary should be "This device" 359 */ 360 @Test 361 public void updateState_a2dpDevicesAvailableCurrentDeviceActivated_shouldSetDefaultSummary() { 362 mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); 363 mProfileConnectedDevices.clear(); 364 mProfileConnectedDevices.add(mBluetoothDevice); 365 when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 366 when(mA2dpProfile.getActiveDevice()).thenReturn(null); 367 368 mController.updateState(mPreference); 369 370 assertThat(mPreference.isVisible()).isTrue(); 371 assertThat(mPreference.getSummary()).isEqualTo( 372 mContext.getString(R.string.media_output_default_summary)); 373 } 374 375 /** 376 * One hearing aid profile Bluetooth device is available and active. 377 * Preference should be visible 378 * Preference summary should be the activated device name 379 */ 380 @Test 381 public void updateState_oneHapBtDeviceAreAvailable_shouldSetActivatedDeviceName() { 382 mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); 383 mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); 384 mProfileConnectedDevices.clear(); 385 mProfileConnectedDevices.add(mLeftBluetoothHapDevice); 386 mHearingAidActiveDevices.clear(); 387 mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); 388 when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 389 when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); 390 when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); 391 392 mController.updateState(mPreference); 393 394 assertThat(mPreference.isVisible()).isTrue(); 395 assertThat(mPreference.getSummary()).isEqualTo(mLeftBluetoothHapDevice.getName()); 396 } 397 398 /** 399 * More than one hearing aid profile Bluetooth devices are available, and second 400 * device is active. 401 * Preference should be visible 402 * Preference summary should be the activated device name 403 */ 404 @Test 405 public void updateState_moreThanOneHapBtDevicesAreAvailable_shouldSetActivatedDeviceName() { 406 mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); 407 mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); 408 mProfileConnectedDevices.clear(); 409 mProfileConnectedDevices.add(mLeftBluetoothHapDevice); 410 mProfileConnectedDevices.add(mRightBluetoothHapDevice); 411 mHearingAidActiveDevices.clear(); 412 mHearingAidActiveDevices.add(mRightBluetoothHapDevice); 413 when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 414 when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); 415 when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); 416 when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID2); 417 418 mController.updateState(mPreference); 419 420 assertThat(mPreference.isVisible()).isTrue(); 421 assertThat(mPreference.getSummary()).isEqualTo(mRightBluetoothHapDevice.getName()); 422 } 423 424 /** 425 * Both hearing aid profile and A2dp Bluetooth devices are available, and two hearing aid 426 * profile devices with same HisyncId are active. Both of HAP device are active, 427 * "left" side HAP device is added first. 428 * Preference should be visible 429 * Preference summary should be the activated device name 430 * ConnectedDevice should not contain second HAP device with same HisyncId 431 */ 432 @Test 433 public void updateState_hapBtDeviceWithSameId_shouldSetActivatedDeviceName() { 434 mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); 435 mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); 436 mProfileConnectedDevices.clear(); 437 mProfileConnectedDevices.add(mBluetoothDevice); 438 //with same HisyncId, first one will remain in UI. 439 mProfileConnectedDevices.add(mLeftBluetoothHapDevice); 440 mProfileConnectedDevices.add(mRightBluetoothHapDevice); 441 mHearingAidActiveDevices.clear(); 442 mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); 443 mHearingAidActiveDevices.add(mRightBluetoothHapDevice); 444 when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 445 when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); 446 when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); 447 when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID1); 448 449 mController.updateState(mPreference); 450 451 assertThat(mPreference.isVisible()).isTrue(); 452 assertThat(mPreference.getSummary()).isEqualTo(mLeftBluetoothHapDevice.getName()); 453 assertThat(mController.mConnectedDevices.contains(mLeftBluetoothHapDevice)).isTrue(); 454 assertThat(mController.mConnectedDevices.contains(mRightBluetoothHapDevice)).isFalse(); 455 } 456 457 /** 458 * Both hearing aid profile and A2dp Bluetooth devices are available, and two hearing aid 459 * profile devices with same HisyncId. Both of HAP device are active, 460 * "right" side HAP device is added first. 461 * Preference should be visible 462 * Preference summary should be the activated device name 463 * ConnectedDevice should not contain second HAP device with same HisyncId 464 */ 465 @Test 466 public void updateState_hapBtDeviceWithSameIdButDifferentOrder_shouldSetActivatedDeviceName() { 467 mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); 468 mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); 469 mProfileConnectedDevices.clear(); 470 mProfileConnectedDevices.add(mBluetoothDevice); 471 //with same HisyncId, first one will remain in UI. 472 mProfileConnectedDevices.add(mRightBluetoothHapDevice); 473 mProfileConnectedDevices.add(mLeftBluetoothHapDevice); 474 mHearingAidActiveDevices.clear(); 475 mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); 476 mHearingAidActiveDevices.add(mRightBluetoothHapDevice); 477 when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 478 when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); 479 when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); 480 when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID1); 481 482 mController.updateState(mPreference); 483 484 assertThat(mPreference.isVisible()).isTrue(); 485 assertThat(mPreference.getSummary()).isEqualTo(mRightBluetoothHapDevice.getName()); 486 assertThat(mController.mConnectedDevices.contains(mRightBluetoothHapDevice)).isTrue(); 487 assertThat(mController.mConnectedDevices.contains(mLeftBluetoothHapDevice)).isFalse(); 488 } 489 490 /** 491 * Both hearing aid profile and A2dp Bluetooth devices are available, and two hearing aid 492 * profile devices with different HisyncId. One of HAP device is active. 493 * Preference should be visible 494 * Preference summary should be the activated device name 495 * ConnectedDevice should contain both HAP device with different HisyncId 496 */ 497 @Test 498 public void updateState_hapBtDeviceWithDifferentId_shouldSetActivatedDeviceName() { 499 mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); 500 mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); 501 mProfileConnectedDevices.clear(); 502 mProfileConnectedDevices.add(mBluetoothDevice); 503 mProfileConnectedDevices.add(mLeftBluetoothHapDevice); 504 mProfileConnectedDevices.add(mRightBluetoothHapDevice); 505 mHearingAidActiveDevices.clear(); 506 mHearingAidActiveDevices.add(null); 507 mHearingAidActiveDevices.add(mRightBluetoothHapDevice); 508 when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 509 when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); 510 when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); 511 when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID2); 512 513 mController.updateState(mPreference); 514 515 assertThat(mPreference.isVisible()).isTrue(); 516 assertThat(mPreference.getSummary()).isEqualTo(mRightBluetoothHapDevice.getName()); 517 assertThat(mController.mConnectedDevices).containsExactly(mBluetoothDevice, 518 mLeftBluetoothHapDevice, mRightBluetoothHapDevice); 519 } 520 } 521