2 * Copyright (C) 2018 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.settings.sound;
20 import static com.android.settings.core.BasePreferenceController.AVAILABLE;
21 import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
23 import static com.google.common.truth.Truth.assertThat;
25 import static org.mockito.ArgumentMatchers.any;
26 import static org.mockito.Mockito.mock;
27 import static org.mockito.Mockito.spy;
28 import static org.mockito.Mockito.verify;
29 import static org.mockito.Mockito.when;
31 import android.bluetooth.BluetoothAdapter;
32 import android.bluetooth.BluetoothDevice;
33 import android.bluetooth.BluetoothManager;
34 import android.content.BroadcastReceiver;
35 import android.content.Context;
36 import android.content.IntentFilter;
37 import android.support.v7.preference.ListPreference;
38 import android.support.v7.preference.PreferenceManager;
39 import android.support.v7.preference.PreferenceScreen;
40 import android.util.FeatureFlagUtils;
42 import com.android.settings.R;
43 import com.android.settings.core.FeatureFlags;
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.BluetoothCallback;
50 import com.android.settingslib.bluetooth.BluetoothEventManager;
51 import com.android.settingslib.bluetooth.HeadsetProfile;
52 import com.android.settingslib.bluetooth.HearingAidProfile;
53 import com.android.settingslib.bluetooth.LocalBluetoothManager;
54 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
56 import org.junit.After;
57 import org.junit.Before;
58 import org.junit.Test;
59 import org.junit.runner.RunWith;
60 import org.mockito.Mock;
61 import org.mockito.MockitoAnnotations;
62 import org.robolectric.RuntimeEnvironment;
63 import org.robolectric.Shadows;
64 import org.robolectric.annotation.Config;
65 import org.robolectric.shadows.ShadowBluetoothDevice;
67 import java.util.ArrayList;
68 import java.util.List;
70 @RunWith(SettingsRobolectricTestRunner.class)
72 ShadowAudioManager.class,
73 ShadowMediaRouter.class,
74 ShadowBluetoothUtils.class,
75 ShadowBluetoothDevice.class}
77 public class AudioOutputSwitchPreferenceControllerTest {
78 private static final String TEST_KEY = "Test_Key";
79 private static final String TEST_DEVICE_NAME_1 = "Test_A2DP_BT_Device_NAME_1";
80 private static final String TEST_DEVICE_NAME_2 = "Test_A2DP_BT_Device_NAME_2";
81 private static final String TEST_DEVICE_ADDRESS_1 = "00:A1:A1:A1:A1:A1";
82 private static final String TEST_DEVICE_ADDRESS_2 = "00:B2:B2:B2:B2:B2";
83 private static final String TEST_DEVICE_ADDRESS_3 = "00:C3:C3:C3:C3:C3";
84 private final static long HISYNCID1 = 10;
85 private final static long HISYNCID2 = 11;
88 private LocalBluetoothManager mLocalManager;
90 private BluetoothEventManager mBluetoothEventManager;
92 private LocalBluetoothProfileManager mLocalBluetoothProfileManager;
94 private A2dpProfile mA2dpProfile;
96 private HeadsetProfile mHeadsetProfile;
98 private HearingAidProfile mHearingAidProfile;
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 mBluetoothHapDevice;
109 private BluetoothDevice mSecondBluetoothHapDevice;
110 private LocalBluetoothManager mLocalBluetoothManager;
111 private AudioSwitchPreferenceController mController;
112 private List<BluetoothDevice> mConnectedDevices;
113 private List<BluetoothDevice> mHearingAidActiveDevices;
114 private List<BluetoothDevice> mEmptyDevices;
117 public void setUp() {
118 MockitoAnnotations.initMocks(this);
119 mContext = spy(RuntimeEnvironment.application);
121 mShadowAudioManager = ShadowAudioManager.getShadow();
122 mShadowMediaRouter = ShadowMediaRouter.getShadow();
124 ShadowBluetoothUtils.sLocalBluetoothManager = mLocalManager;
125 mLocalBluetoothManager = ShadowBluetoothUtils.getLocalBtManager(mContext);
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 when(mLocalBluetoothProfileManager.getHeadsetProfile()).thenReturn(mHeadsetProfile);
133 mBluetoothManager = new BluetoothManager(mContext);
134 mBluetoothAdapter = mBluetoothManager.getAdapter();
136 mBluetoothDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_1));
137 when(mBluetoothDevice.getName()).thenReturn(TEST_DEVICE_NAME_1);
138 when(mBluetoothDevice.isConnected()).thenReturn(true);
140 mBluetoothHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2));
141 when(mBluetoothHapDevice.isConnected()).thenReturn(true);
142 mSecondBluetoothHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_3));
143 when(mSecondBluetoothHapDevice.isConnected()).thenReturn(true);
145 mController = new AudioSwitchPreferenceControllerTestable(mContext, TEST_KEY);
146 mScreen = spy(new PreferenceScreen(mContext, null));
147 mPreference = new ListPreference(mContext);
148 mConnectedDevices = new ArrayList<>(2);
149 mHearingAidActiveDevices = new ArrayList<>(2);
150 mEmptyDevices = new ArrayList<>(2);
152 when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
153 when(mScreen.getContext()).thenReturn(mContext);
154 when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
155 mScreen.addPreference(mPreference);
156 mController.displayPreference(mScreen);
160 public void tearDown() {
161 mShadowAudioManager.reset();
162 mShadowMediaRouter.reset();
163 ShadowBluetoothUtils.reset();
167 public void getAvailabilityStatus_byDefault_isAvailable() {
168 assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
172 public void getAvailabilityStatus_whenNotVisible_isDisable() {
173 FeatureFlagUtils.setEnabled(mContext, FeatureFlags.AUDIO_SWITCHER_SETTINGS, false);
174 assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
178 public void onStart_shouldRegisterCallbackAndRegisterReceiver() {
179 mController.onStart();
181 verify(mLocalBluetoothManager.getEventManager()).registerCallback(
182 any(BluetoothCallback.class));
183 verify(mContext).registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class));
187 public void onStop_shouldUnregisterCallbackAndUnregisterReceiver() {
188 mController.onStart();
189 mController.onStop();
191 verify(mLocalBluetoothManager.getEventManager()).unregisterCallback(
192 any(BluetoothCallback.class));
193 verify(mContext).unregisterReceiver(any(BroadcastReceiver.class));
197 public void onPreferenceChange_toThisDevice_shouldSetDefaultSummary() {
198 mConnectedDevices.clear();
199 mConnectedDevices.add(mBluetoothDevice);
200 mController.mConnectedDevices = mConnectedDevices;
202 mController.onPreferenceChange(mPreference,
203 mContext.getText(R.string.media_output_default_summary));
205 assertThat(mPreference.getSummary()).isEqualTo(
206 mContext.getText(R.string.media_output_default_summary));
210 * One Bluetooth devices are available, and select the device.
211 * Preference summary should be device name.
214 public void onPreferenceChange_toBtDevice_shouldSetBtDeviceName() {
215 mConnectedDevices.clear();
216 mConnectedDevices.add(mBluetoothDevice);
217 mController.mConnectedDevices = mConnectedDevices;
219 mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_1);
221 assertThat(mPreference.getSummary()).isEqualTo(mBluetoothDevice.getName());
225 * More than one Bluetooth devices are available, and select second device.
226 * Preference summary should be second device name.
229 public void onPreferenceChange_toBtDevices_shouldSetSecondBtDeviceName() {
230 ShadowBluetoothDevice shadowBluetoothDevice;
231 BluetoothDevice secondBluetoothDevice;
232 secondBluetoothDevice = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2);
233 shadowBluetoothDevice = Shadows.shadowOf(secondBluetoothDevice);
234 shadowBluetoothDevice.setName(TEST_DEVICE_NAME_2);
235 mConnectedDevices.clear();
236 mConnectedDevices.add(mBluetoothDevice);
237 mConnectedDevices.add(secondBluetoothDevice);
238 mController.mConnectedDevices = mConnectedDevices;
240 mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_2);
242 assertThat(mPreference.getSummary()).isEqualTo(secondBluetoothDevice.getName());
246 * mConnectedDevices is Null.
247 * onPreferenceChange should return false.
250 public void onPreferenceChange_connectedDeviceIsNull_shouldReturnFalse() {
251 mController.mConnectedDevices = null;
253 assertThat(mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_1)).isFalse();
257 * Two hearing aid devices with different HisyncId
258 * getConnectedHearingAidDevices should add both device to list.
261 public void getConnectedHearingAidDevices_deviceHisyncIdIsDifferent_shouldAddBothToList() {
262 mEmptyDevices.clear();
263 mConnectedDevices.clear();
264 mConnectedDevices.add(mBluetoothHapDevice);
265 mConnectedDevices.add(mSecondBluetoothHapDevice);
266 when(mHearingAidProfile.getConnectedDevices()).thenReturn(mConnectedDevices);
267 when(mHearingAidProfile.getHiSyncId(mBluetoothHapDevice)).thenReturn(HISYNCID1);
268 when(mHearingAidProfile.getHiSyncId(mSecondBluetoothHapDevice)).thenReturn(
271 mEmptyDevices.addAll(mController.getConnectedHearingAidDevices());
273 assertThat(mEmptyDevices).containsExactly(mBluetoothHapDevice, mSecondBluetoothHapDevice);
277 * Two hearing aid devices with same HisyncId
278 * getConnectedHearingAidDevices should only add first device to list.
281 public void getConnectedHearingAidDevices_deviceHisyncIdIsSame_shouldAddOneToList() {
282 mEmptyDevices.clear();
283 mConnectedDevices.clear();
284 mConnectedDevices.add(mBluetoothHapDevice);
285 mConnectedDevices.add(mSecondBluetoothHapDevice);
286 when(mHearingAidProfile.getConnectedDevices()).thenReturn(mConnectedDevices);
287 when(mHearingAidProfile.getHiSyncId(mBluetoothHapDevice)).thenReturn(HISYNCID1);
288 when(mHearingAidProfile.getHiSyncId(mSecondBluetoothHapDevice)).thenReturn(
291 mEmptyDevices.addAll(mController.getConnectedHearingAidDevices());
293 assertThat(mEmptyDevices).containsExactly(mBluetoothHapDevice);
297 * One A2dp device is connected.
298 * getConnectedA2dpDevices should add this device to list.
301 public void getConnectedA2dpDevices_oneConnectedA2dpDevice_shouldAddDeviceToList() {
302 mEmptyDevices.clear();
303 mConnectedDevices.clear();
304 mConnectedDevices.add(mBluetoothDevice);
305 when(mA2dpProfile.getConnectedDevices()).thenReturn(mConnectedDevices);
307 mEmptyDevices.addAll(mController.getConnectedA2dpDevices());
309 assertThat(mEmptyDevices).containsExactly(mBluetoothDevice);
313 * More than one A2dp devices are connected.
314 * getConnectedA2dpDevices should add all devices to list.
317 public void getConnectedA2dpDevices_moreThanOneConnectedA2dpDevice_shouldAddDeviceToList() {
318 mEmptyDevices.clear();
319 mConnectedDevices.clear();
320 mConnectedDevices.add(mBluetoothDevice);
321 mConnectedDevices.add(mBluetoothHapDevice);
322 when(mA2dpProfile.getConnectedDevices()).thenReturn(mConnectedDevices);
324 mEmptyDevices.addAll(mController.getConnectedA2dpDevices());
326 assertThat(mEmptyDevices).containsExactly(mBluetoothDevice, mBluetoothHapDevice);
330 * One hands free profile device is connected.
331 * getConnectedA2dpDevices should add this device to list.
334 public void getConnectedHfpDevices_oneConnectedHfpDevice_shouldAddDeviceToList() {
335 mEmptyDevices.clear();
336 mConnectedDevices.clear();
337 mConnectedDevices.add(mBluetoothDevice);
338 when(mHeadsetProfile.getConnectedDevices()).thenReturn(mConnectedDevices);
340 mEmptyDevices.addAll(mController.getConnectedHfpDevices());
342 assertThat(mEmptyDevices).containsExactly(mBluetoothDevice);
346 * More than one hands free profile devices are connected.
347 * getConnectedA2dpDevices should add all devices to list.
350 public void getConnectedHfpDevices_moreThanOneConnectedHfpDevice_shouldAddDeviceToList() {
351 mEmptyDevices.clear();
352 mConnectedDevices.clear();
353 mConnectedDevices.add(mBluetoothDevice);
354 mConnectedDevices.add(mBluetoothHapDevice);
355 when(mHeadsetProfile.getConnectedDevices()).thenReturn(mConnectedDevices);
357 mEmptyDevices.addAll(mController.getConnectedHfpDevices());
359 assertThat(mEmptyDevices).containsExactly(mBluetoothDevice, mBluetoothHapDevice);
362 private class AudioSwitchPreferenceControllerTestable extends
363 AudioSwitchPreferenceController {
364 AudioSwitchPreferenceControllerTestable(Context context, String key) {
369 public void setActiveBluetoothDevice(BluetoothDevice device) {
373 public String getPreferenceKey() {