Merge "Changed Notification shade's background alpha initial and final values to be configurable." into qt-qpr1-dev
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 4db6308..f8522ed 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -71,11 +71,24 @@
     }
 
     /**
-     * Notify the host application that the current page has entered full
-     * screen mode. The host application must show the custom View which
-     * contains the web contents — video or other HTML content —
-     * in full screen mode. Also see "Full screen support" documentation on
-     * {@link WebView}.
+     * Notify the host application that the current page has entered full screen mode. After this
+     * call, web content will no longer be rendered in the WebView, but will instead be rendered
+     * in {@code view}. The host application should add this View to a Window which is configured
+     * with {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN} flag in order to
+     * actually display this web content full screen.
+     *
+     * <p>The application may explicitly exit fullscreen mode by invoking {@code callback} (ex. when
+     * the user presses the back button). However, this is generally not necessary as the web page
+     * will often show its own UI to close out of fullscreen. Regardless of how the WebView exits
+     * fullscreen mode, WebView will invoke {@link #onHideCustomView()}, signaling for the
+     * application to remove the custom View.
+     *
+     * <p>If this method is not overridden, WebView will report to the web page it does not support
+     * fullscreen mode and will not honor the web page's request to run in fullscreen mode.
+     *
+     * <p class="note"><b>Note:</b> if overriding this method, the application must also override
+     * {@link #onHideCustomView()}.
+     *
      * @param view is the View object to be shown.
      * @param callback invoke this callback to request the page to exit
      * full screen mode.
@@ -98,10 +111,13 @@
             CustomViewCallback callback) {};
 
     /**
-     * Notify the host application that the current page has exited full
-     * screen mode. The host application must hide the custom View, ie. the
-     * View passed to {@link #onShowCustomView} when the content entered fullscreen.
-     * Also see "Full screen support" documentation on {@link WebView}.
+     * Notify the host application that the current page has exited full screen mode. The host
+     * application must hide the custom View (the View which was previously passed to {@link
+     * #onShowCustomView(View, CustomViewCallback) onShowCustomView()}). After this call, web
+     * content will render in the original WebView again.
+     *
+     * <p class="note"><b>Note:</b> if overriding this method, the application must also override
+     * {@link #onShowCustomView(View, CustomViewCallback) onShowCustomView()}.
      */
     public void onHideCustomView() {}
 
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 9716a00..a914930 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -44,7 +44,7 @@
     </com.android.systemui.statusbar.BackDropView>
 
     <com.android.systemui.statusbar.ScrimView
-        android:id="@+id/scrim_for_bubble"
+        android:id="@+id/scrim_behind"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:importantForAccessibility="no"
@@ -56,14 +56,6 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content" />
 
-    <com.android.systemui.statusbar.ScrimView
-        android:id="@+id/scrim_behind"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:importantForAccessibility="no"
-        sysui:ignoreRightInset="true"
-        />
-
     <include layout="@layout/status_bar_expanded"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index d151f7d..0899d95 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -123,12 +123,11 @@
     }
 
     public ScrimController createScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
