• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 package com.android.settings.bluetooth;
17 
18 import static com.google.common.truth.Truth.assertThat;
19 
20 import static org.mockito.ArgumentMatchers.any;
21 import static org.mockito.Mockito.doReturn;
22 import static org.mockito.Mockito.never;
23 import static org.mockito.Mockito.verify;
24 import static org.mockito.Mockito.when;
25 
26 import android.bluetooth.BluetoothAdapter;
27 import android.bluetooth.BluetoothDevice;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.graphics.drawable.Drawable;
31 import android.util.Pair;
32 
33 import androidx.preference.Preference;
34 
35 import com.android.settings.SettingsActivity;
36 import com.android.settings.connecteddevice.DevicePreferenceCallback;
37 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
38 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
39 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
40 import com.android.settingslib.bluetooth.LocalBluetoothManager;
41 
42 import com.google.common.collect.ImmutableList;
43 
44 import org.junit.Before;
45 import org.junit.Test;
46 import org.junit.runner.RunWith;
47 import org.mockito.ArgumentCaptor;
48 import org.mockito.Mock;
49 import org.mockito.MockitoAnnotations;
50 import org.robolectric.RobolectricTestRunner;
51 import org.robolectric.RuntimeEnvironment;
52 import org.robolectric.annotation.Config;
53 import org.robolectric.shadow.api.Shadow;
54 
55 import java.util.ArrayList;
56 import java.util.List;
57 
58 @RunWith(RobolectricTestRunner.class)
59 @Config(shadows = {ShadowBluetoothAdapter.class})
60 public class BluetoothDeviceUpdaterTest {
61 
62     private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C";
63     private static final String SUB_MAC_ADDRESS = "05:52:C7:0B:D8:3C";
64     private static final String TEST_NAME = "test_name";
65 
66     @Mock
67     private DevicePreferenceCallback mDevicePreferenceCallback;
68     @Mock
69     private CachedBluetoothDevice mCachedBluetoothDevice;
70     @Mock
71     private CachedBluetoothDevice mSubCachedBluetoothDevice;
72     @Mock
73     private BluetoothDevice mBluetoothDevice;
74     @Mock
75     private BluetoothDevice mSubBluetoothDevice;
76     @Mock
77     private SettingsActivity mSettingsActivity;
78     @Mock
79     private LocalBluetoothManager mLocalManager;
80     @Mock
81     private CachedBluetoothDeviceManager mCachedDeviceManager;
82     @Mock
83     private Drawable mDrawable;
84 
85     private Context mContext;
86     private TestBluetoothDeviceUpdater mBluetoothDeviceUpdater;
87     private BluetoothDevicePreference mPreference;
88     private ShadowBluetoothAdapter mShadowBluetoothAdapter;
89     private List<CachedBluetoothDevice> mCachedDevices = new ArrayList<>();
90 
91     @Before
setUp()92     public void setUp() {
93         MockitoAnnotations.initMocks(this);
94 
95         Pair<Drawable, String> pairs = new Pair<>(mDrawable, "fake_device");
96         mContext = RuntimeEnvironment.application;
97         mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
98         mCachedDevices.add(mCachedBluetoothDevice);
99         when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
100         when(mSubCachedBluetoothDevice.getDevice()).thenReturn(mSubBluetoothDevice);
101         when(mLocalManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
102         when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(mCachedDevices);
103         when(mCachedBluetoothDevice.getAddress()).thenReturn(MAC_ADDRESS);
104         when(mBluetoothDevice.getAddress()).thenReturn(MAC_ADDRESS);
105         when(mSubBluetoothDevice.getAddress()).thenReturn(SUB_MAC_ADDRESS);
106         when(mCachedBluetoothDevice.getDrawableWithDescription()).thenReturn(pairs);
107 
108         mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice,
109                 /* showDeviceWithoutNames= */ false,
110                 BluetoothDevicePreference.SortType.TYPE_DEFAULT);
111         mBluetoothDeviceUpdater = new TestBluetoothDeviceUpdater(mContext,
112                 mDevicePreferenceCallback, mLocalManager, /* metricsCategory= */  0);
113         mBluetoothDeviceUpdater.setPrefContext(mContext);
114     }
115 
116     @Test
testAddPreference_deviceExist_doNothing()117     public void testAddPreference_deviceExist_doNothing() {
118         mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, mPreference);
119 
120         mBluetoothDeviceUpdater.addPreference(mCachedBluetoothDevice);
121 
122         verify(mDevicePreferenceCallback, never()).onDeviceAdded(any(Preference.class));
123     }
124 
125     @Test
testAddPreference_deviceNotExist_addPreference()126     public void testAddPreference_deviceNotExist_addPreference() {
127         mBluetoothDeviceUpdater.addPreference(mCachedBluetoothDevice);
128 
129         final Preference preference = mBluetoothDeviceUpdater.mPreferenceMap.get(mBluetoothDevice);
130         assertThat(preference).isNotNull();
131         verify(mDevicePreferenceCallback).onDeviceAdded(preference);
132     }
133 
134     @Test
testRemovePreference_deviceExist_removePreference()135     public void testRemovePreference_deviceExist_removePreference() {
136         mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, mPreference);
137 
138         mBluetoothDeviceUpdater.removePreference(mCachedBluetoothDevice);
139 
140         verify(mDevicePreferenceCallback).onDeviceRemoved(mPreference);
141         assertThat(mBluetoothDeviceUpdater.mPreferenceMap.containsKey(mBluetoothDevice)).isFalse();
142     }
143 
144     @Test
testOnDeviceDeleted_deviceExists_removePreference()145     public void testOnDeviceDeleted_deviceExists_removePreference() {
146         mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, mPreference);
147 
148         mBluetoothDeviceUpdater.onDeviceDeleted(mCachedBluetoothDevice);
149 
150         verify(mDevicePreferenceCallback).onDeviceRemoved(mPreference);
151         assertThat(mBluetoothDeviceUpdater.mPreferenceMap.containsKey(mBluetoothDevice)).isFalse();
152     }
153 
154     @Test
testRemovePreference_deviceNotExist_doNothing()155     public void testRemovePreference_deviceNotExist_doNothing() {
156         mBluetoothDeviceUpdater.removePreference(mCachedBluetoothDevice);
157 
158         verify(mDevicePreferenceCallback, never()).onDeviceRemoved(any(Preference.class));
159     }
160 
161     @Test
testRemovePreference_subDeviceExist_removePreference()162     public void testRemovePreference_subDeviceExist_removePreference() {
163         when(mCachedBluetoothDevice.getSubDevice()).thenReturn(mSubCachedBluetoothDevice);
164         mBluetoothDeviceUpdater.mPreferenceMap.put(mSubBluetoothDevice, mPreference);
165 
166         assertThat(mBluetoothDeviceUpdater.mPreferenceMap.
167                 containsKey(mSubBluetoothDevice)).isTrue();
168         mBluetoothDeviceUpdater.removePreference(mCachedBluetoothDevice);
169 
170         verify(mDevicePreferenceCallback).onDeviceRemoved(mPreference);
171         assertThat(mBluetoothDeviceUpdater.mPreferenceMap.
172                 containsKey(mSubBluetoothDevice)).isFalse();
173     }
174 
175     @Test
testDeviceProfilesListener_click_startBluetoothDeviceDetailPage()176     public void testDeviceProfilesListener_click_startBluetoothDeviceDetailPage() {
177         mBluetoothDeviceUpdater = new TestBluetoothDeviceUpdater(mSettingsActivity,
178                 mDevicePreferenceCallback, mLocalManager, /* metricsCategory= */  0);
179 
180         final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
181         mBluetoothDeviceUpdater.mDeviceProfilesListener.onGearClick(mPreference);
182 
183         verify(mSettingsActivity).startActivity(intentCaptor.capture());
184         assertThat(intentCaptor.getValue().getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
185                 .isEqualTo(BluetoothDeviceDetailsFragment.class.getName());
186     }
187 
188     @Test
isDeviceConnected_deviceConnected()189     public void isDeviceConnected_deviceConnected() {
190         doReturn(BluetoothDevice.BOND_BONDED).when(mBluetoothDevice).getBondState();
191         doReturn(true).when(mBluetoothDevice).isConnected();
192 
193         assertThat(mBluetoothDeviceUpdater.isDeviceConnected(mCachedBluetoothDevice)).isTrue();
194     }
195 
196     @Test
isDeviceConnected_deviceNotConnected()197     public void isDeviceConnected_deviceNotConnected() {
198         doReturn(BluetoothDevice.BOND_BONDED).when(mBluetoothDevice).getBondState();
199         doReturn(false).when(mBluetoothDevice).isConnected();
200 
201         assertThat(mBluetoothDeviceUpdater.isDeviceConnected(mCachedBluetoothDevice)).isFalse();
202     }
203 
204     @Test
registerCallback_localBluetoothManagerNull_shouldNotCrash()205     public void registerCallback_localBluetoothManagerNull_shouldNotCrash() {
206         mBluetoothDeviceUpdater.mLocalManager = null;
207 
208         // Shouldn't crash
209         mBluetoothDeviceUpdater.registerCallback();
210     }
211 
212     @Test
unregisterCallback_localBluetoothManagerNull_shouldNotCrash()213     public void unregisterCallback_localBluetoothManagerNull_shouldNotCrash() {
214         mBluetoothDeviceUpdater.mLocalManager = null;
215 
216         // Shouldn't crash
217         mBluetoothDeviceUpdater.unregisterCallback();
218     }
219 
220     @Test
forceUpdate_bluetoothDisabled_removeAllDevicesFromPreference()221     public void forceUpdate_bluetoothDisabled_removeAllDevicesFromPreference() {
222         mShadowBluetoothAdapter.setEnabled(false);
223         mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, mPreference);
224 
225         mBluetoothDeviceUpdater.forceUpdate();
226 
227         verify(mDevicePreferenceCallback).onDeviceRemoved(mPreference);
228         assertThat(mBluetoothDeviceUpdater.mPreferenceMap).isEmpty();
229     }
230 
231     @Test
forceUpdate_bluetoothEnabled_addPreference()232     public void forceUpdate_bluetoothEnabled_addPreference() {
233         mShadowBluetoothAdapter.setEnabled(true);
234         mBluetoothDeviceUpdater.forceUpdate();
235 
236         verify(mDevicePreferenceCallback).onDeviceAdded(any(Preference.class));
237     }
238 
239     @Test
onBluetoothStateChanged_bluetoothStateIsOn_forceUpdate()240     public void onBluetoothStateChanged_bluetoothStateIsOn_forceUpdate() {
241         mShadowBluetoothAdapter.setEnabled(true);
242         mBluetoothDeviceUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_ON);
243 
244         verify(mDevicePreferenceCallback).onDeviceAdded(any(Preference.class));
245     }
246 
247     @Test
onBluetoothStateChanged_bluetoothStateIsOff_removeAllDevicesFromPreference()248     public void onBluetoothStateChanged_bluetoothStateIsOff_removeAllDevicesFromPreference() {
249         mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, mPreference);
250 
251         mBluetoothDeviceUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_OFF);
252 
253         verify(mDevicePreferenceCallback).onDeviceRemoved(mPreference);
254         assertThat(mBluetoothDeviceUpdater.mPreferenceMap.containsKey(mBluetoothDevice)).isFalse();
255     }
256 
257     @Test
refreshPreference_havePreference_refresh()258     public void refreshPreference_havePreference_refresh() {
259         mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, mPreference);
260         mPreference.setTitle("fake_name");
261 
262         when(mCachedBluetoothDevice.getName()).thenReturn(TEST_NAME);
263         mBluetoothDeviceUpdater.refreshPreference();
264 
265         assertThat(mPreference.getTitle()).isEqualTo(TEST_NAME);
266     }
267 
268     @Test
refreshPreference_staledPreference_remove()269     public void refreshPreference_staledPreference_remove() {
270         mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, mPreference);
271         mPreference.setTitle("fake_name");
272 
273         when(mCachedBluetoothDevice.getName()).thenReturn(TEST_NAME);
274         when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(ImmutableList.of());
275         mBluetoothDeviceUpdater.refreshPreference();
276 
277         verify(mDevicePreferenceCallback).onDeviceRemoved(mPreference);
278         assertThat(mBluetoothDeviceUpdater.mPreferenceMap.containsKey(mBluetoothDevice)).isFalse();
279     }
280 
281     @Test
refreshPreference_inconsistentPreference_doNothing()282     public void refreshPreference_inconsistentPreference_doNothing() {
283         when(mCachedBluetoothDevice.getDevice()).thenReturn(mSubBluetoothDevice);
284         mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, mPreference);
285         mBluetoothDeviceUpdater.mPreferenceMap.put(mSubBluetoothDevice, mPreference);
286 
287         when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(
288                 ImmutableList.of(mSubCachedBluetoothDevice));
289         mBluetoothDeviceUpdater.refreshPreference();
290 
291         verify(mDevicePreferenceCallback, never()).onDeviceRemoved(mPreference);
292         assertThat(mBluetoothDeviceUpdater.mPreferenceMap.containsKey(mBluetoothDevice)).isFalse();
293     }
294 
295     @Test
refreshPreference_staledInconsistentPreference_remove()296     public void refreshPreference_staledInconsistentPreference_remove() {
297         when(mCachedBluetoothDevice.getDevice()).thenReturn(mSubBluetoothDevice);
298         mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, mPreference);
299 
300         when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(ImmutableList.of());
301         mBluetoothDeviceUpdater.refreshPreference();
302 
303         verify(mDevicePreferenceCallback).onDeviceRemoved(mPreference);
304         assertThat(mBluetoothDeviceUpdater.mPreferenceMap.containsKey(mBluetoothDevice)).isFalse();
305     }
306 
307     public static class TestBluetoothDeviceUpdater extends BluetoothDeviceUpdater {
TestBluetoothDeviceUpdater(Context context, DevicePreferenceCallback devicePreferenceCallback, LocalBluetoothManager localManager, int metricsCategory)308         public TestBluetoothDeviceUpdater(Context context,
309                 DevicePreferenceCallback devicePreferenceCallback,
310                 LocalBluetoothManager localManager, int metricsCategory) {
311             super(context, devicePreferenceCallback, localManager, metricsCategory);
312         }
313 
314         @Override
isFilterMatched(CachedBluetoothDevice cachedBluetoothDevice)315         public boolean isFilterMatched(CachedBluetoothDevice cachedBluetoothDevice) {
316             return true;
317         }
318 
319         @Override
getPreferenceKeyPrefix()320         protected String getPreferenceKeyPrefix() {
321             return "test_bt";
322         }
323     }
324 }
325