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 17 package com.android.systemui.statusbar.phone; 18 19 import static com.android.systemui.qs.dagger.QSFlagsModule.RBC_AVAILABLE; 20 import static com.android.systemui.statusbar.phone.AutoTileManager.DEVICE_CONTROLS; 21 22 import static org.junit.Assert.assertEquals; 23 import static org.junit.Assert.assertFalse; 24 import static org.junit.Assert.assertNull; 25 import static org.junit.Assert.assertTrue; 26 import static org.junit.Assert.fail; 27 import static org.mockito.ArgumentMatchers.any; 28 import static org.mockito.ArgumentMatchers.eq; 29 import static org.mockito.ArgumentMatchers.isNotNull; 30 import static org.mockito.ArgumentMatchers.isNull; 31 import static org.mockito.Mockito.doReturn; 32 import static org.mockito.Mockito.inOrder; 33 import static org.mockito.Mockito.mock; 34 import static org.mockito.Mockito.never; 35 import static org.mockito.Mockito.times; 36 import static org.mockito.Mockito.verify; 37 import static org.mockito.Mockito.when; 38 39 import android.content.ComponentName; 40 import android.content.Context; 41 import android.content.pm.PackageManager; 42 import android.hardware.display.ColorDisplayManager; 43 import android.hardware.display.NightDisplayListener; 44 import android.os.Handler; 45 import android.os.UserHandle; 46 import android.testing.AndroidTestingRunner; 47 import android.testing.TestableLooper; 48 import android.testing.TestableLooper.RunWithLooper; 49 50 import androidx.test.filters.SmallTest; 51 52 import com.android.systemui.R; 53 import com.android.systemui.SysuiTestCase; 54 import com.android.systemui.plugins.qs.QSTile; 55 import com.android.systemui.qs.AutoAddTracker; 56 import com.android.systemui.qs.QSHost; 57 import com.android.systemui.qs.ReduceBrightColorsController; 58 import com.android.systemui.qs.SettingObserver; 59 import com.android.systemui.qs.external.CustomTile; 60 import com.android.systemui.statusbar.policy.CastController; 61 import com.android.systemui.statusbar.policy.CastController.CastDevice; 62 import com.android.systemui.statusbar.policy.DataSaverController; 63 import com.android.systemui.statusbar.policy.DeviceControlsController; 64 import com.android.systemui.statusbar.policy.HotspotController; 65 import com.android.systemui.statusbar.policy.SafetyController; 66 import com.android.systemui.statusbar.policy.WalletController; 67 import com.android.systemui.util.settings.FakeSettings; 68 import com.android.systemui.util.settings.SecureSettings; 69 70 import org.junit.After; 71 import org.junit.Before; 72 import org.junit.Test; 73 import org.junit.runner.RunWith; 74 import org.mockito.Answers; 75 import org.mockito.ArgumentCaptor; 76 import org.mockito.InOrder; 77 import org.mockito.Mock; 78 import org.mockito.Mockito; 79 import org.mockito.MockitoAnnotations; 80 import org.mockito.Spy; 81 import org.mockito.stubbing.Answer; 82 83 import java.util.ArrayList; 84 import java.util.Collections; 85 import java.util.List; 86 87 import javax.inject.Named; 88 89 @RunWith(AndroidTestingRunner.class) 90 @RunWithLooper 91 @SmallTest 92 public class AutoTileManagerTest extends SysuiTestCase { 93 94 private static final String TEST_SETTING = "setting"; 95 private static final String TEST_SPEC = "spec"; 96 private static final String TEST_SETTING_COMPONENT = "setting_component"; 97 private static final String TEST_COMPONENT = "test_pkg/test_cls"; 98 private static final String TEST_CUSTOM_SPEC = "custom(" + TEST_COMPONENT + ")"; 99 private static final String TEST_CUSTOM_SAFETY_CLASS = "safety_cls"; 100 private static final String TEST_CUSTOM_SAFETY_PKG = "safety_pkg"; 101 private static final String TEST_CUSTOM_SAFETY_SPEC = CustomTile.toSpec(new ComponentName( 102 TEST_CUSTOM_SAFETY_PKG, TEST_CUSTOM_SAFETY_CLASS)); 103 private static final String SEPARATOR = AutoTileManager.SETTING_SEPARATOR; 104 105 private static final int USER = 0; 106 107 @Mock private QSHost mQsHost; 108 @Mock private AutoAddTracker mAutoAddTracker; 109 @Mock private CastController mCastController; 110 @Mock private HotspotController mHotspotController; 111 @Mock private DataSaverController mDataSaverController; 112 @Mock private ManagedProfileController mManagedProfileController; 113 @Mock private NightDisplayListener mNightDisplayListener; 114 @Mock private ReduceBrightColorsController mReduceBrightColorsController; 115 @Mock private DeviceControlsController mDeviceControlsController; 116 @Mock private WalletController mWalletController; 117 @Mock private SafetyController mSafetyController; 118 @Mock(answer = Answers.RETURNS_SELF) 119 private AutoAddTracker.Builder mAutoAddTrackerBuilder; 120 @Mock private Context mUserContext; 121 @Spy private PackageManager mPackageManager; 122 private final boolean mIsReduceBrightColorsAvailable = true; 123 124 private AutoTileManager mAutoTileManager; // under test 125 126 private SecureSettings mSecureSettings; 127 private ManagedProfileController.Callback mManagedProfileCallback; 128 129 @Before setUp()130 public void setUp() throws Exception { 131 MockitoAnnotations.initMocks(this); 132 mSecureSettings = new FakeSettings(); 133 134 mContext.getOrCreateTestableResources().addOverride( 135 R.array.config_quickSettingsAutoAdd, 136 new String[] { 137 TEST_SETTING + SEPARATOR + TEST_SPEC, 138 TEST_SETTING_COMPONENT + SEPARATOR + TEST_CUSTOM_SPEC 139 } 140 ); 141 mContext.getOrCreateTestableResources().addOverride( 142 com.android.internal.R.bool.config_nightDisplayAvailable, true); 143 mContext.getOrCreateTestableResources().addOverride( 144 R.string.safety_quick_settings_tile_class, TEST_CUSTOM_SAFETY_CLASS); 145 146 when(mAutoAddTrackerBuilder.build()).thenReturn(mAutoAddTracker); 147 when(mQsHost.getUserContext()).thenReturn(mUserContext); 148 when(mUserContext.getUser()).thenReturn(UserHandle.of(USER)); 149 mPackageManager = Mockito.spy(mContext.getPackageManager()); 150 when(mPackageManager.getPermissionControllerPackageName()) 151 .thenReturn(TEST_CUSTOM_SAFETY_PKG); 152 Context context = Mockito.spy(mContext); 153 when(context.getPackageManager()).thenReturn(mPackageManager); 154 155 mAutoTileManager = createAutoTileManager(context); 156 mAutoTileManager.init(); 157 } 158 159 @After tearDown()160 public void tearDown() { 161 mAutoTileManager.destroy(); 162 } 163 createAutoTileManager( Context context, AutoAddTracker.Builder autoAddTrackerBuilder, HotspotController hotspotController, DataSaverController dataSaverController, ManagedProfileController managedProfileController, NightDisplayListener nightDisplayListener, CastController castController, ReduceBrightColorsController reduceBrightColorsController, DeviceControlsController deviceControlsController, WalletController walletController, SafetyController safetyController, @Named(RBC_AVAILABLE) boolean isReduceBrightColorsAvailable)164 private AutoTileManager createAutoTileManager( 165 Context context, 166 AutoAddTracker.Builder autoAddTrackerBuilder, 167 HotspotController hotspotController, 168 DataSaverController dataSaverController, 169 ManagedProfileController managedProfileController, 170 NightDisplayListener nightDisplayListener, 171 CastController castController, 172 ReduceBrightColorsController reduceBrightColorsController, 173 DeviceControlsController deviceControlsController, 174 WalletController walletController, 175 SafetyController safetyController, 176 @Named(RBC_AVAILABLE) boolean isReduceBrightColorsAvailable) { 177 return new AutoTileManager(context, autoAddTrackerBuilder, mQsHost, 178 Handler.createAsync(TestableLooper.get(this).getLooper()), 179 mSecureSettings, 180 hotspotController, 181 dataSaverController, 182 managedProfileController, 183 nightDisplayListener, 184 castController, 185 reduceBrightColorsController, 186 deviceControlsController, 187 walletController, 188 safetyController, 189 isReduceBrightColorsAvailable); 190 } 191 createAutoTileManager(Context context)192 private AutoTileManager createAutoTileManager(Context context) { 193 return createAutoTileManager(context, mAutoAddTrackerBuilder, mHotspotController, 194 mDataSaverController, mManagedProfileController, mNightDisplayListener, 195 mCastController, mReduceBrightColorsController, mDeviceControlsController, 196 mWalletController, mSafetyController, mIsReduceBrightColorsAvailable); 197 } 198 199 @Test testCreatedAutoTileManagerIsNotInitialized()200 public void testCreatedAutoTileManagerIsNotInitialized() { 201 AutoAddTracker.Builder builder = mock(AutoAddTracker.Builder.class, Answers.RETURNS_SELF); 202 AutoAddTracker tracker = mock(AutoAddTracker.class); 203 when(builder.build()).thenReturn(tracker); 204 HotspotController hC = mock(HotspotController.class); 205 DataSaverController dSC = mock(DataSaverController.class); 206 ManagedProfileController mPC = mock(ManagedProfileController.class); 207 NightDisplayListener nDS = mock(NightDisplayListener.class); 208 CastController cC = mock(CastController.class); 209 ReduceBrightColorsController rBC = mock(ReduceBrightColorsController.class); 210 DeviceControlsController dCC = mock(DeviceControlsController.class); 211 WalletController wC = mock(WalletController.class); 212 SafetyController sC = mock(SafetyController.class); 213 214 AutoTileManager manager = 215 createAutoTileManager(mock(Context.class), builder, hC, dSC, mPC, nDS, cC, rBC, 216 dCC, wC, sC, true); 217 218 verify(tracker, never()).initialize(); 219 verify(hC, never()).addCallback(any()); 220 verify(dSC, never()).addCallback(any()); 221 verify(mPC, never()).addCallback(any()); 222 verify(nDS, never()).setCallback(any()); 223 verify(cC, never()).addCallback(any()); 224 verify(rBC, never()).addCallback(any()); 225 verify(dCC, never()).setCallback(any()); 226 verify(wC, never()).getWalletPosition(); 227 verify(sC, never()).addCallback(any()); 228 assertNull(manager.getSecureSettingForKey(TEST_SETTING)); 229 assertNull(manager.getSecureSettingForKey(TEST_SETTING_COMPONENT)); 230 } 231 232 @Test testChangeUserWhenNotInitializedThrows()233 public void testChangeUserWhenNotInitializedThrows() { 234 AutoTileManager manager = createAutoTileManager(mock(Context.class)); 235 236 try { 237 manager.changeUser(UserHandle.of(USER + 1)); 238 fail(); 239 } catch (Exception e) { 240 // This should throw and take this path 241 } 242 } 243 244 @Test testChangeUserCallbacksStoppedAndStarted()245 public void testChangeUserCallbacksStoppedAndStarted() throws Exception { 246 TestableLooper.get(this).runWithLooper(() -> 247 mAutoTileManager.changeUser(UserHandle.of(USER + 1)) 248 ); 249 250 InOrder inOrderHotspot = inOrder(mHotspotController); 251 inOrderHotspot.verify(mHotspotController).removeCallback(any()); 252 inOrderHotspot.verify(mHotspotController).addCallback(any()); 253 254 InOrder inOrderDataSaver = inOrder(mDataSaverController); 255 inOrderDataSaver.verify(mDataSaverController).removeCallback(any()); 256 inOrderDataSaver.verify(mDataSaverController).addCallback(any()); 257 258 InOrder inOrderManagedProfile = inOrder(mManagedProfileController); 259 inOrderManagedProfile.verify(mManagedProfileController).removeCallback(any()); 260 inOrderManagedProfile.verify(mManagedProfileController).addCallback(any()); 261 262 if (ColorDisplayManager.isNightDisplayAvailable(mContext)) { 263 InOrder inOrderNightDisplay = inOrder(mNightDisplayListener); 264 inOrderNightDisplay.verify(mNightDisplayListener).setCallback(isNull()); 265 inOrderNightDisplay.verify(mNightDisplayListener).setCallback(isNotNull()); 266 } 267 268 InOrder inOrderReduceBrightColors = inOrder(mReduceBrightColorsController); 269 inOrderReduceBrightColors.verify(mReduceBrightColorsController).removeCallback(any()); 270 inOrderReduceBrightColors.verify(mReduceBrightColorsController).addCallback(any()); 271 272 InOrder inOrderCast = inOrder(mCastController); 273 inOrderCast.verify(mCastController).removeCallback(any()); 274 inOrderCast.verify(mCastController).addCallback(any()); 275 276 InOrder inOrderDevices = inOrder(mDeviceControlsController); 277 inOrderDevices.verify(mDeviceControlsController).removeCallback(); 278 inOrderDevices.verify(mDeviceControlsController).setCallback(any()); 279 280 verify(mWalletController, times(2)).getWalletPosition(); 281 282 InOrder inOrderSafety = inOrder(mSafetyController); 283 inOrderSafety.verify(mSafetyController).removeCallback(any()); 284 inOrderSafety.verify(mSafetyController).addCallback(any()); 285 286 SettingObserver setting = mAutoTileManager.getSecureSettingForKey(TEST_SETTING); 287 assertEquals(USER + 1, setting.getCurrentUser()); 288 assertTrue(setting.isListening()); 289 } 290 291 @Test testChangeUserSomeCallbacksNotAdded()292 public void testChangeUserSomeCallbacksNotAdded() throws Exception { 293 when(mAutoAddTracker.isAdded("hotspot")).thenReturn(true); 294 when(mAutoAddTracker.isAdded("work")).thenReturn(true); 295 when(mAutoAddTracker.isAdded("cast")).thenReturn(true); 296 when(mAutoAddTracker.isAdded(TEST_SPEC)).thenReturn(true); 297 298 TestableLooper.get(this).runWithLooper(() -> 299 mAutoTileManager.changeUser(UserHandle.of(USER + 1)) 300 ); 301 302 verify(mAutoAddTracker).changeUser(UserHandle.of(USER + 1)); 303 304 InOrder inOrderHotspot = inOrder(mHotspotController); 305 inOrderHotspot.verify(mHotspotController).removeCallback(any()); 306 inOrderHotspot.verify(mHotspotController, never()).addCallback(any()); 307 308 InOrder inOrderDataSaver = inOrder(mDataSaverController); 309 inOrderDataSaver.verify(mDataSaverController).removeCallback(any()); 310 inOrderDataSaver.verify(mDataSaverController).addCallback(any()); 311 312 InOrder inOrderManagedProfile = inOrder(mManagedProfileController); 313 inOrderManagedProfile.verify(mManagedProfileController).removeCallback(any()); 314 inOrderManagedProfile.verify(mManagedProfileController).addCallback(any()); 315 316 if (ColorDisplayManager.isNightDisplayAvailable(mContext)) { 317 InOrder inOrderNightDisplay = inOrder(mNightDisplayListener); 318 inOrderNightDisplay.verify(mNightDisplayListener).setCallback(isNull()); 319 inOrderNightDisplay.verify(mNightDisplayListener).setCallback(isNotNull()); 320 } 321 322 InOrder inOrderReduceBrightColors = inOrder(mReduceBrightColorsController); 323 inOrderReduceBrightColors.verify(mReduceBrightColorsController).removeCallback(any()); 324 inOrderReduceBrightColors.verify(mReduceBrightColorsController).addCallback(any()); 325 326 InOrder inOrderCast = inOrder(mCastController); 327 inOrderCast.verify(mCastController).removeCallback(any()); 328 inOrderCast.verify(mCastController, never()).addCallback(any()); 329 330 InOrder inOrderDevices = inOrder(mDeviceControlsController); 331 inOrderDevices.verify(mDeviceControlsController).removeCallback(); 332 inOrderDevices.verify(mDeviceControlsController).setCallback(any()); 333 334 verify(mWalletController, times(2)).getWalletPosition(); 335 336 InOrder inOrderSafety = inOrder(mSafetyController); 337 inOrderSafety.verify(mSafetyController).removeCallback(any()); 338 inOrderSafety.verify(mSafetyController).addCallback(any()); 339 340 SettingObserver setting = mAutoTileManager.getSecureSettingForKey(TEST_SETTING); 341 assertEquals(USER + 1, setting.getCurrentUser()); 342 assertFalse(setting.isListening()); 343 } 344 345 @Test testGetCurrentUserId()346 public void testGetCurrentUserId() throws Exception { 347 assertEquals(USER, mAutoTileManager.getCurrentUserId()); 348 349 TestableLooper.get(this).runWithLooper(() -> 350 mAutoTileManager.changeUser(UserHandle.of(USER + 100)) 351 ); 352 353 assertEquals(USER + 100, mAutoTileManager.getCurrentUserId()); 354 } 355 356 @Test nightTileAdded_whenActivated()357 public void nightTileAdded_whenActivated() { 358 if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) { 359 return; 360 } 361 mAutoTileManager.mNightDisplayCallback.onActivated(true); 362 verify(mQsHost).addTile("night"); 363 } 364 365 @Test nightTileNotAdded_whenDeactivated()366 public void nightTileNotAdded_whenDeactivated() { 367 if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) { 368 return; 369 } 370 mAutoTileManager.mNightDisplayCallback.onActivated(false); 371 verify(mQsHost, never()).addTile("night"); 372 } 373 374 @Test nightTileAdded_whenNightModeTwilight()375 public void nightTileAdded_whenNightModeTwilight() { 376 if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) { 377 return; 378 } 379 mAutoTileManager.mNightDisplayCallback.onAutoModeChanged( 380 ColorDisplayManager.AUTO_MODE_TWILIGHT); 381 verify(mQsHost).addTile("night"); 382 } 383 384 @Test nightTileAdded_whenNightModeCustom()385 public void nightTileAdded_whenNightModeCustom() { 386 if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) { 387 return; 388 } 389 mAutoTileManager.mNightDisplayCallback.onAutoModeChanged( 390 ColorDisplayManager.AUTO_MODE_CUSTOM_TIME); 391 verify(mQsHost).addTile("night"); 392 } 393 394 @Test nightTileNotAdded_whenNightModeDisabled()395 public void nightTileNotAdded_whenNightModeDisabled() { 396 if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) { 397 return; 398 } 399 mAutoTileManager.mNightDisplayCallback.onAutoModeChanged( 400 ColorDisplayManager.AUTO_MODE_DISABLED); 401 verify(mQsHost, never()).addTile("night"); 402 } 403 404 @Test reduceBrightColorsTileAdded_whenActivated()405 public void reduceBrightColorsTileAdded_whenActivated() { 406 mAutoTileManager.mReduceBrightColorsCallback.onActivated(true); 407 verify(mQsHost).addTile("reduce_brightness"); 408 } 409 410 @Test reduceBrightColorsTileNotAdded_whenDeactivated()411 public void reduceBrightColorsTileNotAdded_whenDeactivated() { 412 mAutoTileManager.mReduceBrightColorsCallback.onActivated(false); 413 verify(mQsHost, never()).addTile("reduce_brightness"); 414 } 415 buildFakeCastDevice(boolean isCasting)416 private static List<CastDevice> buildFakeCastDevice(boolean isCasting) { 417 CastDevice cd = new CastDevice(); 418 cd.state = isCasting ? CastDevice.STATE_CONNECTED : CastDevice.STATE_DISCONNECTED; 419 return Collections.singletonList(cd); 420 } 421 422 @Test castTileAdded_whenDeviceIsCasting()423 public void castTileAdded_whenDeviceIsCasting() { 424 doReturn(buildFakeCastDevice(true)).when(mCastController).getCastDevices(); 425 mAutoTileManager.mCastCallback.onCastDevicesChanged(); 426 verify(mQsHost).addTile("cast"); 427 } 428 429 @Test castTileNotAdded_whenDeviceIsNotCasting()430 public void castTileNotAdded_whenDeviceIsNotCasting() { 431 doReturn(buildFakeCastDevice(false)).when(mCastController).getCastDevices(); 432 mAutoTileManager.mCastCallback.onCastDevicesChanged(); 433 verify(mQsHost, never()).addTile("cast"); 434 } 435 436 @Test testSettingTileAdded_onChanged()437 public void testSettingTileAdded_onChanged() { 438 changeValue(TEST_SETTING, 1); 439 verify(mAutoAddTracker).setTileAdded(TEST_SPEC); 440 verify(mQsHost).addTile(TEST_SPEC); 441 } 442 443 @Test testSettingTileAddedComponentAtEnd_onChanged()444 public void testSettingTileAddedComponentAtEnd_onChanged() { 445 changeValue(TEST_SETTING_COMPONENT, 1); 446 verify(mAutoAddTracker).setTileAdded(TEST_CUSTOM_SPEC); 447 verify(mQsHost).addTile(ComponentName.unflattenFromString(TEST_COMPONENT) 448 , /* end */ true); 449 } 450 451 @Test testSettingTileAdded_onlyOnce()452 public void testSettingTileAdded_onlyOnce() { 453 changeValue(TEST_SETTING, 1); 454 changeValue(TEST_SETTING, 2); 455 verify(mAutoAddTracker).setTileAdded(TEST_SPEC); 456 verify(mQsHost).addTile(TEST_SPEC); 457 } 458 459 @Test testSettingTileNotAdded_onChangedTo0()460 public void testSettingTileNotAdded_onChangedTo0() { 461 changeValue(TEST_SETTING, 0); 462 verify(mAutoAddTracker, never()).setTileAdded(TEST_SPEC); 463 verify(mQsHost, never()).addTile(TEST_SPEC); 464 } 465 466 @Test testSettingTileNotAdded_ifPreviouslyAdded()467 public void testSettingTileNotAdded_ifPreviouslyAdded() { 468 when(mAutoAddTracker.isAdded(TEST_SPEC)).thenReturn(true); 469 470 changeValue(TEST_SETTING, 1); 471 verify(mAutoAddTracker, never()).setTileAdded(TEST_SPEC); 472 verify(mQsHost, never()).addTile(TEST_SPEC); 473 } 474 475 @Test testSafetyTileNotAdded_ifPreviouslyAdded()476 public void testSafetyTileNotAdded_ifPreviouslyAdded() { 477 ComponentName safetyComponent = CustomTile.getComponentFromSpec(TEST_CUSTOM_SAFETY_SPEC); 478 mAutoTileManager.init(); 479 verify(mQsHost, times(1)).addTile(safetyComponent, true); 480 when(mAutoAddTracker.isAdded(TEST_CUSTOM_SAFETY_SPEC)).thenReturn(true); 481 mAutoTileManager.init(); 482 verify(mQsHost, times(1)).addTile(safetyComponent, true); 483 } 484 485 @Test testSafetyTileAdded_onUserChange()486 public void testSafetyTileAdded_onUserChange() { 487 ComponentName safetyComponent = CustomTile.getComponentFromSpec(TEST_CUSTOM_SAFETY_SPEC); 488 mAutoTileManager.init(); 489 verify(mQsHost, times(1)).addTile(safetyComponent, true); 490 when(mAutoAddTracker.isAdded(TEST_CUSTOM_SAFETY_SPEC)).thenReturn(false); 491 mAutoTileManager.changeUser(UserHandle.of(USER + 1)); 492 verify(mQsHost, times(2)).addTile(safetyComponent, true); 493 } 494 495 @Test testSafetyTileRemoved_onSafetyCenterDisable()496 public void testSafetyTileRemoved_onSafetyCenterDisable() { 497 ComponentName safetyComponent = CustomTile.getComponentFromSpec(TEST_CUSTOM_SAFETY_SPEC); 498 mAutoTileManager.init(); 499 when(mAutoAddTracker.isAdded(TEST_CUSTOM_SAFETY_SPEC)).thenReturn(true); 500 mAutoTileManager.mSafetyCallback.onSafetyCenterEnableChanged(false); 501 verify(mQsHost, times(1)).removeTile(TEST_CUSTOM_SAFETY_SPEC); 502 } 503 504 @Test testSafetyTileAdded_onSafetyCenterEnable()505 public void testSafetyTileAdded_onSafetyCenterEnable() { 506 ComponentName safetyComponent = CustomTile.getComponentFromSpec(TEST_CUSTOM_SAFETY_SPEC); 507 mAutoTileManager.init(); 508 verify(mQsHost, times(1)).addTile(safetyComponent, true); 509 mAutoTileManager.mSafetyCallback.onSafetyCenterEnableChanged(false); 510 mAutoTileManager.mSafetyCallback.onSafetyCenterEnableChanged(true); 511 verify(mQsHost, times(2)).addTile(safetyComponent, true); 512 } 513 514 @Test managedProfileAdded_tileAdded()515 public void managedProfileAdded_tileAdded() { 516 when(mAutoAddTracker.isAdded(eq("work"))).thenReturn(false); 517 when(mAutoAddTracker.getRestoredTilePosition(eq("work"))).thenReturn(2); 518 mAutoTileManager = createAutoTileManager(mContext); 519 Mockito.doAnswer((Answer<Object>) invocation -> { 520 mManagedProfileCallback = invocation.getArgument(0); 521 return null; 522 }).when(mManagedProfileController).addCallback(any()); 523 mAutoTileManager.init(); 524 when(mManagedProfileController.hasActiveProfile()).thenReturn(true); 525 526 mManagedProfileCallback.onManagedProfileChanged(); 527 528 verify(mQsHost, times(1)).addTile(eq("work"), eq(2)); 529 verify(mAutoAddTracker, times(1)).setTileAdded(eq("work")); 530 } 531 532 @Test managedProfileRemoved_tileRemoved()533 public void managedProfileRemoved_tileRemoved() { 534 when(mAutoAddTracker.isAdded(eq("work"))).thenReturn(true); 535 mAutoTileManager = createAutoTileManager(mContext); 536 Mockito.doAnswer((Answer<Object>) invocation -> { 537 mManagedProfileCallback = invocation.getArgument(0); 538 return null; 539 }).when(mManagedProfileController).addCallback(any()); 540 mAutoTileManager.init(); 541 when(mManagedProfileController.hasActiveProfile()).thenReturn(false); 542 543 mManagedProfileCallback.onManagedProfileChanged(); 544 545 verify(mQsHost, times(1)).removeTile(eq("work")); 546 verify(mAutoAddTracker, times(1)).setTileRemoved(eq("work")); 547 } 548 549 @Test testAddControlsTileIfNotPresent()550 public void testAddControlsTileIfNotPresent() { 551 String spec = DEVICE_CONTROLS; 552 when(mAutoAddTracker.isAdded(eq(spec))).thenReturn(false); 553 when(mQsHost.getTiles()).thenReturn(new ArrayList<>()); 554 555 mAutoTileManager.init(); 556 ArgumentCaptor<DeviceControlsController.Callback> captor = 557 ArgumentCaptor.forClass(DeviceControlsController.Callback.class); 558 559 verify(mDeviceControlsController).setCallback(captor.capture()); 560 561 captor.getValue().onControlsUpdate(3); 562 verify(mQsHost).addTile(spec, 3); 563 verify(mAutoAddTracker).setTileAdded(spec); 564 } 565 566 @Test testDontAddControlsTileIfPresent()567 public void testDontAddControlsTileIfPresent() { 568 String spec = DEVICE_CONTROLS; 569 when(mAutoAddTracker.isAdded(eq(spec))).thenReturn(false); 570 when(mQsHost.getTiles()).thenReturn(new ArrayList<>()); 571 572 mAutoTileManager.init(); 573 ArgumentCaptor<DeviceControlsController.Callback> captor = 574 ArgumentCaptor.forClass(DeviceControlsController.Callback.class); 575 576 verify(mDeviceControlsController).setCallback(captor.capture()); 577 578 captor.getValue().removeControlsAutoTracker(); 579 verify(mQsHost, never()).addTile(spec, 3); 580 verify(mAutoAddTracker, never()).setTileAdded(spec); 581 verify(mAutoAddTracker).setTileRemoved(spec); 582 } 583 584 @Test testRemoveControlsTileFromTrackerWhenRequested()585 public void testRemoveControlsTileFromTrackerWhenRequested() { 586 String spec = "controls"; 587 when(mAutoAddTracker.isAdded(eq(spec))).thenReturn(true); 588 QSTile mockTile = mock(QSTile.class); 589 when(mockTile.getTileSpec()).thenReturn(spec); 590 when(mQsHost.getTiles()).thenReturn(List.of(mockTile)); 591 592 mAutoTileManager.init(); 593 ArgumentCaptor<DeviceControlsController.Callback> captor = 594 ArgumentCaptor.forClass(DeviceControlsController.Callback.class); 595 596 verify(mDeviceControlsController).setCallback(captor.capture()); 597 598 captor.getValue().onControlsUpdate(3); 599 verify(mQsHost, never()).addTile(spec, 3); 600 verify(mAutoAddTracker, never()).setTileAdded(spec); 601 } 602 603 604 @Test testEmptyArray_doesNotCrash()605 public void testEmptyArray_doesNotCrash() { 606 mContext.getOrCreateTestableResources().addOverride( 607 R.array.config_quickSettingsAutoAdd, new String[0]); 608 createAutoTileManager(mContext).destroy(); 609 } 610 611 @Test testMissingConfig_doesNotCrash()612 public void testMissingConfig_doesNotCrash() { 613 mContext.getOrCreateTestableResources().addOverride( 614 R.array.config_quickSettingsAutoAdd, null); 615 createAutoTileManager(mContext).destroy(); 616 } 617 618 // Will only notify if it's listening changeValue(String key, int value)619 private void changeValue(String key, int value) { 620 mSecureSettings.putIntForUser(key, value, USER); 621 TestableLooper.get(this).processAllMessages(); 622 } 623 } 624