-            ScrimView scrimForBubble,
             LockscreenWallpaper lockscreenWallpaper,
             TriConsumer<ScrimState, Float, GradientColors> scrimStateListener,
             Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
             AlarmManager alarmManager, KeyguardMonitor keyguardMonitor) {
-        return new ScrimController(scrimBehind, scrimInFront, scrimForBubble, scrimStateListener,
+        return new ScrimController(scrimBehind, scrimInFront, scrimStateListener,
                 scrimVisibleListener, dozeParameters, alarmManager, keyguardMonitor);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 3cc91de..5559d29 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -316,9 +316,10 @@
         if (mStackView == null) {
             mStackView = new BubbleStackView(mContext, mBubbleData, mSurfaceSynchronizer);
             ViewGroup sbv = mStatusBarWindowController.getStatusBarView();
-            int bubbleScrimIndex = sbv.indexOfChild(sbv.findViewById(R.id.scrim_for_bubble));
-            int stackIndex = bubbleScrimIndex + 1;  // Show stack above bubble scrim.
-            sbv.addView(mStackView, stackIndex,
+            // 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,
                     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 ecfc45b..06a2225 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -604,7 +604,7 @@
      */
     public void onScrimVisibilityChanged(@ScrimVisibility int scrimsVisible) {
         if (mWakeAndUnlockRunning
-                && scrimsVisible == ScrimController.TRANSPARENT) {
+                && scrimsVisible == ScrimController.VISIBILITY_FULLY_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 2f56717..9019e9a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -79,24 +79,23 @@
     /**
      * When both scrims have 0 alpha.
      */
-    public static final int TRANSPARENT = 0;
+    public static final int VISIBILITY_FULLY_TRANSPARENT = 0;
     /**
      * When scrims aren't transparent (alpha 0) but also not opaque (alpha 1.)
      */
-    public static final int SEMI_TRANSPARENT = 1;
+    public static final int VISIBILITY_SEMI_TRANSPARENT = 1;
     /**
      * When at least 1 scrim is fully opaque (alpha set to 1.)
      */
-    public static final int OPAQUE = 2;
+    public static final int VISIBILITY_FULLY_OPAQUE = 2;
 
-    @IntDef(prefix = {"VISIBILITY_"}, value = {
-            TRANSPARENT,
-            SEMI_TRANSPARENT,
-            OPAQUE
+    @IntDef(prefix = { "VISIBILITY_" }, value = {
+            VISIBILITY_FULLY_TRANSPARENT,
+            VISIBILITY_SEMI_TRANSPARENT,
+            VISIBILITY_FULLY_OPAQUE
     })
     @Retention(RetentionPolicy.SOURCE)
-    public @interface ScrimVisibility {
-    }
+    public @interface ScrimVisibility {}
 
     /**
      * Default alpha value for most scrims.
@@ -124,11 +123,8 @@
 
     private ScrimState mState = ScrimState.UNINITIALIZED;
     private final Context mContext;
-
-    protected final ScrimView mScrimInFront;
     protected final ScrimView mScrimBehind;
-    protected final ScrimView mScrimForBubble;
-
+    protected final ScrimView mScrimInFront;
     private final UnlockMethodCache mUnlockMethodCache;
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     private final DozeParameters mDozeParameters;
@@ -157,15 +153,10 @@
     private Runnable mOnAnimationFinished;
     private boolean mDeferFinishedListener;
     private final Interpolator mInterpolator = new DecelerateInterpolator();
-
-    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 float mCurrentInFrontAlpha  = NOT_INITIALIZED;
+    private float mCurrentBehindAlpha = NOT_INITIALIZED;
+    private int mCurrentInFrontTint;
+    private int mCurrentBehindTint;
     private boolean mWallpaperVisibilityTimedOut;
     private int mScrimsVisibility;
     private final TriConsumer<ScrimState, Float, GradientColors> mScrimStateListener;
@@ -184,17 +175,14 @@
     private boolean mWakeLockHeld;
     private boolean mKeyguardOccluded;
 
-    public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront, ScrimView scrimForBubble,
+    public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
             TriConsumer<ScrimState, Float, GradientColors> scrimStateListener,
             Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
             AlarmManager alarmManager, KeyguardMonitor keyguardMonitor) {
         mScrimBehind = scrimBehind;
         mScrimInFront = scrimInFront;
-        mScrimForBubble = scrimForBubble;
-
         mScrimStateListener = scrimStateListener;
         mScrimVisibleListener = scrimVisibleListener;
-
         mContext = scrimBehind.getContext();
         mUnlockMethodCache = UnlockMethodCache.getInstance(mContext);
         mDarkenWhileDragging = !mUnlockMethodCache.canSkipBouncer();
@@ -225,13 +213,12 @@
 
         final ScrimState[] states = ScrimState.values();
         for (int i = 0; i < states.length; i++) {
-            states[i].init(mScrimInFront, mScrimBehind, mScrimForBubble, mDozeParameters);
+            states[i].init(mScrimInFront, mScrimBehind, mDozeParameters);
             states[i].setScrimBehindAlphaKeyguard(mScrimBehindAlphaKeyguard);
         }
 
         mScrimBehind.setDefaultFocusHighlightEnabled(false);
         mScrimInFront.setDefaultFocusHighlightEnabled(false);
-        mScrimForBubble.setDefaultFocusHighlightEnabled(false);
 
         updateScrims();
     }
@@ -270,14 +257,10 @@
         mBlankScreen = state.getBlanksScreen();
         mAnimateChange = state.getAnimateChange();
         mAnimationDuration = state.getAnimationDuration();
-
-        mInFrontTint = state.getFrontTint();
-        mBehindTint = state.getBehindTint();
-        mBubbleTint = state.getBubbleTint();
-
-        mInFrontAlpha = state.getFrontAlpha();
-        mBehindAlpha = state.getBehindAlpha();
-        mBubbleAlpha = state.getBubbleAlpha();
+        mCurrentInFrontTint = state.getFrontTint();
+        mCurrentBehindTint = state.getBehindTint();
+        mCurrentInFrontAlpha = state.getFrontAlpha();
+        mCurrentBehindAlpha = state.getBehindAlpha();
         applyExpansionToAlpha();
 
         // Scrim might acquire focus when user is navigating with a D-pad or a keyboard.
@@ -410,20 +393,21 @@
         if (mExpansionFraction != fraction) {
             mExpansionFraction = fraction;
 
-            boolean relevantState = (mState == ScrimState.UNLOCKED
-                    || mState == ScrimState.KEYGUARD
-                    || mState == ScrimState.PULSING
-                    || mState == ScrimState.BUBBLE_EXPANDED);
-            if (!(relevantState && mExpansionAffectsAlpha)) {
+            final boolean keyguardOrUnlocked = mState == ScrimState.UNLOCKED
+                    || mState == ScrimState.KEYGUARD || mState == ScrimState.PULSING;
+            if (!keyguardOrUnlocked || !mExpansionAffectsAlpha) {
                 return;
             }
+
             applyExpansionToAlpha();
+
             if (mUpdatePending) {
                 return;
             }
+
             setOrAdaptCurrentAnimation(mScrimBehind);
             setOrAdaptCurrentAnimation(mScrimInFront);
-            setOrAdaptCurrentAnimation(mScrimForBubble);
+
             dispatchScrimState(mScrimBehind.getViewAlpha());
 
             // Reset wallpaper timeout if it's already timeout like expanding panel while PULSING
@@ -437,10 +421,11 @@
     }
 
     private void setOrAdaptCurrentAnimation(View scrim) {
-        float alpha = getCurrentScrimAlpha(scrim);
-        if (isAnimating(scrim)) {
-            // Adapt current animation.
+        if (!isAnimating(scrim)) {
+            updateScrimColor(scrim, getCurrentScrimAlpha(scrim), getCurrentScrimTint(scrim));
+        } else {
             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;
@@ -448,9 +433,6 @@
             scrim.setTag(TAG_START_ALPHA, newStartValue);
             scrim.setTag(TAG_END_ALPHA, alpha);
             previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
-        } else {
-            // Set animation.
-            updateScrimColor(scrim, alpha, getCurrentScrimTint(scrim));
         }
     }
 
@@ -459,27 +441,27 @@
             return;
         }
 
-        if (mState == ScrimState.UNLOCKED || mState == ScrimState.BUBBLE_EXPANDED) {
+        if (mState == ScrimState.UNLOCKED) {
             // Darken scrim as you pull down the shade when unlocked
             float behindFraction = getInterpolatedFraction();
             behindFraction = (float) Math.pow(behindFraction, 0.8f);
-            mBehindAlpha = behindFraction * GRADIENT_SCRIM_ALPHA_BUSY;
-            mInFrontAlpha = 0;
+            mCurrentBehindAlpha = behindFraction * GRADIENT_SCRIM_ALPHA_BUSY;
+            mCurrentInFrontAlpha = 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) {
-                mBehindAlpha = MathUtils.lerp(GRADIENT_SCRIM_ALPHA_BUSY, alphaBehind,
+                mCurrentBehindAlpha = MathUtils.lerp(GRADIENT_SCRIM_ALPHA_BUSY, alphaBehind,
                         interpolatedFract);
-                mInFrontAlpha = mState.getFrontAlpha();
+                mCurrentInFrontAlpha = mState.getFrontAlpha();
             } else {
-                mBehindAlpha = MathUtils.lerp(0 /* start */, alphaBehind,
+                mCurrentBehindAlpha = MathUtils.lerp(0 /* start */, alphaBehind,
                         interpolatedFract);
-                mInFrontAlpha = mState.getFrontAlpha();
+                mCurrentInFrontAlpha = mState.getFrontAlpha();
             }
-            mBehindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(),
+            mCurrentBehindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(),
                     mState.getBehindTint(), interpolatedFract);
         }
     }
@@ -504,8 +486,8 @@
      */
     public void setAodFrontScrimAlpha(float alpha) {
         if (((mState == ScrimState.AOD && mDozeParameters.getAlwaysOn())
-                || mState == ScrimState.PULSING) && mInFrontAlpha != alpha) {
-            mInFrontAlpha = alpha;
+                || mState == ScrimState.PULSING) && mCurrentInFrontAlpha != alpha) {
+            mCurrentInFrontAlpha = alpha;
             updateScrims();
         }
 
@@ -519,9 +501,9 @@
      */
     public void prepareForGentleWakeUp() {
         if (mState == ScrimState.AOD && mDozeParameters.getAlwaysOn()) {
-            mInFrontAlpha = 1f;
-            mInFrontTint = Color.BLACK;
-            mBehindTint = Color.BLACK;
+            mCurrentInFrontAlpha = 1f;
+            mCurrentInFrontTint = Color.BLACK;
+            mCurrentBehindTint = Color.BLACK;
             mAnimateChange = false;
             updateScrims();
             mAnimateChange = true;
@@ -539,8 +521,8 @@
 
         if (mState == ScrimState.PULSING) {
             float newBehindAlpha = mState.getBehindAlpha();
-            if (mBehindAlpha != newBehindAlpha) {
-                mBehindAlpha = newBehindAlpha;
+            if (mCurrentBehindAlpha != newBehindAlpha) {
+                mCurrentBehindAlpha = newBehindAlpha;
                 updateScrims();
             }
         }
@@ -562,11 +544,8 @@
             // 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;
@@ -585,13 +564,12 @@
         boolean occludedKeyguard = (mState == ScrimState.PULSING || mState == ScrimState.AOD)
                 && mKeyguardOccluded;
         if (aodWallpaperTimeout || occludedKeyguard) {
-            mBehindAlpha = 1;
+            mCurrentBehindAlpha = 1;
         }
-        setScrimAlpha(mScrimInFront, mInFrontAlpha);
-        setScrimAlpha(mScrimBehind, mBehindAlpha);
-        setScrimAlpha(mScrimForBubble, mBubbleAlpha);
-        // The animation could have all already finished, let's call onFinished just in case
-        onFinished();
+
+        setScrimInFrontAlpha(mCurrentInFrontAlpha);
+        setScrimBehindAlpha(mCurrentBehindAlpha);
+
         dispatchScrimsVisible();
     }
 
@@ -602,11 +580,11 @@
     private void dispatchScrimsVisible() {
         final int currentScrimVisibility;
         if (mScrimInFront.getViewAlpha() == 1 || mScrimBehind.getViewAlpha() == 1) {
-            currentScrimVisibility = OPAQUE;
+            currentScrimVisibility = VISIBILITY_FULLY_OPAQUE;
         } else if (mScrimInFront.getViewAlpha() == 0 && mScrimBehind.getViewAlpha() == 0) {
-            currentScrimVisibility = TRANSPARENT;
+            currentScrimVisibility = VISIBILITY_FULLY_TRANSPARENT;
         } else {
-            currentScrimVisibility = SEMI_TRANSPARENT;
+            currentScrimVisibility = VISIBILITY_SEMI_TRANSPARENT;
         }
 
         if (mScrimsVisibility != currentScrimVisibility) {
@@ -623,10 +601,18 @@
             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);
@@ -637,26 +623,17 @@
         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, getScrimName(scrimView) + "_alpha",
+            Trace.traceCounter(Trace.TRACE_TAG_APP,
+                    scrim == mScrimInFront ? "front_scrim_alpha" : "back_scrim_alpha",
                     (int) (alpha * 255));
 
-            Trace.traceCounter(Trace.TRACE_TAG_APP, getScrimName(scrimView) + "_tint",
+            Trace.traceCounter(Trace.TRACE_TAG_APP,
+                    scrim == mScrimInFront ? "front_scrim_tint" : "back_scrim_tint",
                     Color.alpha(tint));
 
             scrimView.setTint(tint);
@@ -690,9 +667,9 @@
 
             @Override
             public void onAnimationEnd(Animator animation) {
-                scrim.setTag(TAG_KEY_ANIM, null);
                 onFinished(lastCallback);
 
+                scrim.setTag(TAG_KEY_ANIM, null);
                 dispatchScrimsVisible();
 
                 if (!mDeferFinishedListener && mOnAnimationFinished != null) {
@@ -713,11 +690,9 @@
 
     private float getCurrentScrimAlpha(View scrim) {
         if (scrim == mScrimInFront) {
-            return mInFrontAlpha;
+            return mCurrentInFrontAlpha;
         } else if (scrim == mScrimBehind) {
-            return mBehindAlpha;
-        } else if (scrim == mScrimForBubble) {
-            return mBubbleAlpha;
+            return mCurrentBehindAlpha;
         } else {
             throw new IllegalArgumentException("Unknown scrim view");
         }
@@ -725,11 +700,9 @@
 
     private int getCurrentScrimTint(View scrim) {
         if (scrim == mScrimInFront) {
-            return mInFrontTint;
+            return mCurrentInFrontTint;
         } else if (scrim == mScrimBehind) {
-            return mBehindTint;
-        } else if (scrim == mScrimForBubble) {
-            return mBubbleTint;
+            return mCurrentBehindTint;
         } else {
             throw new IllegalArgumentException("Unknown scrim view");
         }
@@ -756,16 +729,6 @@
     }
 
     private void onFinished(Callback callback) {
-        if (isAnimating(mScrimBehind)
-            || isAnimating(mScrimInFront)
-            || isAnimating(mScrimForBubble)) {
-            if (callback != null && callback != mCallback) {
-                // Since we only notify the callback that we're finished once everything has
-                // finished, we need to make sure that any changing callbacks are also invoked
-                callback.onFinished();
-            }
-            return;
-        }
         if (mWakeLockHeld) {
             mWakeLock.release(TAG);
             mWakeLockHeld = false;
@@ -782,12 +745,8 @@
         // 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) {
-            mInFrontTint = Color.TRANSPARENT;
-            mBehindTint = Color.TRANSPARENT;
-            mBubbleTint = Color.TRANSPARENT;
-            updateScrimColor(mScrimInFront, mInFrontAlpha, mInFrontTint);
-            updateScrimColor(mScrimBehind, mBehindAlpha, mBehindTint);
-            updateScrimColor(mScrimForBubble, mBubbleAlpha, mBubbleTint);
+            mCurrentInFrontTint = Color.TRANSPARENT;
+            mCurrentBehindTint = Color.TRANSPARENT;
         }
     }
 
@@ -846,7 +805,10 @@
             } else {
                 // update the alpha directly
                 updateScrimColor(scrim, alpha, getCurrentScrimTint(scrim));
+                onFinished();
             }
+        } else {
+            onFinished();
         }
     }
 
@@ -889,7 +851,6 @@
 
     /**
      * Executes a callback after the frame has hit the display.
-     *
      * @param callback What to run.
      */
     @VisibleForTesting
@@ -933,35 +894,16 @@
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println(" ScrimController: ");
-        pw.print("  state: ");
-        pw.println(mState);
+        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("  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("  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("  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);
+        pw.print("   mTracking="); pw.println(mTracking);
     }
 
     public void setWallpaperSupportsAmbientMode(boolean wallpaperSupportsAmbientMode) {
@@ -1008,8 +950,8 @@
         // in this case, back-scrim needs to be re-evaluated
         if (mState == ScrimState.AOD || mState == ScrimState.PULSING) {
             float newBehindAlpha = mState.getBehindAlpha();
-            if (mBehindAlpha != newBehindAlpha) {
-                mBehindAlpha = newBehindAlpha;
+            if (mCurrentBehindAlpha != newBehindAlpha) {
+                mCurrentBehindAlpha = newBehindAlpha;
                 updateScrims();
             }
         }
@@ -1030,13 +972,10 @@
     public interface Callback {
         default void onStart() {
         }
-
         default void onDisplayBlanked() {
         }
-
         default void onFinished() {
         }
-
         default void onCancelled() {
         }
         /** Returns whether to timeout wallpaper or not. */
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 7463c7c..5fa861c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -36,6 +36,7 @@
      * On the lock screen.
      */
     KEYGUARD(0) {
+
         @Override
         public void prepare(ScrimState previousState) {
             mBlankScreen = false;
@@ -52,13 +53,10 @@
             } else {
                 mAnimationDuration = ScrimController.ANIMATION_DURATION;
             }
-            mFrontTint = Color.BLACK;
-            mBehindTint = Color.BLACK;
-            mBubbleTint = Color.TRANSPARENT;
-
-            mFrontAlpha = 0;
-            mBehindAlpha = mScrimBehindAlphaKeyguard;
-            mBubbleAlpha = 0;
+            mCurrentInFrontTint = Color.BLACK;
+            mCurrentBehindTint = Color.BLACK;
+            mCurrentBehindAlpha = mScrimBehindAlphaKeyguard;
+            mCurrentInFrontAlpha = 0;
         }
     },
 
@@ -68,9 +66,8 @@
     BOUNCER(1) {
         @Override
         public void prepare(ScrimState previousState) {
-            mBehindAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY;
-            mFrontAlpha = 0f;
-            mBubbleAlpha = 0f;
+            mCurrentBehindAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY;
+            mCurrentInFrontAlpha = 0f;
         }
     },
 
@@ -80,9 +77,8 @@
     BOUNCER_SCRIMMED(2) {
         @Override
         public void prepare(ScrimState previousState) {
-            mBehindAlpha = 0;
-            mBubbleAlpha = 0f;
-            mFrontAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY;
+            mCurrentBehindAlpha = 0;
+            mCurrentInFrontAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY;
         }
     },
 
@@ -92,9 +88,8 @@
     BRIGHTNESS_MIRROR(3) {
         @Override
         public void prepare(ScrimState previousState) {
-            mBehindAlpha = 0;
-            mFrontAlpha = 0;
-            mBubbleAlpha = 0;
+            mCurrentBehindAlpha = 0;
+            mCurrentInFrontAlpha = 0;
         }
     },
 
@@ -106,16 +101,9 @@
         public void prepare(ScrimState previousState) {
             final boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn();
             mBlankScreen = mDisplayRequiresBlanking;
-
-            mFrontTint = Color.BLACK;
-            mFrontAlpha = alwaysOnEnabled ? mAodFrontScrimAlpha : 1f;
-
-            mBehindTint = Color.BLACK;
-            mBehindAlpha = ScrimController.TRANSPARENT;
-
-            mBubbleTint = Color.TRANSPARENT;
-            mBubbleAlpha = ScrimController.TRANSPARENT;
-
+            mCurrentInFrontAlpha = alwaysOnEnabled ? mAodFrontScrimAlpha : 1f;
+            mCurrentInFrontTint = Color.BLACK;
+            mCurrentBehindTint = Color.BLACK;
             mAnimationDuration = ScrimController.ANIMATION_DURATION_LONG;
             // DisplayPowerManager may blank the screen for us,
             // in this case we just need to set our state.
@@ -139,10 +127,9 @@
     PULSING(5) {
         @Override
         public void prepare(ScrimState previousState) {
-            mFrontAlpha = mAodFrontScrimAlpha;
-            mBubbleAlpha = 0f;
-            mBehindTint = Color.BLACK;
-            mFrontTint = Color.BLACK;
+            mCurrentInFrontAlpha = mAodFrontScrimAlpha;
+            mCurrentBehindTint = Color.BLACK;
+            mCurrentInFrontTint = Color.BLACK;
             mBlankScreen = mDisplayRequiresBlanking;
             mAnimationDuration = mWakeLockScreenSensorActive
                     ? ScrimController.ANIMATION_DURATION_LONG : ScrimController.ANIMATION_DURATION;
@@ -167,33 +154,26 @@
     UNLOCKED(6) {
         @Override
         public void prepare(ScrimState previousState) {
-            // State that UI will sync to.
-            mBehindAlpha = 0;
-            mFrontAlpha = 0;
-            mBubbleAlpha = 0;
-
+            mCurrentBehindAlpha = 0;
+            mCurrentInFrontAlpha = 0;
             mAnimationDuration = mKeyguardFadingAway
                     ? mKeyguardFadingAwayDuration
                     : StatusBar.FADE_KEYGUARD_DURATION;
 
             mAnimateChange = !mLaunchingAffordanceWithPreview;
 
-            mFrontTint = Color.TRANSPARENT;
-            mBehindTint = Color.TRANSPARENT;
-            mBubbleTint = Color.TRANSPARENT;
-            mBlankScreen = false;
-
             if (previousState == ScrimState.AOD) {
-                // 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 */);
-
+                // Fade from black to transparent when coming directly from AOD
+                updateScrimColor(mScrimInFront, 1, Color.BLACK);
+                updateScrimColor(mScrimBehind, 1, Color.BLACK);
                 // Scrims should still be black at the end of the transition.
-                mFrontTint = Color.BLACK;
-                mBehindTint = Color.BLACK;
-                mBubbleTint = Color.BLACK;
+                mCurrentInFrontTint = Color.BLACK;
+                mCurrentBehindTint = Color.BLACK;
                 mBlankScreen = true;
+            } else {
+                mCurrentInFrontTint = Color.TRANSPARENT;
+                mCurrentBehindTint = Color.TRANSPARENT;
+                mBlankScreen = false;
             }
         }
     },
@@ -204,36 +184,25 @@
     BUBBLE_EXPANDED(7) {
         @Override
         public void prepare(ScrimState previousState) {
-            mFrontTint = Color.TRANSPARENT;
-            mBehindTint = Color.TRANSPARENT;
-            mBubbleTint = Color.TRANSPARENT;
-
-            mFrontAlpha = ScrimController.TRANSPARENT;
-            mBehindAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY;
-            mBubbleAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY;
-
+            mCurrentInFrontTint = Color.TRANSPARENT;
+            mCurrentBehindTint = Color.TRANSPARENT;
             mAnimationDuration = ScrimController.ANIMATION_DURATION;
+            mCurrentBehindAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY;
             mBlankScreen = false;
         }
     };
 
     boolean mBlankScreen = false;
     long mAnimationDuration = ScrimController.ANIMATION_DURATION;
-    int mFrontTint = Color.TRANSPARENT;
-    int mBehindTint = Color.TRANSPARENT;
-    int mBubbleTint = Color.TRANSPARENT;
-
+    int mCurrentInFrontTint = Color.TRANSPARENT;
+    int mCurrentBehindTint = 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;
@@ -248,17 +217,13 @@
         mIndex = index;
     }
 
-    public void init(ScrimView scrimInFront, ScrimView scrimBehind, ScrimView scrimForBubble,
-            DozeParameters dozeParameters) {
+    public void init(ScrimView scrimInFront, ScrimView scrimBehind, DozeParameters dozeParameters) {
         mScrimInFront = scrimInFront;
         mScrimBehind = scrimBehind;
-        mScrimForBubble = scrimForBubble;
-
         mDozeParameters = dozeParameters;
         mDisplayRequiresBlanking = dozeParameters.getDisplayNeedsBlanking();
     }
 
-    /** Prepare state for transition. */
     public void prepare(ScrimState previousState) {
     }
 
@@ -267,27 +232,19 @@
     }
 
     public float getFrontAlpha() {
-        return mFrontAlpha;
+        return mCurrentInFrontAlpha;
     }
 
     public float getBehindAlpha() {
-        return mBehindAlpha;
-    }
-
-    public float getBubbleAlpha() {
-        return mBubbleAlpha;
+        return mCurrentBehindAlpha;
     }
 
     public int getFrontTint() {
-        return mFrontTint;
+        return mCurrentInFrontTint;
     }
 
     public int getBehindTint() {
-        return mBehindTint;
-    }
-
-    public int getBubbleTint() {
-        return mBubbleTint;
+        return mCurrentBehindTint;
     }
 
     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 fc20d83..559df18 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -229,6 +229,7 @@
 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;
 
@@ -811,7 +812,6 @@
         // 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;
@@ -932,10 +932,8 @@
 
         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, scrimForBubble, mLockscreenWallpaper,
+                scrimBehind, scrimInFront, 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 d3ae5cf..946fe0b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -222,7 +222,7 @@
         }
 
         final boolean scrimsOccludingWallpaper =
-                state.scrimsVisibility == ScrimController.OPAQUE;
+                state.scrimsVisibility == ScrimController.VISIBILITY_FULLY_OPAQUE;
         final boolean keyguardOrAod = state.keyguardShowing
                 || (state.dozing && mDozeParameters.getAlwaysOn());
         if (keyguardOrAod && !state.backdropShowing && !scrimsOccludingWallpaper) {
@@ -308,7 +308,7 @@
         return !state.forceCollapsed && (state.isKeyguardShowingAndNotOccluded()
                 || state.panelVisible || state.keyguardFadingAway || state.bouncerShowing
                 || state.headsUpShowing || state.bubblesShowing
-                || state.scrimsVisibility != ScrimController.TRANSPARENT);
+                || state.scrimsVisibility != ScrimController.VISIBILITY_FULLY_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 d4ad4b6..205312c 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.OPAQUE;
-import static com.android.systemui.statusbar.phone.ScrimController.SEMI_TRANSPARENT;
-import static com.android.systemui.statusbar.phone.ScrimController.TRANSPARENT;
+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 org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -69,7 +69,6 @@
     private SynchronousScrimController mScrimController;
     private ScrimView mScrimBehind;
     private ScrimView mScrimInFront;
-    private ScrimView mScrimForBubble;
     private ScrimState mScrimState;
     private float mScrimBehindAlpha;
     private GradientColors mScrimInFrontColor;
@@ -85,7 +84,6 @@
     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;
@@ -94,7 +92,6 @@
         when(mDozeParamenters.getAlwaysOn()).thenAnswer(invocation -> mAlwaysOnEnabled);
         when(mDozeParamenters.getDisplayNeedsBlanking()).thenReturn(true);
         mScrimController = new SynchronousScrimController(mScrimBehind, mScrimInFront,
-                mScrimForBubble,
                 (scrimState, scrimBehindAlpha, scrimInFrontColor) -> {
                     mScrimState = scrimState;
                     mScrimBehindAlpha = scrimBehindAlpha;
@@ -117,28 +114,21 @@
     public void transitionToKeyguard() {
         mScrimController.transitionTo(ScrimState.KEYGUARD);
         mScrimController.finishAnimationsImmediately();
-
-        assertScrimAlpha(TRANSPARENT /* front */,
-                SEMI_TRANSPARENT /* back */,
-                TRANSPARENT /* bubble */);
-
-        assertScrimTint(true /* front */,
-                true /* behind */,
-                false /* bubble */);
+        // Front scrim should be transparent
+        // Back scrim should be visible without tint
+        assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
+        assertScrimTint(mScrimBehind, true /* tinted */);
     }
 
     @Test
     public void transitionToAod_withRegularWallpaper() {
         mScrimController.transitionTo(ScrimState.AOD);
         mScrimController.finishAnimationsImmediately();
-
-        assertScrimAlpha(TRANSPARENT /* front */,
-                OPAQUE /* back */,
-                TRANSPARENT /* bubble */);
-
-        assertScrimTint(true /* front */,
-                true /* behind */,
-                false /* bubble */);
+        // 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 */);
     }
 
     @Test
@@ -146,18 +136,14 @@
         mScrimController.setWallpaperSupportsAmbientMode(true);
         mScrimController.transitionTo(ScrimState.AOD);
         mScrimController.finishAnimationsImmediately();
-
-        assertScrimAlpha(TRANSPARENT /* front */,
-                TRANSPARENT /* back */,
-                TRANSPARENT /* bubble */);
+        // Front scrim should be transparent
+        // Back scrim should be transparent
+        assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
 
         // Pulsing notification should conserve AOD wallpaper.
         mScrimController.transitionTo(ScrimState.PULSING);
         mScrimController.finishAnimationsImmediately();
-
-        assertScrimAlpha(TRANSPARENT /* front */,
-                TRANSPARENT /* back */,
-                TRANSPARENT /* bubble */);
+        assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
     }
 
     @Test
@@ -166,14 +152,11 @@
         mScrimController.setWallpaperSupportsAmbientMode(true);
         mScrimController.transitionTo(ScrimState.AOD);
         mScrimController.finishAnimationsImmediately();
-
-        assertScrimAlpha(TRANSPARENT /* front */,
-                OPAQUE /* back */,
-                TRANSPARENT /* bubble */);
-
-        assertScrimTint(true /* front */,
-                true /* behind */,
-                false /* bubble */);
+        // 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 */);
     }
 
     @Test
@@ -183,14 +166,11 @@
         mScrimController.finishAnimationsImmediately();
         mScrimController.setHasBackdrop(true);
         mScrimController.finishAnimationsImmediately();
-
-        assertScrimAlpha(TRANSPARENT /* front */,
-                OPAQUE /* back */,
-                TRANSPARENT /* bubble */);
-
-        assertScrimTint(true /* front */,
-                true /* behind */,
-                false /* bubble */);
+        // 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 */);
     }
 
     @Test
@@ -199,32 +179,27 @@
         mScrimController.transitionTo(ScrimState.KEYGUARD);
         mScrimController.setAodFrontScrimAlpha(0.5f);
         mScrimController.finishAnimationsImmediately();
-
-        assertScrimAlpha(TRANSPARENT /* front */,
-                SEMI_TRANSPARENT /* back */,
-                TRANSPARENT /* bubble */);
+        // Front scrim should be transparent
+        // Back scrim should be visible without tint
+        assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
 
         // ... but that it does take effect once we enter the AOD state.
         mScrimController.transitionTo(ScrimState.AOD);
         mScrimController.finishAnimationsImmediately();
-        assertScrimAlpha(SEMI_TRANSPARENT /* front */,
-                OPAQUE /* back */,
-                TRANSPARENT /* bubble */);
+        // Front scrim should be semi-transparent
+        // Back scrim should be visible
+        assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
 
         // ... and that if we set it while we're in AOD, it does take immediate effect.
         mScrimController.setAodFrontScrimAlpha(1f);
-        assertScrimAlpha(OPAQUE /* front */,
-                OPAQUE /* back */,
-                TRANSPARENT /* bubble */);
+        assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE);
 
         // ... 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();
-        assertScrimAlpha(OPAQUE /* front */,
-                OPAQUE /* back */,
-                TRANSPARENT /* bubble */);
+        assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE);
 
         // ... and alpha updates should be completely ignored if always_on is off.
         // Passing it forward would mess up the wake-up transition.
@@ -248,36 +223,27 @@
         mScrimController.setWallpaperSupportsAmbientMode(false);
         mScrimController.transitionTo(ScrimState.AOD);
         mScrimController.finishAnimationsImmediately();
-        assertScrimAlpha(TRANSPARENT /* front */,
-                OPAQUE /* back */,
-                TRANSPARENT /* bubble */);
+        assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
 
         mScrimController.transitionTo(ScrimState.PULSING);
         mScrimController.finishAnimationsImmediately();
         // Front scrim should be transparent, but tinted
         // Back scrim should be semi-transparent so the user can see the wallpaper
         // Pulse callback should have been invoked
-        assertScrimAlpha(TRANSPARENT /* front */,
-                OPAQUE /* back */,
-                TRANSPARENT /* bubble */);
-
-        assertScrimTint(true /* front */,
-                true /* behind */,
-                false /* bubble */);
+        assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
+        assertScrimTint(mScrimBehind, true /* tinted */);
 
         // ... and when ambient goes dark, front scrim should be semi-transparent
         mScrimController.setAodFrontScrimAlpha(0.5f);
         mScrimController.finishAnimationsImmediately();
         // Front scrim should be semi-transparent
-        assertScrimAlpha(SEMI_TRANSPARENT /* front */,
-                OPAQUE /* back */,
-                TRANSPARENT /* bubble */);
+        assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT /* front */,
+                VISIBILITY_FULLY_OPAQUE /* back */);
 
         mScrimController.setWakeLockScreenSensorActive(true);
         mScrimController.finishAnimationsImmediately();
-        assertScrimAlpha(SEMI_TRANSPARENT /* front */,
-                SEMI_TRANSPARENT /* back */,
-                TRANSPARENT /* bubble */);
+        assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT /* front */,
+                VISIBILITY_SEMI_TRANSPARENT /* back */);
 
         // Reset value since enums are static.
         mScrimController.setAodFrontScrimAlpha(0f);
@@ -289,13 +255,8 @@
         mScrimController.finishAnimationsImmediately();
         // Front scrim should be transparent
         // Back scrim should be visible without tint
-        assertScrimAlpha(TRANSPARENT /* front */,
-                SEMI_TRANSPARENT /* back */,
-                TRANSPARENT /* bubble */);
-
-        assertScrimTint(false /* front */,
-                false /* behind */,
-                false /* bubble */);
+        assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
+        assertScrimTint(mScrimBehind, false /* tinted */);
     }
 
     @Test
@@ -304,12 +265,8 @@
         mScrimController.finishAnimationsImmediately();
         // Front scrim should be transparent
         // Back scrim should be visible without tint
-        assertScrimAlpha(SEMI_TRANSPARENT /* front */,
-                TRANSPARENT /* back */,
-                TRANSPARENT /* bubble */);
-        assertScrimTint(false /* front */,
-                false /* behind */,
-                false /* bubble */);
+        assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
+        assertScrimTint(mScrimBehind, false /* tinted */);
     }
 
     @Test
@@ -317,19 +274,15 @@
         mScrimController.setPanelExpansion(0f);
         mScrimController.transitionTo(ScrimState.UNLOCKED);
         mScrimController.finishAnimationsImmediately();
-        assertScrimAlpha(TRANSPARENT /* front */,
-                TRANSPARENT /* back */,
-                TRANSPARENT /* bubble */);
-
-        assertScrimTint(false /* front */,
-                false /* behind */,
-                false /* bubble */);
+        // 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 */);
 
         // Back scrim should be visible after start dragging
         mScrimController.setPanelExpansion(0.5f);
-        assertScrimAlpha(TRANSPARENT /* front */,
-                SEMI_TRANSPARENT /* back */,
-                TRANSPARENT /* bubble */);
+        assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
     }
 
     @Test
@@ -337,19 +290,12 @@
         mScrimController.transitionTo(ScrimState.BUBBLE_EXPANDED);
         mScrimController.finishAnimationsImmediately();
 
-        assertScrimTint(false /* front */,
-                false /* behind */,
-                false /* bubble */);
-
         // Front scrim should be transparent
-        Assert.assertEquals(ScrimController.TRANSPARENT,
+        Assert.assertEquals(ScrimController.VISIBILITY_FULLY_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
@@ -418,23 +364,16 @@
         mScrimController.setPanelExpansion(0f);
         mScrimController.finishAnimationsImmediately();
         mScrimController.transitionTo(ScrimState.UNLOCKED);
-
-        // Immediately tinted black after the transition starts
-        assertScrimTint(true /* front */,
-                true /* behind */,
-                true  /* bubble */);
-
+        // Immediately tinted after the transition starts
+        assertScrimTint(mScrimInFront, true /* tinted */);
+        assertScrimTint(mScrimBehind, true /* tinted */);
         mScrimController.finishAnimationsImmediately();
-
-        // All scrims should be transparent at the end of fade transition.
-        assertScrimAlpha(TRANSPARENT /* front */,
-                TRANSPARENT /* behind */,
-                TRANSPARENT /* bubble */);
-
-        // Make sure at the very end of the animation, we're reset to transparent
-        assertScrimTint(false /* front */,
-                false /* behind */,
-                false  /* bubble */);
+        // 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 */);
     }
 
     @Test
@@ -449,11 +388,9 @@
                         // 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(true /* front */,
-                                true /* behind */,
-                                true /* bubble */);
+                        assertScrimTint(mScrimInFront, true /* tinted */);
                         Assert.assertSame("Scrim should be visible during transition.",
-                                mScrimVisibility, OPAQUE);
+                                mScrimVisibility, VISIBILITY_FULLY_OPAQUE);
                     }
                 });
         mScrimController.finishAnimationsImmediately();
@@ -661,15 +598,11 @@
         mScrimController.setKeyguardOccluded(true);
         mScrimController.transitionTo(ScrimState.AOD);
         mScrimController.finishAnimationsImmediately();
-        assertScrimAlpha(TRANSPARENT /* front */,
-                OPAQUE /* behind */,
-                TRANSPARENT /* bubble */);
+        assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
 
         mScrimController.transitionTo(ScrimState.PULSING);
         mScrimController.finishAnimationsImmediately();
-        assertScrimAlpha(TRANSPARENT /* front */,
-                OPAQUE /* behind */,
-                TRANSPARENT /* bubble */);
+        assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
     }
 
     @Test
