Home | History | Annotate | Download | only in sound
      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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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