1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15 package com.android.systemui.statusbar; 16 17 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; 18 import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_DEFAULT; 19 import static android.inputmethodservice.InputMethodService.IME_INVISIBLE; 20 import static android.view.Display.DEFAULT_DISPLAY; 21 import static android.view.WindowInsetsController.BEHAVIOR_DEFAULT; 22 23 import static org.mockito.ArgumentMatchers.anyInt; 24 import static org.mockito.Matchers.eq; 25 import static org.mockito.Mockito.mock; 26 import static org.mockito.Mockito.verify; 27 import static org.mockito.Mockito.verifyNoMoreInteractions; 28 29 import android.content.ComponentName; 30 import android.graphics.Rect; 31 import android.hardware.biometrics.IBiometricSysuiReceiver; 32 import android.hardware.biometrics.PromptInfo; 33 import android.hardware.fingerprint.IUdfpsRefreshRateRequestCallback; 34 import android.os.Bundle; 35 import android.view.KeyEvent; 36 import android.view.WindowInsets; 37 import android.view.WindowInsets.Type.InsetsType; 38 import android.view.WindowInsetsController.Appearance; 39 import android.view.WindowInsetsController.Behavior; 40 41 import androidx.test.filters.SmallTest; 42 43 import com.android.internal.statusbar.LetterboxDetails; 44 import com.android.internal.statusbar.StatusBarIcon; 45 import com.android.internal.view.AppearanceRegion; 46 import com.android.systemui.SysuiTestCase; 47 import com.android.systemui.settings.FakeDisplayTracker; 48 import com.android.systemui.statusbar.CommandQueue.Callbacks; 49 50 import org.junit.After; 51 import org.junit.Before; 52 import org.junit.Test; 53 54 @SmallTest 55 public class CommandQueueTest extends SysuiTestCase { 56 57 private static final LetterboxDetails[] TEST_LETTERBOX_DETAILS = new LetterboxDetails[] { 58 new LetterboxDetails( 59 /* letterboxInnerBounds= */ new Rect(100, 0, 200, 500), 60 /* letterboxFullBounds= */ new Rect(0, 0, 500, 100), 61 /* appAppearance= */ 123) 62 }; 63 64 private CommandQueue mCommandQueue; 65 private FakeDisplayTracker mDisplayTracker = new FakeDisplayTracker(mContext); 66 private Callbacks mCallbacks; 67 private static final int SECONDARY_DISPLAY = 1; 68 69 @Before setup()70 public void setup() { 71 mCommandQueue = new CommandQueue(mContext, mDisplayTracker); 72 mCallbacks = mock(Callbacks.class); 73 mCommandQueue.addCallback(mCallbacks); 74 verify(mCallbacks).disable(anyInt(), eq(0), eq(0), eq(false)); 75 } 76 77 @After tearDown()78 public void tearDown() { 79 verifyNoMoreInteractions(mCallbacks); 80 } 81 82 @Test testIcon()83 public void testIcon() { 84 String slot = "testSlot"; 85 StatusBarIcon icon = mock(StatusBarIcon.class); 86 mCommandQueue.setIcon(slot, icon); 87 waitForIdleSync(); 88 verify(mCallbacks).setIcon(eq(slot), eq(icon)); 89 90 mCommandQueue.removeIcon(slot); 91 waitForIdleSync(); 92 verify(mCallbacks).removeIcon(eq(slot)); 93 } 94 95 @Test testDisable()96 public void testDisable() { 97 int state1 = 14; 98 int state2 = 42; 99 mCommandQueue.disable(DEFAULT_DISPLAY, state1, state2); 100 waitForIdleSync(); 101 verify(mCallbacks).disable(eq(DEFAULT_DISPLAY), eq(state1), eq(state2), eq(true)); 102 } 103 104 @Test testDisableForSecondaryDisplay()105 public void testDisableForSecondaryDisplay() { 106 int state1 = 14; 107 int state2 = 42; 108 mCommandQueue.disable(SECONDARY_DISPLAY, state1, state2); 109 waitForIdleSync(); 110 verify(mCallbacks).disable(eq(SECONDARY_DISPLAY), eq(state1), eq(state2), eq(true)); 111 } 112 113 @Test testExpandNotifications()114 public void testExpandNotifications() { 115 mCommandQueue.animateExpandNotificationsPanel(); 116 waitForIdleSync(); 117 verify(mCallbacks).animateExpandNotificationsPanel(); 118 } 119 120 @Test testExpandSettings()121 public void testExpandSettings() { 122 String panel = "some_panel"; 123 mCommandQueue.animateExpandSettingsPanel(panel); 124 waitForIdleSync(); 125 verify(mCallbacks).animateExpandSettingsPanel(eq(panel)); 126 } 127 128 @Test testOnSystemBarAttributesChanged()129 public void testOnSystemBarAttributesChanged() { 130 doTestOnSystemBarAttributesChanged(DEFAULT_DISPLAY, 1, 131 new AppearanceRegion[]{new AppearanceRegion(2, new Rect())}, false, 132 BEHAVIOR_DEFAULT, WindowInsets.Type.defaultVisible(), "test", 133 TEST_LETTERBOX_DETAILS); 134 } 135 136 @Test testOnSystemBarAttributesChangedForSecondaryDisplay()137 public void testOnSystemBarAttributesChangedForSecondaryDisplay() { 138 doTestOnSystemBarAttributesChanged(SECONDARY_DISPLAY, 1, 139 new AppearanceRegion[]{new AppearanceRegion(2, new Rect())}, false, 140 BEHAVIOR_DEFAULT, WindowInsets.Type.defaultVisible(), "test", 141 TEST_LETTERBOX_DETAILS); 142 } 143 doTestOnSystemBarAttributesChanged(int displayId, @Appearance int appearance, AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme, @Behavior int behavior, @InsetsType int requestedVisibleTypes, String packageName, LetterboxDetails[] letterboxDetails)144 private void doTestOnSystemBarAttributesChanged(int displayId, @Appearance int appearance, 145 AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme, 146 @Behavior int behavior, @InsetsType int requestedVisibleTypes, String packageName, 147 LetterboxDetails[] letterboxDetails) { 148 mCommandQueue.onSystemBarAttributesChanged(displayId, appearance, appearanceRegions, 149 navbarColorManagedByIme, behavior, requestedVisibleTypes, packageName, 150 letterboxDetails); 151 waitForIdleSync(); 152 verify(mCallbacks).onSystemBarAttributesChanged(eq(displayId), eq(appearance), 153 eq(appearanceRegions), eq(navbarColorManagedByIme), eq(behavior), 154 eq(requestedVisibleTypes), eq(packageName), eq(letterboxDetails)); 155 } 156 157 @Test testShowTransient()158 public void testShowTransient() { 159 int types = WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars(); 160 mCommandQueue.showTransient(DEFAULT_DISPLAY, types, true /* isGestureOnSystemBar */); 161 waitForIdleSync(); 162 verify(mCallbacks).showTransient(eq(DEFAULT_DISPLAY), eq(types), eq(true)); 163 } 164 165 @Test testShowTransientForSecondaryDisplay()166 public void testShowTransientForSecondaryDisplay() { 167 int types = WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars(); 168 mCommandQueue.showTransient(SECONDARY_DISPLAY, types, true /* isGestureOnSystemBar */); 169 waitForIdleSync(); 170 verify(mCallbacks).showTransient(eq(SECONDARY_DISPLAY), eq(types), eq(true)); 171 } 172 173 @Test testAbortTransient()174 public void testAbortTransient() { 175 int types = WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars(); 176 mCommandQueue.abortTransient(DEFAULT_DISPLAY, types); 177 waitForIdleSync(); 178 verify(mCallbacks).abortTransient(eq(DEFAULT_DISPLAY), eq(types)); 179 } 180 181 @Test testAbortTransientForSecondaryDisplay()182 public void testAbortTransientForSecondaryDisplay() { 183 int types = WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars(); 184 mCommandQueue.abortTransient(SECONDARY_DISPLAY, types); 185 waitForIdleSync(); 186 verify(mCallbacks).abortTransient(eq(SECONDARY_DISPLAY), eq(types)); 187 } 188 189 @Test testShowImeButton()190 public void testShowImeButton() { 191 mCommandQueue.setImeWindowStatus(DEFAULT_DISPLAY, null, 1, 2, true); 192 waitForIdleSync(); 193 verify(mCallbacks).setImeWindowStatus( 194 eq(DEFAULT_DISPLAY), eq(null), eq(1), eq(2), eq(true)); 195 } 196 197 @Test testShowImeButtonForSecondaryDisplay()198 public void testShowImeButtonForSecondaryDisplay() { 199 // First show in default display to update the "last updated ime display" 200 testShowImeButton(); 201 202 mCommandQueue.setImeWindowStatus(SECONDARY_DISPLAY, null, 1, 2, true); 203 waitForIdleSync(); 204 verify(mCallbacks).setImeWindowStatus(eq(DEFAULT_DISPLAY), eq(null), eq(IME_INVISIBLE), 205 eq(BACK_DISPOSITION_DEFAULT), eq(false)); 206 verify(mCallbacks).setImeWindowStatus( 207 eq(SECONDARY_DISPLAY), eq(null), eq(1), eq(2), eq(true)); 208 } 209 210 @Test testShowRecentApps()211 public void testShowRecentApps() { 212 mCommandQueue.showRecentApps(true); 213 waitForIdleSync(); 214 verify(mCallbacks).showRecentApps(eq(true)); 215 } 216 217 @Test testHideRecentApps()218 public void testHideRecentApps() { 219 mCommandQueue.hideRecentApps(true, false); 220 waitForIdleSync(); 221 verify(mCallbacks).hideRecentApps(eq(true), eq(false)); 222 } 223 224 @Test testToggleRecentApps()225 public void testToggleRecentApps() { 226 mCommandQueue.toggleRecentApps(); 227 waitForIdleSync(); 228 verify(mCallbacks).toggleRecentApps(); 229 } 230 231 @Test testPreloadRecentApps()232 public void testPreloadRecentApps() { 233 mCommandQueue.preloadRecentApps(); 234 waitForIdleSync(); 235 verify(mCallbacks).preloadRecentApps(); 236 } 237 238 @Test testCancelPreloadRecentApps()239 public void testCancelPreloadRecentApps() { 240 mCommandQueue.cancelPreloadRecentApps(); 241 waitForIdleSync(); 242 verify(mCallbacks).cancelPreloadRecentApps(); 243 } 244 245 @Test testDismissKeyboardShortcuts()246 public void testDismissKeyboardShortcuts() { 247 mCommandQueue.dismissKeyboardShortcutsMenu(); 248 waitForIdleSync(); 249 verify(mCallbacks).dismissKeyboardShortcutsMenu(); 250 } 251 252 @Test testToggleKeyboardShortcuts()253 public void testToggleKeyboardShortcuts() { 254 mCommandQueue.toggleKeyboardShortcutsMenu(1); 255 waitForIdleSync(); 256 verify(mCallbacks).toggleKeyboardShortcutsMenu(eq(1)); 257 } 258 259 @Test testSetWindowState()260 public void testSetWindowState() { 261 mCommandQueue.setWindowState(DEFAULT_DISPLAY, 1, 2); 262 waitForIdleSync(); 263 verify(mCallbacks).setWindowState(eq(DEFAULT_DISPLAY), eq(1), eq(2)); 264 } 265 266 @Test testSetWindowStateForSecondaryDisplay()267 public void testSetWindowStateForSecondaryDisplay() { 268 mCommandQueue.setWindowState(SECONDARY_DISPLAY, 1, 2); 269 waitForIdleSync(); 270 verify(mCallbacks).setWindowState(eq(SECONDARY_DISPLAY), eq(1), eq(2)); 271 } 272 273 @Test testScreenPinRequest()274 public void testScreenPinRequest() { 275 mCommandQueue.showScreenPinningRequest(1); 276 waitForIdleSync(); 277 verify(mCallbacks).showScreenPinningRequest(eq(1)); 278 } 279 280 @Test testAppTransitionPending()281 public void testAppTransitionPending() { 282 mCommandQueue.appTransitionPending(DEFAULT_DISPLAY); 283 waitForIdleSync(); 284 verify(mCallbacks).appTransitionPending(eq(DEFAULT_DISPLAY), eq(false)); 285 } 286 287 @Test testAppTransitionPendingForSecondaryDisplay()288 public void testAppTransitionPendingForSecondaryDisplay() { 289 mCommandQueue.appTransitionPending(SECONDARY_DISPLAY); 290 waitForIdleSync(); 291 verify(mCallbacks).appTransitionPending(eq(SECONDARY_DISPLAY), eq(false)); 292 } 293 294 @Test testAppTransitionCancelled()295 public void testAppTransitionCancelled() { 296 mCommandQueue.appTransitionCancelled(DEFAULT_DISPLAY); 297 waitForIdleSync(); 298 verify(mCallbacks).appTransitionCancelled(eq(DEFAULT_DISPLAY)); 299 } 300 301 @Test testAppTransitionCancelledForSecondaryDisplay()302 public void testAppTransitionCancelledForSecondaryDisplay() { 303 mCommandQueue.appTransitionCancelled(SECONDARY_DISPLAY); 304 waitForIdleSync(); 305 verify(mCallbacks).appTransitionCancelled(eq(SECONDARY_DISPLAY)); 306 } 307 308 @Test testAppTransitionStarting()309 public void testAppTransitionStarting() { 310 mCommandQueue.appTransitionStarting(DEFAULT_DISPLAY, 1, 2); 311 waitForIdleSync(); 312 verify(mCallbacks).appTransitionStarting( 313 eq(DEFAULT_DISPLAY), eq(1L), eq(2L), eq(false)); 314 } 315 316 @Test testAppTransitionStartingForSecondaryDisplay()317 public void testAppTransitionStartingForSecondaryDisplay() { 318 mCommandQueue.appTransitionStarting(SECONDARY_DISPLAY, 1, 2); 319 waitForIdleSync(); 320 verify(mCallbacks).appTransitionStarting( 321 eq(SECONDARY_DISPLAY), eq(1L), eq(2L), eq(false)); 322 } 323 324 @Test testAppTransitionFinished()325 public void testAppTransitionFinished() { 326 mCommandQueue.appTransitionFinished(DEFAULT_DISPLAY); 327 waitForIdleSync(); 328 verify(mCallbacks).appTransitionFinished(eq(DEFAULT_DISPLAY)); 329 } 330 331 @Test testAppTransitionFinishedForSecondaryDisplay()332 public void testAppTransitionFinishedForSecondaryDisplay() { 333 mCommandQueue.appTransitionFinished(SECONDARY_DISPLAY); 334 waitForIdleSync(); 335 verify(mCallbacks).appTransitionFinished(eq(SECONDARY_DISPLAY)); 336 } 337 338 @Test testAssistDisclosure()339 public void testAssistDisclosure() { 340 mCommandQueue.showAssistDisclosure(); 341 waitForIdleSync(); 342 verify(mCallbacks).showAssistDisclosure(); 343 } 344 345 @Test testStartAssist()346 public void testStartAssist() { 347 Bundle b = new Bundle(); 348 mCommandQueue.startAssist(b); 349 waitForIdleSync(); 350 verify(mCallbacks).startAssist(eq(b)); 351 } 352 353 @Test testCameraLaunchGesture()354 public void testCameraLaunchGesture() { 355 mCommandQueue.onCameraLaunchGestureDetected(1); 356 waitForIdleSync(); 357 verify(mCallbacks).onCameraLaunchGestureDetected(eq(1)); 358 } 359 360 @Test testShowPipMenu()361 public void testShowPipMenu() { 362 mCommandQueue.showPictureInPictureMenu(); 363 waitForIdleSync(); 364 verify(mCallbacks).showPictureInPictureMenu(); 365 } 366 367 @Test testAddQsTile()368 public void testAddQsTile() { 369 ComponentName c = new ComponentName("testpkg", "testcls"); 370 mCommandQueue.addQsTile(c); 371 waitForIdleSync(); 372 verify(mCallbacks).addQsTile(eq(c)); 373 } 374 375 @Test testRemoveQsTile()376 public void testRemoveQsTile() { 377 ComponentName c = new ComponentName("testpkg", "testcls"); 378 mCommandQueue.remQsTile(c); 379 waitForIdleSync(); 380 verify(mCallbacks).remQsTile(eq(c)); 381 } 382 383 @Test testClickQsTile()384 public void testClickQsTile() { 385 ComponentName c = new ComponentName("testpkg", "testcls"); 386 mCommandQueue.clickQsTile(c); 387 waitForIdleSync(); 388 verify(mCallbacks).clickTile(eq(c)); 389 } 390 391 @Test testToggleAppSplitScreen()392 public void testToggleAppSplitScreen() { 393 mCommandQueue.toggleSplitScreen(); 394 waitForIdleSync(); 395 verify(mCallbacks).toggleSplitScreen(); 396 } 397 398 @Test testHandleSysKey()399 public void testHandleSysKey() { 400 KeyEvent testEvent = new KeyEvent(1, 1); 401 mCommandQueue.handleSystemKey(testEvent); 402 waitForIdleSync(); 403 verify(mCallbacks).handleSystemKey(eq(testEvent)); 404 } 405 406 @Test testOnDisplayReady()407 public void testOnDisplayReady() { 408 mCommandQueue.onDisplayReady(DEFAULT_DISPLAY); 409 waitForIdleSync(); 410 verify(mCallbacks).onDisplayReady(eq(DEFAULT_DISPLAY)); 411 } 412 413 @Test testOnDisplayReadyForSecondaryDisplay()414 public void testOnDisplayReadyForSecondaryDisplay() { 415 mCommandQueue.onDisplayReady(SECONDARY_DISPLAY); 416 waitForIdleSync(); 417 verify(mCallbacks).onDisplayReady(eq(SECONDARY_DISPLAY)); 418 } 419 420 @Test testOnDisplayRemoved()421 public void testOnDisplayRemoved() { 422 mDisplayTracker.triggerOnDisplayRemoved(SECONDARY_DISPLAY); 423 waitForIdleSync(); 424 verify(mCallbacks).onDisplayRemoved(eq(SECONDARY_DISPLAY)); 425 } 426 427 @Test testOnRecentsAnimationStateChanged()428 public void testOnRecentsAnimationStateChanged() { 429 mCommandQueue.onRecentsAnimationStateChanged(true); 430 waitForIdleSync(); 431 verify(mCallbacks).onRecentsAnimationStateChanged(eq(true)); 432 } 433 434 @Test testShowAuthenticationDialog()435 public void testShowAuthenticationDialog() { 436 PromptInfo promptInfo = new PromptInfo(); 437 final IBiometricSysuiReceiver receiver = mock(IBiometricSysuiReceiver.class); 438 final int[] sensorIds = {1, 2}; 439 final boolean credentialAllowed = true; 440 final boolean requireConfirmation = true; 441 final int userId = 10; 442 final long operationId = 1; 443 final String packageName = "test"; 444 final long requestId = 10; 445 446 mCommandQueue.showAuthenticationDialog(promptInfo, receiver, sensorIds, 447 credentialAllowed, requireConfirmation, userId, operationId, packageName, requestId); 448 waitForIdleSync(); 449 verify(mCallbacks).showAuthenticationDialog(eq(promptInfo), eq(receiver), eq(sensorIds), 450 eq(credentialAllowed), eq(requireConfirmation), eq(userId), eq(operationId), 451 eq(packageName), eq(requestId)); 452 } 453 454 @Test testOnBiometricAuthenticated()455 public void testOnBiometricAuthenticated() { 456 final int id = 12; 457 mCommandQueue.onBiometricAuthenticated(id); 458 waitForIdleSync(); 459 verify(mCallbacks).onBiometricAuthenticated(eq(id)); 460 } 461 462 @Test testOnBiometricHelp()463 public void testOnBiometricHelp() { 464 final int modality = TYPE_FACE; 465 final String helpMessage = "test_help_message"; 466 mCommandQueue.onBiometricHelp(modality, helpMessage); 467 waitForIdleSync(); 468 verify(mCallbacks).onBiometricHelp(eq(modality), eq(helpMessage)); 469 } 470 471 @Test testOnBiometricError()472 public void testOnBiometricError() { 473 final int modality = 1; 474 final int error = 2; 475 final int vendorCode = 3; 476 mCommandQueue.onBiometricError(modality, error, vendorCode); 477 waitForIdleSync(); 478 verify(mCallbacks).onBiometricError(eq(modality), eq(error), eq(vendorCode)); 479 } 480 481 @Test testHideAuthenticationDialog()482 public void testHideAuthenticationDialog() { 483 final long id = 4; 484 mCommandQueue.hideAuthenticationDialog(id); 485 waitForIdleSync(); 486 verify(mCallbacks).hideAuthenticationDialog(eq(id)); 487 } 488 489 @Test testSetUdfpsRefreshRateCallback()490 public void testSetUdfpsRefreshRateCallback() { 491 final IUdfpsRefreshRateRequestCallback callback = 492 mock(IUdfpsRefreshRateRequestCallback.class); 493 mCommandQueue.setUdfpsRefreshRateCallback(callback); 494 waitForIdleSync(); 495 verify(mCallbacks).setUdfpsRefreshRateCallback(eq(callback)); 496 } 497 498 @Test testSuppressAmbientDisplay()499 public void testSuppressAmbientDisplay() { 500 mCommandQueue.suppressAmbientDisplay(true); 501 waitForIdleSync(); 502 verify(mCallbacks).suppressAmbientDisplay(true); 503 } 504 505 @Test testRequestWindowMagnificationConnection()506 public void testRequestWindowMagnificationConnection() { 507 mCommandQueue.requestWindowMagnificationConnection(true); 508 waitForIdleSync(); 509 verify(mCallbacks).requestWindowMagnificationConnection(true); 510 } 511 512 @Test testSetEnableNavigationBarLumaSampling()513 public void testSetEnableNavigationBarLumaSampling() { 514 mCommandQueue.setNavigationBarLumaSamplingEnabled(1, true); 515 waitForIdleSync(); 516 verify(mCallbacks).setNavigationBarLumaSamplingEnabled(eq(1), eq(true)); 517 } 518 519 @Test testConfirmImmersivePrompt()520 public void testConfirmImmersivePrompt() { 521 mCommandQueue.confirmImmersivePrompt(); 522 waitForIdleSync(); 523 verify(mCallbacks).confirmImmersivePrompt(); 524 } 525 526 @Test testImmersiveModeChanged()527 public void testImmersiveModeChanged() { 528 final int displayAreaId = 10; 529 mCommandQueue.immersiveModeChanged(displayAreaId, true); 530 waitForIdleSync(); 531 verify(mCallbacks).immersiveModeChanged(displayAreaId, true); 532 } 533 534 @Test testShowRearDisplayDialog()535 public void testShowRearDisplayDialog() { 536 final int currentBaseState = 1; 537 mCommandQueue.showRearDisplayDialog(currentBaseState); 538 waitForIdleSync(); 539 verify(mCallbacks).showRearDisplayDialog(eq(currentBaseState)); 540 } 541 } 542