Draw status bar background in BackgroundFrameRenderer while resizing

To make sure there is always enough contrast between the status bar
icons and the background, we move the drawing for the status bar
background into BackdropFrameRenderer while resizing, so we can
extend the width into the full surface width.

Bug: 24365214
Change-Id: Ifbb10bacf66670c3637f6f6730a8ac47eb1c3939
diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
index b101733..75ca639 100644
--- a/core/java/com/android/internal/policy/BackdropFrameRenderer.java
+++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
@@ -17,6 +17,7 @@
 package com.android.internal.policy;
 
 import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Looper;
 import android.view.Choreographer;
@@ -44,6 +45,7 @@
     // The render nodes for the multi threaded renderer.
     private ThreadedRenderer mRenderer;
     private RenderNode mFrameAndBackdropNode;
+    private RenderNode mSystemBarBackgroundNode;
 
     private final Rect mOldTargetRect = new Rect();
     private final Rect mNewTargetRect = new Rect();
@@ -62,13 +64,16 @@
 
     private Drawable mCaptionBackgroundDrawable;
     private Drawable mResizingBackgroundDrawable;
+    private ColorDrawable mStatusBarColor;
 
     public BackdropFrameRenderer(DecorView decorView, ThreadedRenderer renderer, Rect initialBounds,
-            Drawable resizingBackgroundDrawable, Drawable captionBackgroundDrawable) {
+            Drawable resizingBackgroundDrawable, Drawable captionBackgroundDrawable,
+            int statusBarColor) {
         setName("ResizeFrame");
 
         mRenderer = renderer;
-        onResourcesLoaded(decorView, resizingBackgroundDrawable, captionBackgroundDrawable);
+        onResourcesLoaded(decorView, resizingBackgroundDrawable, captionBackgroundDrawable,
+                statusBarColor);
 
         // Create a render node for the content and frame backdrop
         // which can be resized independently from the content.
@@ -87,10 +92,24 @@
     }
 
     void onResourcesLoaded(DecorView decorView, Drawable resizingBackgroundDrawable,
-            Drawable captionBackgroundDrawableDrawable) {
+            Drawable captionBackgroundDrawableDrawable, int statusBarColor) {
         mDecorView = decorView;
         mResizingBackgroundDrawable = resizingBackgroundDrawable;
         mCaptionBackgroundDrawable = captionBackgroundDrawableDrawable;
+        if (statusBarColor != 0) {
+            mStatusBarColor = new ColorDrawable(statusBarColor);
+            addSystemBarNodeIfNeeded();
+        } else {
+            mStatusBarColor = null;
+        }
+    }
+
+    private void addSystemBarNodeIfNeeded() {
+        if (mSystemBarBackgroundNode != null) {
+            return;
+        }
+        mSystemBarBackgroundNode = RenderNode.create("SystemBarBackgroundNode", null);
+        mRenderer.addRenderNode(mSystemBarBackgroundNode, false);
     }
 
     /**
@@ -132,6 +151,9 @@
                 // Remove the render node again
                 // (see comment above - better to do that only once).
                 mRenderer.removeRenderNode(mFrameAndBackdropNode);
+                if (mSystemBarBackgroundNode != null) {
+                    mRenderer.removeRenderNode(mSystemBarBackgroundNode);
+                }
 
                 mRenderer = null;
 
@@ -232,6 +254,8 @@
         // inaccessible. For that case we remember the previous metrics to avoid flashes.
         // Note that even when there is no visible caption, the caption child will exist.
         final int captionHeight = mDecorView.getCaptionHeight();
+        final int statusBarHeight = mDecorView.getStatusBarHeight();
+
         // The caption height will probably never dynamically change while we are resizing.
         // Once set to something other then 0 it should be kept that way.
         if (captionHeight != 0) {
@@ -256,7 +280,7 @@
         mFrameAndBackdropNode.setLeftTopRightBottom(left, top, left + width, top + height);
 
         // Draw the caption and content backdrops in to our render node.
-        final DisplayListCanvas canvas = mFrameAndBackdropNode.start(width, height);
+        DisplayListCanvas canvas = mFrameAndBackdropNode.start(width, height);
         mCaptionBackgroundDrawable.setBounds(0, 0, left + width, top + mLastCaptionHeight);
         mCaptionBackgroundDrawable.draw(canvas);
 
@@ -265,6 +289,15 @@
         mResizingBackgroundDrawable.draw(canvas);
         mFrameAndBackdropNode.end(canvas);
 
+        if (mSystemBarBackgroundNode != null && mStatusBarColor != null) {
+            canvas = mSystemBarBackgroundNode.start(width, height);
+            mSystemBarBackgroundNode.setLeftTopRightBottom(left, top, left + width, top + height);
+            mStatusBarColor.setBounds(0, 0, left + width, statusBarHeight);
+            mStatusBarColor.draw(canvas);
+            mSystemBarBackgroundNode.end(canvas);
+            mRenderer.drawRenderNode(mSystemBarBackgroundNode);
+        }
+
         // We need to render the node explicitly
         mRenderer.drawRenderNode(mFrameAndBackdropNode);
 
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 8b400d3..9107b1f 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -949,6 +949,14 @@
                 : Color.BLACK;
     }
 
+    private int getCurrentColor(ColorViewState state) {
+        if (state.visible) {
+            return state.color;
+        } else {
+            return 0;
+        }
+    }
+
     /**
      * Update a color view
      *
@@ -970,6 +978,7 @@
         boolean show = state.present
                 && (color & Color.BLACK) != 0
                 && ((mWindow.getAttributes().flags & state.translucentFlag) == 0  || force);
+        boolean showView = show && !isResizing();
 
         boolean visibilityChanged = false;
         View view = state.view;
@@ -979,7 +988,7 @@
         int resolvedGravity = verticalBar ? state.horizontalGravity : state.verticalGravity;
 
         if (view == null) {
-            if (show) {
+            if (showView) {
                 state.view = view = new View(mContext);
                 view.setBackgroundColor(color);
                 view.setTransitionName(state.transitionName);
@@ -995,7 +1004,7 @@
                 updateColorViewTranslations();
             }
         } else {
-            int vis = show ? VISIBLE : INVISIBLE;
+            int vis = showView ? VISIBLE : INVISIBLE;
             visibilityChanged = state.targetVisibility != vis;
             state.targetVisibility = vis;
             LayoutParams lp = (LayoutParams) view.getLayoutParams();
@@ -1007,14 +1016,14 @@
                 lp.rightMargin = rightMargin;
                 view.setLayoutParams(lp);
             }
-            if (show) {
+            if (showView) {
                 view.setBackgroundColor(color);
             }
         }
         if (visibilityChanged) {
             view.animate().cancel();
-            if (animate) {
-                if (show) {
+            if (animate && !isResizing()) {
+                if (showView) {
                     if (view.getVisibility() != VISIBLE) {
                         view.setVisibility(VISIBLE);
                         view.setAlpha(0.0f);
@@ -1034,9 +1043,11 @@
                 }
             } else {
                 view.setAlpha(1.0f);
-                view.setVisibility(show ? VISIBLE : INVISIBLE);
+                view.setVisibility(showView ? VISIBLE : INVISIBLE);
             }
         }
+        state.visible = show;
+        state.color = color;
     }
 
     private void updateColorViewTranslations() {
@@ -1568,7 +1579,8 @@
 
         if (mBackdropFrameRenderer != null) {
             mBackdropFrameRenderer.onResourcesLoaded(
-                    this, mResizingBackgroundDrawable, mCaptionBackgroundDrawable);
+                    this, mResizingBackgroundDrawable, mCaptionBackgroundDrawable,
+                    getCurrentColor(mStatusColorViewState));
         }
 
         mDecorCaptionView = createDecorCaptionView(inflater);
@@ -1715,18 +1727,22 @@
         final ThreadedRenderer renderer = (ThreadedRenderer) getHardwareRenderer();
         if (renderer != null) {
             mBackdropFrameRenderer = new BackdropFrameRenderer(this, renderer,
-                    initialBounds, mResizingBackgroundDrawable, mCaptionBackgroundDrawable);
+                    initialBounds, mResizingBackgroundDrawable, mCaptionBackgroundDrawable,
+                    getCurrentColor(mStatusColorViewState));
 
             // Get rid of the shadow while we are resizing. Shadow drawing takes considerable time.
             // If we want to get the shadow shown while resizing, we would need to elevate a new
             // element which owns the caption and has the elevation.
             updateElevation();
+
+            updateColorViews(null /* insets */, false);
         }
     }
 
     @Override
     public void onWindowDragResizeEnd() {
         releaseThreadedRenderer();
+        updateColorViews(null /* insets */, false);
     }
 
     @Override
