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