@@ -677,15 +610,11 @@
         mScrimController.setWallpaperSupportsAmbientMode(true);
         mScrimController.transitionTo(ScrimState.AOD);
         mScrimController.finishAnimationsImmediately();
-        assertScrimAlpha(TRANSPARENT /* front */,
-                TRANSPARENT /* behind */,
-                TRANSPARENT /* bubble */);
+        assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
 
         mScrimController.setKeyguardOccluded(true);
         mScrimController.finishAnimationsImmediately();
-        assertScrimAlpha(TRANSPARENT /* front */,
-                OPAQUE /* behind */,
-                TRANSPARENT /* bubble */);
+        assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
     }
 
     @Test
@@ -724,68 +653,33 @@
                 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(boolean front, boolean behind, boolean bubble) {
+    private void assertScrimTint(ScrimView scrimView, boolean tinted) {
+        final boolean viewIsTinted = scrimView.getTint() != Color.TRANSPARENT;
+        final String name = scrimView == mScrimInFront ? "front" : "back";
         Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
-                        + " 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);
+                +" with scrim: " + name + " and tint: " + Integer.toHexString(scrimView.getTint()),
+                tinted, viewIsTinted);
     }
 
-    private String getScrimName(ScrimView scrim) {
-        if (scrim == mScrimInFront) {
-            return "front";
-        } else if (scrim == mScrimBehind) {
-            return "back";
-        } else if (scrim == mScrimForBubble) {
-            return "bubble";
-        }
-        return "unknown_scrim";
-    }
+    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);
 
