Added support for resizing background color for an app window

R.styleable.Window_windowResizingBackground allows an activity to
specify the background drawable that should be used when it is being
resized in multi-window mode. If unset, the system will try to use
R.styleable.Window_windowBackground if set, then
R.styleable.Window_windowBackgroundFallback if set. Otherwise, the
system default resizing background color set by
R.integer.config_windowResizingBackgroundColorARGB.

Also, use decor title color as caption background color when resizing
instead of black.

Bug: 24534744
Change-Id: I83313865b4044b976ebc78d598e14e17e0f37212
diff --git a/api/current.txt b/api/current.txt
index 3637f14..eb6ad09 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1420,6 +1420,7 @@
     field public static final int windowNoTitle = 16842838; // 0x1010056
     field public static final int windowOverscan = 16843727; // 0x10103cf
     field public static final int windowReenterTransition = 16843951; // 0x10104af
+    field public static final int windowResizingBackground = 16844035; // 0x1010503
     field public static final int windowReturnTransition = 16843950; // 0x10104ae
     field public static final int windowSharedElementEnterTransition = 16843833; // 0x1010439
     field public static final int windowSharedElementExitTransition = 16843834; // 0x101043a
diff --git a/api/system-current.txt b/api/system-current.txt
index 0c3a49c..8410cf6 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1516,6 +1516,7 @@
     field public static final int windowNoTitle = 16842838; // 0x1010056
     field public static final int windowOverscan = 16843727; // 0x10103cf
     field public static final int windowReenterTransition = 16843951; // 0x10104af
+    field public static final int windowResizingBackground = 16844035; // 0x1010503
     field public static final int windowReturnTransition = 16843950; // 0x10104ae
     field public static final int windowSharedElementEnterTransition = 16843833; // 0x1010439
     field public static final int windowSharedElementExitTransition = 16843834; // 0x101043a
diff --git a/core/java/com/android/internal/policy/DecorContext.java b/core/java/com/android/internal/policy/DecorContext.java
index 4f17c39..aa603c1 100644
--- a/core/java/com/android/internal/policy/DecorContext.java
+++ b/core/java/com/android/internal/policy/DecorContext.java
@@ -17,6 +17,7 @@
 package com.android.internal.policy;
 
 import android.content.Context;
+import android.content.res.TypedArray;
 import android.view.ContextThemeWrapper;
 import android.view.WindowManager;
 import android.view.WindowManagerImpl;
@@ -30,6 +31,7 @@
 class DecorContext extends ContextThemeWrapper {
     private PhoneWindow mPhoneWindow;
     private WindowManager mWindowManager;
+    private TypedArray mWindowStyle;
 
     public DecorContext(Context context) {
         super(context, null);
@@ -52,4 +54,13 @@
         }
         return super.getSystemService(name);
     }
+
+    public TypedArray getWindowStyle() {
+        synchronized (this) {
+            if (mWindowStyle == null) {
+                mWindowStyle = obtainStyledAttributes(com.android.internal.R.styleable.Window);
+            }
+            return mWindowStyle;
+        }
+    }
 }
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 75ad916a..3faa46f 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -19,7 +19,6 @@
 import static android.app.ActivityManager.FIRST_DYNAMIC_STACK_ID;
 import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.HOME_STACK_ID;
 import static android.app.ActivityManager.INVALID_STACK_ID;
 import static android.view.View.MeasureSpec.AT_MOST;
 import static android.view.View.MeasureSpec.EXACTLY;
@@ -32,8 +31,7 @@
 import android.animation.ObjectAnimator;
 import android.app.ActivityManagerNative;
 import android.app.SearchManager;
-import android.content.ContextWrapper;
-import android.content.res.Resources;
+import android.graphics.drawable.ColorDrawable;
 import android.os.Build;
 import android.os.UserHandle;
 
@@ -4228,7 +4226,8 @@
                 }
             }
             nonClientDecorView.setPhoneWindow(this, hasNonClientDecor(mWorkspaceId),
-                    nonClientDecorHasShadow(mWorkspaceId));
+                    nonClientDecorHasShadow(mWorkspaceId), getResizingBackgroundDrawable(),
+                    mDecor.getContext().getDrawable(R.drawable.non_client_decor_title_focused));
         }
         // Tell the decor if it has a visible non client decor.
         mDecor.enableNonClientDecor(nonClientDecorView != null && hasNonClientDecor(mWorkspaceId));
