1 /* 2 * Copyright 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 package com.android.settings.connecteddevice; 17 18 import static com.android.settings.core.BasePreferenceController.AVAILABLE; 19 import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE; 20 21 import static com.google.common.truth.Truth.assertThat; 22 23 import static org.mockito.Mockito.doReturn; 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.BluetoothManager; 31 import android.content.Context; 32 import android.content.pm.PackageManager; 33 import android.graphics.drawable.Drawable; 34 import android.platform.test.flag.junit.CheckFlagsRule; 35 import android.platform.test.flag.junit.DeviceFlagsValueProvider; 36 import android.util.Pair; 37 38 import androidx.preference.Preference; 39 import androidx.preference.PreferenceCategory; 40 import androidx.preference.PreferenceGroup; 41 import androidx.preference.PreferenceManager; 42 43 import com.android.settings.R; 44 import com.android.settings.bluetooth.BluetoothDevicePreference; 45 import com.android.settings.bluetooth.BluetoothDeviceUpdater; 46 import com.android.settings.connecteddevice.dock.DockUpdater; 47 import com.android.settings.dashboard.DashboardFragment; 48 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; 49 import com.android.settings.widget.SingleTargetGearPreference; 50 import com.android.settingslib.bluetooth.CachedBluetoothDevice; 51 52 import org.junit.Before; 53 import org.junit.Rule; 54 import org.junit.Test; 55 import org.junit.runner.RunWith; 56 import org.mockito.Mock; 57 import org.mockito.MockitoAnnotations; 58 import org.robolectric.RobolectricTestRunner; 59 import org.robolectric.RuntimeEnvironment; 60 import org.robolectric.annotation.Config; 61 import org.robolectric.shadow.api.Shadow; 62 63 import java.util.ArrayList; 64 import java.util.List; 65 66 @RunWith(RobolectricTestRunner.class) 67 @Config(shadows = ShadowBluetoothAdapter.class) 68 public class PreviouslyConnectedDevicePreferenceControllerTest { 69 70 private static final String KEY = "test_key"; 71 private static final String FAKE_ADDRESS_1 = "AA:AA:AA:AA:AA:01"; 72 private static final String FAKE_ADDRESS_2 = "AA:AA:AA:AA:AA:02"; 73 private static final String FAKE_ADDRESS_3 = "AA:AA:AA:AA:AA:03"; 74 private static final String FAKE_ADDRESS_4 = "AA:AA:AA:AA:AA:04"; 75 private static final String FAKE_ADDRESS_5 = "AA:AA:AA:AA:AA:05"; 76 77 @Rule 78 public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); 79 80 @Mock 81 private DashboardFragment mDashboardFragment; 82 @Mock 83 private BluetoothDeviceUpdater mBluetoothDeviceUpdater; 84 @Mock 85 private DockUpdater mDockUpdater; 86 @Mock 87 private PackageManager mPackageManager; 88 @Mock 89 private PreferenceManager mPreferenceManager; 90 @Mock 91 private Preference mSeeAllPreference; 92 @Mock 93 private CachedBluetoothDevice mCachedDevice1; 94 @Mock 95 private CachedBluetoothDevice mCachedDevice2; 96 @Mock 97 private CachedBluetoothDevice mCachedDevice3; 98 @Mock 99 private CachedBluetoothDevice mCachedDevice4; 100 @Mock 101 private CachedBluetoothDevice mCachedDevice5; 102 @Mock 103 private BluetoothDevice mBluetoothDevice1; 104 @Mock 105 private BluetoothDevice mBluetoothDevice2; 106 @Mock 107 private BluetoothDevice mBluetoothDevice3; 108 @Mock 109 private BluetoothDevice mBluetoothDevice4; 110 @Mock 111 private BluetoothDevice mBluetoothDevice5; 112 @Mock 113 private Drawable mDrawable; 114 115 @Mock private BluetoothManager mBluetoothManager; 116 @Mock private BluetoothAdapter mBluetoothAdapter; 117 118 private Context mContext; 119 private PreviouslyConnectedDevicePreferenceController mPreConnectedDeviceController; 120 private PreferenceGroup mPreferenceGroup; 121 private ShadowBluetoothAdapter mShadowBluetoothAdapter; 122 123 @Before setUp()124 public void setUp() { 125 MockitoAnnotations.initMocks(this); 126 Pair<Drawable, String> pairs = new Pair<>(mDrawable, "fake_device"); 127 mContext = spy(RuntimeEnvironment.application); 128 doReturn(mContext).when(mDashboardFragment).getContext(); 129 doReturn(mPackageManager).when(mContext).getPackageManager(); 130 when(mContext.getSystemService(BluetoothManager.class)).thenReturn(mBluetoothManager); 131 when(mBluetoothManager.getAdapter()).thenReturn(mBluetoothAdapter); 132 when(mBluetoothAdapter.isEnabled()).thenReturn(true); 133 mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter()); 134 135 when(mCachedDevice1.getDevice()).thenReturn(mBluetoothDevice1); 136 when(mCachedDevice1.getAddress()).thenReturn(FAKE_ADDRESS_1); 137 when(mCachedDevice1.getDrawableWithDescription()).thenReturn(pairs); 138 when(mCachedDevice2.getDevice()).thenReturn(mBluetoothDevice2); 139 when(mCachedDevice2.getAddress()).thenReturn(FAKE_ADDRESS_2); 140 when(mCachedDevice2.getDrawableWithDescription()).thenReturn(pairs); 141 when(mCachedDevice3.getDevice()).thenReturn(mBluetoothDevice3); 142 when(mCachedDevice3.getAddress()).thenReturn(FAKE_ADDRESS_3); 143 when(mCachedDevice3.getDrawableWithDescription()).thenReturn(pairs); 144 when(mCachedDevice4.getDevice()).thenReturn(mBluetoothDevice4); 145 when(mCachedDevice4.getAddress()).thenReturn(FAKE_ADDRESS_4); 146 when(mCachedDevice4.getDrawableWithDescription()).thenReturn(pairs); 147 when(mCachedDevice5.getDevice()).thenReturn(mBluetoothDevice5); 148 when(mCachedDevice5.getAddress()).thenReturn(FAKE_ADDRESS_5); 149 when(mCachedDevice5.getDrawableWithDescription()).thenReturn(pairs); 150 151 final List<BluetoothDevice> mMostRecentlyConnectedDevices = new ArrayList<>(); 152 mMostRecentlyConnectedDevices.add(mBluetoothDevice1); 153 mMostRecentlyConnectedDevices.add(mBluetoothDevice2); 154 mMostRecentlyConnectedDevices.add(mBluetoothDevice4); 155 mMostRecentlyConnectedDevices.add(mBluetoothDevice3); 156 mShadowBluetoothAdapter.setMostRecentlyConnectedDevices(mMostRecentlyConnectedDevices); 157 when(mBluetoothAdapter.getMostRecentlyConnectedDevices()) 158 .thenReturn(mMostRecentlyConnectedDevices); 159 160 mPreConnectedDeviceController = 161 new PreviouslyConnectedDevicePreferenceController(mContext, KEY); 162 mPreConnectedDeviceController.setBluetoothDeviceUpdater(mBluetoothDeviceUpdater); 163 mPreConnectedDeviceController.setSavedDockUpdater(mDockUpdater); 164 mPreferenceGroup = spy(new PreferenceCategory(mContext)); 165 doReturn(mPreferenceManager).when(mPreferenceGroup).getPreferenceManager(); 166 mPreferenceGroup.setVisible(false); 167 mPreConnectedDeviceController.setPreferenceGroup(mPreferenceGroup); 168 mPreConnectedDeviceController.mSeeAllPreference = mSeeAllPreference; 169 } 170 171 @Test onStart_registerCallback()172 public void onStart_registerCallback() { 173 // register the callback in onStart() 174 mPreConnectedDeviceController.onStart(); 175 176 verify(mBluetoothDeviceUpdater).registerCallback(); 177 verify(mDockUpdater).registerCallback(); 178 verify(mContext).registerReceiver(mPreConnectedDeviceController.mReceiver, 179 mPreConnectedDeviceController.mIntentFilter, Context.RECEIVER_EXPORTED_UNAUDITED); 180 verify(mBluetoothDeviceUpdater).refreshPreference(); 181 } 182 183 @Test onStop_unregisterCallback()184 public void onStop_unregisterCallback() { 185 // register it first 186 mContext.registerReceiver(mPreConnectedDeviceController.mReceiver, null, 187 Context.RECEIVER_EXPORTED/*UNAUDITED*/); 188 189 // unregister the callback in onStop() 190 mPreConnectedDeviceController.onStop(); 191 192 verify(mBluetoothDeviceUpdater).unregisterCallback(); 193 verify(mDockUpdater).unregisterCallback(); 194 verify(mContext).unregisterReceiver(mPreConnectedDeviceController.mReceiver); 195 } 196 197 @Test getAvailabilityStatus_noBluetoothDockFeature_returnUnSupported()198 public void getAvailabilityStatus_noBluetoothDockFeature_returnUnSupported() { 199 doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH); 200 mPreConnectedDeviceController.setSavedDockUpdater(null); 201 202 assertThat(mPreConnectedDeviceController.getAvailabilityStatus()).isEqualTo( 203 CONDITIONALLY_UNAVAILABLE); 204 } 205 206 @Test getAvailabilityStatus_hasBluetoothFeature_returnSupported()207 public void getAvailabilityStatus_hasBluetoothFeature_returnSupported() { 208 doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH); 209 mPreConnectedDeviceController.setSavedDockUpdater(null); 210 211 assertThat(mPreConnectedDeviceController.getAvailabilityStatus()).isEqualTo( 212 AVAILABLE); 213 } 214 215 @Test getAvailabilityStatus_haveDockFeature_returnSupported()216 public void getAvailabilityStatus_haveDockFeature_returnSupported() { 217 doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH); 218 219 assertThat(mPreConnectedDeviceController.getAvailabilityStatus()).isEqualTo( 220 AVAILABLE); 221 } 222 223 @Test onDeviceAdded_addDevicePreference_displayIt()224 public void onDeviceAdded_addDevicePreference_displayIt() { 225 final BluetoothDevicePreference preference1 = new BluetoothDevicePreference( 226 mContext, mCachedDevice1, true, BluetoothDevicePreference.SortType.TYPE_NO_SORT); 227 228 mPreConnectedDeviceController.onDeviceAdded(preference1); 229 230 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(2); 231 } 232 233 @Test onDeviceAdded_addDockDevicePreference_displayIt()234 public void onDeviceAdded_addDockDevicePreference_displayIt() { 235 final SingleTargetGearPreference dockPreference = new SingleTargetGearPreference( 236 mContext, null /* AttributeSet */); 237 238 mPreConnectedDeviceController.onDeviceAdded(dockPreference); 239 240 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(2); 241 } 242 243 @Test onDeviceAdded_addFourDevicePreference_onlyDisplayThree()244 public void onDeviceAdded_addFourDevicePreference_onlyDisplayThree() { 245 final BluetoothDevicePreference preference1 = new BluetoothDevicePreference( 246 mContext, mCachedDevice1, true, BluetoothDevicePreference.SortType.TYPE_NO_SORT); 247 final BluetoothDevicePreference preference2 = new BluetoothDevicePreference( 248 mContext, mCachedDevice2, true, BluetoothDevicePreference.SortType.TYPE_NO_SORT); 249 final BluetoothDevicePreference preference3 = new BluetoothDevicePreference( 250 mContext, mCachedDevice3, true, BluetoothDevicePreference.SortType.TYPE_NO_SORT); 251 final BluetoothDevicePreference preference4 = new BluetoothDevicePreference( 252 mContext, mCachedDevice4, true, BluetoothDevicePreference.SortType.TYPE_NO_SORT); 253 final SingleTargetGearPreference dockPreference = new SingleTargetGearPreference( 254 mContext, null /* AttributeSet */); 255 256 mPreConnectedDeviceController.onDeviceAdded(preference1); 257 mPreConnectedDeviceController.onDeviceAdded(preference2); 258 mPreConnectedDeviceController.onDeviceAdded(preference3); 259 mPreConnectedDeviceController.onDeviceAdded(preference4); 260 mPreConnectedDeviceController.onDeviceAdded(dockPreference); 261 262 // 3 BluetoothDevicePreference and 1 see all preference 263 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(4); 264 } 265 266 @Test onDeviceAdded_addPreferenceNotExistInRecentlyDevices_noCrash()267 public void onDeviceAdded_addPreferenceNotExistInRecentlyDevices_noCrash() { 268 final BluetoothDevicePreference preference = new BluetoothDevicePreference( 269 mContext, mCachedDevice5, true, BluetoothDevicePreference.SortType.TYPE_NO_SORT); 270 271 mPreConnectedDeviceController.onDeviceAdded(preference); 272 273 // 1 see all preference 274 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1); 275 } 276 277 @Test onDeviceAdded_addPreferenceNotExistInRecentlyDevices_doNothing()278 public void onDeviceAdded_addPreferenceNotExistInRecentlyDevices_doNothing() { 279 final BluetoothDevicePreference preference = new BluetoothDevicePreference( 280 mContext, mCachedDevice5, true, BluetoothDevicePreference.SortType.TYPE_NO_SORT); 281 282 mPreConnectedDeviceController.onDeviceAdded(preference); 283 284 // 1 see all preference 285 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1); 286 } 287 288 @Test onDeviceRemoved_removeLastDevice_showSeeAllPreference()289 public void onDeviceRemoved_removeLastDevice_showSeeAllPreference() { 290 final BluetoothDevicePreference preference1 = new BluetoothDevicePreference( 291 mContext, mCachedDevice1, true, BluetoothDevicePreference.SortType.TYPE_NO_SORT); 292 final SingleTargetGearPreference dockPreference = new SingleTargetGearPreference( 293 mContext, null /* AttributeSet */); 294 mPreferenceGroup.addPreference(preference1); 295 mPreferenceGroup.addPreference(dockPreference); 296 297 mPreConnectedDeviceController.onDeviceRemoved(preference1); 298 mPreConnectedDeviceController.onDeviceRemoved(dockPreference); 299 300 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1); 301 } 302 303 @Test updatePreferenceVisibility_bluetoothIsEnable_shouldShowCorrectText()304 public void updatePreferenceVisibility_bluetoothIsEnable_shouldShowCorrectText() { 305 mShadowBluetoothAdapter.setEnabled(true); 306 when(mBluetoothAdapter.isEnabled()).thenReturn(true); 307 mPreConnectedDeviceController.updatePreferenceVisibility(); 308 309 verify(mSeeAllPreference).setSummary(""); 310 } 311 312 @Test updatePreferenceVisibility_bluetoothIsDisable_shouldShowCorrectText()313 public void updatePreferenceVisibility_bluetoothIsDisable_shouldShowCorrectText() { 314 mShadowBluetoothAdapter.setEnabled(false); 315 when(mBluetoothAdapter.isEnabled()).thenReturn(false); 316 mPreConnectedDeviceController.updatePreferenceVisibility(); 317 318 verify(mSeeAllPreference).setSummary( 319 mContext.getString(R.string.connected_device_see_all_summary)); 320 } 321 322 @Test updatePreferenceGroup_bluetoothIsEnable_shouldOrderByMostRecentlyConnected()323 public void updatePreferenceGroup_bluetoothIsEnable_shouldOrderByMostRecentlyConnected() { 324 when(mBluetoothAdapter.isEnabled()).thenReturn(true); 325 final BluetoothDevicePreference preference4 = 326 new BluetoothDevicePreference( 327 mContext, 328 mCachedDevice4, 329 true, 330 BluetoothDevicePreference.SortType.TYPE_NO_SORT); 331 final BluetoothDevicePreference preference3 = 332 new BluetoothDevicePreference( 333 mContext, 334 mCachedDevice3, 335 true, 336 BluetoothDevicePreference.SortType.TYPE_NO_SORT); 337 final BluetoothDevicePreference preference2 = 338 new BluetoothDevicePreference( 339 mContext, 340 mCachedDevice2, 341 true, 342 BluetoothDevicePreference.SortType.TYPE_NO_SORT); 343 mPreConnectedDeviceController.onDeviceAdded(preference4); 344 mPreConnectedDeviceController.onDeviceAdded(preference3); 345 mPreConnectedDeviceController.onDeviceAdded(preference2); 346 347 mPreConnectedDeviceController.updatePreferenceGroup(); 348 349 // Refer to the order of {@link #mMostRecentlyConnectedDevices}, the first one is see all 350 // preference 351 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(4); 352 assertThat(preference2.getOrder()).isEqualTo(0); 353 assertThat(preference4.getOrder()).isEqualTo(1); 354 assertThat(preference3.getOrder()).isEqualTo(2); 355 } 356 357 @Test updatePreferenceGroup_bluetoothIsDisable_shouldShowOnlySeeAllPreference()358 public void updatePreferenceGroup_bluetoothIsDisable_shouldShowOnlySeeAllPreference() { 359 when(mBluetoothAdapter.isEnabled()).thenReturn(false); 360 final BluetoothDevicePreference preference4 = 361 new BluetoothDevicePreference( 362 mContext, 363 mCachedDevice4, 364 true, 365 BluetoothDevicePreference.SortType.TYPE_NO_SORT); 366 final BluetoothDevicePreference preference3 = 367 new BluetoothDevicePreference( 368 mContext, 369 mCachedDevice3, 370 true, 371 BluetoothDevicePreference.SortType.TYPE_NO_SORT); 372 final BluetoothDevicePreference preference2 = 373 new BluetoothDevicePreference( 374 mContext, 375 mCachedDevice2, 376 true, 377 BluetoothDevicePreference.SortType.TYPE_NO_SORT); 378 mPreConnectedDeviceController.onDeviceAdded(preference4); 379 mPreConnectedDeviceController.onDeviceAdded(preference3); 380 mPreConnectedDeviceController.onDeviceAdded(preference2); 381 382 mPreConnectedDeviceController.updatePreferenceGroup(); 383 384 // 1 see all preference 385 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1); 386 } 387 } 388