-    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;
+        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 = TRANSPARENT;
+            visibility = VISIBILITY_FULLY_TRANSPARENT;
         }
-        Assert.assertEquals("Invalid visibility.",
-                visibility /* expected */,
-                mScrimVisibility);
+        Assert.assertEquals("Invalid visibility.", visibility, mScrimVisibility);
     }
 
     /**
@@ -797,12 +691,11 @@
         boolean mOnPreDrawCalled;
 
         SynchronousScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
-                ScrimView scrimForBubble,
                 TriConsumer<ScrimState, Float, GradientColors> scrimStateListener,
                 Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
                 AlarmManager alarmManager, KeyguardMonitor keyguardMonitor) {
-            super(scrimBehind, scrimInFront, scrimForBubble, scrimStateListener,
-                    scrimVisibleListener, dozeParameters, alarmManager, keyguardMonitor);
+            super(scrimBehind, scrimInFront, scrimStateListener, scrimVisibleListener,
+                    dozeParameters, alarmManager, keyguardMonitor);
         }
 
         @Override
@@ -813,14 +706,13 @@
 
         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");
@@ -858,7 +750,6 @@
 
         /**
          * Do not wait for a frame since we're in a test environment.
-         *
          * @param callback What to execute.
          */
         @Override
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java
index 0bf43b6..2dc2cf0 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -589,16 +589,18 @@
         if (immediate) {
             dtm.setColorMatrix(tintController.getLevel(), to);
         } else {
-            tintController.setAnimator(ValueAnimator.ofObject(COLOR_MATRIX_EVALUATOR,
-                    from == null ? MATRIX_IDENTITY : from, to));
-            tintController.getAnimator().setDuration(TRANSITION_DURATION);
-            tintController.getAnimator().setInterpolator(AnimationUtils.loadInterpolator(
+            TintValueAnimator valueAnimator = TintValueAnimator.ofMatrix(COLOR_MATRIX_EVALUATOR,
+                    from == null ? MATRIX_IDENTITY : from, to);
+            tintController.setAnimator(valueAnimator);
+            valueAnimator.setDuration(TRANSITION_DURATION);
+            valueAnimator.setInterpolator(AnimationUtils.loadInterpolator(
                     getContext(), android.R.interpolator.fast_out_slow_in));
-            tintController.getAnimator().addUpdateListener((ValueAnimator animator) -> {
+            valueAnimator.addUpdateListener((ValueAnimator animator) -> {
                 final float[] value = (float[]) animator.getAnimatedValue();
                 dtm.setColorMatrix(tintController.getLevel(), value);
+                ((TintValueAnimator) animator).updateMinMaxComponents();
             });
-            tintController.getAnimator().addListener(new AnimatorListenerAdapter() {
+            valueAnimator.addListener(new AnimatorListenerAdapter() {
 
                 private boolean mIsCancelled;
 
@@ -609,9 +611,14 @@
 
                 @Override
                 public void onAnimationEnd(Animator animator) {
+                    TintValueAnimator t = (TintValueAnimator) animator;
                     Slog.d(TAG, tintController.getClass().getSimpleName()
                             + " Animation cancelled: " + mIsCancelled
-                            + " to matrix: " + TintController.matrixToString(to, 16));
+                            + " to matrix: " + TintController.matrixToString(to, 16)
+                            + " min matrix coefficients: "
+                            + TintController.matrixToString(t.getMin(), 16)
+                            + " max matrix coefficients: "
+                            + TintController.matrixToString(t.getMax(), 16));
                     if (!mIsCancelled) {
                         // Ensure final color matrix is set at the end of the animation. If the
                         // animation is cancelled then don't set the final color matrix so the new
@@ -621,7 +628,7 @@
                     tintController.setAnimator(null);
                 }
             });
-            tintController.getAnimator().start();
+            valueAnimator.start();
         }
     }
 
@@ -1109,6 +1116,51 @@
     }
 
     /**
+     * Only animates matrices and saves min and max coefficients for logging.
+     */
+    static class TintValueAnimator extends ValueAnimator {
+        private float[] min;
+        private float[] max;
+
+        public static TintValueAnimator ofMatrix(ColorMatrixEvaluator evaluator,
+                Object... values) {
+            TintValueAnimator anim = new TintValueAnimator();
+            anim.setObjectValues(values);
+            anim.setEvaluator(evaluator);
+            if (values == null || values.length == 0) {
+                return null;
+            }
+            float[] m = (float[]) values[0];
+            anim.min = new float[m.length];
+            anim.max = new float[m.length];
+            for (int i = 0; i < m.length; ++i) {
+                anim.min[i] = Float.MAX_VALUE;
+                anim.max[i] = Float.MIN_VALUE;
+            }
+            return anim;
+        }
+
+        public void updateMinMaxComponents() {
+            float[] value = (float[]) getAnimatedValue();
+            if (value == null) {
+                return;
+            }
+            for (int i = 0; i < value.length; ++i) {
+                min[i] = Math.min(min[i], value[i]);
+                max[i] = Math.max(max[i], value[i]);
+            }
+        }
+
+        public float[] getMin() {
+            return min;
+        }
+
+        public float[] getMax() {
+            return max;
+        }
+    }
+
+    /**
      * Interpolates between two 4x4 color transform matrices (in column-major order).
      */
     private static class ColorMatrixEvaluator implements TypeEvaluator<float[]> {
diff --git a/services/core/java/com/android/server/display/color/TintController.java b/services/core/java/com/android/server/display/color/TintController.java
index 8d8b9b2..422dd32 100644
--- a/services/core/java/com/android/server/display/color/TintController.java
+++ b/services/core/java/com/android/server/display/color/TintController.java
@@ -24,14 +24,14 @@
 
 abstract class TintController {
 
-    private ValueAnimator mAnimator;
+    private ColorDisplayService.TintValueAnimator mAnimator;
     private Boolean mIsActivated;
 
-    public ValueAnimator getAnimator() {
+    public ColorDisplayService.TintValueAnimator getAnimator() {
         return mAnimator;
     }
 
-    public void setAnimator(ValueAnimator animator) {
+    public void setAnimator(ColorDisplayService.TintValueAnimator animator) {
         mAnimator = animator;
     }
 
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index b37acf3..8c2145a 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -5353,7 +5353,8 @@
                         public void onError(int errorCode, android.os.ParcelableException detail) {
                             Binder.withCleanCallingIdentity(() ->
                                     executor.execute(() -> callback.onError(
-                                            errorCode, detail.getCause())));
+                                            errorCode,
+                                            detail == null ? null : detail.getCause())));
                         }
                     }, getOpPackageName());
 
@@ -5393,7 +5394,8 @@
                         public void onError(int errorCode, android.os.ParcelableException detail) {
                             Binder.withCleanCallingIdentity(() ->
                                     executor.execute(() -> callback.onError(
-                                            errorCode, detail.getCause())));
+                                            errorCode,
+                                            detail == null ? null : detail.getCause())));
                         }
                     }, getOpPackageName(), workSource);
         } catch (RemoteException ex) {