@@ -5409,7 +5408,7 @@
      * @param workspaceId The Id of the workspace which contains this window.
      * @Return Returns true if the window should show a non client decor.
      **/
-    private boolean hasNonClientDecor(int workspaceId) {
+    private static boolean hasNonClientDecor(int workspaceId) {
         return workspaceId == FREEFORM_WORKSPACE_STACK_ID;
     }
 
@@ -5432,4 +5431,44 @@
             }
         }
     }
+
+    /**
+     * Returns the color used to fill areas the app has not rendered content to yet when the user
+     * is resizing the window of an activity in multi-window mode.
+     * */
+    private Drawable getResizingBackgroundDrawable() {
+        final Context context = mDecor.getContext();
+        final TypedArray windowStyle;
+        if (context instanceof DecorContext) {
+            windowStyle = ((DecorContext) context).getWindowStyle();
+        } else {
+            windowStyle = getWindowStyle();
+        }
+        final int resourceId =
+                windowStyle.getResourceId(R.styleable.Window_windowResizingBackground, 0);
+        if (resourceId != 0) {
+            return context.getDrawable(resourceId);
+        }
+
+        // The app didn't set a resizing background color. In this case we try to use the app's
+        // background drawable for the resizing background.
+        if (mBackgroundResource != 0) {
+            final Drawable drawable = context.getDrawable(mBackgroundResource);
+            if (drawable != null) {
+                return drawable;
+            }
+        }
+
+        // The app background drawable isn't currently set. This might be because the app cleared
+        // it. In this case we try to use the app's background fallback drawable.
+        if (mBackgroundFallbackResource != 0) {
+            final Drawable fallbackDrawable = context.getDrawable(mBackgroundFallbackResource);
+            if (fallbackDrawable != null) {
+                return fallbackDrawable;
+            }
+        }
+
+        return new ColorDrawable(context.getResources().getInteger(
+                com.android.internal.R.integer.config_windowResizingBackgroundColorARGB));
+    }
 }
diff --git a/core/java/com/android/internal/widget/NonClientDecorView.java b/core/java/com/android/internal/widget/NonClientDecorView.java
index ed7492a..5d502c9 100644
--- a/core/java/com/android/internal/widget/NonClientDecorView.java
+++ b/core/java/com/android/internal/widget/NonClientDecorView.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.graphics.Color;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
 import android.os.Looper;
 import android.os.RemoteException;
 import android.util.AttributeSet;
@@ -52,7 +53,7 @@
  * <li>The resize handles which allow to resize the window.</li>
  * </ul>
  * After creating the view, the function
- * {@link #setPhoneWindow(PhoneWindow owner, boolean windowHasShadow)} needs to be called to make
+ * {@link #setPhoneWindow} needs to be called to make
  * the connection to it's owning PhoneWindow.
  * Note: At this time the application can change various attributes of the DecorView which
  * will break things (in settle/unexpected ways):
@@ -97,6 +98,9 @@
     // The resize frame renderer.
     private ResizeFrameThread mFrameRendererThread = null;
 
+    private Drawable mResizingBackgroundDrawable;
+    private Drawable mCaptionBackgroundDrawable;
+
     public NonClientDecorView(Context context) {
         super(context);
     }
@@ -133,10 +137,13 @@
         }
     }
 
