1 /* 2 * Copyright (C) 2016 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.server.telecom.tests; 18 19 import static android.media.AudioDeviceInfo.TYPE_BUILTIN_SPEAKER; 20 21 import static com.android.server.telecom.CallAudioRouteAdapter.SWITCH_BASELINE_ROUTE; 22 import static com.android.server.telecom.CallAudioRouteController.INCLUDE_BLUETOOTH_IN_BASELINE; 23 24 import static org.junit.Assert.assertEquals; 25 import static org.junit.Assert.assertFalse; 26 import static org.junit.Assert.assertNull; 27 import static org.junit.Assert.assertTrue; 28 import static org.mockito.ArgumentMatchers.isNull; 29 import static org.mockito.ArgumentMatchers.nullable; 30 import static org.mockito.ArgumentMatchers.any; 31 import static org.mockito.ArgumentMatchers.eq; 32 import static org.mockito.Mockito.atLeastOnce; 33 import static org.mockito.Mockito.mock; 34 import static org.mockito.Mockito.never; 35 import static org.mockito.Mockito.times; 36 import static org.mockito.Mockito.verify; 37 import static org.mockito.Mockito.when; 38 39 import android.bluetooth.BluetoothAdapter; 40 import android.bluetooth.BluetoothDevice; 41 import android.bluetooth.BluetoothHeadset; 42 import android.bluetooth.BluetoothHearingAid; 43 import android.bluetooth.BluetoothLeAudio; 44 import android.bluetooth.BluetoothProfile; 45 import android.content.Intent; 46 import android.media.AudioDeviceInfo; 47 import android.media.AudioManager; 48 import android.os.Bundle; 49 import android.os.Parcel; 50 import android.telecom.CallAudioState; 51 52 import androidx.test.filters.SmallTest; 53 54 import com.android.server.telecom.AudioRoute; 55 import com.android.server.telecom.CallAudioCommunicationDeviceTracker; 56 import com.android.server.telecom.CallAudioRouteAdapter; 57 import com.android.server.telecom.CallAudioRouteController; 58 import com.android.server.telecom.bluetooth.BluetoothDeviceManager; 59 import com.android.server.telecom.bluetooth.BluetoothRouteManager; 60 import com.android.server.telecom.bluetooth.BluetoothStateReceiver; 61 62 import org.junit.After; 63 import org.junit.Before; 64 import org.junit.Test; 65 import org.junit.runner.RunWith; 66 import org.junit.runners.JUnit4; 67 import org.mockito.ArgumentCaptor; 68 import org.mockito.Mock; 69 70 import static org.mockito.Mockito.reset; 71 import java.util.ArrayList; 72 import java.util.Arrays; 73 import java.util.HashMap; 74 import java.util.List; 75 import java.util.Map; 76 import java.util.concurrent.Executor; 77 78 @RunWith(JUnit4.class) 79 public class BluetoothDeviceManagerTest extends TelecomTestCase { 80 private static final String DEVICE_ADDRESS_1 = "00:00:00:00:00:01"; 81 82 @Mock BluetoothRouteManager mRouteManager; 83 @Mock BluetoothHeadset mBluetoothHeadset; 84 @Mock BluetoothAdapter mAdapter; 85 @Mock BluetoothHearingAid mBluetoothHearingAid; 86 @Mock BluetoothLeAudio mBluetoothLeAudio; 87 @Mock AudioManager mockAudioManager; 88 @Mock AudioDeviceInfo mSpeakerInfo; 89 @Mock Executor mExecutor; 90 @Mock CallAudioRouteController mCallAudioRouteController; 91 @Mock CallAudioState mCallAudioState; 92 93 BluetoothDeviceManager mBluetoothDeviceManager; 94 BluetoothProfile.ServiceListener serviceListenerUnderTest; 95 BluetoothStateReceiver receiverUnderTest; 96 CallAudioCommunicationDeviceTracker mCommunicationDeviceTracker; 97 ArgumentCaptor<BluetoothLeAudio.Callback> leAudioCallbacksTest; 98 99 private BluetoothDevice device1; 100 private BluetoothDevice device2; 101 private BluetoothDevice device3; 102 private BluetoothDevice device4; 103 private BluetoothDevice device5; 104 private BluetoothDevice device6; 105 106 @Override 107 @Before setUp()108 public void setUp() throws Exception { 109 super.setUp(); 110 device1 = makeBluetoothDevice("00:00:00:00:00:01"); 111 // hearing aid 112 device2 = makeBluetoothDevice("00:00:00:00:00:02"); 113 device3 = makeBluetoothDevice("00:00:00:00:00:03"); 114 // hearing aid 115 device4 = makeBluetoothDevice("00:00:00:00:00:04"); 116 // le audio 117 device5 = makeBluetoothDevice("00:00:00:00:00:05"); 118 device6 = makeBluetoothDevice("00:00:00:00:00:06"); 119 120 when(mBluetoothHearingAid.getHiSyncId(device2)).thenReturn(100L); 121 when(mBluetoothHearingAid.getHiSyncId(device4)).thenReturn(100L); 122 123 mContext = mComponentContextFixture.getTestDouble().getApplicationContext(); 124 mCommunicationDeviceTracker = new CallAudioCommunicationDeviceTracker(mContext); 125 mBluetoothDeviceManager = new BluetoothDeviceManager(mContext, mAdapter, 126 mCommunicationDeviceTracker, mFeatureFlags); 127 mBluetoothDeviceManager.setBluetoothRouteManager(mRouteManager); 128 mBluetoothDeviceManager.setCallAudioRouteAdapter(mCallAudioRouteController); 129 mCommunicationDeviceTracker.setBluetoothRouteManager(mRouteManager); 130 131 mockAudioManager = mContext.getSystemService(AudioManager.class); 132 mExecutor = mContext.getMainExecutor(); 133 134 ArgumentCaptor<BluetoothProfile.ServiceListener> serviceCaptor = 135 ArgumentCaptor.forClass(BluetoothProfile.ServiceListener.class); 136 verify(mAdapter).getProfileProxy(eq(mContext), 137 serviceCaptor.capture(), eq(BluetoothProfile.HEADSET)); 138 serviceListenerUnderTest = serviceCaptor.getValue(); 139 140 receiverUnderTest = new BluetoothStateReceiver(mBluetoothDeviceManager, 141 mRouteManager, mCommunicationDeviceTracker, mFeatureFlags); 142 143 mBluetoothDeviceManager.setHeadsetServiceForTesting(mBluetoothHeadset); 144 mBluetoothDeviceManager.setHearingAidServiceForTesting(mBluetoothHearingAid); 145 146 leAudioCallbacksTest = 147 ArgumentCaptor.forClass(BluetoothLeAudio.Callback.class); 148 mBluetoothDeviceManager.setLeAudioServiceForTesting(mBluetoothLeAudio); 149 verify(mBluetoothLeAudio).registerCallback(any(), leAudioCallbacksTest.capture()); 150 151 when(mSpeakerInfo.getType()).thenReturn(TYPE_BUILTIN_SPEAKER); 152 when(mFeatureFlags.callAudioCommunicationDeviceRefactor()).thenReturn(false); 153 when(mFeatureFlags.useRefactoredAudioRouteSwitching()).thenReturn(false); 154 } 155 156 @Override 157 @After tearDown()158 public void tearDown() throws Exception { 159 super.tearDown(); 160 } 161 162 @SmallTest 163 @Test testSingleDeviceConnectAndDisconnect()164 public void testSingleDeviceConnectAndDisconnect() { 165 receiverUnderTest.onReceive(mContext, 166 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, 167 BluetoothDeviceManager.DEVICE_TYPE_HEADSET)); 168 assertEquals(1, mBluetoothDeviceManager.getNumConnectedDevices()); 169 receiverUnderTest.onReceive(mContext, 170 buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device1, 171 BluetoothDeviceManager.DEVICE_TYPE_HEADSET)); 172 assertEquals(0, mBluetoothDeviceManager.getNumConnectedDevices()); 173 } 174 175 @SmallTest 176 @Test testAddDeviceFailsWhenServicesAreNull()177 public void testAddDeviceFailsWhenServicesAreNull() { 178 mBluetoothDeviceManager.setHeadsetServiceForTesting(null); 179 mBluetoothDeviceManager.setHearingAidServiceForTesting(null); 180 181 receiverUnderTest.onReceive(mContext, 182 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, 183 BluetoothDeviceManager.DEVICE_TYPE_HEADSET)); 184 receiverUnderTest.onReceive(mContext, 185 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, 186 BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID)); 187 receiverUnderTest.onReceive(mContext, 188 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device5, 189 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 190 191 assertEquals(0, mBluetoothDeviceManager.getNumConnectedDevices()); 192 } 193 194 @SmallTest 195 @Test testMultiDeviceConnectAndDisconnect()196 public void testMultiDeviceConnectAndDisconnect() { 197 receiverUnderTest.onReceive(mContext, 198 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, 199 BluetoothDeviceManager.DEVICE_TYPE_HEADSET)); 200 receiverUnderTest.onReceive(mContext, 201 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, 202 BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID)); 203 receiverUnderTest.onReceive(mContext, 204 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device5, 205 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 206 leAudioCallbacksTest.getValue().onGroupNodeAdded(device5, 1); 207 when(mBluetoothLeAudio.getGroupId(device5)).thenReturn(1); 208 when(mBluetoothLeAudio.getConnectedGroupLeadDevice(1)).thenReturn(device5); 209 210 receiverUnderTest.onReceive(mContext, 211 buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device1, 212 BluetoothDeviceManager.DEVICE_TYPE_HEADSET)); 213 receiverUnderTest.onReceive(mContext, 214 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device6, 215 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 216 leAudioCallbacksTest.getValue().onGroupNodeAdded(device6, 2); 217 when(mBluetoothLeAudio.getConnectedGroupLeadDevice(2)).thenReturn(device6); 218 when(mBluetoothLeAudio.getGroupId(device6)).thenReturn(1); 219 receiverUnderTest.onReceive(mContext, 220 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device3, 221 BluetoothDeviceManager.DEVICE_TYPE_HEADSET)); 222 receiverUnderTest.onReceive(mContext, 223 buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device5, 224 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 225 assertEquals(3, mBluetoothDeviceManager.getNumConnectedDevices()); 226 receiverUnderTest.onReceive(mContext, 227 buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device3, 228 BluetoothDeviceManager.DEVICE_TYPE_HEADSET)); 229 receiverUnderTest.onReceive(mContext, 230 buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device6, 231 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 232 assertEquals(1, mBluetoothDeviceManager.getNumConnectedDevices()); 233 } 234 235 @SmallTest 236 @Test testLeAudioMissedGroupCallbackBeforeConnected()237 public void testLeAudioMissedGroupCallbackBeforeConnected() { 238 /* This should be called on connection state changed */ 239 when(mBluetoothLeAudio.getGroupId(device5)).thenReturn(1); 240 when(mBluetoothLeAudio.getGroupId(device6)).thenReturn(1); 241 242 receiverUnderTest.onReceive(mContext, 243 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device5, 244 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 245 receiverUnderTest.onReceive(mContext, 246 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device6, 247 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 248 when(mBluetoothLeAudio.getConnectedGroupLeadDevice(1)).thenReturn(device5); 249 assertEquals(1, mBluetoothDeviceManager.getNumConnectedDevices()); 250 assertEquals(1, mBluetoothDeviceManager.getUniqueConnectedDevices().size()); 251 } 252 253 @SmallTest 254 @Test testLeAudioGroupAvailableBeforeConnect()255 public void testLeAudioGroupAvailableBeforeConnect() { 256 /* Device is known (e.g. from storage) */ 257 leAudioCallbacksTest.getValue().onGroupNodeAdded(device5, 1); 258 leAudioCallbacksTest.getValue().onGroupNodeAdded(device6, 1); 259 /* Make sure getGroupId is not called for known devices */ 260 verify(mBluetoothLeAudio, never()).getGroupId(device5); 261 verify(mBluetoothLeAudio, never()).getGroupId(device6); 262 263 receiverUnderTest.onReceive(mContext, 264 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device5, 265 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 266 receiverUnderTest.onReceive(mContext, 267 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device6, 268 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 269 when(mBluetoothLeAudio.getConnectedGroupLeadDevice(1)).thenReturn(device5); 270 assertEquals(1, mBluetoothDeviceManager.getNumConnectedDevices()); 271 assertEquals(1, mBluetoothDeviceManager.getUniqueConnectedDevices().size()); 272 } 273 274 @SmallTest 275 @Test testHearingAidDedup()276 public void testHearingAidDedup() { 277 receiverUnderTest.onReceive(mContext, 278 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, 279 BluetoothDeviceManager.DEVICE_TYPE_HEADSET)); 280 receiverUnderTest.onReceive(mContext, 281 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, 282 BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID)); 283 receiverUnderTest.onReceive(mContext, 284 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device4, 285 BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID)); 286 assertEquals(3, mBluetoothDeviceManager.getNumConnectedDevices()); 287 assertEquals(2, mBluetoothDeviceManager.getUniqueConnectedDevices().size()); 288 } 289 290 @SmallTest 291 @Test testLeAudioDedup()292 public void testLeAudioDedup() { 293 receiverUnderTest.onReceive(mContext, 294 buildConnectionActionIntent(BluetoothProfile.STATE_CONNECTED, device1, 295 BluetoothDeviceManager.DEVICE_TYPE_HEADSET)); 296 receiverUnderTest.onReceive(mContext, 297 buildConnectionActionIntent(BluetoothProfile.STATE_CONNECTED, device5, 298 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 299 leAudioCallbacksTest.getValue().onGroupNodeAdded(device5, 1); 300 receiverUnderTest.onReceive(mContext, 301 buildConnectionActionIntent(BluetoothProfile.STATE_CONNECTED, device6, 302 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 303 leAudioCallbacksTest.getValue().onGroupNodeAdded(device6, 1); 304 when(mBluetoothLeAudio.getConnectedGroupLeadDevice(1)).thenReturn(device5); 305 when(mBluetoothLeAudio.getGroupId(device5)).thenReturn(1); 306 when(mBluetoothLeAudio.getGroupId(device6)).thenReturn(1); 307 assertEquals(2, mBluetoothDeviceManager.getNumConnectedDevices()); 308 assertEquals(2, mBluetoothDeviceManager.getUniqueConnectedDevices().size()); 309 } 310 311 @SmallTest 312 @Test testHandleAudioRefactoringServiceDisconnectedWhileBluetooth()313 public void testHandleAudioRefactoringServiceDisconnectedWhileBluetooth() { 314 when(mFeatureFlags.skipBaselineSwitchWhenRouteNotBluetooth()).thenReturn(true); 315 Map<AudioRoute, BluetoothDevice> btRoutes = new HashMap<>(); 316 when(mCallAudioRouteController.getBluetoothRoutes()).thenReturn(btRoutes); 317 when(mCallAudioRouteController.getCurrentCallAudioState()).thenReturn(mCallAudioState); 318 when(mCallAudioState.getRoute()).thenReturn(CallAudioState.ROUTE_BLUETOOTH); 319 320 mBluetoothDeviceManager 321 .handleAudioRefactoringServiceDisconnected(BluetoothProfile.LE_AUDIO); 322 323 verify(mCallAudioRouteController).sendMessageWithSessionInfo(SWITCH_BASELINE_ROUTE, 324 INCLUDE_BLUETOOTH_IN_BASELINE, (String) null); 325 } 326 327 @SmallTest 328 @Test testHandleAudioRefactoringServiceDisconnectedWhileSpeaker()329 public void testHandleAudioRefactoringServiceDisconnectedWhileSpeaker() { 330 when(mFeatureFlags.skipBaselineSwitchWhenRouteNotBluetooth()).thenReturn(true); 331 Map<AudioRoute, BluetoothDevice> btRoutes = new HashMap<>(); 332 when(mCallAudioRouteController.getBluetoothRoutes()).thenReturn(btRoutes); 333 when(mCallAudioRouteController.getCurrentCallAudioState()).thenReturn(mCallAudioState); 334 when(mCallAudioState.getRoute()).thenReturn(CallAudioState.ROUTE_SPEAKER); 335 336 mBluetoothDeviceManager 337 .handleAudioRefactoringServiceDisconnected(BluetoothProfile.LE_AUDIO); 338 339 verify(mCallAudioRouteController, never()).sendMessageWithSessionInfo(SWITCH_BASELINE_ROUTE, 340 INCLUDE_BLUETOOTH_IN_BASELINE, (String) null); 341 } 342 343 @SmallTest 344 @Test testHeadsetServiceDisconnect()345 public void testHeadsetServiceDisconnect() { 346 receiverUnderTest.onReceive(mContext, 347 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, 348 BluetoothDeviceManager.DEVICE_TYPE_HEADSET)); 349 receiverUnderTest.onReceive(mContext, 350 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device3, 351 BluetoothDeviceManager.DEVICE_TYPE_HEADSET)); 352 receiverUnderTest.onReceive(mContext, 353 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, 354 BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID)); 355 serviceListenerUnderTest.onServiceDisconnected(BluetoothProfile.HEADSET); 356 357 verify(mRouteManager).onActiveDeviceChanged(isNull(), 358 eq(BluetoothDeviceManager.DEVICE_TYPE_HEADSET)); 359 verify(mRouteManager).onDeviceLost(device1.getAddress()); 360 verify(mRouteManager).onDeviceLost(device3.getAddress()); 361 verify(mRouteManager, never()).onDeviceLost(device2.getAddress()); 362 assertNull(mBluetoothDeviceManager.getBluetoothHeadset()); 363 assertEquals(1, mBluetoothDeviceManager.getNumConnectedDevices()); 364 } 365 366 @SmallTest 367 @Test testHearingAidServiceDisconnect()368 public void testHearingAidServiceDisconnect() { 369 receiverUnderTest.onReceive(mContext, 370 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, 371 BluetoothDeviceManager.DEVICE_TYPE_HEADSET)); 372 receiverUnderTest.onReceive(mContext, 373 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device3, 374 BluetoothDeviceManager.DEVICE_TYPE_HEADSET)); 375 receiverUnderTest.onReceive(mContext, 376 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, 377 BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID)); 378 serviceListenerUnderTest.onServiceDisconnected(BluetoothProfile.HEARING_AID); 379 380 verify(mRouteManager).onActiveDeviceChanged(isNull(), 381 eq(BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID)); 382 verify(mRouteManager).onDeviceLost(device2.getAddress()); 383 verify(mRouteManager, never()).onDeviceLost(device1.getAddress()); 384 verify(mRouteManager, never()).onDeviceLost(device3.getAddress()); 385 assertNull(mBluetoothDeviceManager.getBluetoothHearingAid()); 386 assertEquals(2, mBluetoothDeviceManager.getNumConnectedDevices()); 387 } 388 389 @SmallTest 390 @Test testLeAudioServiceDisconnect()391 public void testLeAudioServiceDisconnect() { 392 receiverUnderTest.onReceive(mContext, 393 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, 394 BluetoothDeviceManager.DEVICE_TYPE_HEADSET)); 395 receiverUnderTest.onReceive(mContext, 396 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device3, 397 BluetoothDeviceManager.DEVICE_TYPE_HEADSET)); 398 receiverUnderTest.onReceive(mContext, 399 buildConnectionActionIntent(BluetoothLeAudio.STATE_CONNECTED, device5, 400 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 401 serviceListenerUnderTest.onServiceDisconnected(BluetoothProfile.LE_AUDIO); 402 403 verify(mRouteManager).onActiveDeviceChanged(isNull(), 404 eq(BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 405 verify(mRouteManager).onDeviceLost(device5.getAddress()); 406 verify(mRouteManager, never()).onDeviceLost(device1.getAddress()); 407 verify(mRouteManager, never()).onDeviceLost(device3.getAddress()); 408 assertNull(mBluetoothDeviceManager.getLeAudioService()); 409 assertEquals(2, mBluetoothDeviceManager.getNumConnectedDevices()); 410 } 411 412 @SmallTest 413 @Test testHearingAidChangesIgnoredWhenNotInCall()414 public void testHearingAidChangesIgnoredWhenNotInCall() { 415 receiverUnderTest.setIsInCall(false); 416 receiverUnderTest.onReceive(mContext, 417 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, 418 BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID)); 419 Intent activeDeviceChangedIntent = 420 new Intent(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED); 421 activeDeviceChangedIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, device2); 422 receiverUnderTest.onReceive(mContext, activeDeviceChangedIntent); 423 424 verify(mRouteManager).onActiveDeviceChanged(device2, 425 BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID); 426 verify(mRouteManager, never()).sendMessage(BluetoothRouteManager.BT_AUDIO_IS_ON); 427 } 428 429 @SmallTest 430 @Test testLeAudioGroupChangesIgnoredWhenNotInCall()431 public void testLeAudioGroupChangesIgnoredWhenNotInCall() { 432 receiverUnderTest.setIsInCall(false); 433 receiverUnderTest.onReceive(mContext, 434 buildConnectionActionIntent(BluetoothLeAudio.STATE_CONNECTED, device5, 435 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 436 Intent activeDeviceChangedIntent = 437 new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED); 438 activeDeviceChangedIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, device5); 439 receiverUnderTest.onReceive(mContext, activeDeviceChangedIntent); 440 441 verify(mRouteManager).onActiveDeviceChanged(device5, 442 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO); 443 verify(mRouteManager, never()).sendMessage(BluetoothRouteManager.BT_AUDIO_IS_ON); 444 } 445 446 @SmallTest 447 @Test testConnectDisconnectAudioHeadset()448 public void testConnectDisconnectAudioHeadset() { 449 receiverUnderTest.onReceive(mContext, 450 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, 451 BluetoothDeviceManager.DEVICE_TYPE_HEADSET)); 452 when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class), 453 eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true); 454 mBluetoothDeviceManager.connectAudio(device1.getAddress(), false); 455 verify(mAdapter).setActiveDevice(eq(device1), 456 eq(BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL)); 457 verify(mAdapter, never()).setActiveDevice(nullable(BluetoothDevice.class), 458 eq(BluetoothAdapter.ACTIVE_DEVICE_ALL)); 459 mBluetoothDeviceManager.disconnectAudio(); 460 verify(mBluetoothHeadset).disconnectAudio(); 461 } 462 463 @SmallTest 464 @Test testConnectDisconnectAudioHearingAid()465 public void testConnectDisconnectAudioHearingAid() { 466 receiverUnderTest.setIsInCall(true); 467 receiverUnderTest.onReceive(mContext, 468 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device5, 469 BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID)); 470 leAudioCallbacksTest.getValue().onGroupNodeAdded(device5, 1); 471 when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class), 472 eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true); 473 474 AudioDeviceInfo mockAudioDeviceInfo = createMockAudioDeviceInfo(device5.getAddress(), 475 AudioDeviceInfo.TYPE_HEARING_AID); 476 List<AudioDeviceInfo> devices = new ArrayList<>(); 477 devices.add(mockAudioDeviceInfo); 478 479 when(mockAudioManager.getAvailableCommunicationDevices()) 480 .thenReturn(devices); 481 when(mockAudioManager.setCommunicationDevice(eq(mockAudioDeviceInfo))) 482 .thenReturn(true); 483 484 mBluetoothDeviceManager.connectAudio(device5.getAddress(), false); 485 verify(mAdapter).setActiveDevice(device5, BluetoothAdapter.ACTIVE_DEVICE_ALL); 486 verify(mBluetoothHeadset, never()).connectAudio(); 487 verify(mAdapter, never()).setActiveDevice(nullable(BluetoothDevice.class), 488 eq(BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL)); 489 490 receiverUnderTest.onReceive(mContext, buildActiveDeviceChangeActionIntent(device5, 491 BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID)); 492 493 when(mockAudioManager.getCommunicationDevice()).thenReturn(mockAudioDeviceInfo); 494 mBluetoothDeviceManager.disconnectAudio(); 495 verify(mockAudioManager, atLeastOnce()).clearCommunicationDevice(); 496 } 497 498 @SmallTest 499 @Test testConnectDisconnectAudioLeAudio()500 public void testConnectDisconnectAudioLeAudio() { 501 receiverUnderTest.setIsInCall(true); 502 receiverUnderTest.onReceive(mContext, 503 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device5, 504 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 505 leAudioCallbacksTest.getValue().onGroupNodeAdded(device5, 1); 506 when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class), 507 eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true); 508 509 AudioDeviceInfo mockAudioDeviceInfo = createMockAudioDeviceInfo(device5.getAddress(), 510 AudioDeviceInfo.TYPE_BLE_HEADSET); 511 List<AudioDeviceInfo> devices = new ArrayList<>(); 512 devices.add(mockAudioDeviceInfo); 513 514 when(mockAudioManager.getAvailableCommunicationDevices()) 515 .thenReturn(devices); 516 when(mockAudioManager.setCommunicationDevice(mockAudioDeviceInfo)) 517 .thenReturn(true); 518 519 mBluetoothDeviceManager.connectAudio(device5.getAddress(), false); 520 verify(mAdapter).setActiveDevice(device5, BluetoothAdapter.ACTIVE_DEVICE_ALL); 521 verify(mBluetoothHeadset, never()).connectAudio(); 522 verify(mAdapter, never()).setActiveDevice(nullable(BluetoothDevice.class), 523 eq(BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL)); 524 verify(mAdapter, never()).setActiveDevice(nullable(BluetoothDevice.class), 525 eq(BluetoothAdapter.ACTIVE_DEVICE_AUDIO)); 526 527 receiverUnderTest.onReceive(mContext, buildActiveDeviceChangeActionIntent(device5, 528 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 529 530 mBluetoothDeviceManager.disconnectAudio(); 531 verify(mockAudioManager, atLeastOnce()).clearCommunicationDevice(); 532 } 533 534 @SmallTest 535 @Test testConnectEarbudLeAudio()536 public void testConnectEarbudLeAudio() { 537 receiverUnderTest.setIsInCall(true); 538 receiverUnderTest.onReceive(mContext, 539 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device5, 540 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 541 leAudioCallbacksTest.getValue().onGroupNodeAdded(device5, 1); 542 receiverUnderTest.onReceive(mContext, 543 buildConnectionActionIntent(BluetoothLeAudio.STATE_CONNECTED, device6, 544 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 545 leAudioCallbacksTest.getValue().onGroupNodeAdded(device6, 1); 546 when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class), 547 eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true); 548 mBluetoothDeviceManager.connectAudio(device5.getAddress(), false); 549 verify(mAdapter).setActiveDevice(device5, BluetoothAdapter.ACTIVE_DEVICE_ALL); 550 verify(mBluetoothHeadset, never()).connectAudio(); 551 verify(mAdapter, never()).setActiveDevice(nullable(BluetoothDevice.class), 552 eq(BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL)); 553 verify(mAdapter, never()).setActiveDevice(nullable(BluetoothDevice.class), 554 eq(BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL)); 555 556 when(mAdapter.getActiveDevices(eq(BluetoothProfile.LE_AUDIO))) 557 .thenReturn(Arrays.asList(device5, device6)); 558 559 receiverUnderTest.onReceive(mContext, 560 buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device5, 561 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 562 563 mBluetoothDeviceManager.connectAudio(device6.getAddress(), false); 564 verify(mAdapter).setActiveDevice(device6, BluetoothAdapter.ACTIVE_DEVICE_ALL); 565 } 566 567 @SmallTest 568 @Test testConnectMultipleLeAudioDevices()569 public void testConnectMultipleLeAudioDevices() { 570 when(mFeatureFlags.callAudioCommunicationDeviceRefactor()).thenReturn(true); 571 receiverUnderTest.setIsInCall(true); 572 receiverUnderTest.onReceive(mContext, 573 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, 574 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 575 leAudioCallbacksTest.getValue().onGroupNodeAdded(device1, 1); 576 receiverUnderTest.onReceive(mContext, 577 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, 578 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 579 leAudioCallbacksTest.getValue().onGroupNodeAdded(device2, 1); 580 when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class), 581 eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true); 582 583 List<AudioDeviceInfo> devices = new ArrayList<>(); 584 AudioDeviceInfo leAudioDevice1 = createMockAudioDeviceInfo(device1.getAddress(), 585 AudioDeviceInfo.TYPE_BLE_HEADSET); 586 AudioDeviceInfo leAudioDevice2 = createMockAudioDeviceInfo(device2.getAddress(), 587 AudioDeviceInfo.TYPE_BLE_HEADSET); 588 devices.add(leAudioDevice1); 589 devices.add(leAudioDevice2); 590 591 when(mockAudioManager.getAvailableCommunicationDevices()) 592 .thenReturn(devices); 593 when(mockAudioManager.setCommunicationDevice(any(AudioDeviceInfo.class))) 594 .thenReturn(true); 595 596 // Connect LE audio device 597 mBluetoothDeviceManager.connectAudio(device1.getAddress(), false); 598 verify(mAdapter).setActiveDevice(device1, BluetoothAdapter.ACTIVE_DEVICE_ALL); 599 verify(mBluetoothHeadset, never()).connectAudio(); 600 verify(mAdapter, never()).setActiveDevice(nullable(BluetoothDevice.class), 601 eq(BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL)); 602 // Verify that we set the communication device for device 1 603 verify(mockAudioManager).setCommunicationDevice(leAudioDevice1); 604 605 // Change active device to other LE audio device 606 receiverUnderTest.onReceive(mContext, buildActiveDeviceChangeActionIntent(device2, 607 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 608 609 // Verify call to clearLeAudioCommunicationDevice 610 verify(mRouteManager).onAudioLost(eq(DEVICE_ADDRESS_1)); 611 // Verify that we set the communication device for device2 612 verify(mockAudioManager).setCommunicationDevice(leAudioDevice2); 613 } 614 615 @SmallTest 616 @Test testClearCommunicationDeviceOnActiveDeviceChange()617 public void testClearCommunicationDeviceOnActiveDeviceChange() { 618 when(mFeatureFlags.callAudioCommunicationDeviceRefactor()).thenReturn(true); 619 receiverUnderTest.setIsInCall(true); 620 621 List<AudioDeviceInfo> devices = new ArrayList<>(); 622 AudioDeviceInfo leAudioDevice1 = createMockAudioDeviceInfo(device1.getAddress(), 623 AudioDeviceInfo.TYPE_BLE_HEADSET); 624 devices.add(leAudioDevice1); 625 626 when(mockAudioManager.getAvailableCommunicationDevices()) 627 .thenReturn(devices); 628 when(mockAudioManager.setCommunicationDevice(any(AudioDeviceInfo.class))) 629 .thenReturn(true); 630 631 // Pretend that the speaker device is currently the requested device set for communication. 632 // This test ensures that the set/clear communication logic for audio switching in/out of BT 633 // is properly working when the receiver processes an active device change intent. 634 mCommunicationDeviceTracker.setTestCommunicationDevice(TYPE_BUILTIN_SPEAKER); 635 636 // Notify that LE audio device has been turned on 637 receiverUnderTest.onReceive(mContext, buildActiveDeviceChangeActionIntent(device1, 638 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 639 // Verify call to clear speaker communication device 640 verify(mockAudioManager).clearCommunicationDevice(); 641 // Verify that LE audio communication device was set after clearing the speaker device 642 verify(mockAudioManager).setCommunicationDevice(leAudioDevice1); 643 } 644 645 @SmallTest 646 @Test testConnectDualModeEarbud()647 public void testConnectDualModeEarbud() { 648 when(mFeatureFlags.callAudioCommunicationDeviceRefactor()).thenReturn(true); 649 receiverUnderTest.setIsInCall(true); 650 651 // LE Audio earbuds connected 652 receiverUnderTest.onReceive(mContext, 653 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device5, 654 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 655 leAudioCallbacksTest.getValue().onGroupNodeAdded(device5, 1); 656 receiverUnderTest.onReceive(mContext, 657 buildConnectionActionIntent(BluetoothLeAudio.STATE_CONNECTED, device6, 658 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 659 leAudioCallbacksTest.getValue().onGroupNodeAdded(device6, 1); 660 // HFP device connected 661 receiverUnderTest.onReceive(mContext, 662 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device5, 663 BluetoothDeviceManager.DEVICE_TYPE_HEADSET)); 664 when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class), 665 eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true); 666 667 AudioDeviceInfo mockAudioDevice5Info = createMockAudioDeviceInfo(device5.getAddress(), 668 AudioDeviceInfo.TYPE_BLE_HEADSET); 669 AudioDeviceInfo mockAudioDevice6Info = createMockAudioDeviceInfo(device6.getAddress(), 670 AudioDeviceInfo.TYPE_BLE_HEADSET); 671 when(mockAudioDevice5Info.getType()).thenReturn(AudioDeviceInfo.TYPE_BLE_HEADSET); 672 when(mockAudioDevice6Info.getType()).thenReturn(AudioDeviceInfo.TYPE_BLE_HEADSET); 673 List<AudioDeviceInfo> devices = new ArrayList<>(); 674 devices.add(mockAudioDevice5Info); 675 devices.add(mockAudioDevice6Info); 676 677 when(mockAudioManager.getAvailableCommunicationDevices()) 678 .thenReturn(devices); 679 when(mockAudioManager.setCommunicationDevice(mockAudioDevice5Info)) 680 .thenReturn(true); 681 682 Bundle hfpPreferred = new Bundle(); 683 hfpPreferred.putInt(BluetoothAdapter.AUDIO_MODE_DUPLEX, BluetoothProfile.HEADSET); 684 Bundle leAudioPreferred = new Bundle(); 685 leAudioPreferred.putInt(BluetoothAdapter.AUDIO_MODE_DUPLEX, BluetoothProfile.LE_AUDIO); 686 687 // TEST 1: LE Audio preferred for DUPLEX 688 when(mAdapter.getPreferredAudioProfiles(device5)).thenReturn(leAudioPreferred); 689 when(mAdapter.getPreferredAudioProfiles(device6)).thenReturn(leAudioPreferred); 690 mBluetoothDeviceManager.connectAudio(device5.getAddress(), false); 691 verify(mAdapter, times(1)).setActiveDevice(device5, BluetoothAdapter.ACTIVE_DEVICE_ALL); 692 verify(mBluetoothHeadset, never()).connectAudio(); 693 verify(mAdapter, never()).setActiveDevice(nullable(BluetoothDevice.class), 694 eq(BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL)); 695 verify(mockAudioManager).setCommunicationDevice(mockAudioDevice5Info); 696 697 when(mAdapter.getActiveDevices(eq(BluetoothProfile.LE_AUDIO))) 698 .thenReturn(Arrays.asList(device5, device6)); 699 700 // Check disconnect during a call 701 devices.remove(mockAudioDevice5Info); 702 receiverUnderTest.onReceive(mContext, 703 buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device5, 704 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 705 leAudioCallbacksTest.getValue().onGroupNodeRemoved(device5, 1); 706 707 mBluetoothDeviceManager.connectAudio(device6.getAddress(), false); 708 verify(mAdapter).setActiveDevice(device6, BluetoothAdapter.ACTIVE_DEVICE_ALL); 709 verify(mBluetoothHeadset, never()).connectAudio(); 710 verify(mAdapter, never()).setActiveDevice(nullable(BluetoothDevice.class), 711 eq(BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL)); 712 verify(mockAudioManager, times(1)).clearCommunicationDevice(); 713 714 // Reconnect other LE Audio earbud 715 devices.add(mockAudioDevice5Info); 716 receiverUnderTest.onReceive(mContext, 717 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device5, 718 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 719 leAudioCallbacksTest.getValue().onGroupNodeAdded(device5, 1); 720 721 // Disconnects audio 722 mBluetoothDeviceManager.disconnectAudio(); 723 verify(mockAudioManager, times(2)).clearCommunicationDevice(); 724 verify(mBluetoothHeadset, times(1)).disconnectAudio(); 725 726 // TEST 2: HFP preferred for DUPLEX 727 when(mAdapter.getPreferredAudioProfiles(device5)).thenReturn(hfpPreferred); 728 when(mAdapter.getPreferredAudioProfiles(device6)).thenReturn(hfpPreferred); 729 when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class), 730 eq(BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL))).thenReturn(true); 731 mBluetoothDeviceManager.connectAudio(device5.getAddress(), false); 732 verify(mAdapter).setActiveDevice(device5, BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL); 733 verify(mAdapter, times(1)).setActiveDevice(device5, 734 BluetoothAdapter.ACTIVE_DEVICE_ALL); 735 verify(mBluetoothHeadset).connectAudio(); 736 mBluetoothDeviceManager.disconnectAudio(); 737 verify(mBluetoothHeadset, times(2)).disconnectAudio(); 738 } 739 740 @SmallTest 741 @Test testClearHearingAidCommunicationDeviceLegacy()742 public void testClearHearingAidCommunicationDeviceLegacy() { 743 assertClearHearingAidOrLeCommunicationDevice(false, AudioDeviceInfo.TYPE_HEARING_AID); 744 } 745 746 @SmallTest 747 @Test testClearHearingAidCommunicationDeviceWithFlag()748 public void testClearHearingAidCommunicationDeviceWithFlag() { 749 when(mFeatureFlags.callAudioCommunicationDeviceRefactor()).thenReturn(true); 750 assertClearHearingAidOrLeCommunicationDevice(true, AudioDeviceInfo.TYPE_HEARING_AID); 751 } 752 753 @SmallTest 754 @Test testClearLeAudioCommunicationDeviceLegacy()755 public void testClearLeAudioCommunicationDeviceLegacy() { 756 assertClearHearingAidOrLeCommunicationDevice(false, AudioDeviceInfo.TYPE_BLE_HEADSET); 757 } 758 759 @SmallTest 760 @Test testClearLeAudioCommunicationDeviceWithFlag()761 public void testClearLeAudioCommunicationDeviceWithFlag() { 762 when(mFeatureFlags.callAudioCommunicationDeviceRefactor()).thenReturn(true); 763 assertClearHearingAidOrLeCommunicationDevice(true, AudioDeviceInfo.TYPE_BLE_HEADSET); 764 } 765 766 @SmallTest 767 @Test testConnectedDevicesDoNotContainDuplicateDevices()768 public void testConnectedDevicesDoNotContainDuplicateDevices() { 769 BluetoothDevice hfpDevice = mock(BluetoothDevice.class); 770 when(hfpDevice.getAddress()).thenReturn("00:00:00:00:00:00"); 771 when(hfpDevice.getType()).thenReturn(BluetoothDeviceManager.DEVICE_TYPE_HEADSET); 772 BluetoothDevice leDevice = mock(BluetoothDevice.class); 773 when(hfpDevice.getAddress()).thenReturn("00:00:00:00:00:00"); 774 when(hfpDevice.getType()).thenReturn(BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO); 775 776 mBluetoothDeviceManager.onDeviceConnected(hfpDevice, 777 BluetoothDeviceManager.DEVICE_TYPE_HEADSET); 778 mBluetoothDeviceManager.onDeviceConnected(leDevice, 779 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO); 780 781 assertEquals(1, mBluetoothDeviceManager.getNumConnectedDevices()); 782 } 783 784 @SmallTest 785 @Test testInBandRingingEnabledForLeDevice()786 public void testInBandRingingEnabledForLeDevice() { 787 when(mBluetoothHeadset.isInbandRingingEnabled()).thenReturn(false); 788 when(mBluetoothLeAudio.isInbandRingtoneEnabled(1)).thenReturn(true); 789 when(mBluetoothLeAudio.getGroupId(eq(device3))).thenReturn(1); 790 receiverUnderTest.onReceive(mContext, 791 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device3, 792 BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO)); 793 leAudioCallbacksTest.getValue().onGroupNodeAdded(device3, 1); 794 when(mRouteManager.getBluetoothAudioConnectedDevice()).thenReturn(device3); 795 when(mRouteManager.isCachedLeAudioDevice(eq(device3))).thenReturn(true); 796 when(mBluetoothLeAudio.getConnectedGroupLeadDevice(1)).thenReturn(device3); 797 when(mRouteManager.getMostRecentlyReportedActiveDevice()).thenReturn(device3); 798 assertEquals(1, mBluetoothDeviceManager.getNumConnectedDevices()); 799 assertTrue(mBluetoothDeviceManager.isInbandRingingEnabled()); 800 } 801 802 @SmallTest 803 @Test testRegisterLeAudioCallbackNoPostpone()804 public void testRegisterLeAudioCallbackNoPostpone() { 805 reset(mBluetoothLeAudio); 806 when(mFeatureFlags.postponeRegisterToLeaudio()).thenReturn(false); 807 serviceListenerUnderTest.onServiceConnected(BluetoothProfile.LE_AUDIO, 808 (BluetoothProfile) mBluetoothLeAudio); 809 // Second time on purpose 810 serviceListenerUnderTest.onServiceConnected(BluetoothProfile.LE_AUDIO, 811 (BluetoothProfile) mBluetoothLeAudio); 812 verify(mExecutor, times(0)).execute(any()); 813 verify(mBluetoothLeAudio, times(1)).registerCallback(any(Executor.class), 814 any(BluetoothLeAudio.Callback.class)); 815 } 816 817 @SmallTest 818 @Test testRegisterLeAudioCallbackWithPostpone()819 public void testRegisterLeAudioCallbackWithPostpone() { 820 reset(mBluetoothLeAudio); 821 when(mFeatureFlags.postponeRegisterToLeaudio()).thenReturn(true); 822 serviceListenerUnderTest.onServiceConnected(BluetoothProfile.LE_AUDIO, 823 (BluetoothProfile) mBluetoothLeAudio); 824 verify(mExecutor, times(1)).execute(any()); 825 } 826 assertClearHearingAidOrLeCommunicationDevice( boolean flagEnabled, int device_type )827 private void assertClearHearingAidOrLeCommunicationDevice( 828 boolean flagEnabled, int device_type 829 ) { 830 AudioDeviceInfo mockAudioDeviceInfo = mock(AudioDeviceInfo.class); 831 when(mockAudioDeviceInfo.getAddress()).thenReturn(DEVICE_ADDRESS_1); 832 when(mockAudioDeviceInfo.getType()).thenReturn(device_type); 833 List<AudioDeviceInfo> devices = new ArrayList<>(); 834 devices.add(mockAudioDeviceInfo); 835 836 when(mockAudioManager.getAvailableCommunicationDevices()) 837 .thenReturn(devices); 838 when(mockAudioManager.setCommunicationDevice(eq(mockAudioDeviceInfo))) 839 .thenReturn(true); 840 841 if (flagEnabled) { 842 BluetoothDevice btDevice = device_type == AudioDeviceInfo.TYPE_BLE_HEADSET 843 ? device1 : null; 844 mCommunicationDeviceTracker.setCommunicationDevice(device_type, btDevice); 845 } else { 846 if (device_type == AudioDeviceInfo.TYPE_BLE_HEADSET) { 847 mBluetoothDeviceManager.setLeAudioCommunicationDevice(); 848 } else { 849 mBluetoothDeviceManager.setHearingAidCommunicationDevice(); 850 } 851 } 852 when(mockAudioManager.getCommunicationDevice()).thenReturn(mSpeakerInfo); 853 if (flagEnabled) { 854 mCommunicationDeviceTracker.clearCommunicationDevice(device_type); 855 assertFalse(mCommunicationDeviceTracker.isAudioDeviceSetForType(device_type)); 856 } else { 857 if (device_type == AudioDeviceInfo.TYPE_BLE_HEADSET) { 858 mBluetoothDeviceManager.clearLeAudioCommunicationDevice(); 859 assertFalse(mBluetoothDeviceManager.isLeAudioCommunicationDevice()); 860 } else { 861 mBluetoothDeviceManager.clearHearingAidCommunicationDevice(); 862 assertFalse(mBluetoothDeviceManager.isHearingAidSetAsCommunicationDevice()); 863 } 864 } 865 verify(mRouteManager).onAudioLost(eq(DEVICE_ADDRESS_1)); 866 } 867 createMockAudioDeviceInfo(String address, int audioType)868 private AudioDeviceInfo createMockAudioDeviceInfo(String address, int audioType) { 869 AudioDeviceInfo mockAudioDeviceInfo = mock(AudioDeviceInfo.class); 870 when(mockAudioDeviceInfo.getType()).thenReturn(audioType); 871 if (address != null) { 872 when(mockAudioDeviceInfo.getAddress()).thenReturn(address); 873 } 874 return mockAudioDeviceInfo; 875 } 876 buildConnectionActionIntent(int state, BluetoothDevice device, int deviceType)877 private Intent buildConnectionActionIntent(int state, BluetoothDevice device, int deviceType) { 878 String intentString; 879 880 switch (deviceType) { 881 case BluetoothDeviceManager.DEVICE_TYPE_HEADSET: 882 intentString = BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED; 883 break; 884 case BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID: 885 intentString = BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED; 886 break; 887 case BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO: 888 intentString = BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED; 889 break; 890 default: 891 return null; 892 } 893 894 Intent i = new Intent(intentString); 895 i.putExtra(BluetoothHeadset.EXTRA_STATE, state); 896 i.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 897 return i; 898 } 899 900 buildActiveDeviceChangeActionIntent(BluetoothDevice device, int deviceType)901 private Intent buildActiveDeviceChangeActionIntent(BluetoothDevice device, int deviceType) { 902 String intentString; 903 904 switch (deviceType) { 905 case BluetoothDeviceManager.DEVICE_TYPE_HEADSET: 906 intentString = BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED; 907 break; 908 case BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID: 909 intentString = BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED; 910 break; 911 case BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO: 912 intentString = BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED; 913 break; 914 default: 915 return null; 916 } 917 918 Intent i = new Intent(intentString); 919 i.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 920 i.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 921 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); 922 return i; 923 } 924 makeBluetoothDevice(String address)925 private BluetoothDevice makeBluetoothDevice(String address) { 926 Parcel p1 = Parcel.obtain(); 927 p1.writeString(address); 928 p1.setDataPosition(0); 929 BluetoothDevice device = BluetoothDevice.CREATOR.createFromParcel(p1); 930 p1.recycle(); 931 return device; 932 } 933 } 934