@@ -1759,6 +1775,10 @@
         }
     }
 
+    private boolean isResizing() {
+        return mBackdropFrameRenderer != null;
+    }
+
     /**
      * The elevation gets set for the first time and the framework needs to be informed that
      * the surface layer gets created with the shadow size in mind.
@@ -1774,8 +1794,7 @@
         final boolean wasAdjustedForStack = mElevationAdjustedForStack;
         // Do not use a shadow when we are in resizing mode (mBackdropFrameRenderer not null)
         // since the shadow is bound to the content size and not the target size.
-        if (ActivityManager.StackId.hasWindowShadow(mStackId)
-                && mBackdropFrameRenderer == null) {
+        if (ActivityManager.StackId.hasWindowShadow(mStackId) && !isResizing()) {
             elevation = hasWindowFocus() ?
                     DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP : DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
             // TODO(skuhne): Remove this if clause once b/22668382 got fixed.
@@ -1805,6 +1824,10 @@
         return isShowingCaption() ? mDecorCaptionView.getCaptionHeight() : 0;
     }
 
+    int getStatusBarHeight() {
+        return mStatusColorViewState.view != null ? mStatusColorViewState.view.getHeight() : 0;
+    }
+
     /**
      * Converts a DIP measure into physical pixels.
      * @param dip The dip value.
@@ -1819,6 +1842,8 @@
         View view = null;
         int targetVisibility = View.INVISIBLE;
         boolean present = false;
+        boolean visible;
+        int color;
 
         final int id;
         final int systemUiHideFlag;