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_BLUETOOTH_SCO_HEADSET; 20 import static android.media.AudioSystem.STREAM_MUSIC; 21 22 import static com.android.settings.core.BasePreferenceController.AVAILABLE; 23 import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE; 24 import static com.android.settingslib.media.flags.Flags.FLAG_ENABLE_OUTPUT_SWITCHER_FOR_SYSTEM_ROUTING; 25 26 import static com.google.common.truth.Truth.assertThat; 27 28 import static org.mockito.ArgumentMatchers.any; 29 import static org.mockito.ArgumentMatchers.eq; 30 import static org.mockito.Mockito.mock; 31 import static org.mockito.Mockito.spy; 32 import static org.mockito.Mockito.verify; 33 import static org.mockito.Mockito.when; 34 35 import android.bluetooth.BluetoothAdapter; 36 import android.bluetooth.BluetoothDevice; 37 import android.bluetooth.BluetoothManager; 38 import android.content.BroadcastReceiver; 39 import android.content.Context; 40 import android.content.IntentFilter; 41 import android.content.pm.PackageManager; 42 import android.media.AudioManager; 43 import android.media.session.MediaSessionManager; 44 import android.platform.test.flag.junit.SetFlagsRule; 45 import android.util.FeatureFlagUtils; 46 47 import androidx.preference.ListPreference; 48 import androidx.preference.PreferenceManager; 49 import androidx.preference.PreferenceScreen; 50 51 import com.android.settings.bluetooth.Utils; 52 import com.android.settings.core.FeatureFlags; 53 import com.android.settings.testutils.shadow.ShadowAudioManager; 54 import com.android.settings.testutils.shadow.ShadowBluetoothUtils; 55 import com.android.settingslib.bluetooth.A2dpProfile; 56 import com.android.settingslib.bluetooth.BluetoothCallback; 57 import com.android.settingslib.bluetooth.BluetoothEventManager; 58 import com.android.settingslib.bluetooth.CachedBluetoothDevice; 59 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; 60 import com.android.settingslib.bluetooth.HeadsetProfile; 61 import com.android.settingslib.bluetooth.HearingAidProfile; 62 import com.android.settingslib.bluetooth.LeAudioProfile; 63 import com.android.settingslib.bluetooth.LocalBluetoothManager; 64 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; 65 66 import org.junit.After; 67 import org.junit.Before; 68 import org.junit.Rule; 69 import org.junit.Test; 70 import org.junit.runner.RunWith; 71 import org.mockito.Mock; 72 import org.mockito.MockitoAnnotations; 73 import org.robolectric.RobolectricTestRunner; 74 import org.robolectric.RuntimeEnvironment; 75 import org.robolectric.annotation.Config; 76 import org.robolectric.shadow.api.Shadow; 77 import org.robolectric.shadows.ShadowBluetoothDevice; 78 import org.robolectric.shadows.ShadowPackageManager; 79 80 import java.util.ArrayList; 81 import java.util.Collection; 82 import java.util.List; 83 84 @RunWith(RobolectricTestRunner.class) 85 @Config(shadows = { 86 ShadowAudioManager.class, 87 ShadowBluetoothUtils.class, 88 ShadowBluetoothDevice.class} 89 ) 90 public class AudioOutputSwitchPreferenceControllerTest { 91 private static final String TEST_KEY = "Test_Key"; 92 private static final String TEST_DEVICE_NAME_1 = "Test_A2DP_BT_Device_NAME_1"; 93 private static final String TEST_DEVICE_NAME_2 = "Test_A2DP_BT_Device_NAME_2"; 94 private static final String TEST_DEVICE_ADDRESS_1 = "00:A1:A1:A1:A1:A1"; 95 private static final String TEST_DEVICE_ADDRESS_2 = "00:B2:B2:B2:B2:B2"; 96 private static final String TEST_DEVICE_ADDRESS_3 = "00:C3:C3:C3:C3:C3"; 97 private final static long HISYNCID1 = 10; 98 private final static long HISYNCID2 = 11; 99 100 @Mock 101 private LocalBluetoothManager mLocalManager; 102 @Mock 103 private BluetoothEventManager mBluetoothEventManager; 104 @Mock 105 private LocalBluetoothProfileManager mLocalBluetoothProfileManager; 106 @Mock 107 private A2dpProfile mA2dpProfile; 108 @Mock 109 private HeadsetProfile mHeadsetProfile; 110 @Mock 111 private HearingAidProfile mHearingAidProfile; 112 @Mock 113 private LeAudioProfile mLeAudioProfile; 114 @Mock 115 private CachedBluetoothDeviceManager mCachedDeviceManager; 116 @Mock 117 private CachedBluetoothDevice mCachedBluetoothDeviceL; 118 @Mock 119 private CachedBluetoothDevice mCachedBluetoothDeviceR; 120 121 @Rule 122 public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); 123 124 private Context mContext; 125 private PreferenceScreen mScreen; 126 private ListPreference mPreference; 127 private AudioManager mAudioManager; 128 private ShadowAudioManager mShadowAudioManager; 129 private BluetoothManager mBluetoothManager; 130 private BluetoothAdapter mBluetoothAdapter; 131 private BluetoothDevice mBluetoothDevice; 132 private BluetoothDevice mLeftBluetoothHapDevice; 133 private BluetoothDevice mRightBluetoothHapDevice; 134 private LocalBluetoothManager mLocalBluetoothManager; 135 private AudioSwitchPreferenceController mController; 136 private List<BluetoothDevice> mProfileConnectedDevices; 137 private List<BluetoothDevice> mHearingAidActiveDevices; 138 private List<BluetoothDevice> mLeAudioActiveDevices; 139 private List<BluetoothDevice> mEmptyDevices; 140 private ShadowPackageManager mPackageManager; 141 private Collection<CachedBluetoothDevice> mCachedDevices; 142 143 @Before setUp()144 public void setUp() { 145 MockitoAnnotations.initMocks(this); 146 mContext = spy(RuntimeEnvironment.application); 147 148 mAudioManager = mContext.getSystemService(AudioManager.class); 149 mShadowAudioManager = ShadowAudioManager.getShadow(); 150 151 ShadowBluetoothUtils.sLocalBluetoothManager = mLocalManager; 152 mLocalBluetoothManager = Utils.getLocalBtManager(mContext); 153 154 when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager); 155 when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager); 156 when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager); 157 when(mLocalBluetoothProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile); 158 when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile); 159 when(mLocalBluetoothProfileManager.getHeadsetProfile()).thenReturn(mHeadsetProfile); 160 when(mLocalBluetoothProfileManager.getLeAudioProfile()).thenReturn(mLeAudioProfile); 161 mPackageManager = Shadow.extract(mContext.getPackageManager()); 162 mPackageManager.setSystemFeature(PackageManager.FEATURE_BLUETOOTH, true); 163 164 mBluetoothManager = mContext.getSystemService(BluetoothManager.class); 165 mBluetoothAdapter = mBluetoothManager.getAdapter(); 166 167 mCachedDevices = new ArrayList<>(); 168 mCachedDevices.add(mCachedBluetoothDeviceL); 169 mCachedDevices.add(mCachedBluetoothDeviceR); 170 when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(mCachedDevices); 171 172 mBluetoothDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_1)); 173 when(mBluetoothDevice.getName()).thenReturn(TEST_DEVICE_NAME_1); 174 when(mBluetoothDevice.isConnected()).thenReturn(true); 175 176 mLeftBluetoothHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2)); 177 when(mLeftBluetoothHapDevice.isConnected()).thenReturn(true); 178 mRightBluetoothHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_3)); 179 when(mRightBluetoothHapDevice.isConnected()).thenReturn(true); 180 181 mController = new AudioSwitchPreferenceControllerTestable(mContext, TEST_KEY); 182 mScreen = spy(new PreferenceScreen(mContext, null)); 183 mPreference = new ListPreference(mContext); 184 mProfileConnectedDevices = new ArrayList<>(); 185 mHearingAidActiveDevices = new ArrayList<>(2); 186 mLeAudioActiveDevices = new ArrayList<>(); 187 mEmptyDevices = new ArrayList<>(2); 188 189 when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); 190 when(mScreen.getContext()).thenReturn(mContext); 191 when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference); 192 mScreen.addPreference(mPreference); 193 mController.displayPreference(mScreen); 194 } 195 196 @After tearDown()197 public void tearDown() { 198 ShadowBluetoothUtils.reset(); 199 } 200 201 @Test constructor_notSupportBluetooth_shouldReturnBeforeUsingLocalBluetoothManager()202 public void constructor_notSupportBluetooth_shouldReturnBeforeUsingLocalBluetoothManager() { 203 ShadowBluetoothUtils.reset(); 204 mLocalBluetoothManager = Utils.getLocalBtManager(mContext); 205 206 AudioSwitchPreferenceController controller = new AudioSwitchPreferenceControllerTestable( 207 mContext, TEST_KEY); 208 controller.onStart(); 209 controller.onStop(); 210 211 assertThat(mLocalBluetoothManager).isNull(); 212 } 213 214 @Test getAvailabilityStatus_disableFlagNoBluetoothFeature_returnUnavailable()215 public void getAvailabilityStatus_disableFlagNoBluetoothFeature_returnUnavailable() { 216 FeatureFlagUtils.setEnabled(mContext, FeatureFlags.AUDIO_SWITCHER_SETTINGS, false); 217 mPackageManager.setSystemFeature(PackageManager.FEATURE_BLUETOOTH, false); 218 219 assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE); 220 } 221 222 @Test getAvailabilityStatus_disableFlagWithBluetoothFeature_returnUnavailable()223 public void getAvailabilityStatus_disableFlagWithBluetoothFeature_returnUnavailable() { 224 FeatureFlagUtils.setEnabled(mContext, FeatureFlags.AUDIO_SWITCHER_SETTINGS, false); 225 mPackageManager.setSystemFeature(PackageManager.FEATURE_BLUETOOTH, true); 226 227 228 assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE); 229 } 230 231 @Test getAvailabilityStatus_enableFlagWithBluetoothFeature_returnAvailable()232 public void getAvailabilityStatus_enableFlagWithBluetoothFeature_returnAvailable() { 233 FeatureFlagUtils.setEnabled(mContext, FeatureFlags.AUDIO_SWITCHER_SETTINGS, true); 234 mPackageManager.setSystemFeature(PackageManager.FEATURE_BLUETOOTH, true); 235 236 assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); 237 } 238 239 @Test getAvailabilityStatus_enableFlagNoBluetoothFeature_returnUnavailable()240 public void getAvailabilityStatus_enableFlagNoBluetoothFeature_returnUnavailable() { 241 FeatureFlagUtils.setEnabled(mContext, FeatureFlags.AUDIO_SWITCHER_SETTINGS, true); 242 mPackageManager.setSystemFeature(PackageManager.FEATURE_BLUETOOTH, false); 243 244 assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE); 245 } 246 247 @Test onStart_shouldRegisterCallbackAndRegisterReceiver()248 public void onStart_shouldRegisterCallbackAndRegisterReceiver() { 249 mSetFlagsRule.disableFlags(FLAG_ENABLE_OUTPUT_SWITCHER_FOR_SYSTEM_ROUTING); 250 mController.onStart(); 251 252 verify(mLocalBluetoothManager.getEventManager()).registerCallback( 253 any(BluetoothCallback.class)); 254 verify(mContext).registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class)); 255 verify(mLocalBluetoothManager).setForegroundActivity(mContext); 256 } 257 258 @Test onStop_shouldUnregisterCallbackAndUnregisterReceiver()259 public void onStop_shouldUnregisterCallbackAndUnregisterReceiver() { 260 mSetFlagsRule.disableFlags(FLAG_ENABLE_OUTPUT_SWITCHER_FOR_SYSTEM_ROUTING); 261 mController.onStart(); 262 mController.onStop(); 263 264 verify(mLocalBluetoothManager.getEventManager()).unregisterCallback( 265 any(BluetoothCallback.class)); 266 verify(mContext).unregisterReceiver(any(BroadcastReceiver.class)); 267 verify(mLocalBluetoothManager).setForegroundActivity(null); 268 } 269 270 @Test onStart_shouldRegisterCallbackAndRegisterReceiverWithDefaultMediaOutput()271 public void onStart_shouldRegisterCallbackAndRegisterReceiverWithDefaultMediaOutput() { 272 MediaSessionManager mediaSessionManager = 273 spy(mContext.getSystemService(MediaSessionManager.class)); 274 mSetFlagsRule.enableFlags(FLAG_ENABLE_OUTPUT_SWITCHER_FOR_SYSTEM_ROUTING); 275 when(mContext.getSystemService(MediaSessionManager.class)).thenReturn(mediaSessionManager); 276 mController = new AudioSwitchPreferenceControllerTestable(mContext, TEST_KEY); 277 278 mController.onStart(); 279 280 verify(mLocalBluetoothManager.getEventManager()).registerCallback( 281 any(BluetoothCallback.class)); 282 verify(mContext).registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class), 283 eq(Context.RECEIVER_NOT_EXPORTED)); 284 verify(mLocalBluetoothManager).setForegroundActivity(mContext); 285 verify(mediaSessionManager).addOnActiveSessionsChangedListener( 286 any(MediaSessionManager.OnActiveSessionsChangedListener.class), any(), any()); 287 } 288 289 290 @Test onStop_shouldUnregisterCallbackAndUnregisterReceiverWithDefaultMediaOutput()291 public void onStop_shouldUnregisterCallbackAndUnregisterReceiverWithDefaultMediaOutput() { 292 MediaSessionManager mediaSessionManager = 293 spy(mContext.getSystemService(MediaSessionManager.class)); 294 mSetFlagsRule.enableFlags(FLAG_ENABLE_OUTPUT_SWITCHER_FOR_SYSTEM_ROUTING); 295 when(mContext.getSystemService(MediaSessionManager.class)).thenReturn(mediaSessionManager); 296 mController = new AudioSwitchPreferenceControllerTestable(mContext, TEST_KEY); 297 mController.onStart(); 298 299 mController.onStop(); 300 301 verify(mLocalBluetoothManager.getEventManager()).unregisterCallback( 302 any(BluetoothCallback.class)); 303 verify(mContext).unregisterReceiver(any(BroadcastReceiver.class)); 304 verify(mLocalBluetoothManager).setForegroundActivity(null); 305 verify(mediaSessionManager).removeOnActiveSessionsChangedListener( 306 any(MediaSessionManager.OnActiveSessionsChangedListener.class)); 307 } 308 309 /** 310 * Audio stream output to bluetooth sco headset which is the subset of all sco device. 311 * isStreamFromOutputDevice should return true. 312 */ 313 @Test isStreamFromOutputDevice_outputDeviceIsBtScoHeadset_shouldReturnTrue()314 public void isStreamFromOutputDevice_outputDeviceIsBtScoHeadset_shouldReturnTrue() { 315 mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_SCO_HEADSET); 316 317 assertThat(mController.isStreamFromOutputDevice( 318 STREAM_MUSIC, DEVICE_OUT_BLUETOOTH_SCO_HEADSET)).isTrue(); 319 } 320 321 /** 322 * Left side of HAP device is active. 323 * findActiveHearingAidDevice should return hearing aid device active device. 324 */ 325 @Test findActiveHearingAidDevice_leftActiveDevice_returnLeftDeviceAsActiveHapDevice()326 public void findActiveHearingAidDevice_leftActiveDevice_returnLeftDeviceAsActiveHapDevice() { 327 mController.mConnectedDevices.clear(); 328 mController.mConnectedDevices.add(mBluetoothDevice); 329 mController.mConnectedDevices.add(mLeftBluetoothHapDevice); 330 mHearingAidActiveDevices.clear(); 331 mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); 332 mHearingAidActiveDevices.add(null); 333 when(mHeadsetProfile.getActiveDevice()).thenReturn(mBluetoothDevice); 334 when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); 335 336 assertThat(mController.findActiveHearingAidDevice()).isEqualTo(mLeftBluetoothHapDevice); 337 } 338 339 /** 340 * Right side of HAP device is active. 341 * findActiveHearingAidDevice should return hearing aid device active device. 342 */ 343 @Test findActiveHearingAidDevice_rightActiveDevice_returnRightDeviceAsActiveHapDevice()344 public void findActiveHearingAidDevice_rightActiveDevice_returnRightDeviceAsActiveHapDevice() { 345 mController.mConnectedDevices.clear(); 346 mController.mConnectedDevices.add(mBluetoothDevice); 347 mController.mConnectedDevices.add(mRightBluetoothHapDevice); 348 mHearingAidActiveDevices.clear(); 349 mHearingAidActiveDevices.add(null); 350 mHearingAidActiveDevices.add(mRightBluetoothHapDevice); 351 when(mHeadsetProfile.getActiveDevice()).thenReturn(mBluetoothDevice); 352 when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); 353 354 assertThat(mController.findActiveHearingAidDevice()).isEqualTo(mRightBluetoothHapDevice); 355 } 356 357 /** 358 * Both are active device. 359 * findActiveHearingAidDevice only return the active device in mConnectedDevices. 360 */ 361 @Test findActiveHearingAidDevice_twoActiveDevice_returnActiveDeviceInConnectedDevices()362 public void findActiveHearingAidDevice_twoActiveDevice_returnActiveDeviceInConnectedDevices() { 363 mController.mConnectedDevices.clear(); 364 mController.mConnectedDevices.add(mBluetoothDevice); 365 mController.mConnectedDevices.add(mRightBluetoothHapDevice); 366 mHearingAidActiveDevices.clear(); 367 mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); 368 mHearingAidActiveDevices.add(mRightBluetoothHapDevice); 369 when(mHeadsetProfile.getActiveDevice()).thenReturn(mBluetoothDevice); 370 when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); 371 372 assertThat(mController.findActiveHearingAidDevice()).isEqualTo(mRightBluetoothHapDevice); 373 } 374 375 /** 376 * None of them are active. 377 * findActiveHearingAidDevice should return null. 378 */ 379 @Test findActiveHearingAidDevice_noActiveDevice_returnNull()380 public void findActiveHearingAidDevice_noActiveDevice_returnNull() { 381 mController.mConnectedDevices.clear(); 382 mController.mConnectedDevices.add(mBluetoothDevice); 383 mController.mConnectedDevices.add(mLeftBluetoothHapDevice); 384 mHearingAidActiveDevices.clear(); 385 when(mHeadsetProfile.getActiveDevice()).thenReturn(mBluetoothDevice); 386 when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); 387 388 assertThat(mController.findActiveHearingAidDevice()).isNull(); 389 } 390 391 /** 392 * Two hearing aid devices with different HisyncId 393 * getConnectedHearingAidDevices should add both device to list. 394 */ 395 @Test getConnectedHearingAidDevices_deviceHisyncIdIsDifferent_shouldAddBothToList()396 public void getConnectedHearingAidDevices_deviceHisyncIdIsDifferent_shouldAddBothToList() { 397 mEmptyDevices.clear(); 398 mProfileConnectedDevices.clear(); 399 mProfileConnectedDevices.add(mLeftBluetoothHapDevice); 400 mProfileConnectedDevices.add(mRightBluetoothHapDevice); 401 when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 402 when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); 403 when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID2); 404 405 mEmptyDevices.addAll(mController.getConnectedHearingAidDevices()); 406 407 assertThat(mEmptyDevices).containsExactly(mLeftBluetoothHapDevice, 408 mRightBluetoothHapDevice); 409 } 410 411 /** 412 * Two hearing aid devices with same HisyncId 413 * getConnectedHearingAidDevices should only add first device to list. 414 */ 415 @Test getConnectedHearingAidDevices_deviceHisyncIdIsSame_shouldAddOneToList()416 public void getConnectedHearingAidDevices_deviceHisyncIdIsSame_shouldAddOneToList() { 417 mEmptyDevices.clear(); 418 mProfileConnectedDevices.clear(); 419 mProfileConnectedDevices.add(mLeftBluetoothHapDevice); 420 mProfileConnectedDevices.add(mRightBluetoothHapDevice); 421 when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 422 when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1); 423 when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID1); 424 425 mEmptyDevices.addAll(mController.getConnectedHearingAidDevices()); 426 427 assertThat(mEmptyDevices).containsExactly(mLeftBluetoothHapDevice); 428 } 429 430 /** 431 * One hands free profile device is connected. 432 * getConnectedA2dpDevices should add this device to list. 433 */ 434 @Test getConnectedHfpDevices_oneConnectedHfpDevice_shouldAddDeviceToList()435 public void getConnectedHfpDevices_oneConnectedHfpDevice_shouldAddDeviceToList() { 436 mEmptyDevices.clear(); 437 mProfileConnectedDevices.clear(); 438 mProfileConnectedDevices.add(mBluetoothDevice); 439 when(mHeadsetProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 440 441 mEmptyDevices.addAll(mController.getConnectedHfpDevices()); 442 443 assertThat(mEmptyDevices).containsExactly(mBluetoothDevice); 444 } 445 446 /** 447 * More than one hands free profile devices are connected. 448 * getConnectedA2dpDevices should add all devices to list. 449 */ 450 @Test getConnectedHfpDevices_moreThanOneConnectedHfpDevice_shouldAddDeviceToList()451 public void getConnectedHfpDevices_moreThanOneConnectedHfpDevice_shouldAddDeviceToList() { 452 mEmptyDevices.clear(); 453 mProfileConnectedDevices.clear(); 454 mProfileConnectedDevices.add(mBluetoothDevice); 455 mProfileConnectedDevices.add(mLeftBluetoothHapDevice); 456 when(mHeadsetProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 457 458 mEmptyDevices.addAll(mController.getConnectedHfpDevices()); 459 460 assertThat(mEmptyDevices).containsExactly(mBluetoothDevice, mLeftBluetoothHapDevice); 461 } 462 463 @Test getConnectedLeAudioDevices_connectedLeAudioDevice_shouldAddDeviceToList()464 public void getConnectedLeAudioDevices_connectedLeAudioDevice_shouldAddDeviceToList() { 465 when(mCachedBluetoothDeviceL.getDevice()).thenReturn(mBluetoothDevice); 466 mEmptyDevices.clear(); 467 mProfileConnectedDevices.clear(); 468 mProfileConnectedDevices.add(mBluetoothDevice); 469 when(mLeAudioProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 470 471 mEmptyDevices.addAll(mController.getConnectedLeAudioDevices()); 472 473 assertThat(mEmptyDevices).containsExactly(mBluetoothDevice); 474 } 475 476 @Test getConnectedLeAudioDevices_disconnectedLeAudioDevice_shouldNotAddDeviceToList()477 public void getConnectedLeAudioDevices_disconnectedLeAudioDevice_shouldNotAddDeviceToList() { 478 BluetoothDevice connectedBtLeAduioDevice = 479 spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2)); 480 when(connectedBtLeAduioDevice.isConnected()).thenReturn(true); 481 BluetoothDevice disconnectedBtLeAduioDevice = 482 spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_3)); 483 when(disconnectedBtLeAduioDevice.isConnected()).thenReturn(false); 484 when(mCachedBluetoothDeviceL.getDevice()).thenReturn(mBluetoothDevice); 485 when(mCachedBluetoothDeviceR.getDevice()).thenReturn(connectedBtLeAduioDevice); 486 mEmptyDevices.clear(); 487 mProfileConnectedDevices.clear(); 488 mProfileConnectedDevices.add(mBluetoothDevice); 489 mProfileConnectedDevices.add(connectedBtLeAduioDevice); 490 mProfileConnectedDevices.add(disconnectedBtLeAduioDevice); 491 when(mLeAudioProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 492 493 mEmptyDevices.addAll(mController.getConnectedLeAudioDevices()); 494 495 assertThat(mEmptyDevices).containsExactly(mBluetoothDevice, connectedBtLeAduioDevice); 496 } 497 498 @Test getConnectedLeAudioDevices_notInCachedDeviceList_shouldNotAddDeviceToList()499 public void getConnectedLeAudioDevices_notInCachedDeviceList_shouldNotAddDeviceToList() { 500 BluetoothDevice connectedBtLeAduioDevice1 = 501 spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2)); 502 when(connectedBtLeAduioDevice1.isConnected()).thenReturn(true); 503 BluetoothDevice connectedBtLeAduioDevice2 = 504 spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_3)); 505 when(connectedBtLeAduioDevice2.isConnected()).thenReturn(true); 506 when(mCachedBluetoothDeviceL.getDevice()).thenReturn(mBluetoothDevice); 507 when(mCachedBluetoothDeviceR.getDevice()).thenReturn(connectedBtLeAduioDevice1); 508 mEmptyDevices.clear(); 509 mProfileConnectedDevices.clear(); 510 mProfileConnectedDevices.add(connectedBtLeAduioDevice1); 511 mProfileConnectedDevices.add(connectedBtLeAduioDevice2); 512 when(mLeAudioProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); 513 514 mEmptyDevices.addAll(mController.getConnectedLeAudioDevices()); 515 516 assertThat(mEmptyDevices).containsExactly(connectedBtLeAduioDevice1); 517 } 518 519 @Test getConnectedLeAudioDevices_nullConnectedDevices_returnEmptyList()520 public void getConnectedLeAudioDevices_nullConnectedDevices_returnEmptyList() { 521 when(mLeAudioProfile.getConnectedDevices()).thenReturn(null); 522 523 List<BluetoothDevice> connectedDevices = mController.getConnectedLeAudioDevices(); 524 525 assertThat(connectedDevices.isEmpty()).isTrue(); 526 } 527 528 @Test findActiveLeAudioDevice_noActiveDevice_returnNull()529 public void findActiveLeAudioDevice_noActiveDevice_returnNull() { 530 mLeAudioActiveDevices.clear(); 531 when(mLeAudioProfile.getActiveDevices()).thenReturn(mLeAudioActiveDevices); 532 533 assertThat(mController.findActiveLeAudioDevice()).isNull(); 534 } 535 536 @Test findActiveLeAudioDevice_withActiveDevice_returnActiveDevice()537 public void findActiveLeAudioDevice_withActiveDevice_returnActiveDevice() { 538 mLeAudioActiveDevices.clear(); 539 mLeAudioActiveDevices.add(mBluetoothDevice); 540 when(mLeAudioProfile.getActiveDevices()).thenReturn(mLeAudioActiveDevices); 541 542 assertThat(mController.findActiveLeAudioDevice()).isEqualTo(mBluetoothDevice); 543 } 544 545 private class AudioSwitchPreferenceControllerTestable extends 546 AudioSwitchPreferenceController { AudioSwitchPreferenceControllerTestable(Context context, String key)547 AudioSwitchPreferenceControllerTestable(Context context, String key) { 548 super(context, key); 549 } 550 551 @Override findActiveDevice()552 public BluetoothDevice findActiveDevice() { 553 return null; 554 } 555 556 @Override getPreferenceKey()557 public String getPreferenceKey() { 558 return TEST_KEY; 559 } 560 } 561 } 562