• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.bluetooth;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.mockito.Mockito.spy;
22 import static org.mockito.Mockito.verify;
23 import static org.mockito.Mockito.when;
24 
25 import android.bluetooth.BluetoothDevice;
26 import android.media.AudioDeviceAttributes;
27 import android.media.AudioDeviceInfo;
28 import android.media.AudioManager;
29 import android.media.Spatializer;
30 
31 import androidx.preference.PreferenceCategory;
32 import androidx.preference.SwitchPreference;
33 
34 import com.android.settingslib.core.lifecycle.Lifecycle;
35 
36 import org.junit.Before;
37 import org.junit.Test;
38 import org.junit.runner.RunWith;
39 import org.mockito.Mock;
40 import org.mockito.MockitoAnnotations;
41 import org.robolectric.RobolectricTestRunner;
42 import org.robolectric.RuntimeEnvironment;
43 
44 import java.util.ArrayList;
45 import java.util.List;
46 
47 @RunWith(RobolectricTestRunner.class)
48 public class BluetoothDetailsSpatialAudioControllerTest extends BluetoothDetailsControllerTestBase {
49 
50     private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C";
51     private static final String KEY_SPATIAL_AUDIO = "spatial_audio";
52     private static final String KEY_HEAD_TRACKING = "head_tracking";
53 
54     @Mock
55     private AudioManager mAudioManager;
56     @Mock
57     private Spatializer mSpatializer;
58     @Mock
59     private Lifecycle mSpatialAudioLifecycle;
60     @Mock
61     private PreferenceCategory mProfilesContainer;
62     @Mock
63     private BluetoothDevice mBluetoothDevice;
64 
65     private BluetoothDetailsSpatialAudioController mController;
66     private SwitchPreference mSpatialAudioPref;
67     private SwitchPreference mHeadTrackingPref;
68 
69     @Before
setUp()70     public void setUp() {
71         MockitoAnnotations.initMocks(this);
72 
73         mContext = spy(RuntimeEnvironment.application);
74         when(mContext.getSystemService(AudioManager.class)).thenReturn(mAudioManager);
75         when(mAudioManager.getSpatializer()).thenReturn(mSpatializer);
76         when(mCachedDevice.getAddress()).thenReturn(MAC_ADDRESS);
77         when(mCachedDevice.getDevice()).thenReturn(mBluetoothDevice);
78         when(mBluetoothDevice.getAnonymizedAddress()).thenReturn(MAC_ADDRESS);
79 
80         mController = new BluetoothDetailsSpatialAudioController(mContext, mFragment,
81                 mCachedDevice, mSpatialAudioLifecycle);
82         mController.mProfilesContainer = mProfilesContainer;
83 
84         mSpatialAudioPref = mController.createSpatialAudioPreference(mContext);
85         mHeadTrackingPref = mController.createHeadTrackingPreference(mContext);
86 
87         when(mProfilesContainer.findPreference(KEY_SPATIAL_AUDIO)).thenReturn(mSpatialAudioPref);
88         when(mProfilesContainer.findPreference(KEY_HEAD_TRACKING)).thenReturn(mHeadTrackingPref);
89     }
90 
91     @Test
isAvailable_spatialAudioSupportA2dpDevice_returnsTrue()92     public void isAvailable_spatialAudioSupportA2dpDevice_returnsTrue() {
93         AudioDeviceAttributes a2dpDevice = new AudioDeviceAttributes(
94                 AudioDeviceAttributes.ROLE_OUTPUT,
95                 AudioDeviceInfo.TYPE_BLUETOOTH_A2DP,
96                 MAC_ADDRESS);
97         when(mSpatializer.isAvailableForDevice(a2dpDevice)).thenReturn(true);
98 
99         mController.setAvailableDevice(a2dpDevice);
100 
101         assertThat(mController.isAvailable()).isTrue();
102         assertThat(mController.mAudioDevice.getType())
103                 .isEqualTo(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP);
104     }
105 
106     @Test
isAvailable_spatialAudioSupportBleHeadsetDevice_returnsTrue()107     public void isAvailable_spatialAudioSupportBleHeadsetDevice_returnsTrue() {
108         AudioDeviceAttributes bleHeadsetDevice = new AudioDeviceAttributes(
109                 AudioDeviceAttributes.ROLE_OUTPUT,
110                 AudioDeviceInfo.TYPE_BLE_HEADSET,
111                 MAC_ADDRESS);
112         when(mSpatializer.isAvailableForDevice(bleHeadsetDevice)).thenReturn(true);
113 
114         mController.setAvailableDevice(bleHeadsetDevice);
115 
116         assertThat(mController.isAvailable()).isTrue();
117         assertThat(mController.mAudioDevice.getType())
118                 .isEqualTo(AudioDeviceInfo.TYPE_BLE_HEADSET);
119     }
120 
121     @Test
isAvailable_spatialAudioSupportBleSpeakerDevice_returnsTrue()122     public void isAvailable_spatialAudioSupportBleSpeakerDevice_returnsTrue() {
123         AudioDeviceAttributes bleSpeakerDevice = new AudioDeviceAttributes(
124                 AudioDeviceAttributes.ROLE_OUTPUT,
125                 AudioDeviceInfo.TYPE_BLE_SPEAKER,
126                 MAC_ADDRESS);
127         when(mSpatializer.isAvailableForDevice(bleSpeakerDevice)).thenReturn(true);
128 
129         mController.setAvailableDevice(bleSpeakerDevice);
130 
131         assertThat(mController.isAvailable()).isTrue();
132         assertThat(mController.mAudioDevice.getType())
133                 .isEqualTo(AudioDeviceInfo.TYPE_BLE_SPEAKER);
134     }
135 
136     @Test
isAvailable_spatialAudioSupportBleBroadcastDevice_returnsTrue()137     public void isAvailable_spatialAudioSupportBleBroadcastDevice_returnsTrue() {
138         AudioDeviceAttributes bleBroadcastDevice = new AudioDeviceAttributes(
139                 AudioDeviceAttributes.ROLE_OUTPUT,
140                 AudioDeviceInfo.TYPE_BLE_BROADCAST,
141                 MAC_ADDRESS);
142         when(mSpatializer.isAvailableForDevice(bleBroadcastDevice)).thenReturn(true);
143 
144         mController.setAvailableDevice(bleBroadcastDevice);
145 
146         assertThat(mController.isAvailable()).isTrue();
147         assertThat(mController.mAudioDevice.getType())
148                 .isEqualTo(AudioDeviceInfo.TYPE_BLE_BROADCAST);
149     }
150 
151     @Test
isAvailable_spatialAudioSupportHearingAidDevice_returnsTrue()152     public void isAvailable_spatialAudioSupportHearingAidDevice_returnsTrue() {
153         AudioDeviceAttributes hearingAidDevice = new AudioDeviceAttributes(
154                 AudioDeviceAttributes.ROLE_OUTPUT,
155                 AudioDeviceInfo.TYPE_HEARING_AID,
156                 MAC_ADDRESS);
157         when(mSpatializer.isAvailableForDevice(hearingAidDevice)).thenReturn(true);
158 
159         mController.setAvailableDevice(hearingAidDevice);
160 
161         assertThat(mController.isAvailable()).isTrue();
162         assertThat(mController.mAudioDevice.getType())
163                 .isEqualTo(AudioDeviceInfo.TYPE_HEARING_AID);
164     }
165 
166     @Test
isAvailable_spatialAudioNotSupported_returnsFalse()167     public void isAvailable_spatialAudioNotSupported_returnsFalse() {
168         assertThat(mController.isAvailable()).isFalse();
169         assertThat(mController.mAudioDevice.getType())
170                 .isEqualTo(AudioDeviceInfo.TYPE_HEARING_AID);
171     }
172 
173     @Test
refresh_spatialAudioIsTurnedOn_checksSpatialAudioPreference()174     public void refresh_spatialAudioIsTurnedOn_checksSpatialAudioPreference() {
175         List<AudioDeviceAttributes> compatibleAudioDevices = new ArrayList<>();
176         compatibleAudioDevices.add(mController.mAudioDevice);
177         when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
178 
179         mController.refresh();
180 
181         assertThat(mSpatialAudioPref.isChecked()).isTrue();
182     }
183 
184     @Test
refresh_spatialAudioIsTurnedOff_unchecksSpatialAudioPreference()185     public void refresh_spatialAudioIsTurnedOff_unchecksSpatialAudioPreference() {
186         List<AudioDeviceAttributes> compatibleAudioDevices = new ArrayList<>();
187         when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
188 
189         mController.refresh();
190 
191         assertThat(mSpatialAudioPref.isChecked()).isFalse();
192     }
193 
194     @Test
refresh_spatialAudioOnAndHeadTrackingIsAvailable_showsHeadTrackingPreference()195     public void refresh_spatialAudioOnAndHeadTrackingIsAvailable_showsHeadTrackingPreference() {
196         List<AudioDeviceAttributes> compatibleAudioDevices = new ArrayList<>();
197         compatibleAudioDevices.add(mController.mAudioDevice);
198         when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
199         when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(true);
200 
201         mController.refresh();
202 
203         assertThat(mHeadTrackingPref.isVisible()).isTrue();
204     }
205 
206     @Test
207     public void
refresh_spatialAudioOnAndHeadTrackingIsNotAvailable_hidesHeadTrackingPreference()208             refresh_spatialAudioOnAndHeadTrackingIsNotAvailable_hidesHeadTrackingPreference() {
209         List<AudioDeviceAttributes> compatibleAudioDevices = new ArrayList<>();
210         compatibleAudioDevices.add(mController.mAudioDevice);
211         when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
212         when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(false);
213 
214         mController.refresh();
215 
216         assertThat(mHeadTrackingPref.isVisible()).isFalse();
217     }
218 
219     @Test
refresh_spatialAudioOff_hidesHeadTrackingPreference()220     public void refresh_spatialAudioOff_hidesHeadTrackingPreference() {
221         List<AudioDeviceAttributes> compatibleAudioDevices = new ArrayList<>();
222         when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
223 
224         mController.refresh();
225 
226         assertThat(mHeadTrackingPref.isVisible()).isFalse();
227     }
228 
229     @Test
refresh_headTrackingIsTurnedOn_checksHeadTrackingPreference()230     public void refresh_headTrackingIsTurnedOn_checksHeadTrackingPreference() {
231         List<AudioDeviceAttributes> compatibleAudioDevices = new ArrayList<>();
232         compatibleAudioDevices.add(mController.mAudioDevice);
233         when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
234         when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(true);
235         when(mSpatializer.isHeadTrackerEnabled(mController.mAudioDevice)).thenReturn(true);
236 
237         mController.refresh();
238 
239         assertThat(mHeadTrackingPref.isChecked()).isTrue();
240     }
241 
242     @Test
refresh_headTrackingIsTurnedOff_unchecksHeadTrackingPreference()243     public void refresh_headTrackingIsTurnedOff_unchecksHeadTrackingPreference() {
244         List<AudioDeviceAttributes> compatibleAudioDevices = new ArrayList<>();
245         compatibleAudioDevices.add(mController.mAudioDevice);
246         when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
247         when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(true);
248         when(mSpatializer.isHeadTrackerEnabled(mController.mAudioDevice)).thenReturn(false);
249 
250         mController.refresh();
251 
252         assertThat(mHeadTrackingPref.isChecked()).isFalse();
253     }
254 
255     @Test
turnedOnSpatialAudio_invokesAddCompatibleAudioDevice()256     public void turnedOnSpatialAudio_invokesAddCompatibleAudioDevice() {
257         mSpatialAudioPref.setChecked(true);
258         mController.onPreferenceClick(mSpatialAudioPref);
259         verify(mSpatializer).addCompatibleAudioDevice(mController.mAudioDevice);
260     }
261 
262     @Test
turnedOffSpatialAudio_invokesRemoveCompatibleAudioDevice()263     public void turnedOffSpatialAudio_invokesRemoveCompatibleAudioDevice() {
264         mSpatialAudioPref.setChecked(false);
265         mController.onPreferenceClick(mSpatialAudioPref);
266         verify(mSpatializer).removeCompatibleAudioDevice(mController.mAudioDevice);
267     }
268 
269     @Test
turnedOnHeadTracking_invokesSetHeadTrackerEnabled_setsTrue()270     public void turnedOnHeadTracking_invokesSetHeadTrackerEnabled_setsTrue() {
271         mHeadTrackingPref.setChecked(true);
272         mController.onPreferenceClick(mHeadTrackingPref);
273         verify(mSpatializer).setHeadTrackerEnabled(true, mController.mAudioDevice);
274     }
275 
276     @Test
turnedOffHeadTracking_invokesSetHeadTrackerEnabled_setsFalse()277     public void turnedOffHeadTracking_invokesSetHeadTrackerEnabled_setsFalse() {
278         mHeadTrackingPref.setChecked(false);
279         mController.onPreferenceClick(mHeadTrackingPref);
280         verify(mSpatializer).setHeadTrackerEnabled(false, mController.mAudioDevice);
281     }
282 }
283