• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
20 import static android.media.AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
21 import static android.media.AudioSystem.DEVICE_OUT_HEARING_AID;
22 import static android.media.AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
23 import static android.media.AudioSystem.DEVICE_OUT_USB_HEADSET;
24 
25 import static com.google.common.truth.Truth.assertThat;
26 
27 import static org.mockito.ArgumentMatchers.any;
28 import static org.mockito.Mockito.mock;
29 import static org.mockito.Mockito.spy;
30 import static org.mockito.Mockito.times;
31 import static org.mockito.Mockito.verify;
32 import static org.mockito.Mockito.when;
33 
34 import android.bluetooth.BluetoothAdapter;
35 import android.bluetooth.BluetoothDevice;
36 import android.bluetooth.BluetoothManager;
37 import android.content.Context;
38 import android.media.AudioManager;
39 import android.support.v7.preference.ListPreference;
40 import android.support.v7.preference.PreferenceManager;
41 import android.support.v7.preference.PreferenceScreen;
42 
43 import com.android.settings.R;
44 import com.android.settings.testutils.SettingsRobolectricTestRunner;
45 import com.android.settings.testutils.shadow.ShadowAudioManager;
46 import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
47 import com.android.settings.testutils.shadow.ShadowMediaRouter;
48 import com.android.settingslib.bluetooth.A2dpProfile;
49 import com.android.settingslib.bluetooth.BluetoothEventManager;
50 import com.android.settingslib.bluetooth.HearingAidProfile;
51 import com.android.settingslib.bluetooth.LocalBluetoothManager;
52 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
53 
54 import org.junit.After;
55 import org.junit.Before;
56 import org.junit.Test;
57 import org.junit.runner.RunWith;
58 import org.mockito.Mock;
59 import org.mockito.MockitoAnnotations;
60 import org.robolectric.RuntimeEnvironment;
61 import org.robolectric.annotation.Config;
62 import org.robolectric.shadows.ShadowBluetoothDevice;
63 
64 import java.util.ArrayList;
65 import java.util.List;
66 
67 @RunWith(SettingsRobolectricTestRunner.class)
68 @Config(shadows = {
69         ShadowAudioManager.class,
70         ShadowMediaRouter.class,
71         ShadowBluetoothUtils.class,
72         ShadowBluetoothDevice.class}
73 )
74 public class MediaOutputPreferenceControllerTest {
75     private static final String TEST_KEY = "Test_Key";
76     private static final String TEST_DEVICE_NAME_1 = "Test_A2DP_BT_Device_NAME_1";
77     private static final String TEST_DEVICE_NAME_2 = "Test_A2DP_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 A2dpProfile mA2dpProfile;
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 ShadowAudioManager mShadowAudioManager;
104     private ShadowMediaRouter mShadowMediaRouter;
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 AudioSwitchPreferenceController 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         mShadowAudioManager = ShadowAudioManager.getShadow();
122         mShadowMediaRouter = ShadowMediaRouter.getShadow();
123 
124         ShadowBluetoothUtils.sLocalBluetoothManager = mLocalManager;
125         mLocalBluetoothManager = ShadowBluetoothUtils.getLocalBtManager(mContext);
126 
127         when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager);
128         when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
129         when(mLocalBluetoothProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
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 MediaOutputPreferenceController(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         mShadowAudioManager.reset();
168         mShadowMediaRouter.reset();
169         ShadowBluetoothUtils.reset();
170     }
171 
172     /**
173      * In normal mode, bluetooth device with HisyncId.
174      * HearingAidProfile should set active device to this device.
175      */
176     @Test
setActiveBluetoothDevice_btDeviceWithHisyncId_shouldSetBtDeviceActive()177     public void setActiveBluetoothDevice_btDeviceWithHisyncId_shouldSetBtDeviceActive() {
178         mShadowAudioManager.setMode(AudioManager.MODE_NORMAL);
179         when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1);
180 
181         mController.setActiveBluetoothDevice(mLeftBluetoothHapDevice);
182 
183         verify(mHearingAidProfile).setActiveDevice(mLeftBluetoothHapDevice);
184     }
185 
186     /**
187      * In normal mode, bluetooth device without HisyncId.
188      * A2dpProfile should set active device to this device.
189      */
190     @Test
setActiveBluetoothDevice_btDeviceWithoutHisyncId_shouldSetBtDeviceActive()191     public void setActiveBluetoothDevice_btDeviceWithoutHisyncId_shouldSetBtDeviceActive() {
192         mShadowAudioManager.setMode(AudioManager.MODE_NORMAL);
193 
194         mController.setActiveBluetoothDevice(mBluetoothDevice);
195 
196         verify(mA2dpProfile).setActiveDevice(mBluetoothDevice);
197     }
198 
199     /**
200      * In normal mode, set active device to "this device".
201      * A2dpProfile should set to null.
202      * HearingAidProfile should set to null.
203      */
204     @Test
setActiveBluetoothDevice_setNull_shouldSetNullToBothProfiles()205     public void setActiveBluetoothDevice_setNull_shouldSetNullToBothProfiles() {
206         mShadowAudioManager.setMode(AudioManager.MODE_NORMAL);
207 
208         mController.setActiveBluetoothDevice(null);
209 
210         verify(mA2dpProfile).setActiveDevice(null);
211         verify(mHearingAidProfile).setActiveDevice(null);
212     }
213 
214     /**
215      * During a call
216      * A2dpProfile should not set active device.
217      */
218     @Test
setActiveBluetoothDevice_duringACall_shouldNotSetActiveDeviceToA2dpProfile()219     public void setActiveBluetoothDevice_duringACall_shouldNotSetActiveDeviceToA2dpProfile() {
220         mShadowAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
221 
222         mController.setActiveBluetoothDevice(mBluetoothDevice);
223 
224         verify(mA2dpProfile, 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      * During a call
243      * Preference should be invisible
244      * Default string should be "Unavailable during calls"
245      */
246     @Test
updateState_duringACall_shouldSetDefaultSummary()247     public void updateState_duringACall_shouldSetDefaultSummary() {
248         mShadowAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
249 
250         mController.updateState(mPreference);
251 
252         assertThat(mPreference.isVisible()).isFalse();
253         assertThat(mPreference.getSummary()).isEqualTo(
254                 mContext.getText(R.string.media_out_summary_ongoing_call_state));
255     }
256 
257     /**
258      * No available A2dp BT devices:
259      * Preference should be invisible
260      * Preference summary should be "This device"
261      */
262     @Test
updateState_noAvailableA2dpBtDevices_shouldDisableAndSetDefaultSummary()263     public void updateState_noAvailableA2dpBtDevices_shouldDisableAndSetDefaultSummary() {
264         mShadowAudioManager.setMode(AudioManager.MODE_NORMAL);
265         List<BluetoothDevice> emptyDeviceList = new ArrayList<>();
266         when(mA2dpProfile.getConnectedDevices()).thenReturn(emptyDeviceList);
267 
268         mController.updateState(mPreference);
269 
270         assertThat(mPreference.isVisible()).isFalse();
271         String defaultString = mContext.getString(R.string.media_output_default_summary);
272         assertThat(mPreference.getSummary()).isEqualTo(defaultString);
273     }
274 
275     /**
276      * Media stream is captured by something else (cast device):
277      * Preference should be invisible
278      * Preference summary should be "unavailable"
279      */
280     @Test
updateState_mediaStreamIsCapturedByCast_shouldDisableAndSetDefaultSummary()281     public void updateState_mediaStreamIsCapturedByCast_shouldDisableAndSetDefaultSummary() {
282         mShadowAudioManager.setOutputDevice(DEVICE_OUT_REMOTE_SUBMIX);
283 
284         mController.updateState(mPreference);
285 
286         assertThat(mPreference.isVisible()).isFalse();
287         String defaultString = mContext.getString(R.string.media_output_summary_unavailable);
288         assertThat(mPreference.getSummary()).isEqualTo(defaultString);
289     }
290 
291     /**
292      * One A2DP Bluetooth device is available and active.
293      * Preference should be visible
294      * Preference summary should be the activated device name
295      */
296     @Test
updateState_oneA2dpBtDeviceAreAvailable_shouldSetActivatedDeviceName()297     public void updateState_oneA2dpBtDeviceAreAvailable_shouldSetActivatedDeviceName() {
298         mShadowAudioManager.setMode(AudioManager.MODE_NORMAL);
299         mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_A2DP);
300         mProfileConnectedDevices.clear();
301         mProfileConnectedDevices.add(mBluetoothDevice);
302         when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
303         when(mA2dpProfile.getActiveDevice()).thenReturn(mBluetoothDevice);
304 
305         mController.updateState(mPreference);
306 
307         assertThat(mPreference.isVisible()).isTrue();
308         assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_1);
309     }
310 
311     /**
312      * More than one A2DP Bluetooth devices are available, and second device is active.
313      * Preference should be visible
314      * Preference summary should be the activated device name
315      */
316     @Test
updateState_moreThanOneA2DpBtDevicesAreAvailable_shouldSetActivatedDeviceName()317     public void updateState_moreThanOneA2DpBtDevicesAreAvailable_shouldSetActivatedDeviceName() {
318         mShadowAudioManager.setMode(AudioManager.MODE_NORMAL);
319         mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_A2DP);
320         mProfileConnectedDevices.clear();
321         mProfileConnectedDevices.add(mBluetoothDevice);
322         mProfileConnectedDevices.add(mSecondBluetoothDevice);
323         when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
324         when(mA2dpProfile.getActiveDevice()).thenReturn(mSecondBluetoothDevice);
325 
326         mController.updateState(mPreference);
327 
328         assertThat(mPreference.isVisible()).isTrue();
329         assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_2);
330     }
331 
332     /**
333      * A2DP Bluetooth device(s) are available, but wired headset is plugged in and activated
334      * Preference should be visible
335      * Preference summary should be "This device"
336      */
337     @Test
updateState_a2dpDevicesAvailableWiredHeadsetIsActivated_shouldSetDefaultSummary()338     public void updateState_a2dpDevicesAvailableWiredHeadsetIsActivated_shouldSetDefaultSummary() {
339         mShadowAudioManager.setMode(AudioManager.MODE_NORMAL);
340         mShadowAudioManager.setOutputDevice(DEVICE_OUT_USB_HEADSET);
341         mProfileConnectedDevices.clear();
342         mProfileConnectedDevices.add(mBluetoothDevice);
343         when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
344         when(mA2dpProfile.getActiveDevice()).thenReturn(
345                 mBluetoothDevice); // BT device is still activated in this case
346 
347         mController.updateState(mPreference);
348 
349         assertThat(mPreference.isVisible()).isTrue();
350         assertThat(mPreference.getSummary()).isEqualTo(
351                 mContext.getString(R.string.media_output_default_summary));
352     }
353 
354 
355     /**
356      * A2DP Bluetooth device(s) are available, but current device speaker is activated
357      * Preference should be visible
358      * Preference summary should be "This device"
359      */
360     @Test
updateState_a2dpDevicesAvailableCurrentDeviceActivated_shouldSetDefaultSummary()361     public void updateState_a2dpDevicesAvailableCurrentDeviceActivated_shouldSetDefaultSummary() {
362         mShadowAudioManager.setMode(AudioManager.MODE_NORMAL);
363         mProfileConnectedDevices.clear();
364         mProfileConnectedDevices.add(mBluetoothDevice);
365         when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
366         when(mA2dpProfile.getActiveDevice()).thenReturn(null);
367 
368         mController.updateState(mPreference);
369 
370         assertThat(mPreference.isVisible()).isTrue();
371         assertThat(mPreference.getSummary()).isEqualTo(
372                 mContext.getString(R.string.media_output_default_summary));
373     }
374 
375     /**
376      * One hearing aid profile Bluetooth device is available and active.
377      * Preference should be visible
378      * Preference summary should be the activated device name
379      */
380     @Test
updateState_oneHapBtDeviceAreAvailable_shouldSetActivatedDeviceName()381     public void updateState_oneHapBtDeviceAreAvailable_shouldSetActivatedDeviceName() {
382         mShadowAudioManager.setMode(AudioManager.MODE_NORMAL);
383         mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
384         mProfileConnectedDevices.clear();
385         mProfileConnectedDevices.add(mLeftBluetoothHapDevice);
386         mHearingAidActiveDevices.clear();
387         mHearingAidActiveDevices.add(mLeftBluetoothHapDevice);
388         when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
389         when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices);
390         when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1);
391 
392         mController.updateState(mPreference);
393 
394         assertThat(mPreference.isVisible()).isTrue();
395         assertThat(mPreference.getSummary()).isEqualTo(mLeftBluetoothHapDevice.getName());
396     }
397 
398     /**
399      * More than one hearing aid profile Bluetooth devices are available, and second
400      * device is active.
401      * Preference should be visible
402      * Preference summary should be the activated device name
403      */
404     @Test
updateState_moreThanOneHapBtDevicesAreAvailable_shouldSetActivatedDeviceName()405     public void updateState_moreThanOneHapBtDevicesAreAvailable_shouldSetActivatedDeviceName() {
406         mShadowAudioManager.setMode(AudioManager.MODE_NORMAL);
407         mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
408         mProfileConnectedDevices.clear();
409         mProfileConnectedDevices.add(mLeftBluetoothHapDevice);
410         mProfileConnectedDevices.add(mRightBluetoothHapDevice);
411         mHearingAidActiveDevices.clear();
412         mHearingAidActiveDevices.add(mRightBluetoothHapDevice);
413         when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
414         when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices);
415         when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1);
416         when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID2);
417 
418         mController.updateState(mPreference);
419 
420         assertThat(mPreference.isVisible()).isTrue();
421         assertThat(mPreference.getSummary()).isEqualTo(mRightBluetoothHapDevice.getName());
422     }
423 
424     /**
425      * Both hearing aid profile and A2dp Bluetooth devices are available, and two hearing aid
426      * profile devices with same HisyncId are active. Both of HAP device are active,
427      * "left" side HAP device is added first.
428      * Preference should be visible
429      * Preference summary should be the activated device name
430      * ConnectedDevice should not contain second HAP device with same HisyncId
431      */
432     @Test
updateState_hapBtDeviceWithSameId_shouldSetActivatedDeviceName()433     public void updateState_hapBtDeviceWithSameId_shouldSetActivatedDeviceName() {
434         mShadowAudioManager.setMode(AudioManager.MODE_NORMAL);
435         mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
436         mProfileConnectedDevices.clear();
437         mProfileConnectedDevices.add(mBluetoothDevice);
438         //with same HisyncId, first one will remain in UI.
439         mProfileConnectedDevices.add(mLeftBluetoothHapDevice);
440         mProfileConnectedDevices.add(mRightBluetoothHapDevice);
441         mHearingAidActiveDevices.clear();
442         mHearingAidActiveDevices.add(mLeftBluetoothHapDevice);
443         mHearingAidActiveDevices.add(mRightBluetoothHapDevice);
444         when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
445         when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices);
446         when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1);
447         when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID1);
448 
449         mController.updateState(mPreference);
450 
451         assertThat(mPreference.isVisible()).isTrue();
452         assertThat(mPreference.getSummary()).isEqualTo(mLeftBluetoothHapDevice.getName());
453         assertThat(mController.mConnectedDevices.contains(mLeftBluetoothHapDevice)).isTrue();
454         assertThat(mController.mConnectedDevices.contains(mRightBluetoothHapDevice)).isFalse();
455     }
456 
457     /**
458      * Both hearing aid profile and A2dp Bluetooth devices are available, and two hearing aid
459      * profile devices with same HisyncId. Both of HAP device are active,
460      * "right" side HAP device is added first.
461      * Preference should be visible
462      * Preference summary should be the activated device name
463      * ConnectedDevice should not contain second HAP device with same HisyncId
464      */
465     @Test
updateState_hapBtDeviceWithSameIdButDifferentOrder_shouldSetActivatedDeviceName()466     public void updateState_hapBtDeviceWithSameIdButDifferentOrder_shouldSetActivatedDeviceName() {
467         mShadowAudioManager.setMode(AudioManager.MODE_NORMAL);
468         mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
469         mProfileConnectedDevices.clear();
470         mProfileConnectedDevices.add(mBluetoothDevice);
471         //with same HisyncId, first one will remain in UI.
472         mProfileConnectedDevices.add(mRightBluetoothHapDevice);
473         mProfileConnectedDevices.add(mLeftBluetoothHapDevice);
474         mHearingAidActiveDevices.clear();
475         mHearingAidActiveDevices.add(mLeftBluetoothHapDevice);
476         mHearingAidActiveDevices.add(mRightBluetoothHapDevice);
477         when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
478         when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices);
479         when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1);
480         when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID1);
481 
482         mController.updateState(mPreference);
483 
484         assertThat(mPreference.isVisible()).isTrue();
485         assertThat(mPreference.getSummary()).isEqualTo(mRightBluetoothHapDevice.getName());
486         assertThat(mController.mConnectedDevices.contains(mRightBluetoothHapDevice)).isTrue();
487         assertThat(mController.mConnectedDevices.contains(mLeftBluetoothHapDevice)).isFalse();
488     }
489 
490     /**
491      * Both hearing aid profile and A2dp Bluetooth devices are available, and two hearing aid
492      * profile devices with different HisyncId. One of HAP device is active.
493      * Preference should be visible
494      * Preference summary should be the activated device name
495      * ConnectedDevice should contain both HAP device with different HisyncId
496      */
497     @Test
updateState_hapBtDeviceWithDifferentId_shouldSetActivatedDeviceName()498     public void updateState_hapBtDeviceWithDifferentId_shouldSetActivatedDeviceName() {
499         mShadowAudioManager.setMode(AudioManager.MODE_NORMAL);
500         mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
501         mProfileConnectedDevices.clear();
502         mProfileConnectedDevices.add(mBluetoothDevice);
503         mProfileConnectedDevices.add(mLeftBluetoothHapDevice);
504         mProfileConnectedDevices.add(mRightBluetoothHapDevice);
505         mHearingAidActiveDevices.clear();
506         mHearingAidActiveDevices.add(null);
507         mHearingAidActiveDevices.add(mRightBluetoothHapDevice);
508         when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
509         when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices);
510         when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1);
511         when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID2);
512 
513         mController.updateState(mPreference);
514 
515         assertThat(mPreference.isVisible()).isTrue();
516         assertThat(mPreference.getSummary()).isEqualTo(mRightBluetoothHapDevice.getName());
517         assertThat(mController.mConnectedDevices).containsExactly(mBluetoothDevice,
518                 mLeftBluetoothHapDevice, mRightBluetoothHapDevice);
519     }
520 }
521