• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.connecteddevice.audiosharing;
18 
19 import static com.android.settings.core.BasePreferenceController.AVAILABLE;
20 import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
21 
22 import static com.google.common.truth.Truth.assertThat;
23 
24 import static org.mockito.ArgumentMatchers.any;
25 import static org.mockito.ArgumentMatchers.anyInt;
26 import static org.mockito.ArgumentMatchers.eq;
27 import static org.mockito.Mockito.mock;
28 import static org.mockito.Mockito.never;
29 import static org.mockito.Mockito.verify;
30 import static org.mockito.Mockito.when;
31 import static org.robolectric.Shadows.shadowOf;
32 
33 import android.app.settings.SettingsEnums;
34 import android.bluetooth.BluetoothAdapter;
35 import android.bluetooth.BluetoothCsipSetCoordinator;
36 import android.bluetooth.BluetoothDevice;
37 import android.bluetooth.BluetoothLeBroadcastAssistant;
38 import android.bluetooth.BluetoothLeBroadcastMetadata;
39 import android.bluetooth.BluetoothLeBroadcastReceiveState;
40 import android.bluetooth.BluetoothProfile;
41 import android.bluetooth.BluetoothStatusCodes;
42 import android.content.ContentResolver;
43 import android.content.Context;
44 import android.database.ContentObserver;
45 import android.os.Looper;
46 import android.platform.test.annotations.DisableFlags;
47 import android.platform.test.annotations.EnableFlags;
48 import android.platform.test.flag.junit.SetFlagsRule;
49 import android.provider.Settings;
50 import android.view.View;
51 import android.widget.CheckedTextView;
52 
53 import androidx.appcompat.app.AlertDialog;
54 import androidx.fragment.app.Fragment;
55 import androidx.fragment.app.FragmentActivity;
56 import androidx.lifecycle.LifecycleOwner;
57 import androidx.preference.Preference;
58 import androidx.preference.PreferenceScreen;
59 import androidx.test.core.app.ApplicationProvider;
60 
61 import com.android.settings.R;
62 import com.android.settings.bluetooth.Utils;
63 import com.android.settings.testutils.FakeFeatureFactory;
64 import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
65 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
66 import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
67 import com.android.settings.testutils.shadow.ShadowThreadUtils;
68 import com.android.settingslib.bluetooth.BluetoothEventManager;
69 import com.android.settingslib.bluetooth.BluetoothUtils;
70 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
71 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
72 import com.android.settingslib.bluetooth.LeAudioProfile;
73 import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
74 import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
75 import com.android.settingslib.bluetooth.LocalBluetoothManager;
76 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
77 import com.android.settingslib.bluetooth.VolumeControlProfile;
78 import com.android.settingslib.core.lifecycle.Lifecycle;
79 import com.android.settingslib.flags.Flags;
80 
81 import com.google.common.collect.ImmutableList;
82 import com.google.common.collect.ImmutableSet;
83 import com.google.common.collect.Iterables;
84 
85 import org.junit.After;
86 import org.junit.Before;
87 import org.junit.Rule;
88 import org.junit.Test;
89 import org.junit.runner.RunWith;
90 import org.mockito.Mock;
91 import org.mockito.Spy;
92 import org.mockito.junit.MockitoJUnit;
93 import org.mockito.junit.MockitoRule;
94 import org.robolectric.RobolectricTestRunner;
95 import org.robolectric.Shadows;
96 import org.robolectric.annotation.Config;
97 import org.robolectric.shadow.api.Shadow;
98 import org.robolectric.shadows.ShadowListView;
99 import org.robolectric.shadows.androidx.fragment.FragmentController;
100 
101 import java.util.ArrayList;
102 import java.util.List;
103 
104 @RunWith(RobolectricTestRunner.class)
105 @Config(
106         shadows = {
107             ShadowBluetoothAdapter.class,
108             ShadowBluetoothUtils.class,
109             ShadowThreadUtils.class,
110             ShadowAlertDialogCompat.class,
111         })
112 public class AudioSharingCallAudioPreferenceControllerTest {
113     private static final String PREF_KEY = "calls_and_alarms";
114     private static final String TEST_DEVICE_NAME1 = "test1";
115     private static final String TEST_DEVICE_NAME2 = "test2";
116     private static final int TEST_DEVICE_GROUP_ID1 = 1;
117     private static final int TEST_DEVICE_GROUP_ID2 = 2;
118 
119     @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
120     @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
121 
122     @Spy Context mContext = ApplicationProvider.getApplicationContext();
123     @Mock private PreferenceScreen mScreen;
124     @Mock private LocalBluetoothManager mLocalBtManager;
125     @Mock private BluetoothEventManager mBtEventManager;
126     @Mock private LocalBluetoothProfileManager mBtProfileManager;
127     @Mock private CachedBluetoothDeviceManager mCacheManager;
128     @Mock private LeAudioProfile mLeaProfile;
129     @Mock private LocalBluetoothLeBroadcast mBroadcast;
130     @Mock private LocalBluetoothLeBroadcastAssistant mAssistant;
131     @Mock private VolumeControlProfile mVolumeControl;
132     @Mock private BluetoothDevice mDevice1;
133     @Mock private BluetoothDevice mDevice2;
134     @Mock private BluetoothDevice mDevice3;
135     @Mock private CachedBluetoothDevice mCachedDevice1;
136     @Mock private CachedBluetoothDevice mCachedDevice2;
137     @Mock private CachedBluetoothDevice mCachedDevice3;
138     @Mock private BluetoothLeBroadcastReceiveState mState;
139     @Mock private BluetoothLeBroadcastMetadata mSource;
140     @Mock private ContentResolver mContentResolver;
141     private AudioSharingCallAudioPreferenceController mController;
142     @Spy private ContentObserver mContentObserver;
143     private ShadowBluetoothAdapter mShadowBluetoothAdapter;
144     private FakeFeatureFactory mFeatureFactory;
145     private Lifecycle mLifecycle;
146     private LifecycleOwner mLifecycleOwner;
147     private Preference mPreference;
148     private Fragment mParentFragment;
149 
150     @Before
setUp()151     public void setUp() {
152         ShadowAlertDialogCompat.reset();
153         mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
154         mShadowBluetoothAdapter.setEnabled(true);
155         mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
156                 BluetoothStatusCodes.FEATURE_SUPPORTED);
157         mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
158                 BluetoothStatusCodes.FEATURE_SUPPORTED);
159         mLifecycleOwner = () -> mLifecycle;
160         mLifecycle = new Lifecycle(mLifecycleOwner);
161         mParentFragment = new Fragment();
162         FragmentController.setupFragment(
163                 mParentFragment,
164                 FragmentActivity.class,
165                 0 /* containerViewId */,
166                 null /* bundle */);
167         ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager;
168         LocalBluetoothManager btManager = Utils.getLocalBtManager(mContext);
169         mFeatureFactory = FakeFeatureFactory.setupForTest();
170         when(btManager.getEventManager()).thenReturn(mBtEventManager);
171         when(btManager.getProfileManager()).thenReturn(mBtProfileManager);
172         when(btManager.getCachedDeviceManager()).thenReturn(mCacheManager);
173         when(mBtProfileManager.getLeAudioProfile()).thenReturn(mLeaProfile);
174         when(mBtProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast);
175         when(mBtProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(mAssistant);
176         when(mBtProfileManager.getVolumeControlProfile()).thenReturn(mVolumeControl);
177         when(mBroadcast.isProfileReady()).thenReturn(true);
178         when(mAssistant.isProfileReady()).thenReturn(true);
179         when(mVolumeControl.isProfileReady()).thenReturn(true);
180         List<Long> bisSyncState = new ArrayList<>();
181         bisSyncState.add(1L);
182         when(mState.getBisSyncState()).thenReturn(bisSyncState);
183         when(mContext.getContentResolver()).thenReturn(mContentResolver);
184         when(mCachedDevice1.getDevice()).thenReturn(mDevice1);
185         when(mCachedDevice1.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID1);
186         when(mCachedDevice1.getName()).thenReturn(TEST_DEVICE_NAME1);
187         when(mCachedDevice1.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(false);
188         when(mCachedDevice1.getMemberDevice()).thenReturn(ImmutableSet.of(mCachedDevice2));
189         when(mCacheManager.findDevice(mDevice1)).thenReturn(mCachedDevice1);
190         when(mCachedDevice2.getDevice()).thenReturn(mDevice2);
191         when(mCachedDevice2.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID1);
192         when(mCachedDevice2.getName()).thenReturn(TEST_DEVICE_NAME1);
193         when(mCachedDevice2.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(false);
194         when(mCacheManager.findDevice(mDevice2)).thenReturn(mCachedDevice2);
195         when(mCachedDevice3.getDevice()).thenReturn(mDevice3);
196         when(mCachedDevice3.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID2);
197         when(mCachedDevice3.getName()).thenReturn(TEST_DEVICE_NAME2);
198         when(mCachedDevice3.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(false);
199         when(mCacheManager.findDevice(mDevice3)).thenReturn(mCachedDevice3);
200         mController = new AudioSharingCallAudioPreferenceController(mContext);
201         mController.init(null);
202         mContentObserver = mController.getSettingsObserver();
203         mPreference = new Preference(mContext);
204         when(mScreen.findPreference(PREF_KEY)).thenReturn(mPreference);
205     }
206 
207     @After
tearDown()208     public void tearDown() {
209         ShadowAlertDialogCompat.reset();
210         ShadowThreadUtils.reset();
211         ShadowBluetoothUtils.reset();
212     }
213 
214     @Test
215     @DisableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
onStart_flagOff_doNothing()216     public void onStart_flagOff_doNothing() {
217         mController.onStart(mLifecycleOwner);
218         verify(mBtEventManager, never()).registerCallback(mController);
219         verify(mContentResolver, never())
220                 .registerContentObserver(
221                         Settings.Secure.getUriFor(
222                                 BluetoothUtils.getPrimaryGroupIdUriForBroadcast()),
223                         false,
224                         mContentObserver);
225         verify(mAssistant, never())
226                 .registerServiceCallBack(any(), any(BluetoothLeBroadcastAssistant.Callback.class));
227     }
228 
229     @Test
230     @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
onStart_flagOn_registerCallback()231     public void onStart_flagOn_registerCallback() {
232         mController.onStart(mLifecycleOwner);
233         verify(mBtEventManager).registerCallback(mController);
234         verify(mContentResolver)
235                 .registerContentObserver(
236                         Settings.Secure.getUriFor(
237                                 BluetoothUtils.getPrimaryGroupIdUriForBroadcast()),
238                         false,
239                         mContentObserver);
240         verify(mAssistant)
241                 .registerServiceCallBack(any(), any(BluetoothLeBroadcastAssistant.Callback.class));
242     }
243 
244     @Test
245     @DisableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
onStop_flagOff_doNothing()246     public void onStop_flagOff_doNothing() {
247         mController.setCallbacksRegistered(true);
248         mController.onStop(mLifecycleOwner);
249         verify(mBtEventManager, never()).unregisterCallback(mController);
250         verify(mContentResolver, never()).unregisterContentObserver(mContentObserver);
251         verify(mAssistant, never())
252                 .unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
253     }
254 
255     @Test
256     @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
onStop_flagOn_notRegistered_doNothing()257     public void onStop_flagOn_notRegistered_doNothing() {
258         mController.setCallbacksRegistered(false);
259         mController.onStop(mLifecycleOwner);
260         verify(mBtEventManager, never()).unregisterCallback(mController);
261         verify(mContentResolver, never()).unregisterContentObserver(mContentObserver);
262         verify(mAssistant, never())
263                 .unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
264     }
265 
266     @Test
267     @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
onStop_flagOn_registered_unregisterCallback()268     public void onStop_flagOn_registered_unregisterCallback() {
269         mController.setCallbacksRegistered(true);
270         mController.onStop(mLifecycleOwner);
271         verify(mBtEventManager).unregisterCallback(mController);
272         verify(mContentResolver).unregisterContentObserver(mContentObserver);
273         verify(mAssistant)
274                 .unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
275     }
276 
277     @Test
278     @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
getAvailabilityStatus_flagOn()279     public void getAvailabilityStatus_flagOn() {
280         assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
281     }
282 
283     @Test
284     @DisableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
getAvailabilityStatus_flagOff()285     public void getAvailabilityStatus_flagOff() {
286         assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
287     }
288 
289     @Test
290     @DisableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
updateVisibility_flagOff_invisible()291     public void updateVisibility_flagOff_invisible() {
292         when(mBroadcast.isEnabled(any())).thenReturn(true);
293         mController.displayPreference(mScreen);
294         mController.updateVisibility();
295         shadowOf(Looper.getMainLooper()).idle();
296         assertThat(mPreference.isVisible()).isFalse();
297     }
298 
299     @Test
300     @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
updateVisibility_broadcastOffBluetoothOff_invisible()301     public void updateVisibility_broadcastOffBluetoothOff_invisible() {
302         when(mBroadcast.isEnabled(any())).thenReturn(false);
303         mShadowBluetoothAdapter.setEnabled(false);
304         mController.displayPreference(mScreen);
305         mController.updateVisibility();
306         shadowOf(Looper.getMainLooper()).idle();
307         assertThat(mPreference.isVisible()).isFalse();
308     }
309 
310     @Test
311     @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
updateVisibility_broadcastOnBluetoothOff_invisible()312     public void updateVisibility_broadcastOnBluetoothOff_invisible() {
313         when(mBroadcast.isEnabled(any())).thenReturn(true);
314         mShadowBluetoothAdapter.setEnabled(false);
315         mController.displayPreference(mScreen);
316         mController.updateVisibility();
317         shadowOf(Looper.getMainLooper()).idle();
318         assertThat(mPreference.isVisible()).isFalse();
319     }
320 
321     @Test
322     @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
updateVisibility_broadcastOffBluetoothOn_invisible()323     public void updateVisibility_broadcastOffBluetoothOn_invisible() {
324         when(mBroadcast.isEnabled(any())).thenReturn(false);
325         mController.displayPreference(mScreen);
326         mController.updateVisibility();
327         shadowOf(Looper.getMainLooper()).idle();
328         assertThat(mPreference.isVisible()).isFalse();
329     }
330 
331     @Test
332     @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
updateVisibility_broadcastOnBluetoothOn_visible()333     public void updateVisibility_broadcastOnBluetoothOn_visible() {
334         when(mBroadcast.isEnabled(any())).thenReturn(true);
335         mController.displayPreference(mScreen);
336         mController.updateVisibility();
337         shadowOf(Looper.getMainLooper()).idle();
338         assertThat(mPreference.isVisible()).isTrue();
339     }
340 
341     @Test
342     @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2)
onProfileConnectionStateChanged_adoptApi_noDeviceInSharing_updateSummary()343     public void onProfileConnectionStateChanged_adoptApi_noDeviceInSharing_updateSummary() {
344         when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID1);
345         when(mBroadcast.isEnabled(any())).thenReturn(true);
346         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of());
347         mController.displayPreference(mScreen);
348         shadowOf(Looper.getMainLooper()).idle();
349         mPreference.setSummary("test");
350 
351         mController.onProfileConnectionStateChanged(
352                 mCachedDevice1,
353                 BluetoothAdapter.STATE_DISCONNECTED,
354                 BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
355         shadowOf(Looper.getMainLooper()).idle();
356         assertThat(mPreference.getSummary().toString()).isEmpty();
357     }
358 
359     @Test
360     @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2)
onFallbackDeviceChanged_adoptApi_updateSummary()361     public void onFallbackDeviceChanged_adoptApi_updateSummary() {
362         when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID1);
363         when(mBroadcast.isEnabled(any())).thenReturn(true);
364         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1));
365         when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
366         mController.displayPreference(mScreen);
367         shadowOf(Looper.getMainLooper()).idle();
368         mPreference.setSummary("test");
369 
370         mContentObserver.onChange(true);
371         shadowOf(Looper.getMainLooper()).idle();
372         assertThat(mPreference.getSummary().toString())
373                 .isEqualTo(
374                         mContext.getString(
375                                 R.string.audio_sharing_call_audio_description, TEST_DEVICE_NAME1));
376     }
377 
378     @Test
379     @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2)
onActiveDeviceChanged_adoptApi_updateSummary()380     public void onActiveDeviceChanged_adoptApi_updateSummary() {
381         when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(
382                 BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
383         when(mCachedDevice1.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(true);
384         when(mBroadcast.isEnabled(any())).thenReturn(true);
385         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1));
386         when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
387         mController.displayPreference(mScreen);
388         shadowOf(Looper.getMainLooper()).idle();
389         mPreference.setSummary("test");
390 
391         mController.onActiveDeviceChanged(mCachedDevice1, BluetoothProfile.LE_AUDIO);
392         shadowOf(Looper.getMainLooper()).idle();
393         assertThat(mPreference.getSummary().toString())
394                 .isEqualTo(
395                         mContext.getString(
396                                 R.string.audio_sharing_call_audio_description, TEST_DEVICE_NAME1));
397     }
398 
399     @Test
400     @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2)
displayPreference_adoptApi_fallbackDeviceInSharing_showCorrectSummary()401     public void displayPreference_adoptApi_fallbackDeviceInSharing_showCorrectSummary() {
402         when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID1);
403         when(mCachedDevice3.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(true);
404         when(mBroadcast.isEnabled(any())).thenReturn(true);
405         when(mAssistant.getAllConnectedDevices())
406                 .thenReturn(ImmutableList.of(mDevice1, mDevice2, mDevice3));
407         when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
408         mController.displayPreference(mScreen);
409         shadowOf(Looper.getMainLooper()).idle();
410         assertThat(mPreference.getSummary().toString())
411                 .isEqualTo(
412                         mContext.getString(
413                                 R.string.audio_sharing_call_audio_description, TEST_DEVICE_NAME1));
414     }
415 
416     @Test
417     @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2)
displayPreference_adoptApi_activeDeviceInSharing_showCorrectSummary()418     public void displayPreference_adoptApi_activeDeviceInSharing_showCorrectSummary() {
419         when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID2);
420         when(mCachedDevice1.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(true);
421         when(mBroadcast.isEnabled(any())).thenReturn(true);
422         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1, mDevice2));
423         when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
424         mController.displayPreference(mScreen);
425         shadowOf(Looper.getMainLooper()).idle();
426         assertThat(mPreference.getSummary().toString())
427                 .isEqualTo(mContext.getString(
428                         R.string.audio_sharing_call_audio_description, TEST_DEVICE_NAME1));
429     }
430 
431     @Test
432     @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2)
displayPreference_adoptApi_noFallbackDeviceOrActiveInSharing_showEmptySummary()433     public void displayPreference_adoptApi_noFallbackDeviceOrActiveInSharing_showEmptySummary() {
434         when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID2);
435         when(mBroadcast.isEnabled(any())).thenReturn(true);
436         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1, mDevice2));
437         when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
438         mController.displayPreference(mScreen);
439         shadowOf(Looper.getMainLooper()).idle();
440         assertThat(mPreference.getSummary().toString()).isEmpty();
441     }
442 
443     @Test
444     @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2)
displayPreference_adoptApi_noFallbackOrActiveDevice_showEmptySummary()445     public void displayPreference_adoptApi_noFallbackOrActiveDevice_showEmptySummary() {
446         when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(
447                 BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
448         when(mBroadcast.isEnabled(any())).thenReturn(true);
449         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of());
450         mController.displayPreference(mScreen);
451         shadowOf(Looper.getMainLooper()).idle();
452         assertThat(mPreference.getSummary().toString()).isEmpty();
453     }
454 
455     @Test
456     @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2)
displayPreference_adoptApi_clickToShowCorrectDialog()457     public void displayPreference_adoptApi_clickToShowCorrectDialog() {
458         AlertDialog latestAlertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
459         if (latestAlertDialog != null) {
460             latestAlertDialog.dismiss();
461             ShadowAlertDialogCompat.reset();
462         }
463         when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID1);
464         mShadowBluetoothAdapter.setMostRecentlyConnectedDevices(
465                 List.of(mDevice1, mDevice2, mDevice3));
466         when(mBroadcast.isEnabled(any())).thenReturn(true);
467         when(mAssistant.getAllConnectedDevices()).thenReturn(
468                 ImmutableList.of(mDevice1, mDevice2, mDevice3));
469         when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
470         mController.init(mParentFragment);
471         mController.displayPreference(mScreen);
472         shadowOf(Looper.getMainLooper()).idle();
473         mPreference.performClick();
474         shadowOf(Looper.getMainLooper()).idle();
475         AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
476         assertThat(dialog.isShowing()).isTrue();
477         assertThat(dialog.getListView().getCount()).isEqualTo(2);
478         ArrayList<View> outViews = new ArrayList<>();
479         dialog.getListView()
480                 .findViewsWithText(outViews, TEST_DEVICE_NAME1, View.FIND_VIEWS_WITH_TEXT);
481         assertThat(outViews.size()).isEqualTo(1);
482         View view = Iterables.getOnlyElement(outViews);
483         assertThat(view instanceof CheckedTextView).isTrue();
484         assertThat(((CheckedTextView) view).isChecked()).isTrue();
485         verify(mFeatureFactory.metricsFeatureProvider)
486                 .visible(
487                         /* context= */ eq(null),
488                         /* source= */ anyInt(),
489                         eq(SettingsEnums.DIALOG_AUDIO_SHARING_CALL_AUDIO),
490                         /* latency= */ anyInt());
491     }
492 
493     @Test
494     @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2)
testBluetoothLeBroadcastAssistantCallbacks_adoptApi_updateSummary()495     public void testBluetoothLeBroadcastAssistantCallbacks_adoptApi_updateSummary() {
496         when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(
497                 BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
498         when(mBroadcast.isEnabled(any())).thenReturn(true);
499         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of());
500         mController.displayPreference(mScreen);
501         shadowOf(Looper.getMainLooper()).idle();
502         assertThat(mPreference.getSummary().toString()).isEmpty();
503 
504         // onSourceAdded will update summary
505         when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID1);
506         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1));
507         when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
508         mController.mBroadcastAssistantCallback.onSourceAdded(mDevice1, /* sourceId= */
509                 1, /* reason= */ 1);
510         shadowOf(Looper.getMainLooper()).idle();
511         assertThat(mPreference.getSummary().toString())
512                 .isEqualTo(
513                         mContext.getString(
514                                 R.string.audio_sharing_call_audio_description, TEST_DEVICE_NAME1));
515     }
516 
517     @Test
518     @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2)
testBluetoothLeBroadcastAssistantCallbacks_adoptApi_doNothing()519     public void testBluetoothLeBroadcastAssistantCallbacks_adoptApi_doNothing() {
520         when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(
521                 BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
522         when(mBroadcast.isEnabled(any())).thenReturn(true);
523         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of());
524         mController.displayPreference(mScreen);
525         shadowOf(Looper.getMainLooper()).idle();
526         assertThat(mPreference.getSummary().toString()).isEmpty();
527 
528         when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID1);
529         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1));
530         when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
531         mController.mBroadcastAssistantCallback.onSearchStarted(/* reason= */ 1);
532         mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1);
533         mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1);
534         mController.mBroadcastAssistantCallback.onSearchStopFailed(/* reason= */ 1);
535         mController.mBroadcastAssistantCallback.onSourceAddFailed(
536                 mDevice1, mSource, /* reason= */ 1);
537         mController.mBroadcastAssistantCallback.onSourceRemoved(
538                 mDevice1, /* sourceId= */ 1, /* reason= */ 1);
539         mController.mBroadcastAssistantCallback.onSourceRemoveFailed(
540                 mDevice1, /* sourceId= */ 1, /* reason= */ 1);
541         mController.mBroadcastAssistantCallback.onSourceModified(
542                 mDevice1, /* sourceId= */ 1, /* reason= */ 1);
543         mController.mBroadcastAssistantCallback.onSourceModifyFailed(
544                 mDevice1, /* sourceId= */ 1, /* reason= */ 1);
545         mController.mBroadcastAssistantCallback.onSourceFound(mSource);
546         mController.mBroadcastAssistantCallback.onSourceLost(/* broadcastId= */ 1);
547         shadowOf(Looper.getMainLooper()).idle();
548         mController.mBroadcastAssistantCallback.onReceiveStateChanged(mDevice1, /* sourceId= */ 1,
549                 mState);
550 
551         // Above callbacks won't update summary.
552         assertThat(mPreference.getSummary().toString()).isEmpty();
553     }
554 
555     @Test
556     @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2)
onProfileConnectionStateChanged_noDeviceInSharing_updateSummary()557     public void onProfileConnectionStateChanged_noDeviceInSharing_updateSummary() {
558         Settings.Secure.putInt(mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(),
559                 TEST_DEVICE_GROUP_ID1);
560         when(mBroadcast.isEnabled(any())).thenReturn(true);
561         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of());
562         mController.displayPreference(mScreen);
563         shadowOf(Looper.getMainLooper()).idle();
564         mPreference.setSummary("test");
565 
566         mController.onProfileConnectionStateChanged(
567                 mCachedDevice1,
568                 BluetoothAdapter.STATE_DISCONNECTED,
569                 BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
570         shadowOf(Looper.getMainLooper()).idle();
571         assertThat(mPreference.getSummary().toString()).isEmpty();
572     }
573 
574     @Test
575     @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2)
onFallbackDeviceChanged_updateSummary()576     public void onFallbackDeviceChanged_updateSummary() {
577         Settings.Secure.putInt(mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(),
578                 TEST_DEVICE_GROUP_ID1);
579         when(mBroadcast.isEnabled(any())).thenReturn(true);
580         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1));
581         when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
582         mController.displayPreference(mScreen);
583         shadowOf(Looper.getMainLooper()).idle();
584         mPreference.setSummary("test");
585 
586         mContentObserver.onChange(true);
587         shadowOf(Looper.getMainLooper()).idle();
588         assertThat(mPreference.getSummary().toString())
589                 .isEqualTo(
590                         mContext.getString(
591                                 R.string.audio_sharing_call_audio_description, TEST_DEVICE_NAME1));
592     }
593 
594     @Test
595     @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2)
onActiveDeviceChanged_updateSummary()596     public void onActiveDeviceChanged_updateSummary() {
597         Settings.Secure.putInt(mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(),
598                 BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
599         when(mCachedDevice1.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(true);
600         when(mBroadcast.isEnabled(any())).thenReturn(true);
601         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1));
602         when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
603         mController.displayPreference(mScreen);
604         shadowOf(Looper.getMainLooper()).idle();
605         mPreference.setSummary("test");
606 
607         mController.onActiveDeviceChanged(mCachedDevice1, BluetoothProfile.LE_AUDIO);
608         shadowOf(Looper.getMainLooper()).idle();
609         assertThat(mPreference.getSummary().toString())
610                 .isEqualTo(
611                         mContext.getString(
612                                 R.string.audio_sharing_call_audio_description, TEST_DEVICE_NAME1));
613     }
614 
615     @Test
616     @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2)
displayPreference_fallbackDeviceInSharing_showCorrectSummary()617     public void displayPreference_fallbackDeviceInSharing_showCorrectSummary() {
618         Settings.Secure.putInt(mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(),
619                 TEST_DEVICE_GROUP_ID1);
620         when(mCachedDevice3.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(true);
621         when(mBroadcast.isEnabled(any())).thenReturn(true);
622         when(mAssistant.getAllConnectedDevices())
623                 .thenReturn(ImmutableList.of(mDevice1, mDevice2, mDevice3));
624         when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
625         mController.displayPreference(mScreen);
626         shadowOf(Looper.getMainLooper()).idle();
627         assertThat(mPreference.getSummary().toString())
628                 .isEqualTo(
629                         mContext.getString(
630                                 R.string.audio_sharing_call_audio_description, TEST_DEVICE_NAME1));
631     }
632 
633     @Test
634     @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2)
displayPreference_activeDeviceInSharing_showCorrectSummary()635     public void displayPreference_activeDeviceInSharing_showCorrectSummary() {
636         Settings.Secure.putInt(mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(),
637                 TEST_DEVICE_GROUP_ID2);
638         when(mCachedDevice1.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(true);
639         when(mBroadcast.isEnabled(any())).thenReturn(true);
640         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1, mDevice2));
641         when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
642         mController.displayPreference(mScreen);
643         shadowOf(Looper.getMainLooper()).idle();
644         assertThat(mPreference.getSummary().toString())
645                 .isEqualTo(mContext.getString(
646                         R.string.audio_sharing_call_audio_description, TEST_DEVICE_NAME1));
647     }
648 
649     @Test
650     @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2)
displayPreference_noFallbackDeviceOrActiveInSharing_showEmptySummary()651     public void displayPreference_noFallbackDeviceOrActiveInSharing_showEmptySummary() {
652         Settings.Secure.putInt(mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(),
653                 TEST_DEVICE_GROUP_ID2);
654         when(mBroadcast.isEnabled(any())).thenReturn(true);
655         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1, mDevice2));
656         when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
657         mController.displayPreference(mScreen);
658         shadowOf(Looper.getMainLooper()).idle();
659         assertThat(mPreference.getSummary().toString()).isEmpty();
660     }
661 
662     @Test
663     @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2)
displayPreference_noFallbackOrActiveDevice_showEmptySummary()664     public void displayPreference_noFallbackOrActiveDevice_showEmptySummary() {
665         Settings.Secure.putInt(
666                 mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(),
667                 BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
668         when(mBroadcast.isEnabled(any())).thenReturn(true);
669         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of());
670         mController.displayPreference(mScreen);
671         shadowOf(Looper.getMainLooper()).idle();
672         assertThat(mPreference.getSummary().toString()).isEmpty();
673     }
674 
675     @Test
676     @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2)
displayPreference_clickToShowCorrectDialog()677     public void displayPreference_clickToShowCorrectDialog() {
678         AlertDialog latestAlertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
679         if (latestAlertDialog != null) {
680             latestAlertDialog.dismiss();
681             ShadowAlertDialogCompat.reset();
682         }
683         Settings.Secure.putInt(mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(),
684                 TEST_DEVICE_GROUP_ID1);
685         mShadowBluetoothAdapter.setMostRecentlyConnectedDevices(
686                 List.of(mDevice1, mDevice2, mDevice3));
687         when(mBroadcast.isEnabled(any())).thenReturn(true);
688         when(mAssistant.getAllConnectedDevices()).thenReturn(
689                 ImmutableList.of(mDevice1, mDevice2, mDevice3));
690         when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
691         mController.init(mParentFragment);
692         mController.displayPreference(mScreen);
693         shadowOf(Looper.getMainLooper()).idle();
694         mPreference.performClick();
695         shadowOf(Looper.getMainLooper()).idle();
696         AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
697         assertThat(dialog.isShowing()).isTrue();
698         assertThat(dialog.getListView().getCount()).isEqualTo(2);
699         ShadowListView listView = Shadows.shadowOf(dialog.getListView());
700         View view1 = listView.findItemContainingText(TEST_DEVICE_NAME1);
701         assertThat(view1).isNotNull();
702         assertThat(view1 instanceof CheckedTextView).isTrue();
703         assertThat(((CheckedTextView) view1).isChecked()).isTrue();
704         View view2 = listView.findItemContainingText(TEST_DEVICE_NAME2);
705         assertThat(view2).isNotNull();
706         assertThat(view2 instanceof CheckedTextView).isTrue();
707         assertThat(((CheckedTextView) view2).isChecked()).isFalse();
708 
709         verify(mFeatureFactory.metricsFeatureProvider)
710                 .visible(
711                         /* context= */ eq(null),
712                         /* source= */ anyInt(),
713                         eq(SettingsEnums.DIALOG_AUDIO_SHARING_CALL_AUDIO),
714                         /* latency= */ anyInt());
715 
716         LeAudioProfile leAudioProfile = mock(LeAudioProfile.class);
717         when(mBtProfileManager.getLeAudioProfile()).thenReturn(leAudioProfile);
718 
719         // Perform click to switch call audio device by set active
720         mSetFlagsRule.disableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API);
721         int index = listView.findIndexOfItemContainingText(TEST_DEVICE_NAME2);
722         listView.performItemClick(index);
723         shadowOf(Looper.getMainLooper()).idle();
724         assertThat(((CheckedTextView) view1).isChecked()).isFalse();
725         assertThat(((CheckedTextView) view2).isChecked()).isTrue();
726         verify(mCachedDevice3).setActive();
727         verify(leAudioProfile, never()).setBroadcastToUnicastFallbackGroup(TEST_DEVICE_GROUP_ID2);
728 
729         // Perform click to switch call audio device with API
730         mSetFlagsRule.enableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API);
731         Settings.Secure.putInt(mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(),
732                 TEST_DEVICE_GROUP_ID2);
733         index = listView.findIndexOfItemContainingText(TEST_DEVICE_NAME1);
734         listView.performItemClick(index);
735         shadowOf(Looper.getMainLooper()).idle();
736         assertThat(((CheckedTextView) view1).isChecked()).isTrue();
737         assertThat(((CheckedTextView) view2).isChecked()).isFalse();
738         verify(mCachedDevice1, never()).setActive();
739         verify(leAudioProfile).setBroadcastToUnicastFallbackGroup(TEST_DEVICE_GROUP_ID1);
740     }
741 
742     @Test
logCallAudioDeviceChange_changeCallAudioToEarlierConnectedDevice()743     public void logCallAudioDeviceChange_changeCallAudioToEarlierConnectedDevice() {
744         mShadowBluetoothAdapter.setMostRecentlyConnectedDevices(
745                 List.of(mDevice1, mDevice2, mDevice3));
746         mController.logCallAudioDeviceChange(TEST_DEVICE_GROUP_ID1, mCachedDevice3);
747         verify(mFeatureFactory.metricsFeatureProvider)
748                 .action(
749                         mContext,
750                         SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_CALL_AUDIO,
751                         AudioSharingCallAudioPreferenceController.ChangeCallAudioType
752                                 .CONNECTED_EARLIER
753                                 .ordinal());
754     }
755 
756     @Test
logCallAudioDeviceChange_changeCallAudioToLaterConnectedDevice()757     public void logCallAudioDeviceChange_changeCallAudioToLaterConnectedDevice() {
758         mShadowBluetoothAdapter.setMostRecentlyConnectedDevices(
759                 List.of(mDevice1, mDevice2, mDevice3));
760         mController.logCallAudioDeviceChange(TEST_DEVICE_GROUP_ID2, mCachedDevice1);
761         verify(mFeatureFactory.metricsFeatureProvider)
762                 .action(
763                         mContext,
764                         SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_CALL_AUDIO,
765                         AudioSharingCallAudioPreferenceController.ChangeCallAudioType
766                                 .CONNECTED_LATER
767                                 .ordinal());
768     }
769 
770     @Test
logCallAudioDeviceChange_deviceNotFoundInRecentList_unknownChangeType()771     public void logCallAudioDeviceChange_deviceNotFoundInRecentList_unknownChangeType() {
772         mShadowBluetoothAdapter.setMostRecentlyConnectedDevices(List.of(mDevice1, mDevice2));
773         mController.logCallAudioDeviceChange(TEST_DEVICE_GROUP_ID1, mCachedDevice3);
774         verify(mFeatureFactory.metricsFeatureProvider)
775                 .action(
776                         mContext,
777                         SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_CALL_AUDIO,
778                         AudioSharingCallAudioPreferenceController.ChangeCallAudioType.UNKNOWN
779                                 .ordinal());
780     }
781 
782     @Test
783     @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2)
testBluetoothLeBroadcastAssistantCallbacks_updateSummary()784     public void testBluetoothLeBroadcastAssistantCallbacks_updateSummary() {
785         Settings.Secure.putInt(
786                 mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(),
787                 BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
788         when(mBroadcast.isEnabled(any())).thenReturn(true);
789         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of());
790         mController.displayPreference(mScreen);
791         shadowOf(Looper.getMainLooper()).idle();
792         assertThat(mPreference.getSummary().toString()).isEmpty();
793 
794         // onSourceAdded will update summary
795         Settings.Secure.putInt(mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(),
796                 TEST_DEVICE_GROUP_ID1);
797         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1));
798         when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
799         mController.mBroadcastAssistantCallback.onSourceAdded(mDevice1, /* sourceId= */
800                 1, /* reason= */ 1);
801         shadowOf(Looper.getMainLooper()).idle();
802         assertThat(mPreference.getSummary().toString())
803                 .isEqualTo(
804                         mContext.getString(
805                                 R.string.audio_sharing_call_audio_description, TEST_DEVICE_NAME1));
806     }
807 
808     @Test
809     @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2)
testBluetoothLeBroadcastAssistantCallbacks_doNothing()810     public void testBluetoothLeBroadcastAssistantCallbacks_doNothing() {
811         Settings.Secure.putInt(
812                 mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(),
813                 BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
814         when(mBroadcast.isEnabled(any())).thenReturn(true);
815         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of());
816         mController.displayPreference(mScreen);
817         shadowOf(Looper.getMainLooper()).idle();
818         assertThat(mPreference.getSummary().toString()).isEmpty();
819 
820         Settings.Secure.putInt(mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(),
821                 TEST_DEVICE_GROUP_ID1);
822         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1));
823         when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
824         mController.mBroadcastAssistantCallback.onSearchStarted(/* reason= */ 1);
825         mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1);
826         mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1);
827         mController.mBroadcastAssistantCallback.onSearchStopFailed(/* reason= */ 1);
828         mController.mBroadcastAssistantCallback.onSourceAddFailed(
829                 mDevice1, mSource, /* reason= */ 1);
830         mController.mBroadcastAssistantCallback.onSourceRemoved(
831                 mDevice1, /* sourceId= */ 1, /* reason= */ 1);
832         mController.mBroadcastAssistantCallback.onSourceRemoveFailed(
833                 mDevice1, /* sourceId= */ 1, /* reason= */ 1);
834         mController.mBroadcastAssistantCallback.onSourceModified(
835                 mDevice1, /* sourceId= */ 1, /* reason= */ 1);
836         mController.mBroadcastAssistantCallback.onSourceModifyFailed(
837                 mDevice1, /* sourceId= */ 1, /* reason= */ 1);
838         mController.mBroadcastAssistantCallback.onSourceFound(mSource);
839         mController.mBroadcastAssistantCallback.onSourceLost(/* broadcastId= */ 1);
840         shadowOf(Looper.getMainLooper()).idle();
841         mController.mBroadcastAssistantCallback.onReceiveStateChanged(mDevice1, /* sourceId= */ 1,
842                 mState);
843 
844         // Above callbacks won't update summary.
845         assertThat(mPreference.getSummary().toString()).isEmpty();
846     }
847 }
848