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 org.mockito.ArgumentMatchers.any; 19 import static org.mockito.Mockito.doNothing; 20 import static org.mockito.Mockito.doReturn; 21 import static org.mockito.Mockito.doThrow; 22 import static org.mockito.Mockito.mock; 23 import static org.mockito.Mockito.never; 24 import static org.mockito.Mockito.spy; 25 import static org.mockito.Mockito.verify; 26 import static org.mockito.Mockito.when; 27 28 import android.bluetooth.BluetoothAdapter; 29 import android.bluetooth.BluetoothDevice; 30 import android.bluetooth.BluetoothProfile; 31 import android.content.Context; 32 import android.content.pm.ApplicationInfo; 33 import android.content.pm.PackageManager; 34 import android.graphics.drawable.Drawable; 35 import android.util.Pair; 36 37 import com.android.settings.connecteddevice.DevicePreferenceCallback; 38 import com.android.settings.dashboard.DashboardFragment; 39 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; 40 import com.android.settingslib.bluetooth.CachedBluetoothDevice; 41 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; 42 import com.android.settingslib.bluetooth.LocalBluetoothManager; 43 44 import org.junit.Before; 45 import org.junit.Test; 46 import org.junit.runner.RunWith; 47 import org.mockito.Mock; 48 import org.mockito.MockitoAnnotations; 49 import org.robolectric.RobolectricTestRunner; 50 import org.robolectric.RuntimeEnvironment; 51 import org.robolectric.annotation.Config; 52 53 import java.util.ArrayList; 54 import java.util.Collection; 55 import java.util.List; 56 57 @RunWith(RobolectricTestRunner.class) 58 @Config(shadows = {ShadowBluetoothAdapter.class}) 59 public class SavedBluetoothDeviceUpdaterTest { 60 61 private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C"; 62 private static final String TEST_EXCLUSIVE_MANAGER = "com.test.manager"; 63 64 @Mock 65 private DashboardFragment mDashboardFragment; 66 @Mock 67 private DevicePreferenceCallback mDevicePreferenceCallback; 68 @Mock 69 private CachedBluetoothDevice mCachedBluetoothDevice; 70 @Mock 71 private BluetoothDevice mBluetoothDevice; 72 @Mock 73 private BluetoothAdapter mBluetoothAdapter; 74 @Mock 75 private CachedBluetoothDeviceManager mDeviceManager; 76 @Mock 77 private LocalBluetoothManager mBluetoothManager; 78 @Mock 79 private Drawable mDrawable; 80 @Mock 81 private PackageManager mPackageManager; 82 83 private Context mContext; 84 private SavedBluetoothDeviceUpdater mBluetoothDeviceUpdater; 85 private BluetoothDevicePreference mPreference; 86 private List<CachedBluetoothDevice> mCachedDevices = new ArrayList<>(); 87 88 @Before setUp()89 public void setUp() { 90 MockitoAnnotations.initMocks(this); 91 92 Pair<Drawable, String> pairs = new Pair<>(mDrawable, "fake_device"); 93 mContext = spy(RuntimeEnvironment.application); 94 doReturn(mContext).when(mDashboardFragment).getContext(); 95 when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); 96 when(mCachedBluetoothDevice.getAddress()).thenReturn(MAC_ADDRESS); 97 when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); 98 when(mCachedBluetoothDevice.getDrawableWithDescription()).thenReturn(pairs); 99 when(mContext.getPackageManager()).thenReturn(mPackageManager); 100 101 mBluetoothDeviceUpdater = spy(new SavedBluetoothDeviceUpdater(mContext, 102 mDevicePreferenceCallback, false, /* metricsCategory= */ 0)); 103 mBluetoothDeviceUpdater.setPrefContext(mContext); 104 mBluetoothDeviceUpdater.mBluetoothAdapter = mBluetoothAdapter; 105 mBluetoothDeviceUpdater.mLocalManager = mBluetoothManager; 106 mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, 107 false, BluetoothDevicePreference.SortType.TYPE_DEFAULT); 108 doNothing().when(mBluetoothDeviceUpdater).addPreference(any()); 109 doNothing().when(mBluetoothDeviceUpdater).removePreference( 110 any(CachedBluetoothDevice.class)); 111 mCachedDevices.add(mCachedBluetoothDevice); 112 when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager); 113 when(mDeviceManager.getCachedDevicesCopy()).thenReturn(mCachedDevices); 114 } 115 116 @Test onProfileConnectionStateChanged_deviceConnected_removePreference()117 public void onProfileConnectionStateChanged_deviceConnected_removePreference() { 118 when(mBluetoothDevice.isConnected()).thenReturn(true); 119 120 mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice, 121 BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP); 122 123 verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice); 124 } 125 126 @Test onProfileConnectionStateChanged_deviceDisconnected_addPreference()127 public void onProfileConnectionStateChanged_deviceDisconnected_addPreference() { 128 when(mBluetoothDevice.isConnected()).thenReturn(false); 129 130 mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice, 131 BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.A2DP); 132 133 verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice, 134 BluetoothDevicePreference.SortType.TYPE_NO_SORT); 135 } 136 137 @Test 138 public void onProfileConnectionStateChanged_leDeviceDisconnected_inDeviceList_invokesAddPreference()139 onProfileConnectionStateChanged_leDeviceDisconnected_inDeviceList_invokesAddPreference() 140 { 141 when(mBluetoothDevice.isConnected()).thenReturn(false); 142 143 mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice, 144 BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.LE_AUDIO); 145 146 verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice, 147 BluetoothDevicePreference.SortType.TYPE_NO_SORT); 148 } 149 150 @Test 151 public void onProfileConnectionStateChanged_deviceDisconnected_notInDeviceList_invokesRemovePreference()152 onProfileConnectionStateChanged_deviceDisconnected_notInDeviceList_invokesRemovePreference() { 153 when(mBluetoothDevice.isConnected()).thenReturn(false); 154 mCachedDevices.clear(); 155 156 mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice, 157 BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.LE_AUDIO); 158 159 verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice); 160 } 161 162 @Test onClick_Preference_setConnect()163 public void onClick_Preference_setConnect() { 164 mBluetoothDeviceUpdater.onPreferenceClick(mPreference); 165 166 verify(mCachedBluetoothDevice).connect(); 167 } 168 169 @Test onClick_Preference_connected_setActive()170 public void onClick_Preference_connected_setActive() { 171 when(mCachedBluetoothDevice.isConnected()).thenReturn(true); 172 173 mBluetoothDeviceUpdater.onPreferenceClick(mPreference); 174 175 verify(mCachedBluetoothDevice).setActive(); 176 } 177 178 @Test forceUpdate_findCachedBluetoothDeviceIsMatched_addPreference()179 public void forceUpdate_findCachedBluetoothDeviceIsMatched_addPreference() { 180 final List<BluetoothDevice> bluetoothDevices = new ArrayList<>(); 181 bluetoothDevices.add(mBluetoothDevice); 182 183 when(mBluetoothAdapter.isEnabled()).thenReturn(true); 184 when(mBluetoothAdapter.getMostRecentlyConnectedDevices()).thenReturn(bluetoothDevices); 185 when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager); 186 when(mDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedBluetoothDevice); 187 when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); 188 when(mBluetoothDevice.isConnected()).thenReturn(false); 189 190 mBluetoothDeviceUpdater.forceUpdate(); 191 192 verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice, 193 BluetoothDevicePreference.SortType.TYPE_NO_SORT); 194 } 195 196 @Test forceUpdate_findCachedBluetoothDeviceNotMatched_removePreference()197 public void forceUpdate_findCachedBluetoothDeviceNotMatched_removePreference() { 198 final List<BluetoothDevice> bluetoothDevices = new ArrayList<>(); 199 bluetoothDevices.add(mBluetoothDevice); 200 201 when(mBluetoothAdapter.isEnabled()).thenReturn(true); 202 when(mBluetoothAdapter.getMostRecentlyConnectedDevices()).thenReturn(bluetoothDevices); 203 when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager); 204 when(mDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedBluetoothDevice); 205 when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); 206 when(mBluetoothDevice.isConnected()).thenReturn(true); 207 208 mBluetoothDeviceUpdater.forceUpdate(); 209 210 verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice); 211 } 212 213 @Test forceUpdate_notFindCachedBluetoothDevice_doNothing()214 public void forceUpdate_notFindCachedBluetoothDevice_doNothing() { 215 final List<BluetoothDevice> bluetoothDevices = new ArrayList<>(); 216 bluetoothDevices.add(mBluetoothDevice); 217 218 when(mBluetoothAdapter.isEnabled()).thenReturn(true); 219 when(mBluetoothAdapter.getMostRecentlyConnectedDevices()).thenReturn(bluetoothDevices); 220 when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager); 221 when(mDeviceManager.findDevice(mBluetoothDevice)).thenReturn(null); 222 223 mBluetoothDeviceUpdater.forceUpdate(); 224 225 verify(mBluetoothDeviceUpdater, never()).removePreference(mCachedBluetoothDevice); 226 verify(mBluetoothDeviceUpdater, never()).addPreference(mCachedBluetoothDevice, 227 BluetoothDevicePreference.SortType.TYPE_NO_SORT); 228 } 229 230 @Test forceUpdate_bluetoothAdapterNotEnable_removeAllDevicesFromPreference()231 public void forceUpdate_bluetoothAdapterNotEnable_removeAllDevicesFromPreference() { 232 final Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>(); 233 cachedDevices.add(mCachedBluetoothDevice); 234 235 when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager); 236 when(mDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices); 237 when(mBluetoothAdapter.isEnabled()).thenReturn(false); 238 239 mBluetoothDeviceUpdater.forceUpdate(); 240 241 verify(mBluetoothDeviceUpdater).removeAllDevicesFromPreference(); 242 } 243 244 @Test forceUpdate_deviceNotContain_removePreference()245 public void forceUpdate_deviceNotContain_removePreference() { 246 final List<BluetoothDevice> bluetoothDevices = new ArrayList<>(); 247 bluetoothDevices.add(mBluetoothDevice); 248 final BluetoothDevice device2 = mock(BluetoothDevice.class); 249 final CachedBluetoothDevice cachedDevice2 = mock(CachedBluetoothDevice.class); 250 251 mBluetoothDeviceUpdater.mPreferenceMap.put(device2, mPreference); 252 253 when(cachedDevice2.getDevice()).thenReturn(device2); 254 when(cachedDevice2.getAddress()).thenReturn("04:52:C7:0B:D8:3S"); 255 when(mDeviceManager.findDevice(device2)).thenReturn(cachedDevice2); 256 when(mBluetoothAdapter.isEnabled()).thenReturn(true); 257 when(mBluetoothAdapter.getMostRecentlyConnectedDevices()).thenReturn(bluetoothDevices); 258 when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager); 259 when(mDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedBluetoothDevice); 260 when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); 261 when(mBluetoothDevice.isConnected()).thenReturn(false); 262 263 mBluetoothDeviceUpdater.forceUpdate(); 264 265 verify(mBluetoothDeviceUpdater).removePreference(cachedDevice2); 266 verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice, 267 BluetoothDevicePreference.SortType.TYPE_NO_SORT); 268 } 269 270 @Test forceUpdate_deviceIsSubDevice_doesNothing()271 public void forceUpdate_deviceIsSubDevice_doesNothing() { 272 final List<BluetoothDevice> bluetoothDevices = new ArrayList<>(); 273 bluetoothDevices.add(mBluetoothDevice); 274 275 when(mBluetoothAdapter.isEnabled()).thenReturn(true); 276 when(mBluetoothAdapter.getMostRecentlyConnectedDevices()).thenReturn(bluetoothDevices); 277 when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager); 278 when(mDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedBluetoothDevice); 279 when(mDeviceManager.isSubDevice(mBluetoothDevice)).thenReturn(true); 280 281 mBluetoothDeviceUpdater.forceUpdate(); 282 283 verify(mBluetoothDeviceUpdater, never()).removePreference(mCachedBluetoothDevice); 284 verify(mBluetoothDeviceUpdater, never()).addPreference(mCachedBluetoothDevice, 285 BluetoothDevicePreference.SortType.TYPE_NO_SORT); 286 } 287 288 @Test update_notExclusivelyManagedDevice_addDevice()289 public void update_notExclusivelyManagedDevice_addDevice() { 290 final Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>(); 291 cachedDevices.add(mCachedBluetoothDevice); 292 293 when(mBluetoothAdapter.isEnabled()).thenReturn(true); 294 when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager); 295 when(mDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices); 296 when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); 297 when(mBluetoothDevice.isConnected()).thenReturn(false); 298 when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn( 299 null); 300 301 mBluetoothDeviceUpdater.update(mCachedBluetoothDevice); 302 303 verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice, 304 BluetoothDevicePreference.SortType.TYPE_NO_SORT); 305 } 306 307 @Test update_existingExclusivelyManagedDevice_packageEnabled_removePreference()308 public void update_existingExclusivelyManagedDevice_packageEnabled_removePreference() 309 throws Exception { 310 final Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>(); 311 when(mBluetoothAdapter.isEnabled()).thenReturn(true); 312 when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager); 313 when(mDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices); 314 when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); 315 when(mBluetoothDevice.isConnected()).thenReturn(false); 316 when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn( 317 TEST_EXCLUSIVE_MANAGER.getBytes()); 318 doReturn(new ApplicationInfo()).when(mPackageManager).getApplicationInfo( 319 TEST_EXCLUSIVE_MANAGER, 0); 320 mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, mPreference); 321 322 mBluetoothDeviceUpdater.update(mCachedBluetoothDevice); 323 324 verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice); 325 verify(mBluetoothDeviceUpdater, never()).addPreference(mCachedBluetoothDevice, 326 BluetoothDevicePreference.SortType.TYPE_NO_SORT); 327 } 328 329 @Test update_newExclusivelyManagedDevice_packageEnabled_doNotAddPreference()330 public void update_newExclusivelyManagedDevice_packageEnabled_doNotAddPreference() 331 throws Exception { 332 final Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>(); 333 cachedDevices.add(mCachedBluetoothDevice); 334 when(mBluetoothAdapter.isEnabled()).thenReturn(true); 335 when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager); 336 when(mDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices); 337 when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); 338 when(mBluetoothDevice.isConnected()).thenReturn(false); 339 when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn( 340 TEST_EXCLUSIVE_MANAGER.getBytes()); 341 doReturn(new ApplicationInfo()).when(mPackageManager).getApplicationInfo( 342 TEST_EXCLUSIVE_MANAGER, 0); 343 344 mBluetoothDeviceUpdater.update(mCachedBluetoothDevice); 345 346 verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice); 347 verify(mBluetoothDeviceUpdater, never()).addPreference(mCachedBluetoothDevice, 348 BluetoothDevicePreference.SortType.TYPE_NO_SORT); 349 } 350 351 @Test update_exclusivelyManagedDevice_packageNotInstalled_addDevice()352 public void update_exclusivelyManagedDevice_packageNotInstalled_addDevice() 353 throws Exception { 354 final Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>(); 355 cachedDevices.add(mCachedBluetoothDevice); 356 when(mBluetoothAdapter.isEnabled()).thenReturn(true); 357 when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager); 358 when(mDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices); 359 when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); 360 when(mBluetoothDevice.isConnected()).thenReturn(false); 361 when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn( 362 TEST_EXCLUSIVE_MANAGER.getBytes()); 363 doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager) 364 .getApplicationInfo(TEST_EXCLUSIVE_MANAGER, 0); 365 366 mBluetoothDeviceUpdater.update(mCachedBluetoothDevice); 367 368 verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice, 369 BluetoothDevicePreference.SortType.TYPE_NO_SORT); 370 } 371 372 @Test update_exclusivelyManagedDevice_packageNotEnabled_addDevice()373 public void update_exclusivelyManagedDevice_packageNotEnabled_addDevice() 374 throws Exception { 375 final Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>(); 376 cachedDevices.add(mCachedBluetoothDevice); 377 ApplicationInfo appInfo = new ApplicationInfo(); 378 appInfo.enabled = false; 379 when(mBluetoothAdapter.isEnabled()).thenReturn(true); 380 when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager); 381 when(mDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices); 382 when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); 383 when(mBluetoothDevice.isConnected()).thenReturn(false); 384 when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn( 385 TEST_EXCLUSIVE_MANAGER.getBytes()); 386 doReturn(appInfo).when(mPackageManager).getApplicationInfo(TEST_EXCLUSIVE_MANAGER, 0); 387 388 mBluetoothDeviceUpdater.update(mCachedBluetoothDevice); 389 390 verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice, 391 BluetoothDevicePreference.SortType.TYPE_NO_SORT); 392 } 393 } 394