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.statusbar.phone.ScrimController.OPAQUE; 20 import static com.android.systemui.statusbar.phone.ScrimController.SEMI_TRANSPARENT; 21 import static com.android.systemui.statusbar.phone.ScrimController.TRANSPARENT; 22 import static com.android.systemui.statusbar.phone.ScrimState.BOUNCER; 23 import static com.android.systemui.statusbar.phone.ScrimState.SHADE_LOCKED; 24 25 import static com.google.common.truth.Truth.assertThat; 26 27 import static kotlinx.coroutines.flow.FlowKt.emptyFlow; 28 29 import static org.junit.Assert.assertEquals; 30 import static org.junit.Assert.assertFalse; 31 import static org.mockito.ArgumentMatchers.any; 32 import static org.mockito.ArgumentMatchers.anyFloat; 33 import static org.mockito.ArgumentMatchers.anyInt; 34 import static org.mockito.ArgumentMatchers.anyLong; 35 import static org.mockito.ArgumentMatchers.anyString; 36 import static org.mockito.ArgumentMatchers.eq; 37 import static org.mockito.Mockito.doAnswer; 38 import static org.mockito.Mockito.mock; 39 import static org.mockito.Mockito.never; 40 import static org.mockito.Mockito.reset; 41 import static org.mockito.Mockito.spy; 42 import static org.mockito.Mockito.verify; 43 import static org.mockito.Mockito.verifyZeroInteractions; 44 import static org.mockito.Mockito.when; 45 46 import android.animation.Animator; 47 import android.app.AlarmManager; 48 import android.content.Context; 49 import android.content.res.ColorStateList; 50 import android.content.res.TypedArray; 51 import android.graphics.Color; 52 import android.testing.TestableLooper; 53 import android.testing.ViewUtils; 54 import android.util.MathUtils; 55 import android.view.View; 56 57 import androidx.test.ext.junit.runners.AndroidJUnit4; 58 import androidx.test.filters.SmallTest; 59 60 import com.android.internal.colorextraction.ColorExtractor.GradientColors; 61 import com.android.keyguard.BouncerPanelExpansionCalculator; 62 import com.android.keyguard.KeyguardUpdateMonitor; 63 import com.android.systemui.DejankUtils; 64 import com.android.systemui.SysuiTestCase; 65 import com.android.systemui.animation.ShadeInterpolation; 66 import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants; 67 import com.android.systemui.dock.DockManager; 68 import com.android.systemui.keyguard.KeyguardUnlockAnimationController; 69 import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository; 70 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; 71 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor; 72 import com.android.systemui.keyguard.shared.model.KeyguardState; 73 import com.android.systemui.keyguard.shared.model.TransitionState; 74 import com.android.systemui.keyguard.shared.model.TransitionStep; 75 import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToGoneTransitionViewModel; 76 import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel; 77 import com.android.systemui.kosmos.KosmosJavaAdapter; 78 import com.android.systemui.scrim.ScrimView; 79 import com.android.systemui.shade.transition.LargeScreenShadeInterpolator; 80 import com.android.systemui.shade.transition.LinearLargeScreenShadeInterpolator; 81 import com.android.systemui.statusbar.policy.FakeConfigurationController; 82 import com.android.systemui.statusbar.policy.KeyguardStateController; 83 import com.android.systemui.util.concurrency.FakeExecutor; 84 import com.android.systemui.util.kotlin.JavaAdapter; 85 import com.android.systemui.util.time.FakeSystemClock; 86 import com.android.systemui.util.wakelock.DelayedWakeLock; 87 import com.android.systemui.utils.os.FakeHandler; 88 import com.android.systemui.wallpapers.data.repository.FakeWallpaperRepository; 89 90 import com.google.common.truth.Expect; 91 92 import kotlinx.coroutines.test.TestScope; 93 94 import org.junit.After; 95 import org.junit.Assert; 96 import org.junit.Before; 97 import org.junit.Rule; 98 import org.junit.Test; 99 import org.junit.runner.RunWith; 100 import org.mockito.Mock; 101 import org.mockito.MockitoAnnotations; 102 import org.mockito.stubbing.Answer; 103 104 import java.util.Arrays; 105 import java.util.Collections; 106 import java.util.HashMap; 107 import java.util.HashSet; 108 import java.util.Map; 109 110 @RunWith(AndroidJUnit4.class) 111 @TestableLooper.RunWithLooper(setAsMainLooper = true) 112 @SmallTest 113 public class ScrimControllerTest extends SysuiTestCase { 114 115 @Rule public Expect mExpect = Expect.create(); 116 private final KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this); 117 118 private final FakeConfigurationController mConfigurationController = 119 new FakeConfigurationController(); 120 private final LargeScreenShadeInterpolator 121 mLinearLargeScreenShadeInterpolator = new LinearLargeScreenShadeInterpolator(); 122 123 private final TestScope mTestScope = mKosmos.getTestScope(); 124 private final JavaAdapter mJavaAdapter = new JavaAdapter(mTestScope.getBackgroundScope()); 125 126 private ScrimController mScrimController; 127 private ScrimView mScrimBehind; 128 private ScrimView mNotificationsScrim; 129 private ScrimView mScrimInFront; 130 private ScrimState mScrimState; 131 private float mScrimBehindAlpha; 132 private GradientColors mScrimInFrontColor; 133 private int mScrimVisibility; 134 private boolean mAlwaysOnEnabled; 135 private TestableLooper mLooper; 136 private Context mContext; 137 @Mock private AlarmManager mAlarmManager; 138 @Mock private DozeParameters mDozeParameters; 139 @Mock private LightBarController mLightBarController; 140 @Mock private DelayedWakeLock.Factory mDelayedWakeLockFactory; 141 @Mock private DelayedWakeLock mWakeLock; 142 @Mock private KeyguardStateController mKeyguardStateController; 143 @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor; 144 @Mock private DockManager mDockManager; 145 @Mock private ScreenOffAnimationController mScreenOffAnimationController; 146 @Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; 147 @Mock private PrimaryBouncerToGoneTransitionViewModel mPrimaryBouncerToGoneTransitionViewModel; 148 @Mock private AlternateBouncerToGoneTransitionViewModel 149 mAlternateBouncerToGoneTransitionViewModel; 150 private final KeyguardTransitionInteractor mKeyguardTransitionInteractor = 151 mKosmos.getKeyguardTransitionInteractor(); 152 private final FakeKeyguardTransitionRepository mKeyguardTransitionRepository = 153 mKosmos.getKeyguardTransitionRepository(); 154 @Mock private KeyguardInteractor mKeyguardInteractor; 155 private final FakeWallpaperRepository mWallpaperRepository = new FakeWallpaperRepository(); 156 @Mock private TypedArray mMockTypedArray; 157 158 // TODO(b/204991468): Use a real PanelExpansionStateManager object once this bug is fixed. (The 159 // event-dispatch-on-registration pattern caused some of these unit tests to fail.) 160 @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; 161 162 private static class AnimatorListener implements Animator.AnimatorListener { 163 private int mNumStarts; 164 private int mNumEnds; 165 private int mNumCancels; 166 167 @Override onAnimationStart(Animator animation)168 public void onAnimationStart(Animator animation) { 169 mNumStarts++; 170 } 171 172 @Override onAnimationEnd(Animator animation)173 public void onAnimationEnd(Animator animation) { 174 mNumEnds++; 175 } 176 177 @Override onAnimationCancel(Animator animation)178 public void onAnimationCancel(Animator animation) { 179 mNumCancels++; 180 } 181 182 @Override onAnimationRepeat(Animator animation)183 public void onAnimationRepeat(Animator animation) { 184 185 } 186 getNumStarts()187 public int getNumStarts() { 188 return mNumStarts; 189 } 190 getNumEnds()191 public int getNumEnds() { 192 return mNumEnds; 193 } 194 getNumCancels()195 public int getNumCancels() { 196 return mNumCancels; 197 } 198 reset()199 public void reset() { 200 mNumStarts = 0; 201 mNumEnds = 0; 202 mNumCancels = 0; 203 } 204 } 205 206 private AnimatorListener mAnimatorListener = new AnimatorListener(); 207 208 private int mSurfaceColor = 0x112233; 209 finishAnimationsImmediately()210 private void finishAnimationsImmediately() { 211 // Execute code that will trigger animations. 212 mScrimController.onPreDraw(); 213 // Force finish all animations. 214 mLooper.processAllMessages(); 215 endAnimation(mNotificationsScrim); 216 endAnimation(mScrimBehind); 217 endAnimation(mScrimInFront); 218 219 assertEquals("Animators did not finish", 220 mAnimatorListener.getNumStarts(), mAnimatorListener.getNumEnds()); 221 } 222 endAnimation(View scrimView)223 private void endAnimation(View scrimView) { 224 Animator animator = getAnimator(scrimView); 225 if (animator != null) { 226 animator.end(); 227 } 228 } 229 getAnimator(View scrimView)230 private Animator getAnimator(View scrimView) { 231 return (Animator) scrimView.getTag(ScrimController.TAG_KEY_ANIM); 232 } 233 234 @Before setup()235 public void setup() { 236 MockitoAnnotations.initMocks(this); 237 mContext = spy(getContext()); 238 when(mContext.obtainStyledAttributes( 239 new int[]{com.android.internal.R.attr.materialColorSurface})) 240 .thenReturn(mMockTypedArray); 241 242 when(mMockTypedArray.getColorStateList(anyInt())) 243 .thenAnswer((invocation) -> ColorStateList.valueOf(mSurfaceColor)); 244 245 mScrimBehind = spy(new ScrimView(mContext)); 246 mScrimInFront = new ScrimView(mContext); 247 mNotificationsScrim = new ScrimView(mContext); 248 mAlwaysOnEnabled = true; 249 mLooper = TestableLooper.get(this); 250 DejankUtils.setImmediate(true); 251 252 // ScrimController uses mScrimBehind to delay some callbacks that we should run immediately. 253 doAnswer(invocation -> { 254 ((Runnable) invocation.getArgument(0)).run(); 255 return null; 256 }).when(mScrimBehind).postOnAnimationDelayed(any(Runnable.class), anyLong()); 257 258 when(mDozeParameters.getAlwaysOn()).thenAnswer(invocation -> mAlwaysOnEnabled); 259 when(mDozeParameters.getDisplayNeedsBlanking()).thenReturn(true); 260 261 doAnswer((Answer<Void>) invocation -> { 262 mScrimState = invocation.getArgument(0); 263 mScrimBehindAlpha = invocation.getArgument(1); 264 mScrimInFrontColor = invocation.getArgument(2); 265 return null; 266 }).when(mLightBarController).setScrimState( 267 any(ScrimState.class), anyFloat(), any(GradientColors.class)); 268 269 when(mDelayedWakeLockFactory.create(any(String.class))).thenReturn(mWakeLock); 270 when(mDockManager.isDocked()).thenReturn(false); 271 272 when(mPrimaryBouncerToGoneTransitionViewModel.getScrimAlpha()) 273 .thenReturn(emptyFlow()); 274 when(mAlternateBouncerToGoneTransitionViewModel.getScrimAlpha()) 275 .thenReturn(emptyFlow()); 276 277 mScrimController = new ScrimController( 278 mLightBarController, 279 mDozeParameters, 280 mAlarmManager, 281 mKeyguardStateController, 282 mDelayedWakeLockFactory, 283 new FakeHandler(mLooper.getLooper()), 284 mKeyguardUpdateMonitor, 285 mDockManager, 286 mConfigurationController, 287 new FakeExecutor(new FakeSystemClock()), 288 mJavaAdapter, 289 mScreenOffAnimationController, 290 mKeyguardUnlockAnimationController, 291 mStatusBarKeyguardViewManager, 292 mPrimaryBouncerToGoneTransitionViewModel, 293 mAlternateBouncerToGoneTransitionViewModel, 294 mKeyguardTransitionInteractor, 295 mKeyguardInteractor, 296 mWallpaperRepository, 297 mKosmos.getTestDispatcher(), 298 mLinearLargeScreenShadeInterpolator); 299 mScrimController.start(); 300 mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible); 301 mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront); 302 mScrimController.setAnimatorListener(mAnimatorListener); 303 304 // Attach behind scrim so flows that are collecting on it start running. 305 ViewUtils.attachView(mScrimBehind); 306 307 mScrimController.setHasBackdrop(false); 308 309 mWallpaperRepository.getWallpaperSupportsAmbientMode().setValue(false); 310 mTestScope.getTestScheduler().runCurrent(); 311 312 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 313 finishAnimationsImmediately(); 314 } 315 316 @After tearDown()317 public void tearDown() { 318 // Detaching view stops flow collection and prevents memory leak. 319 ViewUtils.detachView(mScrimBehind); 320 finishAnimationsImmediately(); 321 Arrays.stream(ScrimState.values()).forEach((scrim) -> { 322 scrim.setAodFrontScrimAlpha(0f); 323 scrim.setClipQsScrim(false); 324 }); 325 DejankUtils.setImmediate(false); 326 } 327 328 @Test transitionToKeyguard()329 public void transitionToKeyguard() { 330 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 331 finishAnimationsImmediately(); 332 333 assertScrimAlpha(Map.of( 334 mScrimInFront, TRANSPARENT, 335 mScrimBehind, SEMI_TRANSPARENT)); 336 337 assertScrimTinted(Map.of( 338 mScrimInFront, true, 339 mScrimBehind, true 340 )); 341 } 342 343 @Test transitionToShadeLocked()344 public void transitionToShadeLocked() { 345 mScrimController.legacyTransitionTo(SHADE_LOCKED); 346 mScrimController.setQsPosition(1f, 0); 347 finishAnimationsImmediately(); 348 349 assertScrimAlpha(Map.of( 350 mNotificationsScrim, OPAQUE, 351 mScrimInFront, TRANSPARENT, 352 mScrimBehind, OPAQUE)); 353 354 assertScrimTinted(Map.of( 355 mScrimInFront, false, 356 mScrimBehind, true 357 )); 358 } 359 360 @Test transitionToShadeLocked_clippingQs()361 public void transitionToShadeLocked_clippingQs() { 362 mScrimController.setClipsQsScrim(true); 363 mScrimController.legacyTransitionTo(SHADE_LOCKED); 364 mScrimController.setQsPosition(1f, 0); 365 finishAnimationsImmediately(); 366 367 assertScrimAlpha(Map.of( 368 mNotificationsScrim, OPAQUE, 369 mScrimInFront, TRANSPARENT, 370 mScrimBehind, OPAQUE)); 371 372 assertScrimTinted(Map.of( 373 mScrimInFront, false, 374 mScrimBehind, true 375 )); 376 } 377 378 @Test transitionToOff()379 public void transitionToOff() { 380 mScrimController.legacyTransitionTo(ScrimState.OFF); 381 finishAnimationsImmediately(); 382 383 assertScrimAlpha(Map.of( 384 mScrimInFront, OPAQUE, 385 mScrimBehind, OPAQUE)); 386 387 assertScrimTinted(Map.of( 388 mScrimInFront, true, 389 mScrimBehind, true 390 )); 391 392 assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f); 393 } 394 395 @Test transitionToAod_withRegularWallpaper()396 public void transitionToAod_withRegularWallpaper() { 397 mScrimController.legacyTransitionTo(ScrimState.AOD); 398 finishAnimationsImmediately(); 399 400 assertScrimAlpha(Map.of( 401 mScrimInFront, TRANSPARENT, 402 mScrimBehind, TRANSPARENT, 403 mNotificationsScrim, TRANSPARENT)); 404 assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f); 405 406 assertScrimTinted(Map.of( 407 mScrimInFront, true, 408 mScrimBehind, true 409 )); 410 } 411 412 @Test transitionToAod_withAodWallpaper()413 public void transitionToAod_withAodWallpaper() { 414 mWallpaperRepository.getWallpaperSupportsAmbientMode().setValue(true); 415 mTestScope.getTestScheduler().runCurrent(); 416 417 mScrimController.legacyTransitionTo(ScrimState.AOD); 418 finishAnimationsImmediately(); 419 420 assertScrimAlpha(Map.of( 421 mScrimInFront, TRANSPARENT, 422 mScrimBehind, TRANSPARENT)); 423 assertEquals(0f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f); 424 425 // Pulsing notification should conserve AOD wallpaper. 426 mScrimController.legacyTransitionTo(ScrimState.PULSING); 427 finishAnimationsImmediately(); 428 429 assertScrimAlpha(Map.of( 430 mScrimInFront, TRANSPARENT, 431 mScrimBehind, TRANSPARENT)); 432 assertEquals(0f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f); 433 } 434 435 @Test transitionToAod_withAodWallpaperAndLockScreenWallpaper()436 public void transitionToAod_withAodWallpaperAndLockScreenWallpaper() { 437 mScrimController.setHasBackdrop(true); 438 mWallpaperRepository.getWallpaperSupportsAmbientMode().setValue(true); 439 mTestScope.getTestScheduler().runCurrent(); 440 441 mScrimController.legacyTransitionTo(ScrimState.AOD); 442 finishAnimationsImmediately(); 443 444 assertScrimAlpha(Map.of( 445 mScrimInFront, TRANSPARENT, 446 mScrimBehind, TRANSPARENT)); 447 assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f); 448 449 assertScrimTinted(Map.of( 450 mScrimInFront, true, 451 mScrimBehind, true 452 )); 453 } 454 455 @Test setHasBackdrop_withAodWallpaperAndAlbumArt()456 public void setHasBackdrop_withAodWallpaperAndAlbumArt() { 457 mWallpaperRepository.getWallpaperSupportsAmbientMode().setValue(true); 458 mTestScope.getTestScheduler().runCurrent(); 459 460 mScrimController.legacyTransitionTo(ScrimState.AOD); 461 finishAnimationsImmediately(); 462 mScrimController.setHasBackdrop(true); 463 finishAnimationsImmediately(); 464 465 assertScrimAlpha(Map.of( 466 mScrimInFront, TRANSPARENT, 467 mScrimBehind, TRANSPARENT)); 468 assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f); 469 470 assertScrimTinted(Map.of( 471 mScrimInFront, true, 472 mScrimBehind, true 473 )); 474 } 475 476 @Test transitionToAod_withFrontAlphaUpdates()477 public void transitionToAod_withFrontAlphaUpdates() { 478 // Assert that setting the AOD front scrim alpha doesn't take effect in a non-AOD state. 479 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 480 mScrimController.setAodFrontScrimAlpha(0.5f); 481 finishAnimationsImmediately(); 482 483 assertScrimAlpha(Map.of( 484 mScrimInFront, TRANSPARENT, 485 mScrimBehind, SEMI_TRANSPARENT)); 486 487 // ... but that it does take effect once we enter the AOD state. 488 mScrimController.legacyTransitionTo(ScrimState.AOD); 489 finishAnimationsImmediately(); 490 assertScrimAlpha(Map.of( 491 mScrimInFront, SEMI_TRANSPARENT, 492 mScrimBehind, TRANSPARENT)); 493 assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f); 494 495 // ... and that if we set it while we're in AOD, it does take immediate effect. 496 mScrimController.setAodFrontScrimAlpha(1f); 497 assertScrimAlpha(Map.of( 498 mScrimInFront, OPAQUE, 499 mScrimBehind, TRANSPARENT)); 500 assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f); 501 502 // ... and make sure we recall the previous front scrim alpha even if we transition away 503 // for a bit. 504 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED); 505 mScrimController.legacyTransitionTo(ScrimState.AOD); 506 finishAnimationsImmediately(); 507 assertScrimAlpha(Map.of( 508 mScrimInFront, OPAQUE, 509 mScrimBehind, TRANSPARENT)); 510 assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f); 511 512 // ... and alpha updates should be completely ignored if always_on is off. 513 // Passing it forward would mess up the wake-up transition. 514 mAlwaysOnEnabled = false; 515 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED); 516 mScrimController.legacyTransitionTo(ScrimState.AOD); 517 finishAnimationsImmediately(); 518 mScrimController.setAodFrontScrimAlpha(0.3f); 519 assertEquals(ScrimState.AOD.getFrontAlpha(), mScrimInFront.getViewAlpha(), 0.001f); 520 Assert.assertNotEquals(0.3f, mScrimInFront.getViewAlpha(), 0.001f); 521 } 522 523 @Test transitionToAod_afterDocked_ignoresAlwaysOnAndUpdatesFrontAlpha()524 public void transitionToAod_afterDocked_ignoresAlwaysOnAndUpdatesFrontAlpha() { 525 // Assert that setting the AOD front scrim alpha doesn't take effect in a non-AOD state. 526 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 527 mScrimController.setAodFrontScrimAlpha(0.5f); 528 finishAnimationsImmediately(); 529 530 assertScrimAlpha(Map.of( 531 mScrimInFront, TRANSPARENT, 532 mScrimBehind, SEMI_TRANSPARENT)); 533 534 // ... and doesn't take effect when disabled always_on 535 mAlwaysOnEnabled = false; 536 mScrimController.legacyTransitionTo(ScrimState.AOD); 537 finishAnimationsImmediately(); 538 assertScrimAlpha(Map.of( 539 mScrimInFront, OPAQUE, 540 mScrimBehind, TRANSPARENT)); 541 assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f); 542 543 // ... but will take effect after docked 544 when(mDockManager.isDocked()).thenReturn(true); 545 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 546 mScrimController.setAodFrontScrimAlpha(0.5f); 547 mScrimController.legacyTransitionTo(ScrimState.AOD); 548 finishAnimationsImmediately(); 549 550 assertScrimAlpha(Map.of( 551 mScrimInFront, SEMI_TRANSPARENT, 552 mScrimBehind, TRANSPARENT)); 553 assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f); 554 555 // ... and that if we set it while we're in AOD, it does take immediate effect after docked. 556 mScrimController.setAodFrontScrimAlpha(1f); 557 finishAnimationsImmediately(); 558 assertScrimAlpha(Map.of( 559 mScrimInFront, OPAQUE, 560 mScrimBehind, TRANSPARENT)); 561 assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f); 562 563 // Reset value since enums are static. 564 mScrimController.setAodFrontScrimAlpha(0f); 565 } 566 567 @Test transitionToPulsing_withFrontAlphaUpdates()568 public void transitionToPulsing_withFrontAlphaUpdates() { 569 // Pre-condition 570 // Need to go to AoD first because PULSING doesn't change 571 // the back scrim opacity - otherwise it would hide AoD wallpapers. 572 mWallpaperRepository.getWallpaperSupportsAmbientMode().setValue(false); 573 mTestScope.getTestScheduler().runCurrent(); 574 575 mScrimController.legacyTransitionTo(ScrimState.AOD); 576 finishAnimationsImmediately(); 577 assertScrimAlpha(Map.of( 578 mScrimInFront, TRANSPARENT, 579 mScrimBehind, TRANSPARENT)); 580 assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f); 581 582 mScrimController.legacyTransitionTo(ScrimState.PULSING); 583 finishAnimationsImmediately(); 584 // Front scrim should be transparent, but tinted 585 // Back scrim should be semi-transparent so the user can see the wallpaper 586 // Pulse callback should have been invoked 587 assertScrimAlpha(Map.of( 588 mScrimInFront, TRANSPARENT, 589 mScrimBehind, TRANSPARENT)); 590 assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f); 591 592 assertScrimTinted(Map.of( 593 mScrimInFront, true, 594 mScrimBehind, true 595 )); 596 597 // ... and when ambient goes dark, front scrim should be semi-transparent 598 mScrimController.setAodFrontScrimAlpha(0.5f); 599 finishAnimationsImmediately(); 600 // Front scrim should be semi-transparent 601 assertScrimAlpha(Map.of( 602 mScrimInFront, SEMI_TRANSPARENT, 603 mScrimBehind, TRANSPARENT)); 604 assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f); 605 606 mScrimController.setWakeLockScreenSensorActive(true); 607 finishAnimationsImmediately(); 608 assertScrimAlpha(Map.of( 609 mScrimInFront, SEMI_TRANSPARENT, 610 mScrimBehind, TRANSPARENT)); 611 assertEquals(ScrimController.WAKE_SENSOR_SCRIM_ALPHA, 612 mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f); 613 614 // Reset value since enums are static. 615 mScrimController.setAodFrontScrimAlpha(0f); 616 } 617 618 @Test transitionToKeyguardBouncer()619 public void transitionToKeyguardBouncer() { 620 mScrimController.legacyTransitionTo(BOUNCER); 621 finishAnimationsImmediately(); 622 // Front scrim should be transparent 623 // Back scrim should be visible and tinted to the surface color 624 assertScrimAlpha(Map.of( 625 mScrimInFront, TRANSPARENT, 626 mNotificationsScrim, TRANSPARENT, 627 mScrimBehind, OPAQUE)); 628 629 assertScrimTinted(Map.of( 630 mScrimInFront, false, 631 mScrimBehind, true, 632 mNotificationsScrim, false 633 )); 634 635 assertScrimTint(mScrimBehind, mSurfaceColor); 636 } 637 638 @Test lockscreenToHubTransition_setsBehindScrimAlpha()639 public void lockscreenToHubTransition_setsBehindScrimAlpha() { 640 // Start on lockscreen. 641 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 642 finishAnimationsImmediately(); 643 644 // Behind scrim starts at default alpha. 645 final float transitionProgress = 0f; 646 float expectedAlpha = ScrimState.KEYGUARD.getBehindAlpha(); 647 mKeyguardTransitionRepository.sendTransitionStepJava(mKosmos.getTestScope(), 648 new TransitionStep( 649 KeyguardState.LOCKSCREEN, 650 KeyguardState.GLANCEABLE_HUB, 651 transitionProgress, 652 TransitionState.STARTED 653 ), true); 654 mTestScope.getTestScheduler().runCurrent(); 655 assertThat(mScrimBehind.getViewAlpha()).isEqualTo(expectedAlpha); 656 657 // Scrim fades out as transition runs. 658 final float runningProgress = 0.2f; 659 expectedAlpha = (1 - runningProgress) * ScrimState.KEYGUARD.getBehindAlpha(); 660 mKeyguardTransitionRepository.sendTransitionStepJava(mKosmos.getTestScope(), 661 new TransitionStep( 662 KeyguardState.LOCKSCREEN, 663 KeyguardState.GLANCEABLE_HUB, 664 runningProgress, 665 TransitionState.RUNNING 666 ), true); 667 mTestScope.getTestScheduler().runCurrent(); 668 assertThat(mScrimBehind.getViewAlpha()).isEqualTo(expectedAlpha); 669 670 // Scrim invisible at end of transition. 671 final float finishedProgress = 1f; 672 expectedAlpha = 0f; 673 mKeyguardTransitionRepository.sendTransitionStepJava(mKosmos.getTestScope(), 674 new TransitionStep( 675 KeyguardState.LOCKSCREEN, 676 KeyguardState.GLANCEABLE_HUB, 677 finishedProgress, 678 TransitionState.FINISHED 679 ), true); 680 mTestScope.getTestScheduler().runCurrent(); 681 assertThat(mScrimBehind.getViewAlpha()).isEqualTo(expectedAlpha); 682 } 683 684 @Test hubToLockscreenTransition_setsViewAlpha()685 public void hubToLockscreenTransition_setsViewAlpha() { 686 // Start on glanceable hub. 687 mScrimController.legacyTransitionTo(ScrimState.GLANCEABLE_HUB); 688 finishAnimationsImmediately(); 689 690 // Behind scrim starts at 0 alpha. 691 final float transitionProgress = 0f; 692 float expectedAlpha = 0f; 693 mKeyguardTransitionRepository.sendTransitionStepJava(mKosmos.getTestScope(), 694 new TransitionStep( 695 KeyguardState.GLANCEABLE_HUB, 696 KeyguardState.LOCKSCREEN, 697 transitionProgress, 698 TransitionState.STARTED 699 ), true); 700 mTestScope.getTestScheduler().runCurrent(); 701 assertThat(mScrimBehind.getViewAlpha()).isEqualTo(expectedAlpha); 702 703 // Scrim fades in as transition runs. 704 final float runningProgress = 0.2f; 705 expectedAlpha = runningProgress * ScrimState.KEYGUARD.getBehindAlpha(); 706 mKeyguardTransitionRepository.sendTransitionStepJava(mKosmos.getTestScope(), 707 new TransitionStep( 708 KeyguardState.GLANCEABLE_HUB, 709 KeyguardState.LOCKSCREEN, 710 runningProgress, 711 TransitionState.RUNNING 712 ), true); 713 mTestScope.getTestScheduler().runCurrent(); 714 assertThat(mScrimBehind.getViewAlpha()).isEqualTo(expectedAlpha); 715 716 // Scrim at default visibility at end of transition. 717 final float finishedProgress = 1f; 718 expectedAlpha = finishedProgress * ScrimState.KEYGUARD.getBehindAlpha(); 719 mKeyguardTransitionRepository.sendTransitionStepJava(mKosmos.getTestScope(), 720 new TransitionStep( 721 KeyguardState.GLANCEABLE_HUB, 722 KeyguardState.LOCKSCREEN, 723 finishedProgress, 724 TransitionState.FINISHED 725 ), true); 726 mTestScope.getTestScheduler().runCurrent(); 727 assertThat(mScrimBehind.getViewAlpha()).isEqualTo(expectedAlpha); 728 } 729 730 @Test transitionToHub()731 public void transitionToHub() { 732 mScrimController.setRawPanelExpansionFraction(0f); 733 mScrimController.setBouncerHiddenFraction(KeyguardBouncerConstants.EXPANSION_HIDDEN); 734 mScrimController.legacyTransitionTo(ScrimState.GLANCEABLE_HUB); 735 finishAnimationsImmediately(); 736 737 // All scrims transparent on the hub. 738 assertScrimAlpha(Map.of( 739 mScrimInFront, TRANSPARENT, 740 mNotificationsScrim, TRANSPARENT, 741 mScrimBehind, TRANSPARENT)); 742 } 743 744 @Test openBouncerOnHub()745 public void openBouncerOnHub() { 746 mScrimController.legacyTransitionTo(ScrimState.GLANCEABLE_HUB); 747 748 // Open the bouncer. 749 mScrimController.setRawPanelExpansionFraction(0f); 750 when(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(true); 751 mScrimController.setBouncerHiddenFraction(KeyguardBouncerConstants.EXPANSION_VISIBLE); 752 finishAnimationsImmediately(); 753 754 // Only behind scrim is visible. 755 assertScrimAlpha(Map.of( 756 mScrimInFront, TRANSPARENT, 757 mNotificationsScrim, TRANSPARENT, 758 mScrimBehind, OPAQUE)); 759 assertScrimTint(mScrimBehind, mSurfaceColor); 760 761 // Bouncer is closed. 762 mScrimController.setBouncerHiddenFraction(KeyguardBouncerConstants.EXPANSION_HIDDEN); 763 mScrimController.legacyTransitionTo(ScrimState.GLANCEABLE_HUB); 764 finishAnimationsImmediately(); 765 766 // All scrims are transparent. 767 assertScrimAlpha(Map.of( 768 mScrimInFront, TRANSPARENT, 769 mNotificationsScrim, TRANSPARENT, 770 mScrimBehind, TRANSPARENT)); 771 } 772 773 @Test openShadeOnHub()774 public void openShadeOnHub() { 775 mScrimController.legacyTransitionTo(ScrimState.GLANCEABLE_HUB); 776 777 // Open the shade. 778 mScrimController.setQsPosition(1f, 0); 779 mScrimController.setRawPanelExpansionFraction(1); 780 mScrimController.setTransitionToFullShadeProgress(1, 0); 781 finishAnimationsImmediately(); 782 783 // Shade scrims are visible. 784 assertScrimAlpha(Map.of( 785 mNotificationsScrim, OPAQUE, 786 mScrimInFront, TRANSPARENT, 787 mScrimBehind, OPAQUE)); 788 assertScrimTint(mScrimBehind, Color.BLACK); 789 assertScrimTint(mNotificationsScrim, Color.TRANSPARENT); 790 791 mScrimController.setTransitionToFullShadeProgress(0, 0); 792 finishAnimationsImmediately(); 793 794 // All scrims are transparent. 795 assertScrimAlpha(Map.of( 796 mScrimInFront, TRANSPARENT, 797 mNotificationsScrim, TRANSPARENT, 798 mScrimBehind, TRANSPARENT)); 799 } 800 801 @Test transitionToHubOverDream()802 public void transitionToHubOverDream() { 803 mScrimController.setRawPanelExpansionFraction(0f); 804 mScrimController.setBouncerHiddenFraction(KeyguardBouncerConstants.EXPANSION_HIDDEN); 805 mScrimController.legacyTransitionTo(ScrimState.GLANCEABLE_HUB_OVER_DREAM); 806 finishAnimationsImmediately(); 807 808 // All scrims transparent on the hub. 809 assertScrimAlpha(Map.of( 810 mScrimInFront, TRANSPARENT, 811 mNotificationsScrim, TRANSPARENT, 812 mScrimBehind, TRANSPARENT)); 813 } 814 815 @Test openBouncerOnHubOverDream()816 public void openBouncerOnHubOverDream() { 817 mScrimController.legacyTransitionTo(ScrimState.GLANCEABLE_HUB_OVER_DREAM); 818 819 // Open the bouncer. 820 mScrimController.setRawPanelExpansionFraction(0f); 821 when(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(true); 822 mScrimController.setBouncerHiddenFraction(KeyguardBouncerConstants.EXPANSION_VISIBLE); 823 finishAnimationsImmediately(); 824 825 // Only behind scrim is visible. 826 assertScrimAlpha(Map.of( 827 mScrimInFront, TRANSPARENT, 828 mNotificationsScrim, TRANSPARENT, 829 mScrimBehind, OPAQUE)); 830 assertScrimTint(mScrimBehind, mSurfaceColor); 831 832 // Bouncer is closed. 833 mScrimController.setBouncerHiddenFraction(KeyguardBouncerConstants.EXPANSION_HIDDEN); 834 mScrimController.legacyTransitionTo(ScrimState.GLANCEABLE_HUB_OVER_DREAM); 835 finishAnimationsImmediately(); 836 837 // All scrims are transparent. 838 assertScrimAlpha(Map.of( 839 mScrimInFront, TRANSPARENT, 840 mNotificationsScrim, TRANSPARENT, 841 mScrimBehind, TRANSPARENT)); 842 } 843 844 @Test openShadeOnHubOverDream()845 public void openShadeOnHubOverDream() { 846 mScrimController.legacyTransitionTo(ScrimState.GLANCEABLE_HUB_OVER_DREAM); 847 848 // Open the shade. 849 mScrimController.setQsPosition(1f, 0); 850 mScrimController.setRawPanelExpansionFraction(1f); 851 finishAnimationsImmediately(); 852 853 // Shade scrims are visible. 854 assertScrimAlpha(Map.of( 855 mNotificationsScrim, OPAQUE, 856 mScrimInFront, TRANSPARENT, 857 mScrimBehind, OPAQUE)); 858 assertScrimTint(mScrimBehind, Color.BLACK); 859 assertScrimTint(mNotificationsScrim, Color.TRANSPARENT); 860 861 mScrimController.setQsPosition(0f, 0); 862 mScrimController.setRawPanelExpansionFraction(0f); 863 finishAnimationsImmediately(); 864 865 // All scrims are transparent. 866 assertScrimAlpha(Map.of( 867 mScrimInFront, TRANSPARENT, 868 mNotificationsScrim, TRANSPARENT, 869 mScrimBehind, TRANSPARENT)); 870 } 871 872 @Test onThemeChange_bouncerBehindTint_isUpdatedToSurfaceColor()873 public void onThemeChange_bouncerBehindTint_isUpdatedToSurfaceColor() { 874 assertEquals(BOUNCER.getBehindTint(), 0x112233); 875 mSurfaceColor = 0x223344; 876 mConfigurationController.notifyThemeChanged(); 877 assertEquals(BOUNCER.getBehindTint(), 0x223344); 878 } 879 880 @Test onThemeChangeWhileClipQsScrim_bouncerBehindTint_remainsBlack()881 public void onThemeChangeWhileClipQsScrim_bouncerBehindTint_remainsBlack() { 882 mScrimController.setClipsQsScrim(true); 883 mScrimController.legacyTransitionTo(BOUNCER); 884 finishAnimationsImmediately(); 885 886 assertEquals(BOUNCER.getBehindTint(), Color.BLACK); 887 mSurfaceColor = 0x223344; 888 mConfigurationController.notifyThemeChanged(); 889 assertEquals(BOUNCER.getBehindTint(), Color.BLACK); 890 } 891 892 @Test transitionToKeyguardBouncer_clippingQs()893 public void transitionToKeyguardBouncer_clippingQs() { 894 mScrimController.setClipsQsScrim(true); 895 mScrimController.legacyTransitionTo(BOUNCER); 896 finishAnimationsImmediately(); 897 // Front scrim should be transparent 898 // Back scrim should be clipping QS 899 // Notif scrim should be visible without tint 900 assertScrimAlpha(Map.of( 901 mScrimInFront, TRANSPARENT, 902 mNotificationsScrim, OPAQUE, 903 mScrimBehind, OPAQUE)); 904 905 assertScrimTinted(Map.of( 906 mScrimInFront, false, 907 mScrimBehind, true, 908 mNotificationsScrim, false 909 )); 910 } 911 912 @Test disableClipQsScrimWithoutStateTransition_updatesTintAndAlpha()913 public void disableClipQsScrimWithoutStateTransition_updatesTintAndAlpha() { 914 mScrimController.setClipsQsScrim(true); 915 mScrimController.legacyTransitionTo(BOUNCER); 916 917 mScrimController.setClipsQsScrim(false); 918 919 finishAnimationsImmediately(); 920 // Front scrim should be transparent 921 // Back scrim should be visible and has a tint of surfaceColor 922 assertScrimAlpha(Map.of( 923 mScrimInFront, TRANSPARENT, 924 mNotificationsScrim, TRANSPARENT, 925 mScrimBehind, OPAQUE)); 926 assertScrimTinted(Map.of( 927 mScrimInFront, false, 928 mScrimBehind, true, 929 mNotificationsScrim, false 930 )); 931 assertScrimTint(mScrimBehind, mSurfaceColor); 932 } 933 934 @Test enableClipQsScrimWithoutStateTransition_updatesTintAndAlpha()935 public void enableClipQsScrimWithoutStateTransition_updatesTintAndAlpha() { 936 mScrimController.setClipsQsScrim(false); 937 mScrimController.legacyTransitionTo(BOUNCER); 938 939 mScrimController.setClipsQsScrim(true); 940 941 finishAnimationsImmediately(); 942 // Front scrim should be transparent 943 // Back scrim should be clipping QS 944 // Notif scrim should be visible without tint 945 assertScrimAlpha(Map.of( 946 mScrimInFront, TRANSPARENT, 947 mNotificationsScrim, OPAQUE, 948 mScrimBehind, OPAQUE)); 949 assertScrimTinted(Map.of( 950 mScrimInFront, false, 951 mScrimBehind, true, 952 mNotificationsScrim, false 953 )); 954 } 955 956 @Test transitionToBouncer()957 public void transitionToBouncer() { 958 mScrimController.legacyTransitionTo(ScrimState.BOUNCER_SCRIMMED); 959 finishAnimationsImmediately(); 960 assertScrimAlpha(Map.of( 961 mScrimInFront, OPAQUE, 962 mScrimBehind, TRANSPARENT)); 963 assertScrimTinted(Map.of( 964 mScrimInFront, false, 965 mScrimBehind, false 966 )); 967 } 968 969 @Test transitionToUnlocked_clippedQs()970 public void transitionToUnlocked_clippedQs() { 971 mScrimController.setClipsQsScrim(true); 972 mScrimController.setRawPanelExpansionFraction(0f); 973 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED); 974 finishAnimationsImmediately(); 975 976 assertScrimTinted(Map.of( 977 mNotificationsScrim, false, 978 mScrimInFront, false, 979 mScrimBehind, true 980 )); 981 assertScrimAlpha(Map.of( 982 mScrimInFront, TRANSPARENT, 983 mNotificationsScrim, TRANSPARENT, 984 mScrimBehind, OPAQUE)); 985 986 mScrimController.setRawPanelExpansionFraction(0.25f); 987 assertScrimAlpha(Map.of( 988 mScrimInFront, TRANSPARENT, 989 mNotificationsScrim, SEMI_TRANSPARENT, 990 mScrimBehind, OPAQUE)); 991 992 mScrimController.setRawPanelExpansionFraction(0.5f); 993 assertScrimAlpha(Map.of( 994 mScrimInFront, TRANSPARENT, 995 mNotificationsScrim, OPAQUE, 996 mScrimBehind, OPAQUE)); 997 } 998 999 @Test transitionToUnlocked_nonClippedQs_followsLargeScreensInterpolator()1000 public void transitionToUnlocked_nonClippedQs_followsLargeScreensInterpolator() { 1001 mScrimController.setClipsQsScrim(false); 1002 mScrimController.setRawPanelExpansionFraction(0f); 1003 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED); 1004 finishAnimationsImmediately(); 1005 1006 assertScrimTinted(Map.of( 1007 mNotificationsScrim, false, 1008 mScrimInFront, false, 1009 mScrimBehind, true 1010 )); 1011 // The large screens interpolator used in this test is a linear one, just for tests. 1012 // Assertions below are based on this assumption, and that the code uses that interpolator 1013 // when on a large screen (QS not clipped). 1014 assertScrimAlpha(Map.of( 1015 mScrimInFront, TRANSPARENT, 1016 mNotificationsScrim, TRANSPARENT, 1017 mScrimBehind, TRANSPARENT)); 1018 1019 mScrimController.setRawPanelExpansionFraction(0.5f); 1020 assertScrimAlpha(Map.of( 1021 mScrimInFront, TRANSPARENT, 1022 mNotificationsScrim, SEMI_TRANSPARENT, 1023 mScrimBehind, SEMI_TRANSPARENT)); 1024 1025 mScrimController.setRawPanelExpansionFraction(0.99f); 1026 assertScrimAlpha(Map.of( 1027 mScrimInFront, TRANSPARENT, 1028 mNotificationsScrim, SEMI_TRANSPARENT, 1029 mScrimBehind, SEMI_TRANSPARENT)); 1030 1031 mScrimController.setRawPanelExpansionFraction(1f); 1032 assertScrimAlpha(Map.of( 1033 mScrimInFront, TRANSPARENT, 1034 mNotificationsScrim, OPAQUE, 1035 mScrimBehind, OPAQUE)); 1036 } 1037 1038 @Test scrimStateCallback()1039 public void scrimStateCallback() { 1040 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED); 1041 finishAnimationsImmediately(); 1042 assertEquals(mScrimState, ScrimState.UNLOCKED); 1043 1044 mScrimController.legacyTransitionTo(BOUNCER); 1045 finishAnimationsImmediately(); 1046 assertEquals(mScrimState, BOUNCER); 1047 1048 mScrimController.legacyTransitionTo(ScrimState.BOUNCER_SCRIMMED); 1049 finishAnimationsImmediately(); 1050 assertEquals(mScrimState, ScrimState.BOUNCER_SCRIMMED); 1051 } 1052 1053 @Test panelExpansion()1054 public void panelExpansion() { 1055 mScrimController.setRawPanelExpansionFraction(0f); 1056 mScrimController.setRawPanelExpansionFraction(0.5f); 1057 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED); 1058 finishAnimationsImmediately(); 1059 1060 reset(mScrimBehind); 1061 mScrimController.setRawPanelExpansionFraction(0f); 1062 mScrimController.setRawPanelExpansionFraction(1.0f); 1063 finishAnimationsImmediately(); 1064 1065 assertEquals("Scrim alpha should change after setPanelExpansion", 1066 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f); 1067 1068 mScrimController.setRawPanelExpansionFraction(0f); 1069 finishAnimationsImmediately(); 1070 1071 assertEquals("Scrim alpha should change after setPanelExpansion", 1072 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f); 1073 } 1074 1075 @Test qsExpansion()1076 public void qsExpansion() { 1077 reset(mScrimBehind); 1078 mScrimController.setQsPosition(1f, 999 /* value doesn't matter */); 1079 finishAnimationsImmediately(); 1080 1081 assertScrimAlpha(Map.of( 1082 mScrimInFront, TRANSPARENT, 1083 mScrimBehind, OPAQUE, 1084 mNotificationsScrim, OPAQUE)); 1085 } 1086 1087 @Test qsExpansion_clippingQs()1088 public void qsExpansion_clippingQs() { 1089 reset(mScrimBehind); 1090 mScrimController.setClipsQsScrim(true); 1091 mScrimController.setQsPosition(1f, 999 /* value doesn't matter */); 1092 finishAnimationsImmediately(); 1093 1094 assertScrimAlpha(Map.of( 1095 mScrimInFront, TRANSPARENT, 1096 mScrimBehind, OPAQUE, 1097 mNotificationsScrim, OPAQUE)); 1098 } 1099 1100 @Test qsExpansion_half_clippingQs()1101 public void qsExpansion_half_clippingQs() { 1102 reset(mScrimBehind); 1103 mScrimController.setClipsQsScrim(true); 1104 mScrimController.setQsPosition(0.25f, 999 /* value doesn't matter */); 1105 finishAnimationsImmediately(); 1106 1107 assertScrimAlpha(Map.of( 1108 mScrimInFront, TRANSPARENT, 1109 mScrimBehind, OPAQUE, 1110 mNotificationsScrim, SEMI_TRANSPARENT)); 1111 } 1112 1113 @Test panelExpansionAffectsAlpha()1114 public void panelExpansionAffectsAlpha() { 1115 mScrimController.setRawPanelExpansionFraction(0f); 1116 mScrimController.setRawPanelExpansionFraction(0.5f); 1117 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED); 1118 finishAnimationsImmediately(); 1119 1120 final float scrimAlpha = mScrimBehind.getViewAlpha(); 1121 reset(mScrimBehind); 1122 mScrimController.setExpansionAffectsAlpha(false); 1123 mScrimController.setRawPanelExpansionFraction(0.8f); 1124 verifyZeroInteractions(mScrimBehind); 1125 assertEquals("Scrim opacity shouldn't change when setExpansionAffectsAlpha " 1126 + "is false", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f); 1127 1128 mScrimController.setExpansionAffectsAlpha(true); 1129 mScrimController.setRawPanelExpansionFraction(0.1f); 1130 finishAnimationsImmediately(); 1131 Assert.assertNotEquals("Scrim opacity should change when setExpansionAffectsAlpha " 1132 + "is true", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f); 1133 } 1134 1135 @Test transitionToUnlockedFromOff()1136 public void transitionToUnlockedFromOff() { 1137 // Simulate unlock with fingerprint without AOD 1138 mScrimController.legacyTransitionTo(ScrimState.OFF); 1139 mScrimController.setRawPanelExpansionFraction(0f); 1140 finishAnimationsImmediately(); 1141 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED); 1142 1143 finishAnimationsImmediately(); 1144 1145 // All scrims should be transparent at the end of fade transition. 1146 assertScrimAlpha(Map.of( 1147 mScrimInFront, TRANSPARENT, 1148 mScrimBehind, TRANSPARENT)); 1149 1150 // Make sure at the very end of the animation, we're reset to transparent 1151 assertScrimTinted(Map.of( 1152 mScrimInFront, false, 1153 mScrimBehind, true 1154 )); 1155 } 1156 1157 @Test transitionToUnlockedFromAod()1158 public void transitionToUnlockedFromAod() { 1159 // Simulate unlock with fingerprint 1160 mScrimController.legacyTransitionTo(ScrimState.AOD); 1161 mScrimController.setRawPanelExpansionFraction(0f); 1162 finishAnimationsImmediately(); 1163 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED); 1164 1165 finishAnimationsImmediately(); 1166 1167 // All scrims should be transparent at the end of fade transition. 1168 assertScrimAlpha(Map.of( 1169 mScrimInFront, TRANSPARENT, 1170 mScrimBehind, TRANSPARENT)); 1171 1172 // Make sure at the very end of the animation, we're reset to transparent 1173 assertScrimTinted(Map.of( 1174 mScrimInFront, false, 1175 mScrimBehind, true 1176 )); 1177 } 1178 1179 @Test scrimBlanksBeforeLeavingAod()1180 public void scrimBlanksBeforeLeavingAod() { 1181 // Simulate unlock with fingerprint 1182 mScrimController.legacyTransitionTo(ScrimState.AOD); 1183 finishAnimationsImmediately(); 1184 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED, 1185 new ScrimController.Callback() { 1186 @Override 1187 public void onDisplayBlanked() { 1188 // Front scrim should be black in the middle of the transition 1189 Assert.assertTrue("Scrim should be visible during transition. Alpha: " 1190 + mScrimInFront.getViewAlpha(), mScrimInFront.getViewAlpha() > 0); 1191 assertScrimTinted(Map.of( 1192 mScrimInFront, true, 1193 mScrimBehind, true 1194 )); 1195 Assert.assertSame("Scrim should be visible during transition.", 1196 mScrimVisibility, OPAQUE); 1197 } 1198 }); 1199 finishAnimationsImmediately(); 1200 } 1201 1202 @Test scrimBlankCallbackWhenUnlockingFromPulse()1203 public void scrimBlankCallbackWhenUnlockingFromPulse() { 1204 boolean[] blanked = {false}; 1205 // Simulate unlock with fingerprint 1206 mScrimController.legacyTransitionTo(ScrimState.PULSING); 1207 finishAnimationsImmediately(); 1208 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED, 1209 new ScrimController.Callback() { 1210 @Override 1211 public void onDisplayBlanked() { 1212 blanked[0] = true; 1213 } 1214 }); 1215 finishAnimationsImmediately(); 1216 Assert.assertTrue("Scrim should send display blanked callback when unlocking " 1217 + "from pulse.", blanked[0]); 1218 } 1219 1220 @Test blankingNotRequired_leavingAoD()1221 public void blankingNotRequired_leavingAoD() { 1222 // GIVEN display does NOT need blanking 1223 when(mDozeParameters.getDisplayNeedsBlanking()).thenReturn(false); 1224 1225 mScrimController = new ScrimController( 1226 mLightBarController, 1227 mDozeParameters, 1228 mAlarmManager, 1229 mKeyguardStateController, 1230 mDelayedWakeLockFactory, 1231 new FakeHandler(mLooper.getLooper()), 1232 mKeyguardUpdateMonitor, 1233 mDockManager, 1234 mConfigurationController, 1235 new FakeExecutor(new FakeSystemClock()), 1236 mJavaAdapter, 1237 mScreenOffAnimationController, 1238 mKeyguardUnlockAnimationController, 1239 mStatusBarKeyguardViewManager, 1240 mPrimaryBouncerToGoneTransitionViewModel, 1241 mAlternateBouncerToGoneTransitionViewModel, 1242 mKeyguardTransitionInteractor, 1243 mKeyguardInteractor, 1244 mWallpaperRepository, 1245 mKosmos.getTestDispatcher(), 1246 mLinearLargeScreenShadeInterpolator); 1247 mScrimController.start(); 1248 mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible); 1249 mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront); 1250 mScrimController.setAnimatorListener(mAnimatorListener); 1251 mScrimController.setHasBackdrop(false); 1252 mWallpaperRepository.getWallpaperSupportsAmbientMode().setValue(false); 1253 mTestScope.getTestScheduler().runCurrent(); 1254 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 1255 finishAnimationsImmediately(); 1256 1257 // WHEN Simulate unlock with fingerprint 1258 mScrimController.legacyTransitionTo(ScrimState.AOD); 1259 finishAnimationsImmediately(); 1260 1261 // WHEN transitioning to UNLOCKED, onDisplayCallbackBlanked callback called to continue 1262 // the transition but the scrim was not actually blanked 1263 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED, 1264 new ScrimController.Callback() { 1265 @Override 1266 public void onDisplayBlanked() { 1267 // Front scrim should not be black nor opaque 1268 Assert.assertTrue("Scrim should NOT be visible during transition." 1269 + " Alpha: " + mScrimInFront.getViewAlpha(), 1270 mScrimInFront.getViewAlpha() == 0f); 1271 Assert.assertSame("Scrim should not be visible during transition.", 1272 mScrimVisibility, TRANSPARENT); 1273 } 1274 }); 1275 finishAnimationsImmediately(); 1276 } 1277 1278 @Test testScrimCallback()1279 public void testScrimCallback() { 1280 int[] callOrder = {0, 0, 0}; 1281 int[] currentCall = {0}; 1282 mScrimController.legacyTransitionTo(ScrimState.AOD, new ScrimController.Callback() { 1283 @Override 1284 public void onStart() { 1285 callOrder[0] = ++currentCall[0]; 1286 } 1287 1288 @Override 1289 public void onDisplayBlanked() { 1290 callOrder[1] = ++currentCall[0]; 1291 } 1292 1293 @Override 1294 public void onFinished() { 1295 callOrder[2] = ++currentCall[0]; 1296 } 1297 }); 1298 finishAnimationsImmediately(); 1299 assertEquals("onStart called in wrong order", 1, callOrder[0]); 1300 assertEquals("onDisplayBlanked called in wrong order", 2, callOrder[1]); 1301 assertEquals("onFinished called in wrong order", 3, callOrder[2]); 1302 } 1303 1304 @Test testScrimCallbacksWithoutAmbientDisplay()1305 public void testScrimCallbacksWithoutAmbientDisplay() { 1306 mAlwaysOnEnabled = false; 1307 testScrimCallback(); 1308 } 1309 1310 @Test testScrimCallbackCancelled()1311 public void testScrimCallbackCancelled() { 1312 boolean[] cancelledCalled = {false}; 1313 mScrimController.legacyTransitionTo(ScrimState.AOD, new ScrimController.Callback() { 1314 @Override 1315 public void onCancelled() { 1316 cancelledCalled[0] = true; 1317 } 1318 }); 1319 mScrimController.legacyTransitionTo(ScrimState.PULSING); 1320 Assert.assertTrue("onCancelled should have been called", cancelledCalled[0]); 1321 } 1322 1323 @Test testHoldsWakeLock_whenAOD()1324 public void testHoldsWakeLock_whenAOD() { 1325 mScrimController.legacyTransitionTo(ScrimState.AOD); 1326 verify(mWakeLock).acquire(anyString()); 1327 verify(mWakeLock, never()).release(anyString()); 1328 finishAnimationsImmediately(); 1329 verify(mWakeLock).release(anyString()); 1330 } 1331 1332 @Test testDoesNotHoldWakeLock_whenUnlocking()1333 public void testDoesNotHoldWakeLock_whenUnlocking() { 1334 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED); 1335 finishAnimationsImmediately(); 1336 verifyZeroInteractions(mWakeLock); 1337 } 1338 1339 @Test testCallbackInvokedOnSameStateTransition()1340 public void testCallbackInvokedOnSameStateTransition() { 1341 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED); 1342 finishAnimationsImmediately(); 1343 ScrimController.Callback callback = mock(ScrimController.Callback.class); 1344 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED, callback); 1345 verify(callback).onFinished(); 1346 } 1347 1348 @Test testHoldsAodWallpaperAnimationLock()1349 public void testHoldsAodWallpaperAnimationLock() { 1350 // Pre-conditions 1351 mScrimController.legacyTransitionTo(ScrimState.AOD); 1352 finishAnimationsImmediately(); 1353 reset(mWakeLock); 1354 1355 mScrimController.onHideWallpaperTimeout(); 1356 verify(mWakeLock).acquire(anyString()); 1357 verify(mWakeLock, never()).release(anyString()); 1358 finishAnimationsImmediately(); 1359 verify(mWakeLock).release(anyString()); 1360 } 1361 1362 @Test testHoldsPulsingWallpaperAnimationLock()1363 public void testHoldsPulsingWallpaperAnimationLock() { 1364 // Pre-conditions 1365 mScrimController.legacyTransitionTo(ScrimState.PULSING); 1366 finishAnimationsImmediately(); 1367 reset(mWakeLock); 1368 1369 mScrimController.onHideWallpaperTimeout(); 1370 verify(mWakeLock).acquire(anyString()); 1371 verify(mWakeLock, never()).release(anyString()); 1372 finishAnimationsImmediately(); 1373 verify(mWakeLock).release(anyString()); 1374 } 1375 1376 @Test testWillHideAodWallpaper()1377 public void testWillHideAodWallpaper() { 1378 mWallpaperRepository.getWallpaperSupportsAmbientMode().setValue(true); 1379 mTestScope.getTestScheduler().runCurrent(); 1380 1381 mScrimController.legacyTransitionTo(ScrimState.AOD); 1382 verify(mAlarmManager).setExact(anyInt(), anyLong(), any(), any(), any()); 1383 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 1384 verify(mAlarmManager).cancel(any(AlarmManager.OnAlarmListener.class)); 1385 } 1386 1387 @Test testWillHideDockedWallpaper()1388 public void testWillHideDockedWallpaper() { 1389 mAlwaysOnEnabled = false; 1390 when(mDockManager.isDocked()).thenReturn(true); 1391 mWallpaperRepository.getWallpaperSupportsAmbientMode().setValue(true); 1392 mTestScope.getTestScheduler().runCurrent(); 1393 1394 mScrimController.legacyTransitionTo(ScrimState.AOD); 1395 1396 verify(mAlarmManager).setExact(anyInt(), anyLong(), any(), any(), any()); 1397 } 1398 1399 @Test testConservesExpansionOpacityAfterTransition()1400 public void testConservesExpansionOpacityAfterTransition() { 1401 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED); 1402 mScrimController.setRawPanelExpansionFraction(0.5f); 1403 finishAnimationsImmediately(); 1404 1405 final float expandedAlpha = mScrimBehind.getViewAlpha(); 1406 1407 mScrimController.legacyTransitionTo(ScrimState.BRIGHTNESS_MIRROR); 1408 finishAnimationsImmediately(); 1409 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED); 1410 finishAnimationsImmediately(); 1411 1412 assertEquals("Scrim expansion opacity wasn't conserved when transitioning back", 1413 expandedAlpha, mScrimBehind.getViewAlpha(), 0.01f); 1414 } 1415 1416 @Test testCancelsOldAnimationBeforeBlanking()1417 public void testCancelsOldAnimationBeforeBlanking() { 1418 mScrimController.legacyTransitionTo(ScrimState.AOD); 1419 finishAnimationsImmediately(); 1420 // Consume whatever value we had before 1421 mAnimatorListener.reset(); 1422 1423 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 1424 finishAnimationsImmediately(); 1425 Assert.assertTrue("Animators not canceled", mAnimatorListener.getNumCancels() != 0); 1426 } 1427 1428 @Test testScrimsAreNotFocusable()1429 public void testScrimsAreNotFocusable() { 1430 assertFalse("Behind scrim should not be focusable", mScrimBehind.isFocusable()); 1431 assertFalse("Front scrim should not be focusable", mScrimInFront.isFocusable()); 1432 assertFalse("Notifications scrim should not be focusable", 1433 mNotificationsScrim.isFocusable()); 1434 } 1435 1436 @Test testHidesShowWhenLockedActivity()1437 public void testHidesShowWhenLockedActivity() { 1438 mWallpaperRepository.getWallpaperSupportsAmbientMode().setValue(true); 1439 mTestScope.getTestScheduler().runCurrent(); 1440 1441 mScrimController.setKeyguardOccluded(true); 1442 mScrimController.legacyTransitionTo(ScrimState.AOD); 1443 finishAnimationsImmediately(); 1444 assertScrimAlpha(Map.of( 1445 mScrimInFront, TRANSPARENT, 1446 mScrimBehind, OPAQUE)); 1447 1448 mScrimController.legacyTransitionTo(ScrimState.PULSING); 1449 finishAnimationsImmediately(); 1450 assertScrimAlpha(Map.of( 1451 mScrimInFront, TRANSPARENT, 1452 mScrimBehind, OPAQUE)); 1453 } 1454 1455 @Test testHidesShowWhenLockedActivity_whenAlreadyInAod()1456 public void testHidesShowWhenLockedActivity_whenAlreadyInAod() { 1457 mWallpaperRepository.getWallpaperSupportsAmbientMode().setValue(true); 1458 mTestScope.getTestScheduler().runCurrent(); 1459 1460 mScrimController.legacyTransitionTo(ScrimState.AOD); 1461 finishAnimationsImmediately(); 1462 assertScrimAlpha(Map.of( 1463 mScrimInFront, TRANSPARENT, 1464 mScrimBehind, TRANSPARENT)); 1465 1466 mScrimController.setKeyguardOccluded(true); 1467 finishAnimationsImmediately(); 1468 assertScrimAlpha(Map.of( 1469 mScrimInFront, TRANSPARENT, 1470 mScrimBehind, OPAQUE)); 1471 } 1472 1473 @Test testEatsTouchEvent()1474 public void testEatsTouchEvent() { 1475 HashSet<ScrimState> eatsTouches = 1476 new HashSet<>(Collections.singletonList(ScrimState.AOD)); 1477 for (ScrimState state : ScrimState.values()) { 1478 if (state == ScrimState.UNINITIALIZED) { 1479 continue; 1480 } 1481 mScrimController.legacyTransitionTo(state); 1482 finishAnimationsImmediately(); 1483 assertEquals("Should be clickable unless AOD or PULSING, was: " + state, 1484 mScrimBehind.getViewAlpha() != 0 && !eatsTouches.contains(state), 1485 mScrimBehind.isClickable()); 1486 } 1487 } 1488 1489 @Test testAnimatesTransitionToAod()1490 public void testAnimatesTransitionToAod() { 1491 when(mDozeParameters.shouldControlScreenOff()).thenReturn(false); 1492 ScrimState.AOD.prepare(ScrimState.KEYGUARD); 1493 assertFalse("No animation when ColorFade kicks in", 1494 ScrimState.AOD.getAnimateChange()); 1495 1496 reset(mDozeParameters); 1497 when(mDozeParameters.shouldControlScreenOff()).thenReturn(true); 1498 ScrimState.AOD.prepare(ScrimState.KEYGUARD); 1499 Assert.assertTrue("Animate scrims when ColorFade won't be triggered", 1500 ScrimState.AOD.getAnimateChange()); 1501 } 1502 1503 @Test testIsLowPowerMode()1504 public void testIsLowPowerMode() { 1505 HashSet<ScrimState> lowPowerModeStates = new HashSet<>(Arrays.asList( 1506 ScrimState.OFF, ScrimState.AOD, ScrimState.PULSING)); 1507 HashSet<ScrimState> regularStates = new HashSet<>(Arrays.asList( 1508 ScrimState.UNINITIALIZED, ScrimState.KEYGUARD, BOUNCER, 1509 ScrimState.DREAMING, ScrimState.BOUNCER_SCRIMMED, ScrimState.BRIGHTNESS_MIRROR, 1510 ScrimState.UNLOCKED, SHADE_LOCKED, ScrimState.AUTH_SCRIMMED, 1511 ScrimState.AUTH_SCRIMMED_SHADE, ScrimState.GLANCEABLE_HUB, 1512 ScrimState.GLANCEABLE_HUB_OVER_DREAM)); 1513 1514 for (ScrimState state : ScrimState.values()) { 1515 if (!lowPowerModeStates.contains(state) && !regularStates.contains(state)) { 1516 Assert.fail("Scrim state isn't categorized as a low power or regular state."); 1517 } 1518 } 1519 } 1520 1521 @Test testScrimsOpaque_whenShadeFullyExpanded()1522 public void testScrimsOpaque_whenShadeFullyExpanded() { 1523 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED); 1524 mScrimController.setRawPanelExpansionFraction(1); 1525 // notifications scrim alpha change require calling setQsPosition 1526 mScrimController.setQsPosition(0, 300); 1527 finishAnimationsImmediately(); 1528 1529 assertEquals("Behind scrim should be opaque", 1530 mScrimBehind.getViewAlpha(), 1, 0.0); 1531 assertEquals("Notifications scrim should be opaque", 1532 mNotificationsScrim.getViewAlpha(), 1, 0.0); 1533 } 1534 1535 @Test testAuthScrim_setClipQSScrimTrue_notifScrimOpaque_whenShadeFullyExpanded()1536 public void testAuthScrim_setClipQSScrimTrue_notifScrimOpaque_whenShadeFullyExpanded() { 1537 // GIVEN device has an activity showing ('UNLOCKED' state can occur on the lock screen 1538 // with the camera app occluding the keyguard) 1539 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED); 1540 mScrimController.setClipsQsScrim(true); 1541 mScrimController.setRawPanelExpansionFraction(1); 1542 // notifications scrim alpha change require calling setQsPosition 1543 mScrimController.setQsPosition(0, 300); 1544 finishAnimationsImmediately(); 1545 1546 // WHEN the user triggers the auth bouncer 1547 mScrimController.legacyTransitionTo(ScrimState.AUTH_SCRIMMED_SHADE); 1548 finishAnimationsImmediately(); 1549 1550 assertEquals("Behind scrim should be opaque", 1551 mScrimBehind.getViewAlpha(), 1, 0.0); 1552 assertEquals("Notifications scrim should be opaque", 1553 mNotificationsScrim.getViewAlpha(), 1, 0.0); 1554 1555 assertScrimTinted(Map.of( 1556 mScrimInFront, true, 1557 mScrimBehind, true, 1558 mNotificationsScrim, false 1559 )); 1560 } 1561 1562 1563 @Test testAuthScrim_setClipQSScrimFalse_notifScrimOpaque_whenShadeFullyExpanded()1564 public void testAuthScrim_setClipQSScrimFalse_notifScrimOpaque_whenShadeFullyExpanded() { 1565 // GIVEN device has an activity showing ('UNLOCKED' state can occur on the lock screen 1566 // with the camera app occluding the keyguard) 1567 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED); 1568 mScrimController.setClipsQsScrim(false); 1569 mScrimController.setRawPanelExpansionFraction(1); 1570 // notifications scrim alpha change require calling setQsPosition 1571 mScrimController.setQsPosition(0, 300); 1572 finishAnimationsImmediately(); 1573 1574 // WHEN the user triggers the auth bouncer 1575 mScrimController.legacyTransitionTo(ScrimState.AUTH_SCRIMMED_SHADE); 1576 finishAnimationsImmediately(); 1577 1578 assertEquals("Behind scrim should be opaque", 1579 mScrimBehind.getViewAlpha(), 1, 0.0); 1580 assertEquals("Notifications scrim should be opaque", 1581 mNotificationsScrim.getViewAlpha(), 1, 0.0); 1582 1583 assertScrimTinted(Map.of( 1584 mScrimInFront, true, 1585 mScrimBehind, true, 1586 mNotificationsScrim, false 1587 )); 1588 } 1589 1590 @Test testAuthScrimKeyguard()1591 public void testAuthScrimKeyguard() { 1592 // GIVEN device is on the keyguard 1593 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 1594 finishAnimationsImmediately(); 1595 1596 // WHEN the user triggers the auth bouncer 1597 mScrimController.legacyTransitionTo(ScrimState.AUTH_SCRIMMED); 1598 finishAnimationsImmediately(); 1599 1600 // THEN the front scrim is updated and the KEYGUARD scrims are the same as the 1601 // KEYGUARD scrim state 1602 assertScrimAlpha(Map.of( 1603 mScrimInFront, SEMI_TRANSPARENT, 1604 mScrimBehind, SEMI_TRANSPARENT, 1605 mNotificationsScrim, TRANSPARENT)); 1606 } 1607 1608 @Test testScrimsVisible_whenShadeVisible()1609 public void testScrimsVisible_whenShadeVisible() { 1610 mScrimController.setClipsQsScrim(true); 1611 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED); 1612 mScrimController.setRawPanelExpansionFraction(0.3f); 1613 // notifications scrim alpha change require calling setQsPosition 1614 mScrimController.setQsPosition(0, 300); 1615 finishAnimationsImmediately(); 1616 1617 assertScrimAlpha(Map.of( 1618 mScrimBehind, SEMI_TRANSPARENT, 1619 mNotificationsScrim, SEMI_TRANSPARENT, 1620 mScrimInFront, TRANSPARENT)); 1621 } 1622 1623 @Test testDoesntAnimate_whenUnlocking()1624 public void testDoesntAnimate_whenUnlocking() { 1625 // LightRevealScrim will animate the transition, we should only hide the keyguard scrims. 1626 ScrimState.UNLOCKED.prepare(ScrimState.KEYGUARD); 1627 assertThat(ScrimState.UNLOCKED.getAnimateChange()).isTrue(); 1628 ScrimState.UNLOCKED.prepare(ScrimState.PULSING); 1629 assertThat(ScrimState.UNLOCKED.getAnimateChange()).isFalse(); 1630 1631 ScrimState.UNLOCKED.prepare(ScrimState.KEYGUARD); 1632 assertThat(ScrimState.UNLOCKED.getAnimateChange()).isTrue(); 1633 ScrimState.UNLOCKED.prepare(ScrimState.AOD); 1634 assertThat(ScrimState.UNLOCKED.getAnimateChange()).isFalse(); 1635 1636 // LightRevealScrim doesn't animate when AOD is disabled. We need to use the legacy anim. 1637 ScrimState.UNLOCKED.prepare(ScrimState.KEYGUARD); 1638 assertThat(ScrimState.UNLOCKED.getAnimateChange()).isTrue(); 1639 ScrimState.UNLOCKED.prepare(ScrimState.OFF); 1640 assertThat(ScrimState.UNLOCKED.getAnimateChange()).isTrue(); 1641 } 1642 1643 @Test testScrimsVisible_whenShadeVisible_clippingQs()1644 public void testScrimsVisible_whenShadeVisible_clippingQs() { 1645 mScrimController.setClipsQsScrim(true); 1646 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED); 1647 mScrimController.setRawPanelExpansionFraction(0.3f); 1648 // notifications scrim alpha change require calling setQsPosition 1649 mScrimController.setQsPosition(0.5f, 300); 1650 finishAnimationsImmediately(); 1651 1652 assertScrimAlpha(Map.of( 1653 mScrimBehind, OPAQUE, 1654 mNotificationsScrim, SEMI_TRANSPARENT, 1655 mScrimInFront, TRANSPARENT)); 1656 } 1657 1658 @Test testScrimsVisible_whenShadeVisibleOnLockscreen()1659 public void testScrimsVisible_whenShadeVisibleOnLockscreen() { 1660 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 1661 mScrimController.setQsPosition(0.25f, 300); 1662 1663 assertScrimAlpha(Map.of( 1664 mScrimBehind, SEMI_TRANSPARENT, 1665 mNotificationsScrim, SEMI_TRANSPARENT, 1666 mScrimInFront, TRANSPARENT)); 1667 } 1668 1669 @Test testNotificationScrimTransparent_whenOnLockscreen()1670 public void testNotificationScrimTransparent_whenOnLockscreen() { 1671 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 1672 // even if shade is not pulled down, panel has expansion of 1 on the lockscreen 1673 mScrimController.setRawPanelExpansionFraction(1); 1674 mScrimController.setQsPosition(0f, /*qs panel bottom*/ 0); 1675 1676 assertScrimAlpha(Map.of( 1677 mScrimBehind, SEMI_TRANSPARENT, 1678 mNotificationsScrim, TRANSPARENT)); 1679 } 1680 1681 @Test testNotificationScrimVisible_afterOpeningShadeFromLockscreen()1682 public void testNotificationScrimVisible_afterOpeningShadeFromLockscreen() { 1683 mScrimController.setRawPanelExpansionFraction(1); 1684 mScrimController.legacyTransitionTo(SHADE_LOCKED); 1685 finishAnimationsImmediately(); 1686 1687 assertScrimAlpha(Map.of( 1688 mScrimBehind, OPAQUE, 1689 mNotificationsScrim, OPAQUE)); 1690 } 1691 1692 @Test qsExpansion_BehindTint_shadeLocked_bouncerActive_usesBouncerProgress()1693 public void qsExpansion_BehindTint_shadeLocked_bouncerActive_usesBouncerProgress() { 1694 when(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(true); 1695 // clipping doesn't change tested logic but allows to assert scrims more in line with 1696 // their expected large screen behaviour 1697 mScrimController.setClipsQsScrim(false); 1698 mScrimController.legacyTransitionTo(SHADE_LOCKED); 1699 1700 mScrimController.setQsPosition(1f, 100 /* value doesn't matter */); 1701 assertTintAfterExpansion(mScrimBehind, SHADE_LOCKED.getBehindTint(), /* expansion= */ 1f); 1702 1703 mScrimController.setQsPosition(0.8f, 100 /* value doesn't matter */); 1704 // panel expansion of 0.6 means its fully transitioned with bouncer progress interpolation 1705 assertTintAfterExpansion(mScrimBehind, BOUNCER.getBehindTint(), /* expansion= */ 0.6f); 1706 } 1707 1708 @Test expansionNotificationAlpha_shadeLocked_bouncerActive_usesBouncerInterpolator()1709 public void expansionNotificationAlpha_shadeLocked_bouncerActive_usesBouncerInterpolator() { 1710 when(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(true); 1711 1712 mScrimController.legacyTransitionTo(SHADE_LOCKED); 1713 1714 float expansion = 0.8f; 1715 float expectedAlpha = 1716 BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion); 1717 assertAlphaAfterExpansion(mNotificationsScrim, expectedAlpha, expansion); 1718 1719 expansion = 0.2f; 1720 expectedAlpha = BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion); 1721 assertAlphaAfterExpansion(mNotificationsScrim, expectedAlpha, expansion); 1722 } 1723 1724 @Test expansionNotificationAlpha_shadeLocked_bouncerNotActive_usesShadeInterpolator()1725 public void expansionNotificationAlpha_shadeLocked_bouncerNotActive_usesShadeInterpolator() { 1726 when(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(false); 1727 1728 mScrimController.legacyTransitionTo(SHADE_LOCKED); 1729 1730 float expansion = 0.8f; 1731 float expectedAlpha = ShadeInterpolation.getNotificationScrimAlpha(expansion); 1732 assertAlphaAfterExpansion(mNotificationsScrim, expectedAlpha, expansion); 1733 1734 expansion = 0.2f; 1735 expectedAlpha = ShadeInterpolation.getNotificationScrimAlpha(expansion); 1736 assertAlphaAfterExpansion(mNotificationsScrim, expectedAlpha, expansion); 1737 } 1738 1739 @Test notificationAlpha_unnocclusionAnimating_bouncerNotActive_usesKeyguardNotifAlpha()1740 public void notificationAlpha_unnocclusionAnimating_bouncerNotActive_usesKeyguardNotifAlpha() { 1741 when(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(false); 1742 1743 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 1744 1745 assertAlphaAfterExpansion( 1746 mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 0f); 1747 assertAlphaAfterExpansion( 1748 mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 0.4f); 1749 assertAlphaAfterExpansion( 1750 mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 1.0f); 1751 1752 // Verify normal behavior after 1753 float expansion = 0.4f; 1754 float alpha = 1 - ShadeInterpolation.getNotificationScrimAlpha(expansion); 1755 assertAlphaAfterExpansion(mNotificationsScrim, alpha, expansion); 1756 } 1757 1758 @Test notificationAlpha_inKeyguardState_bouncerActive_usesInvertedBouncerInterpolator()1759 public void notificationAlpha_inKeyguardState_bouncerActive_usesInvertedBouncerInterpolator() { 1760 when(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(true); 1761 mScrimController.setClipsQsScrim(true); 1762 1763 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 1764 1765 float expansion = 0.8f; 1766 float alpha = 1 - BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion); 1767 assertAlphaAfterExpansion(mNotificationsScrim, alpha, expansion); 1768 1769 expansion = 0.4f; 1770 alpha = 1 - BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion); 1771 assertAlphaAfterExpansion(mNotificationsScrim, alpha, expansion); 1772 1773 expansion = 0.2f; 1774 alpha = 1 - BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion); 1775 assertAlphaAfterExpansion(mNotificationsScrim, alpha, expansion); 1776 } 1777 1778 @Test notificationAlpha_inKeyguardState_bouncerNotActive_usesInvertedShadeInterpolator()1779 public void notificationAlpha_inKeyguardState_bouncerNotActive_usesInvertedShadeInterpolator() { 1780 when(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(false); 1781 mScrimController.setClipsQsScrim(true); 1782 1783 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 1784 1785 float expansion = 0.8f; 1786 float alpha = 1 - ShadeInterpolation.getNotificationScrimAlpha(expansion); 1787 assertAlphaAfterExpansion(mNotificationsScrim, alpha, expansion); 1788 1789 expansion = 0.4f; 1790 alpha = 1 - ShadeInterpolation.getNotificationScrimAlpha(expansion); 1791 assertAlphaAfterExpansion(mNotificationsScrim, alpha, expansion); 1792 1793 expansion = 0.2f; 1794 alpha = 1 - ShadeInterpolation.getNotificationScrimAlpha(expansion); 1795 assertAlphaAfterExpansion(mNotificationsScrim, alpha, expansion); 1796 } 1797 1798 @Test behindTint_inKeyguardState_bouncerNotActive_usesKeyguardBehindTint()1799 public void behindTint_inKeyguardState_bouncerNotActive_usesKeyguardBehindTint() { 1800 when(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(false); 1801 mScrimController.setClipsQsScrim(false); 1802 1803 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 1804 finishAnimationsImmediately(); 1805 assertThat(mScrimBehind.getTint()) 1806 .isEqualTo(ScrimState.KEYGUARD.getBehindTint()); 1807 } 1808 1809 @Test testNotificationTransparency_followsTransitionToFullShade()1810 public void testNotificationTransparency_followsTransitionToFullShade() { 1811 mScrimController.setClipsQsScrim(true); 1812 1813 mScrimController.legacyTransitionTo(SHADE_LOCKED); 1814 mScrimController.setRawPanelExpansionFraction(1.0f); 1815 finishAnimationsImmediately(); 1816 1817 assertScrimTinted(Map.of( 1818 mScrimInFront, false, 1819 mScrimBehind, true, 1820 mNotificationsScrim, false 1821 )); 1822 1823 float shadeLockedAlpha = mNotificationsScrim.getViewAlpha(); 1824 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 1825 mScrimController.setRawPanelExpansionFraction(1.0f); 1826 finishAnimationsImmediately(); 1827 float keyguardAlpha = mNotificationsScrim.getViewAlpha(); 1828 1829 assertScrimTinted(Map.of( 1830 mScrimInFront, true, 1831 mScrimBehind, true, 1832 mNotificationsScrim, true 1833 )); 1834 1835 float progress = 0.5f; 1836 float lsNotifProgress = 0.3f; 1837 mScrimController.setTransitionToFullShadeProgress(progress, lsNotifProgress); 1838 assertEquals(MathUtils.lerp(keyguardAlpha, shadeLockedAlpha, progress), 1839 mNotificationsScrim.getViewAlpha(), 0.2); 1840 progress = 0.0f; 1841 mScrimController.setTransitionToFullShadeProgress(progress, lsNotifProgress); 1842 assertEquals(MathUtils.lerp(keyguardAlpha, shadeLockedAlpha, progress), 1843 mNotificationsScrim.getViewAlpha(), 0.2); 1844 progress = 1.0f; 1845 mScrimController.setTransitionToFullShadeProgress(progress, lsNotifProgress); 1846 assertEquals(MathUtils.lerp(keyguardAlpha, shadeLockedAlpha, progress), 1847 mNotificationsScrim.getViewAlpha(), 0.2); 1848 } 1849 1850 @Test notificationTransparency_followsNotificationScrimProgress()1851 public void notificationTransparency_followsNotificationScrimProgress() { 1852 mScrimController.legacyTransitionTo(SHADE_LOCKED); 1853 mScrimController.setRawPanelExpansionFraction(1.0f); 1854 finishAnimationsImmediately(); 1855 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 1856 mScrimController.setRawPanelExpansionFraction(1.0f); 1857 finishAnimationsImmediately(); 1858 1859 float progress = 0.5f; 1860 float notifProgress = 0.3f; 1861 mScrimController.setTransitionToFullShadeProgress(progress, notifProgress); 1862 1863 assertThat(mNotificationsScrim.getViewAlpha()).isEqualTo(notifProgress); 1864 } 1865 1866 @Test notificationAlpha_qsNotClipped_alphaMatchesNotificationExpansionProgress()1867 public void notificationAlpha_qsNotClipped_alphaMatchesNotificationExpansionProgress() { 1868 mScrimController.setClipsQsScrim(false); 1869 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 1870 // RawPanelExpansion and QsExpansion are usually used for the notification alpha 1871 // calculation. 1872 // Here we set them to non-zero values explicitly to make sure that in not clipped mode, 1873 // they are not being used even when set. 1874 mScrimController.setRawPanelExpansionFraction(0.5f); 1875 mScrimController.setQsPosition(/* expansionFraction= */ 0.5f, /* qsPanelBottomY= */ 500); 1876 finishAnimationsImmediately(); 1877 1878 float progress = 0.5f; 1879 1880 float notificationExpansionProgress = 0f; 1881 mScrimController.setTransitionToFullShadeProgress(progress, notificationExpansionProgress); 1882 mExpect.that(mNotificationsScrim.getViewAlpha()).isEqualTo(notificationExpansionProgress); 1883 1884 notificationExpansionProgress = 0.25f; 1885 mScrimController.setTransitionToFullShadeProgress(progress, notificationExpansionProgress); 1886 mExpect.that(mNotificationsScrim.getViewAlpha()).isEqualTo(notificationExpansionProgress); 1887 1888 notificationExpansionProgress = 0.5f; 1889 mScrimController.setTransitionToFullShadeProgress(progress, notificationExpansionProgress); 1890 mExpect.that(mNotificationsScrim.getViewAlpha()).isEqualTo(notificationExpansionProgress); 1891 1892 notificationExpansionProgress = 0.75f; 1893 mScrimController.setTransitionToFullShadeProgress(progress, notificationExpansionProgress); 1894 mExpect.that(mNotificationsScrim.getViewAlpha()).isEqualTo(notificationExpansionProgress); 1895 1896 notificationExpansionProgress = 1f; 1897 mScrimController.setTransitionToFullShadeProgress(progress, notificationExpansionProgress); 1898 mExpect.that(mNotificationsScrim.getViewAlpha()).isEqualTo(notificationExpansionProgress); 1899 } 1900 1901 @Test setNotificationsOverScrollAmount_setsTranslationYOnNotificationsScrim()1902 public void setNotificationsOverScrollAmount_setsTranslationYOnNotificationsScrim() { 1903 int overScrollAmount = 10; 1904 1905 mScrimController.setNotificationsOverScrollAmount(overScrollAmount); 1906 1907 assertThat(mNotificationsScrim.getTranslationY()).isEqualTo(overScrollAmount); 1908 } 1909 1910 @Test setNotificationsOverScrollAmount_doesNotSetTranslationYOnBehindScrim()1911 public void setNotificationsOverScrollAmount_doesNotSetTranslationYOnBehindScrim() { 1912 int overScrollAmount = 10; 1913 1914 mScrimController.setNotificationsOverScrollAmount(overScrollAmount); 1915 1916 assertThat(mScrimBehind.getTranslationY()).isEqualTo(0); 1917 } 1918 1919 @Test setNotificationsOverScrollAmount_doesNotSetTranslationYOnFrontScrim()1920 public void setNotificationsOverScrollAmount_doesNotSetTranslationYOnFrontScrim() { 1921 int overScrollAmount = 10; 1922 1923 mScrimController.setNotificationsOverScrollAmount(overScrollAmount); 1924 1925 assertThat(mScrimInFront.getTranslationY()).isEqualTo(0); 1926 } 1927 1928 @Test notificationBoundsTopGetsPassedToKeyguard()1929 public void notificationBoundsTopGetsPassedToKeyguard() { 1930 mScrimController.legacyTransitionTo(SHADE_LOCKED); 1931 mScrimController.setQsPosition(1f, 0); 1932 finishAnimationsImmediately(); 1933 1934 mScrimController.setNotificationsBounds(0f, 100f, 0f, 0f); 1935 verify(mKeyguardInteractor).setTopClippingBounds(eq(100)); 1936 } 1937 1938 @Test notificationBoundsTopDoesNotGetPassedToKeyguardWhenNotifScrimIsNotVisible()1939 public void notificationBoundsTopDoesNotGetPassedToKeyguardWhenNotifScrimIsNotVisible() { 1940 mScrimController.setKeyguardOccluded(true); 1941 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 1942 finishAnimationsImmediately(); 1943 1944 mScrimController.setNotificationsBounds(0f, 100f, 0f, 0f); 1945 verify(mKeyguardInteractor).setTopClippingBounds(eq(null)); 1946 } 1947 1948 @Test transitionToDreaming()1949 public void transitionToDreaming() { 1950 mScrimController.setRawPanelExpansionFraction(0f); 1951 mScrimController.setBouncerHiddenFraction(KeyguardBouncerConstants.EXPANSION_HIDDEN); 1952 mScrimController.legacyTransitionTo(ScrimState.DREAMING); 1953 finishAnimationsImmediately(); 1954 1955 assertScrimAlpha(Map.of( 1956 mScrimInFront, TRANSPARENT, 1957 mNotificationsScrim, TRANSPARENT, 1958 mScrimBehind, TRANSPARENT)); 1959 1960 assertScrimTinted(Map.of( 1961 mScrimInFront, false, 1962 mScrimBehind, true, 1963 mNotificationsScrim, false 1964 )); 1965 } 1966 1967 @Test keyguardGoingAwayUpdateScrims()1968 public void keyguardGoingAwayUpdateScrims() { 1969 when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(true); 1970 mScrimController.updateScrims(); 1971 finishAnimationsImmediately(); 1972 assertThat(mNotificationsScrim.getViewAlpha()).isEqualTo(TRANSPARENT); 1973 } 1974 1975 1976 @Test setUnOccludingAnimationKeyguard()1977 public void setUnOccludingAnimationKeyguard() { 1978 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 1979 finishAnimationsImmediately(); 1980 assertThat(mNotificationsScrim.getViewAlpha()) 1981 .isWithin(0.01f).of(ScrimState.KEYGUARD.getNotifAlpha()); 1982 assertThat(mNotificationsScrim.getTint()) 1983 .isEqualTo(ScrimState.KEYGUARD.getNotifTint()); 1984 assertThat(mScrimBehind.getViewAlpha()) 1985 .isWithin(0.01f).of(ScrimState.KEYGUARD.getBehindAlpha()); 1986 assertThat(mScrimBehind.getTint()) 1987 .isEqualTo(ScrimState.KEYGUARD.getBehindTint()); 1988 } 1989 1990 @Test testHidesScrimFlickerInActivity()1991 public void testHidesScrimFlickerInActivity() { 1992 mScrimController.setKeyguardOccluded(true); 1993 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 1994 finishAnimationsImmediately(); 1995 assertScrimAlpha(Map.of( 1996 mScrimInFront, TRANSPARENT, 1997 mScrimBehind, TRANSPARENT, 1998 mNotificationsScrim, TRANSPARENT)); 1999 2000 mScrimController.legacyTransitionTo(SHADE_LOCKED); 2001 finishAnimationsImmediately(); 2002 assertScrimAlpha(Map.of( 2003 mScrimInFront, TRANSPARENT, 2004 mScrimBehind, TRANSPARENT, 2005 mNotificationsScrim, TRANSPARENT)); 2006 } 2007 2008 @Test notificationAlpha_inKeyguardState_bouncerNotActive_clipsQsScrimFalse()2009 public void notificationAlpha_inKeyguardState_bouncerNotActive_clipsQsScrimFalse() { 2010 mScrimController.setClipsQsScrim(false); 2011 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 2012 2013 float expansion = 0.8f; 2014 assertAlphaAfterExpansion(mNotificationsScrim, 0f, expansion); 2015 } 2016 2017 @Test aodStateSetsFrontScrimToNotBlend()2018 public void aodStateSetsFrontScrimToNotBlend() { 2019 mScrimController.legacyTransitionTo(ScrimState.AOD); 2020 assertFalse("Front scrim should not blend with main color", 2021 mScrimInFront.shouldBlendWithMainColor()); 2022 } 2023 2024 @Test applyState_unlocked_bouncerShowing()2025 public void applyState_unlocked_bouncerShowing() { 2026 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED); 2027 mScrimController.setBouncerHiddenFraction(0.99f); 2028 mScrimController.setRawPanelExpansionFraction(0f); 2029 finishAnimationsImmediately(); 2030 assertScrimAlpha(mScrimBehind, 0); 2031 } 2032 2033 @Test ignoreTransitionRequestWhileKeyguardTransitionRunning()2034 public void ignoreTransitionRequestWhileKeyguardTransitionRunning() { 2035 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED); 2036 mScrimController.mBouncerToGoneTransition.accept( 2037 new TransitionStep(KeyguardState.PRIMARY_BOUNCER, KeyguardState.GONE, 0f, 2038 TransitionState.RUNNING, "ScrimControllerTest")); 2039 2040 // This request should not happen 2041 mScrimController.legacyTransitionTo(ScrimState.BOUNCER); 2042 assertThat(mScrimController.getState()).isEqualTo(ScrimState.UNLOCKED); 2043 } 2044 2045 @Test primaryBouncerToGoneOnFinishCallsKeyguardFadedAway()2046 public void primaryBouncerToGoneOnFinishCallsKeyguardFadedAway() { 2047 when(mKeyguardStateController.isKeyguardFadingAway()).thenReturn(true); 2048 mScrimController.mBouncerToGoneTransition.accept( 2049 new TransitionStep(KeyguardState.PRIMARY_BOUNCER, KeyguardState.GONE, 0f, 2050 TransitionState.FINISHED, "ScrimControllerTest")); 2051 2052 verify(mStatusBarKeyguardViewManager).onKeyguardFadedAway(); 2053 } 2054 2055 @Test testDoNotAnimateChangeIfOccludeAnimationPlaying()2056 public void testDoNotAnimateChangeIfOccludeAnimationPlaying() { 2057 mScrimController.setOccludeAnimationPlaying(true); 2058 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED); 2059 2060 assertFalse(ScrimState.UNLOCKED.mAnimateChange); 2061 } 2062 2063 @Test testNotifScrimAlpha_1f_afterUnlockFinishedAndExpanded()2064 public void testNotifScrimAlpha_1f_afterUnlockFinishedAndExpanded() { 2065 mScrimController.legacyTransitionTo(ScrimState.KEYGUARD); 2066 when(mKeyguardUnlockAnimationController.isPlayingCannedUnlockAnimation()).thenReturn(true); 2067 mScrimController.legacyTransitionTo(ScrimState.UNLOCKED); 2068 mScrimController.onUnlockAnimationFinished(); 2069 assertAlphaAfterExpansion(mNotificationsScrim, 1f, 1f); 2070 } 2071 assertAlphaAfterExpansion(ScrimView scrim, float expectedAlpha, float expansion)2072 private void assertAlphaAfterExpansion(ScrimView scrim, float expectedAlpha, float expansion) { 2073 mScrimController.setRawPanelExpansionFraction(expansion); 2074 finishAnimationsImmediately(); 2075 // alpha is not changing linearly thus 0.2 of leeway when asserting 2076 assertEquals(expectedAlpha, scrim.getViewAlpha(), 0.2); 2077 } 2078 assertTintAfterExpansion(ScrimView scrim, int expectedTint, float expansion)2079 private void assertTintAfterExpansion(ScrimView scrim, int expectedTint, float expansion) { 2080 String message = "Tint test failed with expected scrim tint: " 2081 + Integer.toHexString(expectedTint) + " and actual tint: " 2082 + Integer.toHexString(scrim.getTint()) + " for scrim: " + getScrimName(scrim); 2083 mScrimController.setRawPanelExpansionFraction(expansion); 2084 finishAnimationsImmediately(); 2085 assertEquals(message, expectedTint, scrim.getTint(), 0.1); 2086 } 2087 assertScrimTinted(Map<ScrimView, Boolean> scrimToTint)2088 private void assertScrimTinted(Map<ScrimView, Boolean> scrimToTint) { 2089 scrimToTint.forEach((scrim, hasTint) -> assertScrimTint(scrim, hasTint)); 2090 } 2091 assertScrimTint(ScrimView scrim, boolean hasTint)2092 private void assertScrimTint(ScrimView scrim, boolean hasTint) { 2093 String message = "Tint test failed at state " + mScrimController.getState() 2094 + " with scrim: " + getScrimName(scrim) + " and tint: " 2095 + Integer.toHexString(scrim.getTint()); 2096 assertEquals(message, hasTint, scrim.getTint() != Color.TRANSPARENT); 2097 } 2098 assertScrimTint(ScrimView scrim, int expectedTint)2099 private void assertScrimTint(ScrimView scrim, int expectedTint) { 2100 String message = "Tint test failed with expected scrim tint: " 2101 + Integer.toHexString(expectedTint) + " and actual tint: " 2102 + Integer.toHexString(scrim.getTint()) + " for scrim: " + getScrimName(scrim); 2103 assertEquals(message, expectedTint, scrim.getTint(), 0.1); 2104 } 2105 getScrimName(ScrimView scrim)2106 private String getScrimName(ScrimView scrim) { 2107 if (scrim == mScrimInFront) { 2108 return "front"; 2109 } else if (scrim == mScrimBehind) { 2110 return "behind"; 2111 } else if (scrim == mNotificationsScrim) { 2112 return "notifications"; 2113 } 2114 return "unknown_scrim"; 2115 } 2116 2117 /** 2118 * If {@link #mNotificationsScrim} is not passed in the map 2119 * we assume it must be transparent 2120 */ assertScrimAlpha(Map<ScrimView, Integer> scrimToAlpha)2121 private void assertScrimAlpha(Map<ScrimView, Integer> scrimToAlpha) { 2122 // Check single scrim visibility. 2123 if (!scrimToAlpha.containsKey(mNotificationsScrim)) { 2124 assertScrimAlpha(mNotificationsScrim, TRANSPARENT); 2125 } 2126 scrimToAlpha.forEach((scrimView, alpha) -> assertScrimAlpha(scrimView, alpha)); 2127 2128 // When clipping, QS scrim should not affect combined visibility. 2129 if (mScrimController.getClipQsScrim() && scrimToAlpha.get(mScrimBehind) == OPAQUE) { 2130 scrimToAlpha = new HashMap<>(scrimToAlpha); 2131 scrimToAlpha.remove(mScrimBehind); 2132 } 2133 2134 // Check combined scrim visibility. 2135 final int visibility; 2136 if (scrimToAlpha.values().contains(OPAQUE)) { 2137 visibility = OPAQUE; 2138 } else if (scrimToAlpha.values().contains(SEMI_TRANSPARENT)) { 2139 visibility = SEMI_TRANSPARENT; 2140 } else { 2141 visibility = TRANSPARENT; 2142 } 2143 assertEquals("Invalid visibility.", 2144 visibility /* expected */, 2145 mScrimVisibility); 2146 } 2147 assertScrimAlpha(ScrimView scrim, int expectedAlpha)2148 private void assertScrimAlpha(ScrimView scrim, int expectedAlpha) { 2149 assertEquals("Unexpected " + getScrimName(scrim) + " scrim alpha: " 2150 + scrim.getViewAlpha(), 2151 expectedAlpha != TRANSPARENT /* expected */, 2152 scrim.getViewAlpha() > TRANSPARENT /* actual */); 2153 } 2154 } 2155