-    public void setPhoneWindow(PhoneWindow owner, boolean showDecor, boolean windowHasShadow) {
+    public void setPhoneWindow(PhoneWindow owner, boolean showDecor, boolean windowHasShadow,
+            Drawable resizingBackgroundDrawable, Drawable captionBackgroundDrawableDrawable) {
         mOwner = owner;
         mWindowHasShadow = windowHasShadow;
         mShowDecor = showDecor;
+        mResizingBackgroundDrawable = resizingBackgroundDrawable;
+        mCaptionBackgroundDrawable = captionBackgroundDrawableDrawable;
         updateCaptionVisibility();
         if (mWindowHasShadow) {
             initializeElevation();
@@ -624,7 +631,8 @@
             // barely show while the entire screen is moving.
             mFrameNode.setLeftTopRightBottom(left, top, left + width, top + mLastCaptionHeight);
             DisplayListCanvas canvas = mFrameNode.start(width, height);
-            canvas.drawColor(Color.BLACK);
+            mCaptionBackgroundDrawable.setBounds(0, 0, left + width, top + mLastCaptionHeight);
+            mCaptionBackgroundDrawable.draw(canvas);
             mFrameNode.end(canvas);
 
             mBackdropNode.setLeftTopRightBottom(left, top + mLastCaptionHeight, left + width,
@@ -632,9 +640,8 @@
 
             // The backdrop: clear everything with the background. Clipping is done elsewhere.
             canvas = mBackdropNode.start(width, height - mLastCaptionHeight);
-            // TODO(skuhne): mOwner.getDecorView().mBackgroundFallback.draw(..) - or similar.
-            // Note: This might not work (calculator for example uses a transparent background).
-            canvas.drawColor(0xff808080);
+            mResizingBackgroundDrawable.setBounds(0, 0, left + width, top + height);
+            mResizingBackgroundDrawable.draw(canvas);
             mBackdropNode.end(canvas);
 
             // We need to render both rendered nodes explicitly.
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index b818fe0..90306fd 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -325,6 +325,12 @@
              has been set to null. This protects against seeing visual garbage in the
              surface when the app has not drawn any content into this area. -->
         <attr name="windowBackgroundFallback" format="reference" />
+        <!-- Drawable used to fill in areas the app has not rendered content to yet when the user is
+             resizing the window of an activity that has {@link android.R.attr#resizeableActivity}
+             set for multi-window mode. If unset, the system will try to use windowBackground if
+             set, then windowBackgroundFallback if set. Otherwise, the system default resizing
+             background color -->
+        <attr name="windowResizingBackground" format="reference" />
         <!-- Drawable to use as a frame around the window. -->
         <attr name="windowFrame" format="reference" />
         <!-- Flag indicating whether there should be no title on this window. -->
@@ -1841,6 +1847,7 @@
     <declare-styleable name="Window">
         <attr name="windowBackground" />
         <attr name="windowBackgroundFallback" />
+        <attr name="windowResizingBackground" />
         <attr name="windowContentOverlay" />
         <attr name="windowFrame" />
         <attr name="windowNoTitle" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f833719..1c8062d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2349,6 +2349,9 @@
          is non-interactive. -->
     <bool name="config_cameraDoubleTapPowerGestureEnabled">true</bool>
 
+    <!-- Default background color to use when resizing a window if the app didn't specify one. -->
+    <integer name="config_windowResizingBackgroundColorARGB">0xFF808080</integer>
+
     <!-- Name of the component to handle network policy notifications. If present,
          disables NetworkPolicyManagerService's presentation of data-usage notifications. -->
     <string translatable="false" name="config_networkPolicyNotificationComponent"></string>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 957cb50..839e81b 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2677,6 +2677,7 @@
     <public type="attr" name="level" />
     <public type="attr" name="contextPopupMenuStyle" />
     <public type="attr" name="textAppearancePopupMenuHeader" />
+    <public type="attr" name="windowResizingBackground" />
 
     <public type="style" name="Theme.Material.DayNight" />
     <public type="style" name="Theme.Material.DayNight.DarkActionBar" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1239b87..3ce8ec5 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1956,6 +1956,7 @@
   <java-symbol type="id" name="close_window" />
   <java-symbol type="layout" name="non_client_decor_light" />
   <java-symbol type="layout" name="non_client_decor_dark" />
+  <java-symbol type="drawable" name="non_client_decor_title_focused" />
 
   <!-- From TelephonyProvider -->
   <java-symbol type="xml" name="apns" />
@@ -2330,4 +2331,6 @@
   <java-symbol type="drawable" name="platlogo_m" />
 
   <java-symbol type="string" name="config_iccHotswapPromptForRestartDialogComponent" />
+
+  <java-symbol type="integer" name="config_windowResizingBackgroundColorARGB" />
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 8241ddf..8f634e1 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -36,6 +36,7 @@
     <style name="RecentsTheme.Wallpaper">
         <!-- Wallpaper -->
         <item name="android:windowBackground">@color/transparent</item>
+        <item name="android:windowResizingBackground">@color/transparent</item>
         <item name="android:colorBackgroundCacheHint">@null</item>
         <item name="android:windowShowWallpaper">true</item>
     </style>