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