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 import static android.media.AudioSystem.DEVICE_OUT_BLE_HEADSET; 20 import static android.media.AudioSystem.DEVICE_OUT_BLUETOOTH_SCO; 21 import static android.media.AudioSystem.DEVICE_OUT_HEARING_AID; 22 23 import static com.google.common.truth.Truth.assertThat; 24 25 import static org.mockito.ArgumentMatchers.any; 26 import static org.mockito.Mockito.mock; 27 import static org.mockito.Mockito.never; 28 import static org.mockito.Mockito.spy; 29 import static org.mockito.Mockito.times; 30 import static org.mockito.Mockito.verify; 31 import static org.mockito.Mockito.when; 32 33 import android.bluetooth.BluetoothAdapter; 34 import android.bluetooth.BluetoothDevice; 35 import android.bluetooth.BluetoothManager; 36 import android.content.Context; 37 import android.media.AudioManager; 38 39 import androidx.preference.ListPreference; 40 import androidx.preference.PreferenceManager; 41 import androidx.preference.PreferenceScreen; 42 43 import com.android.settings.R; 44 import com.android.settings.bluetooth.Utils; 45 import com.android.settings.testutils.shadow.ShadowAudioManager; 46 import com.android.settings.testutils.shadow.ShadowBluetoothUtils; 47 import com.android.settingslib.bluetooth.BluetoothEventManager; 48 import com.android.settingslib.bluetooth.CachedBluetoothDevice; 49 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; 50 import com.android.settingslib.bluetooth.HeadsetProfile; 51 import com.android.settingslib.bluetooth.HearingAidProfile; 52 import com.android.settingslib.bluetooth.LeAudioProfile; 53 import com.android.settingslib.bluetooth.LocalBluetoothManager; 54 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; 55 56 import org.junit.After; 57 import org.junit.Before; 58 import org.junit.Test; 59 import org.junit.runner.RunWith; 60 import org.mockito.Mock; 61 import org.mockito.MockitoAnnotations; 62 import org.robolectric.RobolectricTestRunner; 63 import org.robolectric.RuntimeEnvironment; 64 import org.robolectric.annotation.Config; 65 import org.robolectric.shadows.ShadowBluetoothDevice; 66 67 import java.util.ArrayList; 68 import java.util.Collection; 69 import java.util.List; 70 71 @RunWith(RobolectricTestRunner.class) 72 @Config(shadows = { 73 ShadowAudioManager.class, 74 ShadowBluetoothUtils.class, 75 ShadowBluetoothDevice.class} 76 ) 77 public class HandsFreeProfileOutputPreferenceControllerTest { 78 private static final String TEST_KEY = "Test_Key"; 79 private static final String TEST_DEVICE_NAME_1 = "Test_HFP_BT_Device_NAME_1"; 80 private static final String TEST_DEVICE_NAME_2 = "Test_HFP_BT_Device_NAME_2"; 81 private static final String TEST_HAP_DEVICE_NAME_1 = "Test_HAP_BT_Device_NAME_1"; 82 private static final String TEST_HAP_DEVICE_NAME_2 = "Test_HAP_BT_Device_NAME_2"; 83 private static final String TEST_LE_AUDIO_DEVICE_NAME_1 = "Test_LE_AUDIO_Device_NAME_1"; 84 private static final String TEST_DEVICE_ADDRESS_1 = "00:A1:A1:A1:A1:A1"; 85 private static final String TEST_DEVICE_ADDRESS_2 = "00:B2:B2:B2:B2:B2"; 86 private static final String TEST_DEVICE_ADDRESS_3 = "00:C3:C3:C3:C3:C3"; 87 private static final String TEST_DEVICE_ADDRESS_4 = "00:D4:D4:D4:D4:D4"; 88 private static final String TEST_DEVICE_ADDRESS_5 = "00:E5:E5:E5:E5:E5"; 89 private final static long HISYNCID1 = 10; 90 private final static long HISYNCID2 = 11; 91 92 @Mock 93 private LocalBluetoothManager mLocalManager; 94 @Mock 95 private BluetoothEventManager mBluetoothEventManager; 96 @Mock 97 private LocalBluetoothProfileManager mLocalBluetoothProfileManager; 98 @Mock 99 private HeadsetProfile mHeadsetProfile; 100 @Mock 101 private HearingAidProfile mHearingAidProfile; 102 @Mock 103 private LeAudioProfile mLeAudioProfile; 104 @Mock 105 private AudioSwitchPreferenceController.AudioSwitchCallback mAudioSwitchPreferenceCallback; 106 @Mock 107 private CachedBluetoothDeviceManager mCachedDeviceManager; 108 @Mock 109 private CachedBluetoothDevice mCachedBluetoothDeviceL; 110 @Mock 111 private CachedBluetoothDevice mCachedBluetoothDeviceR; 112 113 private Context mContext; 114 private PreferenceScreen mScreen; 115 private ListPreference mPreference; 116 private AudioManager mAudioManager; 117 private ShadowAudioManager mShadowAudioManager; 118 private BluetoothManager mBluetoothManager; 119 private BluetoothAdapter mBluetoothAdapter; 120 private BluetoothDevice mBluetoothDevice; 121 private BluetoothDevice mSecondBluetoothDevice; 122 private BluetoothDevice mLeftBluetoothHapDevice; 123 private BluetoothDevice mRightBluetoothHapDevice; 124 private LocalBluetoothManager mLocalBluetoothManager; 125 private HandsFreeProfileOutputPreferenceController mController; 126 private List<BluetoothDevice> mProfileConnectedDevices; 127 private List<BluetoothDevice> mHearingAidActiveDevices; 128 private List<BluetoothDevice> mLeAudioActiveDevices; 129 private Collection<CachedBluetoothDevice> mCachedDevices; 130 131 @Before setUp()132 public void setUp() { 133 MockitoAnnotations.initMocks(this); 134 mContext = spy(RuntimeEnvironment.application); 135 136 mAudioManager = mContext.getSystemService(AudioManager.class); 137 mShadowAudioManager = ShadowAudioManager.getShadow(); 138 139 ShadowBluetoothUtils.sLocalBluetoothManager = mLocalManager; 140 mLocalBluetoothManager = Utils.getLocalBtManager(mContext); 141 142 when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager); 143 when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager); 144 when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager); 145 when(mLocalBluetoothProfileManager.getHeadsetProfile()).thenReturn(mHeadsetProfile); 146 when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile); 147 when(mLocalBluetoothProfileManager.getLeAudioProfile()).thenReturn(mLeAudioProfile); 148 149 mBluetoothManager = mContext.getSystemService(BluetoothManager.class); 150 mBluetoothAdapter = mBluetoothManager.getAdapter(); 151 152 mCachedDevices = new ArrayList<>(); 153 mCachedDevices.add(mCachedBluetoothDeviceL); 154 mCachedDevices.add(mCachedBluetoothDeviceR); 155 when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(mCachedDevices); 156 157 mBluetoothDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_1)); 158 when(mBluetoothDevice.getName()).thenReturn(TEST_DEVICE_NAME_1); 159 when(mBluetoothDevice.getAlias()).thenReturn(TEST_DEVICE_NAME_1); 160 when(mBluetoothDevice.isConnected()).thenReturn(true); 161 162 mSecondBluetoothDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2)); 163 when(mSecondBluetoothDevice.getName()).thenReturn(TEST_DEVICE_NAME_2); 164 when(mSecondBluetoothDevice.getAlias()).thenReturn(TEST_DEVICE_NAME_2); 165 when(mSecondBluetoothDevice.isConnected()).thenReturn(true); 166 167 mLeftBluetoothHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_3)); 168 when(mLeftBluetoothHapDevice.getName()).thenReturn(TEST_HAP_DEVICE_NAME_1); 169 when(mLeftBluetoothHapDevice.getAlias()).thenReturn(TEST_HAP_DEVICE_NAME_1); 170 when(mLeftBluetoothHapDevice.isConnected()).thenReturn(true); 171 172 mRightBluetoothHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_4)); 173 when(mRightBluetoothHapDevice.getName()).thenReturn(TEST_HAP_DEVICE_NAME_2); 174 when(mRightBluetoothHapDevice.getAlias()).thenReturn(TEST_HAP_DEVICE_NAME_2); 175 when(mRightBluetoothHapDevice.isConnected()).thenReturn(true); 176 177 mController = new HandsFreeProfileOutputPreferenceController(mContext, TEST_KEY); 178 mScreen = spy(new PreferenceScreen(mContext, null)); 179 mPreference = new ListPreference(mContext); 180 mProfileConnectedDevices = new ArrayList<>(); 181 mHearingAidActiveDevices = new ArrayList<>(2); 182 mLeAudioActiveDevices = new ArrayList<>(); 183 184 when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); 185 when(mScreen.getContext()).thenReturn(mContext); 186 when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference); 187 mScreen.addPreference(mPreference); 188 mController.displayPreference(mScreen); 189 mController.setCallback(mAudioSwitchPreferenceCallback); 190 } 191 192 @After tearDown()193 public void tearDown() { 194 ShadowBluetoothUtils.reset(); 195 } 196 197 /** 198 * During a call, bluetooth device with HisyncId. 199 * HearingAidProfile should set active device to this device. 200 */ 201 @Test setActiveBluetoothDevice_btDeviceWithHisyncId_shouldSetBtDeviceActive()202 public void setActiveBluetoothDevice_btDeviceWithHisyncId_shouldSetBtDeviceActive() { 203 mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); 204 when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); 205 206 mController.setActiveBluetoothDevice(mLeftBluetoothHapDevice); 207 208 verify(mHearingAidProfile).setActiveDevice(mLeftBluetoothHapDevice); 209 verify(mHeadsetProfile, never()).setActiveDevice(mLeftBluetoothHapDevice); 210 } 211 212 /** 213 * During a call, Bluetooth device without HisyncId. 214 * HeadsetProfile should set active device to this device. 215 */ 216 @Test setActiveBluetoothDevice_btDeviceWithoutHisyncId_shouldSetBtDeviceActive()217 public void setActiveBluetoothDevice_btDeviceWithoutHisyncId_shouldSetBtDeviceActive() { 218 mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); 219 220 mController.setActiveBluetoothDevice(mBluetoothDevice); 221 222 verify(mHeadsetProfile).setActiveDevice(mBluetoothDevice); 223 verify(mHearingAidProfile, never()).setActiveDevice(mBluetoothDevice); 224 } 225 226 /** 227 * During a call, set active device to "this device". 228 * HeadsetProfile should set to null. 229 * HearingAidProfile should set to null. 230 */ 231 @Test setActiveBluetoothDevice_setNull_shouldSetNullToBothProfiles()232 public void setActiveBluetoothDevice_setNull_shouldSetNullToBothProfiles() { 233 mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); 234 235 mController.setActiveBluetoothDevice(null); 236 237 verify(mHeadsetProfile).setActiveDevice(null); 238 verify(mHearingAidProfile).setActiveDevice(null); 239 } 240 241 /** 242 * In normal mode 243 * HeadsetProfile should not set active device. 244 */ 245 @Test setActiveBluetoothDevice_inNormalMode_shouldNotSetActiveDeviceToHeadsetProfile()246 public void setActiveBluetoothDevice_inNormalMode_shouldNotSetActiveDeviceToHeadsetProfile() { 247 mAudioManager.setMode(AudioManager.MODE_NORMAL); 248 249 mController.setActiveBluetoothDevice(mBluetoothDevice); 250 251 verify(mHeadsetProfile, times(0)).setActiveDevice(any(BluetoothDevice.class)); 252 } 253 254 /** 255 * Default status 256 * Preference should be invisible 257 * Summary should be default summary 258 */ 259 @Test updateState_shouldSetSummary()260 public void updateState_shouldSetSummary() { 261 mController.updateState(mPreference); 262 263 assertThat(mPreference.isVisible()).isFalse(); 264 assertThat(mPreference.getSummary()).isEqualTo( 265 mContext.getText(R.string.media_output_default_summary)); 266 } 267 268 /** 269 * One Hands Free Profile Bluetooth device is available and activated 270 * Preference should be visible 271 * Preference summary should be the activated device name 272 */ 273 @Test updateState_oneHeadsetsAvailableAndActivated_shouldSetDeviceName()274 public void updateState_oneHeadsetsAvailableAndActivated_shouldSetDeviceName() { 275 mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); 276 mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_SCO); 277 mProfileConnectedDevices.clear(); 278 mProfileConnectedDevices.add(mBluetoothDevice); 279 when(mHeadsetProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 280 when(mHeadsetProfile.getActiveDevice()).thenReturn(mBluetoothDevice); 281 282 mController.updateState(mPreference); 283 284 assertThat(mPreference.isVisible()).isTrue(); 285 assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_1); 286 } 287 288 /** 289 * More than one Hands Free Profile Bluetooth devices are available, and second 290 * device is active. 291 * Preference should be visible 292 * Preference summary should be the activated device name 293 */ 294 @Test updateState_moreThanOneHfpBtDevicesAreAvailable_shouldSetActivatedDeviceName()295 public void updateState_moreThanOneHfpBtDevicesAreAvailable_shouldSetActivatedDeviceName() { 296 mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); 297 mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_SCO); 298 List<BluetoothDevice> connectedDevices = new ArrayList<>(2); 299 connectedDevices.add(mBluetoothDevice); 300 connectedDevices.add(mSecondBluetoothDevice); 301 when(mHeadsetProfile.getConnectedDevices()).thenReturn(connectedDevices); 302 when(mHeadsetProfile.getActiveDevice()).thenReturn(mSecondBluetoothDevice); 303 304 mController.updateState(mPreference); 305 306 assertThat(mPreference.isVisible()).isTrue(); 307 assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_2); 308 } 309 310 /** 311 * Hands Free Profile Bluetooth device(s) are available, but wired headset is plugged in 312 * and activated. 313 * Preference should be visible 314 * Preference summary should be "This device" 315 */ 316 @Test updateState_withAvailableDevicesWiredHeadsetActivated_shouldSetDefaultSummary()317 public void updateState_withAvailableDevicesWiredHeadsetActivated_shouldSetDefaultSummary() { 318 mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); 319 mProfileConnectedDevices.clear(); 320 mProfileConnectedDevices.add(mBluetoothDevice); 321 when(mHeadsetProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 322 when(mHeadsetProfile.getActiveDevice()).thenReturn(null); 323 324 mController.updateState(mPreference); 325 326 assertThat(mPreference.isVisible()).isTrue(); 327 assertThat(mPreference.getSummary()).isEqualTo( 328 mContext.getText(R.string.media_output_default_summary)); 329 } 330 331 /** 332 * No available Headset BT devices 333 * Preference should be invisible 334 * Preference summary should be "This device" 335 */ 336 @Test updateState_noAvailableHeadsetBtDevices_shouldSetDefaultSummary()337 public void updateState_noAvailableHeadsetBtDevices_shouldSetDefaultSummary() { 338 mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); 339 List<BluetoothDevice> emptyDeviceList = new ArrayList<>(); 340 when(mHeadsetProfile.getConnectedDevices()).thenReturn(emptyDeviceList); 341 342 mController.updateState(mPreference); 343 344 assertThat(mPreference.isVisible()).isFalse(); 345 assertThat(mPreference.getSummary()).isEqualTo( 346 mContext.getText(R.string.media_output_default_summary)); 347 } 348 349 /** 350 * One hearing aid profile Bluetooth device is available and active. 351 * Preference should be visible 352 * Preference summary should be the activated device name 353 */ 354 @Test updateState_oneHapBtDeviceAreAvailable_shouldSetActivatedDeviceName()355 public void updateState_oneHapBtDeviceAreAvailable_shouldSetActivatedDeviceName() { 356 mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); 357 mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); 358 mProfileConnectedDevices.clear(); 359 mProfileConnectedDevices.add(mLeftBluetoothHapDevice); 360 mHearingAidActiveDevices.clear(); 361 mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); 362 when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 363 when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); 364 when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); 365 366 mController.updateState(mPreference); 367 368 assertThat(mPreference.isVisible()).isTrue(); 369 assertThat(mPreference.getSummary()).isEqualTo(mLeftBluetoothHapDevice.getName()); 370 } 371 372 /** 373 * More than one hearing aid profile Bluetooth devices are available, and second 374 * device is active. 375 * Preference should be visible 376 * Preference summary should be the activated device name 377 */ 378 @Test updateState_moreThanOneHapBtDevicesAreAvailable_shouldSetActivatedDeviceName()379 public void updateState_moreThanOneHapBtDevicesAreAvailable_shouldSetActivatedDeviceName() { 380 mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); 381 mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); 382 mProfileConnectedDevices.clear(); 383 mProfileConnectedDevices.add(mLeftBluetoothHapDevice); 384 mProfileConnectedDevices.add(mRightBluetoothHapDevice); 385 mHearingAidActiveDevices.clear(); 386 mHearingAidActiveDevices.add(mRightBluetoothHapDevice); 387 when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 388 when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); 389 when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); 390 when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID2); 391 392 mController.updateState(mPreference); 393 394 assertThat(mPreference.isVisible()).isTrue(); 395 assertThat(mPreference.getSummary()).isEqualTo(mRightBluetoothHapDevice.getName()); 396 } 397 398 /** 399 * Both hearing aid profile and hands free profile Bluetooth devices are available, and 400 * two hearing aid profile devices with same HisyncId. Both of HAP device are active, 401 * "left" side HAP device is added first. 402 * Preference should be visible 403 * Preference summary should be the activated device name 404 * ConnectedDevice should not contain second HAP device with same HisyncId 405 */ 406 @Test updateState_hapBtDeviceWithSameId_shouldSetActivatedDeviceName()407 public void updateState_hapBtDeviceWithSameId_shouldSetActivatedDeviceName() { 408 mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); 409 mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); 410 mProfileConnectedDevices.clear(); 411 mProfileConnectedDevices.add(mBluetoothDevice); 412 //with same HisyncId, only the first one will remain in UI. 413 mProfileConnectedDevices.add(mLeftBluetoothHapDevice); 414 mProfileConnectedDevices.add(mRightBluetoothHapDevice); 415 mHearingAidActiveDevices.clear(); 416 mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); 417 mHearingAidActiveDevices.add(mRightBluetoothHapDevice); 418 when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 419 when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); 420 when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); 421 when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID1); 422 423 mController.updateState(mPreference); 424 425 assertThat(mPreference.isVisible()).isTrue(); 426 assertThat(mPreference.getSummary()).isEqualTo(mLeftBluetoothHapDevice.getName()); 427 assertThat(mController.mConnectedDevices.contains(mLeftBluetoothHapDevice)).isTrue(); 428 assertThat(mController.mConnectedDevices.contains(mRightBluetoothHapDevice)).isFalse(); 429 } 430 431 /** 432 * Both hearing aid profile and hands free profile Bluetooth devices are available, and 433 * two hearing aid profile devices with same HisyncId. Both of HAP device are active, 434 * "right" side HAP device is added first. 435 * Preference should be visible 436 * Preference summary should be the activated device name 437 * ConnectedDevice should not contain second HAP device with same HisyncId 438 */ 439 @Test updateState_hapBtDeviceWithSameIdButDifferentOrder_shouldSetActivatedDeviceName()440 public void updateState_hapBtDeviceWithSameIdButDifferentOrder_shouldSetActivatedDeviceName() { 441 mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); 442 mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); 443 mProfileConnectedDevices.clear(); 444 mProfileConnectedDevices.add(mBluetoothDevice); 445 //with same HisyncId, only the first one will remain in UI. 446 mProfileConnectedDevices.add(mRightBluetoothHapDevice); 447 mProfileConnectedDevices.add(mLeftBluetoothHapDevice); 448 mHearingAidActiveDevices.clear(); 449 mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); 450 mHearingAidActiveDevices.add(mRightBluetoothHapDevice); 451 when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 452 when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); 453 when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); 454 when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID1); 455 456 mController.updateState(mPreference); 457 458 assertThat(mPreference.isVisible()).isTrue(); 459 assertThat(mController.mConnectedDevices.contains(mRightBluetoothHapDevice)).isTrue(); 460 assertThat(mController.mConnectedDevices.contains(mLeftBluetoothHapDevice)).isFalse(); 461 assertThat(mPreference.getSummary()).isEqualTo(mRightBluetoothHapDevice.getName()); 462 } 463 464 /** 465 * Both hearing aid profile and hands free profile Bluetooth devices are available, and 466 * two hearing aid profile devices with different HisyncId. One of HAP device is active. 467 * Preference should be visible 468 * Preference summary should be the activated device name 469 * ConnectedDevice should contain both HAP device with different HisyncId 470 */ 471 @Test updateState_hapBtDeviceWithDifferentId_shouldSetActivatedDeviceName()472 public void updateState_hapBtDeviceWithDifferentId_shouldSetActivatedDeviceName() { 473 mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); 474 mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); 475 mProfileConnectedDevices.clear(); 476 mProfileConnectedDevices.add(mBluetoothDevice); 477 mProfileConnectedDevices.add(mLeftBluetoothHapDevice); 478 mProfileConnectedDevices.add(mRightBluetoothHapDevice); 479 mHearingAidActiveDevices.clear(); 480 mHearingAidActiveDevices.add(null); 481 mHearingAidActiveDevices.add(mRightBluetoothHapDevice); 482 when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 483 when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); 484 when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); 485 when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID2); 486 487 mController.updateState(mPreference); 488 489 assertThat(mPreference.isVisible()).isTrue(); 490 assertThat(mPreference.getSummary()).isEqualTo(mRightBluetoothHapDevice.getName()); 491 assertThat(mController.mConnectedDevices).containsExactly(mBluetoothDevice, 492 mLeftBluetoothHapDevice, mRightBluetoothHapDevice); 493 } 494 495 @Test updateState_leAudioDeviceActive_shouldSetActivatedDeviceName()496 public void updateState_leAudioDeviceActive_shouldSetActivatedDeviceName() { 497 mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); 498 mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLE_HEADSET); 499 when(mCachedBluetoothDeviceL.getDevice()).thenReturn(mBluetoothDevice); 500 when(mBluetoothDevice.getName()).thenReturn(TEST_LE_AUDIO_DEVICE_NAME_1); 501 when(mBluetoothDevice.getAlias()).thenReturn(TEST_LE_AUDIO_DEVICE_NAME_1); 502 mProfileConnectedDevices.clear(); 503 mProfileConnectedDevices.add(mBluetoothDevice); 504 mLeAudioActiveDevices.clear(); 505 mLeAudioActiveDevices.add(mBluetoothDevice); 506 when(mLeAudioProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 507 when(mLeAudioProfile.getActiveDevices()).thenReturn(mLeAudioActiveDevices); 508 509 mController.updateState(mPreference); 510 511 assertThat(mPreference.isVisible()).isTrue(); 512 assertThat(mPreference.getSummary()).isEqualTo(mBluetoothDevice.getName()); 513 } 514 515 @Test findActiveDevice_onlyHeadsetDeviceActive_returnHeadsetDevice()516 public void findActiveDevice_onlyHeadsetDeviceActive_returnHeadsetDevice() { 517 when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(null); 518 when(mHeadsetProfile.getActiveDevice()).thenReturn(mBluetoothDevice); 519 520 assertThat(mController.findActiveDevice()).isEqualTo(mBluetoothDevice); 521 } 522 523 @Test findActiveDevice_allDevicesNotActive_returnNull()524 public void findActiveDevice_allDevicesNotActive_returnNull() { 525 when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(null); 526 when(mHeadsetProfile.getActiveDevice()).thenReturn(null); 527 528 assertThat(mController.findActiveDevice()).isNull(); 529 } 530 531 @Test findActiveDevice_allProfilesWithActiveDevice_returnHADevice()532 public void findActiveDevice_allProfilesWithActiveDevice_returnHADevice() { 533 BluetoothDevice btLeDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_5)); 534 when(btLeDevice.getName()).thenReturn(TEST_LE_AUDIO_DEVICE_NAME_1); 535 mController.mConnectedDevices.clear(); 536 mController.mConnectedDevices.add(mBluetoothDevice); 537 mController.mConnectedDevices.add(mLeftBluetoothHapDevice); 538 mController.mConnectedDevices.add(btLeDevice); 539 mLeAudioActiveDevices.clear(); 540 mLeAudioActiveDevices.add(btLeDevice); 541 mHearingAidActiveDevices.clear(); 542 mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); 543 when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); 544 when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); 545 when(mHeadsetProfile.getActiveDevice()).thenReturn(mBluetoothDevice); 546 when(mLeAudioProfile.getActiveDevices()).thenReturn(mLeAudioActiveDevices); 547 548 assertThat(mController.findActiveDevice()).isEqualTo(mLeftBluetoothHapDevice); 549 } 550 551 @Test findActiveDevice_headsetDeviceAndLeAudioDeviceActive_returnLeAudioDevice()552 public void findActiveDevice_headsetDeviceAndLeAudioDeviceActive_returnLeAudioDevice() { 553 BluetoothDevice btLeDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_5)); 554 when(btLeDevice.getName()).thenReturn(TEST_LE_AUDIO_DEVICE_NAME_1); 555 mLeAudioActiveDevices.clear(); 556 mLeAudioActiveDevices.add(btLeDevice); 557 mHearingAidActiveDevices.clear(); 558 when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); 559 when(mHeadsetProfile.getActiveDevice()).thenReturn(mBluetoothDevice); 560 when(mLeAudioProfile.getActiveDevices()).thenReturn(mLeAudioActiveDevices); 561 562 assertThat(mController.findActiveDevice()).isEqualTo(btLeDevice); 563 } 564 565 @Test findActiveDevice_onlyLeAudioDeviceActive_returnLeAudioDevice()566 public void findActiveDevice_onlyLeAudioDeviceActive_returnLeAudioDevice() { 567 BluetoothDevice btLeDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_5)); 568 when(btLeDevice.getName()).thenReturn(TEST_LE_AUDIO_DEVICE_NAME_1); 569 mLeAudioActiveDevices.clear(); 570 mLeAudioActiveDevices.add(btLeDevice); 571 mHearingAidActiveDevices.clear(); 572 when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); 573 when(mHeadsetProfile.getActiveDevice()).thenReturn(null); 574 when(mLeAudioProfile.getActiveDevices()).thenReturn(mLeAudioActiveDevices); 575 576 assertThat(mController.findActiveDevice()).isEqualTo(btLeDevice); 577 } 578 579 580 /** 581 * One Bluetooth devices are available, and select the device. 582 * Preference summary should be device name. 583 */ 584 @Test onPreferenceChange_toBtDevice_shouldSetBtDeviceName()585 public void onPreferenceChange_toBtDevice_shouldSetBtDeviceName() { 586 mController.mConnectedDevices.clear(); 587 mController.mConnectedDevices.add(mBluetoothDevice); 588 589 mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_1); 590 591 assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_1); 592 } 593 594 /** 595 * More than one Bluetooth devices are available, and select second device. 596 * Preference summary should be second device name. 597 */ 598 @Test onPreferenceChange_toBtDevices_shouldSetSecondBtDeviceName()599 public void onPreferenceChange_toBtDevices_shouldSetSecondBtDeviceName() { 600 mController.mConnectedDevices.clear(); 601 mController.mConnectedDevices.add(mBluetoothDevice); 602 mController.mConnectedDevices.add(mSecondBluetoothDevice); 603 604 mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_2); 605 606 assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_2); 607 } 608 609 /** 610 * mConnectedDevices is empty. 611 * onPreferenceChange should return false. 612 */ 613 @Test onPreferenceChange_connectedDeviceIsNull_shouldReturnFalse()614 public void onPreferenceChange_connectedDeviceIsNull_shouldReturnFalse() { 615 mController.mConnectedDevices.clear(); 616 617 assertThat(mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_1)).isFalse(); 618 } 619 620 @Test onPreferenceChange_toThisDevice_shouldSetDefaultSummary()621 public void onPreferenceChange_toThisDevice_shouldSetDefaultSummary() { 622 mController.mConnectedDevices.clear(); 623 mController.mConnectedDevices.add(mBluetoothDevice); 624 625 mController.onPreferenceChange(mPreference, 626 mContext.getText(R.string.media_output_default_summary)); 627 628 assertThat(mPreference.getSummary()).isEqualTo( 629 mContext.getText(R.string.media_output_default_summary)); 630 } 631 } 632