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