From bde48202e7bb1ffa04acd5c42a332c62b73f34d8 Mon Sep 17 00:00:00 2001 From: Lyn Han Date: Wed, 29 May 2019 19:18:29 -0700 Subject: [PATCH] New scrim behind bubble stack Top to bottom 1. [Scrim in front] 2. Status bar 3. [Scrim behind] (moved above bubble stack) 4. Bubble stack 5. [Bubble scrim] (new) Fixes: 130237686 Test: atest SystemUITests Test: manual: expand stack (see bubble scrim), then pull down shade (see scrim behind status bar) Change-Id: I2f39f41c524af2134c383c3e12dd193cbc487d93 --- .../SystemUI/res/layout/super_status_bar.xml | 10 +- .../com/android/systemui/SystemUIFactory.java | 3 +- .../systemui/bubbles/BubbleController.java | 7 +- .../systemui/statusbar/phone/LockIcon.java | 2 +- .../statusbar/phone/ScrimController.java | 208 ++++++++----- .../systemui/statusbar/phone/ScrimState.java | 121 +++++--- .../systemui/statusbar/phone/StatusBar.java | 6 +- .../phone/StatusBarWindowController.java | 4 +- .../statusbar/phone/ScrimControllerTest.java | 284 ++++++++++++------ 9 files changed, 428 insertions(+), 217 deletions(-) diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml index a91493003bb54..9716a00a7f72f 100644 --- a/packages/SystemUI/res/layout/super_status_bar.xml +++ b/packages/SystemUI/res/layout/super_status_bar.xml @@ -44,7 +44,7 @@ + + scrimStateListener, Consumer scrimVisibleListener, DozeParameters dozeParameters, AlarmManager alarmManager) { - return new ScrimController(scrimBehind, scrimInFront, scrimStateListener, + return new ScrimController(scrimBehind, scrimInFront, scrimForBubble, scrimStateListener, scrimVisibleListener, dozeParameters, alarmManager); } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index a23c99ef01fee..1fc5c39ff0fa0 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -271,10 +271,9 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (mStackView == null) { mStackView = new BubbleStackView(mContext, mBubbleData, mSurfaceSynchronizer); ViewGroup sbv = mStatusBarWindowController.getStatusBarView(); - // TODO(b/130237686): When you expand the shade on top of expanded bubble, there is no - // scrim between bubble and the shade - int bubblePosition = sbv.indexOfChild(sbv.findViewById(R.id.scrim_behind)) + 1; - sbv.addView(mStackView, bubblePosition, + int bubbleScrimIndex = sbv.indexOfChild(sbv.findViewById(R.id.scrim_for_bubble)); + int stackIndex = bubbleScrimIndex + 1; // Show stack above bubble scrim. + sbv.addView(mStackView, stackIndex, new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)); if (mExpandListener != null) { mStackView.setExpandListener(mExpandListener); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java index 3143971241d83..b742a3762a7df 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java @@ -539,7 +539,7 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange */ public void onScrimVisibilityChanged(@ScrimVisibility int scrimsVisible) { if (mWakeAndUnlockRunning - && scrimsVisible == ScrimController.VISIBILITY_FULLY_TRANSPARENT) { + && scrimsVisible == ScrimController.TRANSPARENT) { mWakeAndUnlockRunning = false; update(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 5dcbea22eea1b..9971c90ac82e5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -78,23 +78,24 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo /** * When both scrims have 0 alpha. */ - public static final int VISIBILITY_FULLY_TRANSPARENT = 0; + public static final int TRANSPARENT = 0; /** * When scrims aren't transparent (alpha 0) but also not opaque (alpha 1.) */ - public static final int VISIBILITY_SEMI_TRANSPARENT = 1; + public static final int SEMI_TRANSPARENT = 1; /** * When at least 1 scrim is fully opaque (alpha set to 1.) */ - public static final int VISIBILITY_FULLY_OPAQUE = 2; + public static final int OPAQUE = 2; - @IntDef(prefix = { "VISIBILITY_" }, value = { - VISIBILITY_FULLY_TRANSPARENT, - VISIBILITY_SEMI_TRANSPARENT, - VISIBILITY_FULLY_OPAQUE + @IntDef(prefix = {"VISIBILITY_"}, value = { + TRANSPARENT, + SEMI_TRANSPARENT, + OPAQUE }) @Retention(RetentionPolicy.SOURCE) - public @interface ScrimVisibility {} + public @interface ScrimVisibility { + } /** * Default alpha value for most scrims. @@ -122,8 +123,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo private ScrimState mState = ScrimState.UNINITIALIZED; private final Context mContext; - protected final ScrimView mScrimBehind; + protected final ScrimView mScrimInFront; + protected final ScrimView mScrimBehind; + protected final ScrimView mScrimForBubble; + private final UnlockMethodCache mUnlockMethodCache; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; private final DozeParameters mDozeParameters; @@ -152,10 +156,15 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo private Runnable mOnAnimationFinished; private boolean mDeferFinishedListener; private final Interpolator mInterpolator = new DecelerateInterpolator(); - private float mCurrentInFrontAlpha = NOT_INITIALIZED; - private float mCurrentBehindAlpha = NOT_INITIALIZED; - private int mCurrentInFrontTint; - private int mCurrentBehindTint; + + private float mInFrontAlpha = NOT_INITIALIZED; + private float mBehindAlpha = NOT_INITIALIZED; + private float mBubbleAlpha = NOT_INITIALIZED; + + private int mInFrontTint; + private int mBehindTint; + private int mBubbleTint; + private boolean mWallpaperVisibilityTimedOut; private int mScrimsVisibility; private final TriConsumer mScrimStateListener; @@ -174,14 +183,18 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo private boolean mWakeLockHeld; private boolean mKeyguardOccluded; - public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront, + public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront, ScrimView scrimForBubble, TriConsumer scrimStateListener, Consumer scrimVisibleListener, DozeParameters dozeParameters, AlarmManager alarmManager) { + mScrimBehind = scrimBehind; mScrimInFront = scrimInFront; + mScrimForBubble = scrimForBubble; + mScrimStateListener = scrimStateListener; mScrimVisibleListener = scrimVisibleListener; + mContext = scrimBehind.getContext(); mUnlockMethodCache = UnlockMethodCache.getInstance(mContext); mDarkenWhileDragging = !mUnlockMethodCache.canSkipBouncer(); @@ -205,12 +218,13 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo final ScrimState[] states = ScrimState.values(); for (int i = 0; i < states.length; i++) { - states[i].init(mScrimInFront, mScrimBehind, mDozeParameters); + states[i].init(mScrimInFront, mScrimBehind, mScrimForBubble, mDozeParameters); states[i].setScrimBehindAlphaKeyguard(mScrimBehindAlphaKeyguard); } mScrimBehind.setDefaultFocusHighlightEnabled(false); mScrimInFront.setDefaultFocusHighlightEnabled(false); + mScrimForBubble.setDefaultFocusHighlightEnabled(false); updateScrims(); } @@ -249,10 +263,14 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo mBlankScreen = state.getBlanksScreen(); mAnimateChange = state.getAnimateChange(); mAnimationDuration = state.getAnimationDuration(); - mCurrentInFrontTint = state.getFrontTint(); - mCurrentBehindTint = state.getBehindTint(); - mCurrentInFrontAlpha = state.getFrontAlpha(); - mCurrentBehindAlpha = state.getBehindAlpha(); + + mInFrontTint = state.getFrontTint(); + mBehindTint = state.getBehindTint(); + mBubbleTint = state.getBubbleTint(); + + mInFrontAlpha = state.getFrontAlpha(); + mBehindAlpha = state.getBehindAlpha(); + mBubbleAlpha = state.getBubbleAlpha(); applyExpansionToAlpha(); // Scrim might acquire focus when user is navigating with a D-pad or a keyboard. @@ -371,31 +389,29 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo if (mExpansionFraction != fraction) { mExpansionFraction = fraction; - final boolean keyguardOrUnlocked = mState == ScrimState.UNLOCKED - || mState == ScrimState.KEYGUARD || mState == ScrimState.PULSING; - if (!keyguardOrUnlocked || !mExpansionAffectsAlpha) { + boolean relevantState = (mState == ScrimState.UNLOCKED + || mState == ScrimState.KEYGUARD + || mState == ScrimState.PULSING + || mState == ScrimState.BUBBLE_EXPANDED); + if (!(relevantState && mExpansionAffectsAlpha)) { return; } - applyExpansionToAlpha(); - if (mUpdatePending) { return; } - setOrAdaptCurrentAnimation(mScrimBehind); setOrAdaptCurrentAnimation(mScrimInFront); - + setOrAdaptCurrentAnimation(mScrimForBubble); dispatchScrimState(mScrimBehind.getViewAlpha()); } } private void setOrAdaptCurrentAnimation(View scrim) { - if (!isAnimating(scrim)) { - updateScrimColor(scrim, getCurrentScrimAlpha(scrim), getCurrentScrimTint(scrim)); - } else { + float alpha = getCurrentScrimAlpha(scrim); + if (isAnimating(scrim)) { + // Adapt current animation. ValueAnimator previousAnimator = (ValueAnimator) scrim.getTag(TAG_KEY_ANIM); - float alpha = getCurrentScrimAlpha(scrim); float previousEndValue = (Float) scrim.getTag(TAG_END_ALPHA); float previousStartValue = (Float) scrim.getTag(TAG_START_ALPHA); float relativeDiff = alpha - previousEndValue; @@ -403,6 +419,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo scrim.setTag(TAG_START_ALPHA, newStartValue); scrim.setTag(TAG_END_ALPHA, alpha); previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime()); + } else { + // Set animation. + updateScrimColor(scrim, alpha, getCurrentScrimTint(scrim)); } } @@ -411,27 +430,27 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo return; } - if (mState == ScrimState.UNLOCKED) { + if (mState == ScrimState.UNLOCKED || mState == ScrimState.BUBBLE_EXPANDED) { // Darken scrim as you pull down the shade when unlocked float behindFraction = getInterpolatedFraction(); behindFraction = (float) Math.pow(behindFraction, 0.8f); - mCurrentBehindAlpha = behindFraction * GRADIENT_SCRIM_ALPHA_BUSY; - mCurrentInFrontAlpha = 0; + mBehindAlpha = behindFraction * GRADIENT_SCRIM_ALPHA_BUSY; + mInFrontAlpha = 0; } else if (mState == ScrimState.KEYGUARD || mState == ScrimState.PULSING) { // Either darken of make the scrim transparent when you // pull down the shade float interpolatedFract = getInterpolatedFraction(); float alphaBehind = mState.getBehindAlpha(); if (mDarkenWhileDragging) { - mCurrentBehindAlpha = MathUtils.lerp(GRADIENT_SCRIM_ALPHA_BUSY, alphaBehind, + mBehindAlpha = MathUtils.lerp(GRADIENT_SCRIM_ALPHA_BUSY, alphaBehind, interpolatedFract); - mCurrentInFrontAlpha = 0; + mInFrontAlpha = 0; } else { - mCurrentBehindAlpha = MathUtils.lerp(0 /* start */, alphaBehind, + mBehindAlpha = MathUtils.lerp(0 /* start */, alphaBehind, interpolatedFract); - mCurrentInFrontAlpha = 0; + mInFrontAlpha = 0; } - mCurrentBehindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(), + mBehindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(), mState.getBehindTint(), interpolatedFract); } } @@ -456,8 +475,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo */ public void setAodFrontScrimAlpha(float alpha) { if (mState == ScrimState.AOD && mDozeParameters.getAlwaysOn() - && mCurrentInFrontAlpha != alpha) { - mCurrentInFrontAlpha = alpha; + && mInFrontAlpha != alpha) { + mInFrontAlpha = alpha; updateScrims(); } @@ -474,8 +493,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo if (mState == ScrimState.PULSING) { float newBehindAlpha = mState.getBehindAlpha(); - if (mCurrentBehindAlpha != newBehindAlpha) { - mCurrentBehindAlpha = newBehindAlpha; + if (mBehindAlpha != newBehindAlpha) { + mBehindAlpha = newBehindAlpha; updateScrims(); } } @@ -497,8 +516,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo // Only animate scrim color if the scrim view is actually visible boolean animateScrimInFront = mScrimInFront.getViewAlpha() != 0 && !mBlankScreen; boolean animateScrimBehind = mScrimBehind.getViewAlpha() != 0 && !mBlankScreen; + boolean animateScrimForBubble = mScrimForBubble.getViewAlpha() != 0 && !mBlankScreen; + mScrimInFront.setColors(mColors, animateScrimInFront); mScrimBehind.setColors(mColors, animateScrimBehind); + mScrimForBubble.setColors(mColors, animateScrimForBubble); // Calculate minimum scrim opacity for white or black text. int textColor = mColors.supportsDarkText() ? Color.BLACK : Color.WHITE; @@ -517,12 +539,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo boolean occludedKeyguard = (mState == ScrimState.PULSING || mState == ScrimState.AOD) && mKeyguardOccluded; if (aodWallpaperTimeout || occludedKeyguard) { - mCurrentBehindAlpha = 1; + mBehindAlpha = 1; } - - setScrimInFrontAlpha(mCurrentInFrontAlpha); - setScrimBehindAlpha(mCurrentBehindAlpha); - + setScrimAlpha(mScrimInFront, mInFrontAlpha); + setScrimAlpha(mScrimBehind, mBehindAlpha); + setScrimAlpha(mScrimForBubble, mBubbleAlpha); dispatchScrimsVisible(); } @@ -533,11 +554,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo private void dispatchScrimsVisible() { final int currentScrimVisibility; if (mScrimInFront.getViewAlpha() == 1 || mScrimBehind.getViewAlpha() == 1) { - currentScrimVisibility = VISIBILITY_FULLY_OPAQUE; + currentScrimVisibility = OPAQUE; } else if (mScrimInFront.getViewAlpha() == 0 && mScrimBehind.getViewAlpha() == 0) { - currentScrimVisibility = VISIBILITY_FULLY_TRANSPARENT; + currentScrimVisibility = TRANSPARENT; } else { - currentScrimVisibility = VISIBILITY_SEMI_TRANSPARENT; + currentScrimVisibility = SEMI_TRANSPARENT; } if (mScrimsVisibility != currentScrimVisibility) { @@ -554,18 +575,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo return 0; } else { // woo, special effects - return (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f)))); + return (float) (1f - 0.5f * (1f - Math.cos(3.14159f * Math.pow(1f - frac, 2f)))); } } - private void setScrimBehindAlpha(float alpha) { - setScrimAlpha(mScrimBehind, alpha); - } - - private void setScrimInFrontAlpha(float alpha) { - setScrimAlpha(mScrimInFront, alpha); - } - private void setScrimAlpha(ScrimView scrim, float alpha) { if (alpha == 0f) { scrim.setClickable(false); @@ -576,17 +589,26 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo updateScrim(scrim, alpha); } + private String getScrimName(ScrimView scrim) { + if (scrim == mScrimInFront) { + return "front_scrim"; + } else if (scrim == mScrimBehind) { + return "back_scrim"; + } else if (scrim == mScrimForBubble) { + return "bubble_scrim"; + } + return "unknown_scrim"; + } + private void updateScrimColor(View scrim, float alpha, int tint) { alpha = Math.max(0, Math.min(1.0f, alpha)); if (scrim instanceof ScrimView) { ScrimView scrimView = (ScrimView) scrim; - Trace.traceCounter(Trace.TRACE_TAG_APP, - scrim == mScrimInFront ? "front_scrim_alpha" : "back_scrim_alpha", + Trace.traceCounter(Trace.TRACE_TAG_APP, getScrimName(scrimView) + "_alpha", (int) (alpha * 255)); - Trace.traceCounter(Trace.TRACE_TAG_APP, - scrim == mScrimInFront ? "front_scrim_tint" : "back_scrim_tint", + Trace.traceCounter(Trace.TRACE_TAG_APP, getScrimName(scrimView) + "_tint", Color.alpha(tint)); scrimView.setTint(tint); @@ -643,9 +665,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo private float getCurrentScrimAlpha(View scrim) { if (scrim == mScrimInFront) { - return mCurrentInFrontAlpha; + return mInFrontAlpha; } else if (scrim == mScrimBehind) { - return mCurrentBehindAlpha; + return mBehindAlpha; + } else if (scrim == mScrimForBubble) { + return mBubbleAlpha; } else { throw new IllegalArgumentException("Unknown scrim view"); } @@ -653,9 +677,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo private int getCurrentScrimTint(View scrim) { if (scrim == mScrimInFront) { - return mCurrentInFrontTint; + return mInFrontTint; } else if (scrim == mScrimBehind) { - return mCurrentBehindTint; + return mBehindTint; + } else if (scrim == mScrimForBubble) { + return mBubbleTint; } else { throw new IllegalArgumentException("Unknown scrim view"); } @@ -698,8 +724,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo // When unlocking with fingerprint, we'll fade the scrims from black to transparent. // At the end of the animation we need to remove the tint. if (mState == ScrimState.UNLOCKED) { - mCurrentInFrontTint = Color.TRANSPARENT; - mCurrentBehindTint = Color.TRANSPARENT; + mInFrontTint = Color.TRANSPARENT; + mBehindTint = Color.TRANSPARENT; + mBubbleTint = Color.TRANSPARENT; } } @@ -804,6 +831,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo /** * Executes a callback after the frame has hit the display. + * * @param callback What to run. */ @VisibleForTesting @@ -847,16 +875,35 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println(" ScrimController: "); - pw.print(" state: "); pw.println(mState); - pw.print(" frontScrim:"); pw.print(" viewAlpha="); pw.print(mScrimInFront.getViewAlpha()); - pw.print(" alpha="); pw.print(mCurrentInFrontAlpha); - pw.print(" tint=0x"); pw.println(Integer.toHexString(mScrimInFront.getTint())); + pw.print(" state: "); + pw.println(mState); - pw.print(" backScrim:"); pw.print(" viewAlpha="); pw.print(mScrimBehind.getViewAlpha()); - pw.print(" alpha="); pw.print(mCurrentBehindAlpha); - pw.print(" tint=0x"); pw.println(Integer.toHexString(mScrimBehind.getTint())); + pw.print(" frontScrim:"); + pw.print(" viewAlpha="); + pw.print(mScrimInFront.getViewAlpha()); + pw.print(" alpha="); + pw.print(mInFrontAlpha); + pw.print(" tint=0x"); + pw.println(Integer.toHexString(mScrimInFront.getTint())); - pw.print(" mTracking="); pw.println(mTracking); + pw.print(" backScrim:"); + pw.print(" viewAlpha="); + pw.print(mScrimBehind.getViewAlpha()); + pw.print(" alpha="); + pw.print(mBehindAlpha); + pw.print(" tint=0x"); + pw.println(Integer.toHexString(mScrimBehind.getTint())); + + pw.print(" bubbleScrim:"); + pw.print(" viewAlpha="); + pw.print(mScrimForBubble.getViewAlpha()); + pw.print(" alpha="); + pw.print(mBubbleAlpha); + pw.print(" tint=0x"); + pw.println(Integer.toHexString(mScrimForBubble.getTint())); + + pw.print(" mTracking="); + pw.println(mTracking); } public void setWallpaperSupportsAmbientMode(boolean wallpaperSupportsAmbientMode) { @@ -903,8 +950,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo // in this case, back-scrim needs to be re-evaluated if (mState == ScrimState.AOD || mState == ScrimState.PULSING) { float newBehindAlpha = mState.getBehindAlpha(); - if (mCurrentBehindAlpha != newBehindAlpha) { - mCurrentBehindAlpha = newBehindAlpha; + if (mBehindAlpha != newBehindAlpha) { + mBehindAlpha = newBehindAlpha; updateScrims(); } } @@ -919,10 +966,13 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo public interface Callback { default void onStart() { } + default void onDisplayBlanked() { } + default void onFinished() { } + default void onCancelled() { } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java index d152ecd8b9300..4d374dc2dc92f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java @@ -36,7 +36,6 @@ public enum ScrimState { * On the lock screen. */ KEYGUARD(0) { - @Override public void prepare(ScrimState previousState) { mBlankScreen = false; @@ -53,10 +52,13 @@ public enum ScrimState { } else { mAnimationDuration = ScrimController.ANIMATION_DURATION; } - mCurrentInFrontTint = Color.BLACK; - mCurrentBehindTint = Color.BLACK; - mCurrentBehindAlpha = mScrimBehindAlphaKeyguard; - mCurrentInFrontAlpha = 0; + mFrontTint = Color.BLACK; + mBehindTint = Color.BLACK; + mBubbleTint = Color.TRANSPARENT; + + mFrontAlpha = 0; + mBehindAlpha = mScrimBehindAlphaKeyguard; + mBubbleAlpha = 0; } }, @@ -66,8 +68,9 @@ public enum ScrimState { BOUNCER(1) { @Override public void prepare(ScrimState previousState) { - mCurrentBehindAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY; - mCurrentInFrontAlpha = 0f; + mBehindAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY; + mFrontAlpha = 0f; + mBubbleAlpha = 0f; } }, @@ -77,8 +80,9 @@ public enum ScrimState { BOUNCER_SCRIMMED(2) { @Override public void prepare(ScrimState previousState) { - mCurrentBehindAlpha = 0; - mCurrentInFrontAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY; + mBehindAlpha = 0; + mBubbleAlpha = 0f; + mFrontAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY; } }, @@ -88,8 +92,9 @@ public enum ScrimState { BRIGHTNESS_MIRROR(3) { @Override public void prepare(ScrimState previousState) { - mCurrentBehindAlpha = 0; - mCurrentInFrontAlpha = 0; + mBehindAlpha = 0; + mFrontAlpha = 0; + mBubbleAlpha = 0; } }, @@ -101,9 +106,16 @@ public enum ScrimState { public void prepare(ScrimState previousState) { final boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn(); mBlankScreen = mDisplayRequiresBlanking; - mCurrentInFrontAlpha = alwaysOnEnabled ? mAodFrontScrimAlpha : 1f; - mCurrentInFrontTint = Color.BLACK; - mCurrentBehindTint = Color.BLACK; + + mFrontTint = Color.BLACK; + mFrontAlpha = alwaysOnEnabled ? mAodFrontScrimAlpha : 1f; + + mBehindTint = Color.BLACK; + mBehindAlpha = ScrimController.TRANSPARENT; + + mBubbleTint = Color.TRANSPARENT; + mBubbleAlpha = ScrimController.TRANSPARENT; + mAnimationDuration = ScrimController.ANIMATION_DURATION_LONG; // DisplayPowerManager may blank the screen for us, // in this case we just need to set our state. @@ -127,8 +139,9 @@ public enum ScrimState { PULSING(5) { @Override public void prepare(ScrimState previousState) { - mCurrentInFrontAlpha = 0f; - mCurrentBehindTint = Color.BLACK; + mFrontAlpha = 0f; + mBubbleAlpha = 0f; + mBehindTint = Color.BLACK; mBlankScreen = mDisplayRequiresBlanking; } @@ -145,23 +158,30 @@ public enum ScrimState { UNLOCKED(6) { @Override public void prepare(ScrimState previousState) { - mCurrentBehindAlpha = 0; - mCurrentInFrontAlpha = 0; + // State that UI will sync to. + mBehindAlpha = 0; + mFrontAlpha = 0; + mBubbleAlpha = 0; + mAnimationDuration = StatusBar.FADE_KEYGUARD_DURATION; mAnimateChange = !mLaunchingAffordanceWithPreview; + mFrontTint = Color.TRANSPARENT; + mBehindTint = Color.TRANSPARENT; + mBubbleTint = Color.TRANSPARENT; + mBlankScreen = false; + if (previousState == ScrimState.AOD) { - // Fade from black to transparent when coming directly from AOD - updateScrimColor(mScrimInFront, 1, Color.BLACK); - updateScrimColor(mScrimBehind, 1, Color.BLACK); + // Set all scrims black, before they fade transparent. + updateScrimColor(mScrimInFront, 1f /* alpha */, Color.BLACK /* tint */); + updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK /* tint */); + updateScrimColor(mScrimForBubble, 1f /* alpha */, Color.BLACK /* tint */); + // Scrims should still be black at the end of the transition. - mCurrentInFrontTint = Color.BLACK; - mCurrentBehindTint = Color.BLACK; + mFrontTint = Color.BLACK; + mBehindTint = Color.BLACK; + mBubbleTint = Color.BLACK; mBlankScreen = true; - } else { - mCurrentInFrontTint = Color.TRANSPARENT; - mCurrentBehindTint = Color.TRANSPARENT; - mBlankScreen = false; } } }, @@ -172,25 +192,36 @@ public enum ScrimState { BUBBLE_EXPANDED(7) { @Override public void prepare(ScrimState previousState) { - mCurrentInFrontTint = Color.TRANSPARENT; - mCurrentBehindTint = Color.TRANSPARENT; + mFrontTint = Color.TRANSPARENT; + mBehindTint = Color.TRANSPARENT; + mBubbleTint = Color.TRANSPARENT; + + mFrontAlpha = ScrimController.TRANSPARENT; + mBehindAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY; + mBubbleAlpha = ScrimController.GRADIENT_SCRIM_ALPHA; + mAnimationDuration = ScrimController.ANIMATION_DURATION; - mCurrentBehindAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY; mBlankScreen = false; } }; boolean mBlankScreen = false; long mAnimationDuration = ScrimController.ANIMATION_DURATION; - int mCurrentInFrontTint = Color.TRANSPARENT; - int mCurrentBehindTint = Color.TRANSPARENT; + int mFrontTint = Color.TRANSPARENT; + int mBehindTint = Color.TRANSPARENT; + int mBubbleTint = Color.TRANSPARENT; + boolean mAnimateChange = true; - float mCurrentInFrontAlpha; - float mCurrentBehindAlpha; float mAodFrontScrimAlpha; + float mFrontAlpha; + float mBehindAlpha; + float mBubbleAlpha; + float mScrimBehindAlphaKeyguard; ScrimView mScrimInFront; ScrimView mScrimBehind; + ScrimView mScrimForBubble; + DozeParameters mDozeParameters; boolean mDisplayRequiresBlanking; boolean mWallpaperSupportsAmbientMode; @@ -203,13 +234,17 @@ public enum ScrimState { mIndex = index; } - public void init(ScrimView scrimInFront, ScrimView scrimBehind, DozeParameters dozeParameters) { + public void init(ScrimView scrimInFront, ScrimView scrimBehind, ScrimView scrimForBubble, + DozeParameters dozeParameters) { mScrimInFront = scrimInFront; mScrimBehind = scrimBehind; + mScrimForBubble = scrimForBubble; + mDozeParameters = dozeParameters; mDisplayRequiresBlanking = dozeParameters.getDisplayNeedsBlanking(); } + /** Prepare state for transition. */ public void prepare(ScrimState previousState) { } @@ -218,19 +253,27 @@ public enum ScrimState { } public float getFrontAlpha() { - return mCurrentInFrontAlpha; + return mFrontAlpha; } public float getBehindAlpha() { - return mCurrentBehindAlpha; + return mBehindAlpha; + } + + public float getBubbleAlpha() { + return mBubbleAlpha; } public int getFrontTint() { - return mCurrentInFrontTint; + return mFrontTint; } public int getBehindTint() { - return mCurrentBehindTint; + return mBehindTint; + } + + public int getBubbleTint() { + return mBubbleTint; } public long getAnimationDuration() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 2c7d204efc33c..c0e8d47814747 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -230,7 +230,6 @@ import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.statusbar.policy.UserInfoControllerImpl; import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.statusbar.policy.ZenModeController; -import com.android.systemui.tuner.TunerService; import com.android.systemui.util.InjectionInflationController; import com.android.systemui.volume.VolumeComponent; @@ -807,6 +806,7 @@ public class StatusBar extends SystemUI implements DemoMode, // TODO: Deal with the ugliness that comes from having some of the statusbar broken out // into fragments, but the rest here, it leaves some awkward lifecycle and whatnot. mNotificationPanel = mStatusBarWindow.findViewById(R.id.notification_panel); + mStackScroller = mStatusBarWindow.findViewById(R.id.notification_stack_scroller); mZenController.addCallback(this); NotificationListContainer notifListContainer = (NotificationListContainer) mStackScroller; @@ -925,8 +925,10 @@ public class StatusBar extends SystemUI implements DemoMode, ScrimView scrimBehind = mStatusBarWindow.findViewById(R.id.scrim_behind); ScrimView scrimInFront = mStatusBarWindow.findViewById(R.id.scrim_in_front); + ScrimView scrimForBubble = mStatusBarWindow.findViewById(R.id.scrim_for_bubble); + mScrimController = SystemUIFactory.getInstance().createScrimController( - scrimBehind, scrimInFront, mLockscreenWallpaper, + scrimBehind, scrimInFront, scrimForBubble, mLockscreenWallpaper, (state, alpha, color) -> mLightBarController.setScrimState(state, alpha, color), scrimsVisible -> { if (mStatusBarWindowController != null) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java index f08db1b5c76c7..13e0065f4e5c2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java @@ -174,7 +174,7 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat } final boolean scrimsOccludingWallpaper = - state.scrimsVisibility == ScrimController.VISIBILITY_FULLY_OPAQUE; + state.scrimsVisibility == ScrimController.OPAQUE; final boolean keyguardOrAod = state.keyguardShowing || (state.dozing && mDozeParameters.getAlwaysOn()); if (keyguardOrAod && !state.backdropShowing && !scrimsOccludingWallpaper) { @@ -248,7 +248,7 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat return !state.forceCollapsed && (state.isKeyguardShowingAndNotOccluded() || state.panelVisible || state.keyguardFadingAway || state.bouncerShowing || state.headsUpShowing || state.bubblesShowing - || state.scrimsVisibility != ScrimController.VISIBILITY_FULLY_TRANSPARENT); + || state.scrimsVisibility != ScrimController.TRANSPARENT); } private void applyFitsSystemWindows(State state) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java index 191c983ad1564..cf75e0574dec0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java @@ -16,9 +16,9 @@ package com.android.systemui.statusbar.phone; -import static com.android.systemui.statusbar.phone.ScrimController.VISIBILITY_FULLY_OPAQUE; -import static com.android.systemui.statusbar.phone.ScrimController.VISIBILITY_FULLY_TRANSPARENT; -import static com.android.systemui.statusbar.phone.ScrimController.VISIBILITY_SEMI_TRANSPARENT; +import static com.android.systemui.statusbar.phone.ScrimController.OPAQUE; +import static com.android.systemui.statusbar.phone.ScrimController.SEMI_TRANSPARENT; +import static com.android.systemui.statusbar.phone.ScrimController.TRANSPARENT; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; @@ -68,6 +68,7 @@ public class ScrimControllerTest extends SysuiTestCase { private SynchronousScrimController mScrimController; private ScrimView mScrimBehind; private ScrimView mScrimInFront; + private ScrimView mScrimForBubble; private ScrimState mScrimState; private float mScrimBehindAlpha; private GradientColors mScrimInFrontColor; @@ -83,6 +84,7 @@ public class ScrimControllerTest extends SysuiTestCase { public void setup() { mScrimBehind = spy(new ScrimView(getContext())); mScrimInFront = new ScrimView(getContext()); + mScrimForBubble = new ScrimView(getContext()); mWakeLock = mock(WakeLock.class); mAlarmManager = mock(AlarmManager.class); mAlwaysOnEnabled = true; @@ -91,6 +93,7 @@ public class ScrimControllerTest extends SysuiTestCase { when(mDozeParamenters.getAlwaysOn()).thenAnswer(invocation -> mAlwaysOnEnabled); when(mDozeParamenters.getDisplayNeedsBlanking()).thenReturn(true); mScrimController = new SynchronousScrimController(mScrimBehind, mScrimInFront, + mScrimForBubble, (scrimState, scrimBehindAlpha, scrimInFrontColor) -> { mScrimState = scrimState; mScrimBehindAlpha = scrimBehindAlpha; @@ -112,21 +115,28 @@ public class ScrimControllerTest extends SysuiTestCase { public void transitionToKeyguard() { mScrimController.transitionTo(ScrimState.KEYGUARD); mScrimController.finishAnimationsImmediately(); - // Front scrim should be transparent - // Back scrim should be visible without tint - assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT); - assertScrimTint(mScrimBehind, true /* tinted */); + + assertScrimAlpha(TRANSPARENT /* front */, + SEMI_TRANSPARENT /* back */, + TRANSPARENT /* bubble */); + + assertScrimTint(true /* front */, + true /* behind */, + false /* bubble */); } @Test public void transitionToAod_withRegularWallpaper() { mScrimController.transitionTo(ScrimState.AOD); mScrimController.finishAnimationsImmediately(); - // Front scrim should be transparent - // Back scrim should be visible with tint - assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); - assertScrimTint(mScrimBehind, true /* tinted */); - assertScrimTint(mScrimInFront, true /* tinted */); + + assertScrimAlpha(TRANSPARENT /* front */, + OPAQUE /* back */, + TRANSPARENT /* bubble */); + + assertScrimTint(true /* front */, + true /* behind */, + false /* bubble */); } @Test @@ -134,14 +144,18 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.setWallpaperSupportsAmbientMode(true); mScrimController.transitionTo(ScrimState.AOD); mScrimController.finishAnimationsImmediately(); - // Front scrim should be transparent - // Back scrim should be transparent - assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT); + + assertScrimAlpha(TRANSPARENT /* front */, + TRANSPARENT /* back */, + TRANSPARENT /* bubble */); // Pulsing notification should conserve AOD wallpaper. mScrimController.transitionTo(ScrimState.PULSING); mScrimController.finishAnimationsImmediately(); - assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT); + + assertScrimAlpha(TRANSPARENT /* front */, + TRANSPARENT /* back */, + TRANSPARENT /* bubble */); } @Test @@ -150,11 +164,14 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.setWallpaperSupportsAmbientMode(true); mScrimController.transitionTo(ScrimState.AOD); mScrimController.finishAnimationsImmediately(); - // Front scrim should be transparent - // Back scrim should be visible with tint - assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); - assertScrimTint(mScrimBehind, true /* tinted */); - assertScrimTint(mScrimInFront, true /* tinted */); + + assertScrimAlpha(TRANSPARENT /* front */, + OPAQUE /* back */, + TRANSPARENT /* bubble */); + + assertScrimTint(true /* front */, + true /* behind */, + false /* bubble */); } @Test @@ -164,11 +181,14 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.finishAnimationsImmediately(); mScrimController.setHasBackdrop(true); mScrimController.finishAnimationsImmediately(); - // Front scrim should be transparent - // Back scrim should be visible with tint - assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); - assertScrimTint(mScrimBehind, true /* tinted */); - assertScrimTint(mScrimInFront, true /* tinted */); + + assertScrimAlpha(TRANSPARENT /* front */, + OPAQUE /* back */, + TRANSPARENT /* bubble */); + + assertScrimTint(true /* front */, + true /* behind */, + false /* bubble */); } @Test @@ -177,27 +197,32 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.transitionTo(ScrimState.KEYGUARD); mScrimController.setAodFrontScrimAlpha(0.5f); mScrimController.finishAnimationsImmediately(); - // Front scrim should be transparent - // Back scrim should be visible without tint - assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT); + + assertScrimAlpha(TRANSPARENT /* front */, + SEMI_TRANSPARENT /* back */, + TRANSPARENT /* bubble */); // ... but that it does take effect once we enter the AOD state. mScrimController.transitionTo(ScrimState.AOD); mScrimController.finishAnimationsImmediately(); - // Front scrim should be semi-transparent - // Back scrim should be visible - assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); + assertScrimAlpha(SEMI_TRANSPARENT /* front */, + OPAQUE /* back */, + TRANSPARENT /* bubble */); // ... and that if we set it while we're in AOD, it does take immediate effect. mScrimController.setAodFrontScrimAlpha(1f); - assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE); + assertScrimAlpha(OPAQUE /* front */, + OPAQUE /* back */, + TRANSPARENT /* bubble */); // ... and make sure we recall the previous front scrim alpha even if we transition away // for a bit. mScrimController.transitionTo(ScrimState.UNLOCKED); mScrimController.transitionTo(ScrimState.AOD); mScrimController.finishAnimationsImmediately(); - assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE); + assertScrimAlpha(OPAQUE /* front */, + OPAQUE /* back */, + TRANSPARENT /* bubble */); // ... and alpha updates should be completely ignored if always_on is off. // Passing it forward would mess up the wake-up transition. @@ -221,19 +246,28 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.setWallpaperSupportsAmbientMode(false); mScrimController.transitionTo(ScrimState.AOD); mScrimController.finishAnimationsImmediately(); - assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); + assertScrimAlpha(TRANSPARENT /* front */, + OPAQUE /* back */, + TRANSPARENT /* bubble */); mScrimController.transitionTo(ScrimState.PULSING); mScrimController.finishAnimationsImmediately(); // Front scrim should be transparent // Back scrim should be semi-transparent so the user can see the wallpaper // Pulse callback should have been invoked - assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); - assertScrimTint(mScrimBehind, true /* tinted */); + assertScrimAlpha(TRANSPARENT /* front */, + OPAQUE /* back */, + TRANSPARENT /* bubble */); + + assertScrimTint(false /* front */, + true /* behind */, + false /* bubble */); mScrimController.setWakeLockScreenSensorActive(true); mScrimController.finishAnimationsImmediately(); - assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT); + assertScrimAlpha(TRANSPARENT /* front */, + SEMI_TRANSPARENT /* back */, + TRANSPARENT /* bubble */); } @Test @@ -242,8 +276,13 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.finishAnimationsImmediately(); // Front scrim should be transparent // Back scrim should be visible without tint - assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT); - assertScrimTint(mScrimBehind, false /* tinted */); + assertScrimAlpha(TRANSPARENT /* front */, + SEMI_TRANSPARENT /* back */, + TRANSPARENT /* bubble */); + + assertScrimTint(false /* front */, + false /* behind */, + false /* bubble */); } @Test @@ -252,8 +291,12 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.finishAnimationsImmediately(); // Front scrim should be transparent // Back scrim should be visible without tint - assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT); - assertScrimTint(mScrimBehind, false /* tinted */); + assertScrimAlpha(SEMI_TRANSPARENT /* front */, + TRANSPARENT /* back */, + TRANSPARENT /* bubble */); + assertScrimTint(false /* front */, + false /* behind */, + false /* bubble */); } @Test @@ -261,15 +304,19 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.setPanelExpansion(0f); mScrimController.transitionTo(ScrimState.UNLOCKED); mScrimController.finishAnimationsImmediately(); - // Front scrim should be transparent - // Back scrim should be transparent - assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT); - assertScrimTint(mScrimBehind, false /* tinted */); - assertScrimTint(mScrimInFront, false /* tinted */); + assertScrimAlpha(TRANSPARENT /* front */, + TRANSPARENT /* back */, + TRANSPARENT /* bubble */); + + assertScrimTint(false /* front */, + false /* behind */, + false /* bubble */); // Back scrim should be visible after start dragging mScrimController.setPanelExpansion(0.5f); - assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT); + assertScrimAlpha(TRANSPARENT /* front */, + SEMI_TRANSPARENT /* back */, + TRANSPARENT /* bubble */); } @Test @@ -277,12 +324,19 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.transitionTo(ScrimState.BUBBLE_EXPANDED); mScrimController.finishAnimationsImmediately(); + assertScrimTint(false /* front */, + false /* behind */, + false /* bubble */); + // Front scrim should be transparent - Assert.assertEquals(ScrimController.VISIBILITY_FULLY_TRANSPARENT, + Assert.assertEquals(ScrimController.TRANSPARENT, mScrimInFront.getViewAlpha(), 0.0f); // Back scrim should be visible Assert.assertEquals(ScrimController.GRADIENT_SCRIM_ALPHA_BUSY, mScrimBehind.getViewAlpha(), 0.0f); + // Bubble scrim should be visible + Assert.assertEquals(ScrimController.GRADIENT_SCRIM_ALPHA_BUSY, + mScrimBehind.getViewAlpha(), 0.0f); } @Test @@ -351,16 +405,22 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.setPanelExpansion(0f); mScrimController.finishAnimationsImmediately(); mScrimController.transitionTo(ScrimState.UNLOCKED); - // Immediately tinted after the transition starts - assertScrimTint(mScrimInFront, true /* tinted */); - assertScrimTint(mScrimBehind, true /* tinted */); + + // Immediately tinted black after the transition starts + assertScrimTint(true /* front */, + true /* behind */, + true /* bubble */); + mScrimController.finishAnimationsImmediately(); - // Front scrim should be transparent - // Back scrim should be transparent - // Neither scrims should be tinted anymore after the animation. - assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT); - assertScrimTint(mScrimInFront, false /* tinted */); - assertScrimTint(mScrimBehind, false /* tinted */); + + // All scrims should be transparent at the end of fade transition. + assertScrimAlpha(TRANSPARENT /* front */, + TRANSPARENT /* behind */, + TRANSPARENT /* bubble */); + + assertScrimTint(false /* front */, + false /* behind */, + false /* bubble */); } @Test @@ -375,9 +435,11 @@ public class ScrimControllerTest extends SysuiTestCase { // Front scrim should be black in the middle of the transition Assert.assertTrue("Scrim should be visible during transition. Alpha: " + mScrimInFront.getViewAlpha(), mScrimInFront.getViewAlpha() > 0); - assertScrimTint(mScrimInFront, true /* tinted */); + assertScrimTint(true /* front */, + true /* behind */, + true /* bubble */); Assert.assertSame("Scrim should be visible during transition.", - mScrimVisibility, VISIBILITY_FULLY_OPAQUE); + mScrimVisibility, OPAQUE); } }); mScrimController.finishAnimationsImmediately(); @@ -553,11 +615,15 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.setKeyguardOccluded(true); mScrimController.transitionTo(ScrimState.AOD); mScrimController.finishAnimationsImmediately(); - assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); + assertScrimAlpha(TRANSPARENT /* front */, + OPAQUE /* behind */, + TRANSPARENT /* bubble */); mScrimController.transitionTo(ScrimState.PULSING); mScrimController.finishAnimationsImmediately(); - assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); + assertScrimAlpha(TRANSPARENT /* front */, + OPAQUE /* behind */, + TRANSPARENT /* bubble */); } @Test @@ -565,11 +631,15 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.setWallpaperSupportsAmbientMode(true); mScrimController.transitionTo(ScrimState.AOD); mScrimController.finishAnimationsImmediately(); - assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT); + assertScrimAlpha(TRANSPARENT /* front */, + TRANSPARENT /* behind */, + TRANSPARENT /* bubble */); mScrimController.setKeyguardOccluded(true); mScrimController.finishAnimationsImmediately(); - assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); + assertScrimAlpha(TRANSPARENT /* front */, + OPAQUE /* behind */, + TRANSPARENT /* bubble */); } @Test @@ -608,33 +678,68 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimInFront.getDefaultFocusHighlightEnabled()); Assert.assertFalse("Scrim shouldn't have focus highlight", mScrimBehind.getDefaultFocusHighlightEnabled()); + Assert.assertFalse("Scrim shouldn't have focus highlight", + mScrimForBubble.getDefaultFocusHighlightEnabled()); } - private void assertScrimTint(ScrimView scrimView, boolean tinted) { - final boolean viewIsTinted = scrimView.getTint() != Color.TRANSPARENT; - final String name = scrimView == mScrimInFront ? "front" : "back"; + private void assertScrimTint(boolean front, boolean behind, boolean bubble) { Assert.assertEquals("Tint test failed at state " + mScrimController.getState() - +" with scrim: " + name + " and tint: " + Integer.toHexString(scrimView.getTint()), - tinted, viewIsTinted); + + " with scrim: " + getScrimName(mScrimInFront) + " and tint: " + + Integer.toHexString(mScrimInFront.getTint()), + front, mScrimInFront.getTint() != Color.TRANSPARENT); + + Assert.assertEquals("Tint test failed at state " + mScrimController.getState() + + " with scrim: " + getScrimName(mScrimBehind) + " and tint: " + + Integer.toHexString(mScrimBehind.getTint()), + behind, mScrimBehind.getTint() != Color.TRANSPARENT); + + Assert.assertEquals("Tint test failed at state " + mScrimController.getState() + + " with scrim: " + getScrimName(mScrimForBubble) + " and tint: " + + Integer.toHexString(mScrimForBubble.getTint()), + bubble, mScrimForBubble.getTint() != Color.TRANSPARENT); } - private void assertScrimVisibility(int inFront, int behind) { - boolean inFrontVisible = inFront != ScrimController.VISIBILITY_FULLY_TRANSPARENT; - boolean behindVisible = behind != ScrimController.VISIBILITY_FULLY_TRANSPARENT; - Assert.assertEquals("Unexpected front scrim visibility. Alpha is " - + mScrimInFront.getViewAlpha(), inFrontVisible, mScrimInFront.getViewAlpha() > 0); - Assert.assertEquals("Unexpected back scrim visibility. Alpha is " - + mScrimBehind.getViewAlpha(), behindVisible, mScrimBehind.getViewAlpha() > 0); - - final int visibility; - if (inFront == VISIBILITY_FULLY_OPAQUE || behind == VISIBILITY_FULLY_OPAQUE) { - visibility = VISIBILITY_FULLY_OPAQUE; - } else if (inFront > VISIBILITY_FULLY_TRANSPARENT || behind > VISIBILITY_FULLY_TRANSPARENT) { - visibility = VISIBILITY_SEMI_TRANSPARENT; - } else { - visibility = VISIBILITY_FULLY_TRANSPARENT; + private String getScrimName(ScrimView scrim) { + if (scrim == mScrimInFront) { + return "front"; + } else if (scrim == mScrimBehind) { + return "back"; + } else if (scrim == mScrimForBubble) { + return "bubble"; } - Assert.assertEquals("Invalid visibility.", visibility, mScrimVisibility); + return "unknown_scrim"; + } + + private void assertScrimAlpha(int front, int behind, int bubble) { + // Check single scrim visibility. + Assert.assertEquals("Unexpected front scrim alpha: " + + mScrimInFront.getViewAlpha(), + front != TRANSPARENT /* expected */, + mScrimInFront.getViewAlpha() > TRANSPARENT /* actual */); + + Assert.assertEquals("Unexpected back scrim alpha: " + + mScrimBehind.getViewAlpha(), + behind != TRANSPARENT /* expected */, + mScrimBehind.getViewAlpha() > TRANSPARENT /* actual */); + + Assert.assertEquals( + "Unexpected bubble scrim alpha: " + + mScrimForBubble.getViewAlpha(), /* message */ + bubble != TRANSPARENT /* expected */, + mScrimForBubble.getViewAlpha() > TRANSPARENT /* actual */); + + // Check combined scrim visibility. + final int visibility; + if (front == OPAQUE || behind == OPAQUE || bubble == OPAQUE) { + visibility = OPAQUE; + } else if (front > TRANSPARENT || behind > TRANSPARENT || bubble > TRANSPARENT) { + visibility = SEMI_TRANSPARENT; + } else { + visibility = TRANSPARENT; + } + Assert.assertEquals("Invalid visibility.", + visibility /* expected */, + mScrimVisibility); } /** @@ -646,11 +751,12 @@ public class ScrimControllerTest extends SysuiTestCase { boolean mOnPreDrawCalled; SynchronousScrimController(ScrimView scrimBehind, ScrimView scrimInFront, + ScrimView scrimForBubble, TriConsumer scrimStateListener, Consumer scrimVisibleListener, DozeParameters dozeParameters, AlarmManager alarmManager) { - super(scrimBehind, scrimInFront, scrimStateListener, scrimVisibleListener, - dozeParameters, alarmManager); + super(scrimBehind, scrimInFront, scrimForBubble, scrimStateListener, + scrimVisibleListener, dozeParameters, alarmManager); } @Override @@ -661,13 +767,14 @@ public class ScrimControllerTest extends SysuiTestCase { void finishAnimationsImmediately() { boolean[] animationFinished = {false}; - setOnAnimationFinished(()-> animationFinished[0] = true); + setOnAnimationFinished(() -> animationFinished[0] = true); // Execute code that will trigger animations. onPreDraw(); // Force finish all animations. mLooper.processAllMessages(); endAnimation(mScrimBehind, TAG_KEY_ANIM); endAnimation(mScrimInFront, TAG_KEY_ANIM); + endAnimation(mScrimForBubble, TAG_KEY_ANIM); if (!animationFinished[0]) { throw new IllegalStateException("Animation never finished"); @@ -705,6 +812,7 @@ public class ScrimControllerTest extends SysuiTestCase { /** * Do not wait for a frame since we're in a test environment. + * * @param callback What to execute. */ @Override