Allow customization of background fade duration.

Bug 15195468

Change-Id: I02c1ef446cfa8aaedce640ab5694b6d9245bb9f7
diff --git a/api/current.txt b/api/current.txt
index 991186f..1973da5 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1343,6 +1343,7 @@
     field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c
     field public static final int windowTitleSize = 16842842; // 0x101005a
     field public static final int windowTitleStyle = 16842843; // 0x101005b
+    field public static final int windowTransitionBackgroundFadeDuration = 16843875; // 0x1010463
     field public static final int windowTranslucentNavigation = 16843760; // 0x10103f0
     field public static final int windowTranslucentStatus = 16843759; // 0x10103ef
     field public static final int writePermission = 16842760; // 0x1010008
@@ -33518,6 +33519,7 @@
     method public android.transition.Transition getSharedElementEnterTransition();
     method public android.transition.Transition getSharedElementExitTransition();
     method public abstract int getStatusBarColor();
+    method public long getTransitionBackgroundFadeDuration();
     method public android.transition.TransitionManager getTransitionManager();
     method public abstract int getVolumeControlStream();
     method public android.view.WindowManager getWindowManager();
@@ -33576,6 +33578,7 @@
     method public abstract void setStatusBarColor(int);
     method public abstract void setTitle(java.lang.CharSequence);
     method public abstract deprecated void setTitleColor(int);
+    method public void setTransitionBackgroundFadeDuration(long);
     method public void setTransitionManager(android.transition.TransitionManager);
     method public void setType(int);
     method public void setUiOptions(int);
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index 1f3218b..0cccedc 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -129,9 +129,6 @@
     protected static final String KEY_SCALE_TYPE = "shared_element:scaleType";
     protected static final String KEY_IMAGE_MATRIX = "shared_element:imageMatrix";
 
-    // The background fade in/out duration. TODO: Enable tuning this.
-    public static final int FADE_BACKGROUND_DURATION_MS = 300;
-
     protected static final ImageView.ScaleType[] SCALE_TYPE_VALUES = ImageView.ScaleType.values();
 
     /**
@@ -512,6 +509,10 @@
         return bundle;
     }
 
+    protected long getFadeDuration() {
+        return getWindow().getTransitionBackgroundFadeDuration();
+    }
+
     /**
      * Captures placement information for Views with a shared element name for
      * Activity Transitions.
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index 779e3de..f54cb87 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -66,15 +66,16 @@
         Bundle resultReceiverBundle = new Bundle();
         resultReceiverBundle.putParcelable(KEY_REMOTE_RECEIVER, this);
         mResultReceiver.send(MSG_SET_REMOTE_RECEIVER, resultReceiverBundle);
-        getDecor().getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
-            @Override
-            public boolean onPreDraw() {
-                if (mIsReadyForTransition) {
-                    getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
-                }
-                return mIsReadyForTransition;
-            }
-        });
+        getDecor().getViewTreeObserver().addOnPreDrawListener(
+                new ViewTreeObserver.OnPreDrawListener() {
+                    @Override
+                    public boolean onPreDraw() {
+                        if (mIsReadyForTransition) {
+                            getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
+                        }
+                        return mIsReadyForTransition;
+                    }
+                });
     }
 
     public void viewsReady(ArrayList<String> accepted, ArrayList<String> localNames) {
@@ -315,7 +316,7 @@
             if (background != null) {
                 background = background.mutate();
                 mBackgroundAnimator = ObjectAnimator.ofInt(background, "alpha", 255);
-                mBackgroundAnimator.setDuration(FADE_BACKGROUND_DURATION_MS);
+                mBackgroundAnimator.setDuration(getFadeDuration());
                 mBackgroundAnimator.addListener(new AnimatorListenerAdapter() {
                     @Override
                     public void onAnimationEnd(Animator animation) {
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index ba1638ff..8d5b8317 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -199,7 +199,7 @@
                     }
                 }
             });
-            mBackgroundAnimator.setDuration(FADE_BACKGROUND_DURATION_MS);
+            mBackgroundAnimator.setDuration(getFadeDuration());
             mBackgroundAnimator.start();
         }
     }
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index ecc4586..0120875 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1516,6 +1516,29 @@
     public boolean getAllowExitTransitionOverlap() { return true; }
 
     /**
+     * Returns the duration, in milliseconds, of the window background fade
+     * when transitioning into or away from an Activity when called with an Activity Transition.
+     * <p>When executing the enter transition, the background starts transparent
+     * and fades in. This requires {@link #FEATURE_CONTENT_TRANSITIONS}. The default is
+     * 300 milliseconds.</p>
+     * @return The duration of the window background fade to opaque during enter transition.
+     * @see #getEnterTransition()
+     */
+    public long getTransitionBackgroundFadeDuration() { return 0; }
+
+    /**
+     * Sets the duration, in milliseconds, of the window background fade
+     * when transitioning into or away from an Activity when called with an Activity Transition.
+     * <p>When executing the enter transition, the background starts transparent
+     * and fades in. This requires {@link #FEATURE_CONTENT_TRANSITIONS}. The default is
+     * 300 milliseconds.</p>
+     * @param fadeDurationMillis The duration of the window background fade to or from opaque
+     *                           during enter transition.
+     * @see #setEnterTransition(android.transition.Transition)
+     */
+    public void setTransitionBackgroundFadeDuration(long fadeDurationMillis) { }
+
+    /**
      * @return the color of the status bar.
      */
     public abstract int getStatusBarColor();
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 2fea91e..90162f4 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -496,6 +496,12 @@
         <!-- Internal layout used internally for window decor -->
         <attr name="windowActionBarFullscreenDecorLayout" format="reference" />
 
+        <!-- The duration, in milliseconds, of the window background fade duration
+             when transitioning into or away from an Activity when called with an
+             Activity Transition. Corresponds to
+             {@link android.view.Window#setTransitionBackgroundFadeDuration(long)}. -->
+        <attr name="windowTransitionBackgroundFadeDuration" format="integer"/>
+
         <!-- ============ -->
         <!-- Alert Dialog styles -->
         <!-- ============ -->
@@ -1813,6 +1819,11 @@
              Corresponds to {@link android.view.Window#setNavigationBarColor(int)}. -->
         <attr name="navigationBarColor" format="color" />
 
+        <!-- The duration, in milliseconds, of the window background fade duration
+             when transitioning into or away from an Activity when called with an
+             Activity Transition. Corresponds to
+             {@link android.view.Window#setTransitionBackgroundFadeDuration(long)}. -->
+        <attr name="windowTransitionBackgroundFadeDuration" />
     </declare-styleable>
 
     <!-- The set of attributes that describe a AlertDialog's theme. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 2792c93..0ea8cf4 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2188,6 +2188,7 @@
   <public type="attr" name="searchKeyphraseId" />
   <public type="attr" name="searchKeyphrase" />
   <public type="attr" name="searchKeyphraseSupportedLocales" />
+  <public type="attr" name="windowTransitionBackgroundFadeDuration" />
 
   <public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index a8645bc..81dcc62 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -118,6 +118,9 @@
     private final static String TAG = "PhoneWindow";
 
     private final static boolean SWEEP_OPEN_MENU = false;
+
+    private final static int DEFAULT_BACKGROUND_FADE_DURATION_MS = 300;
+
     /**
      * Simple callback used by the context menu and its submenus. The options
      * menu submenus do not use this (their behavior is more complex).
@@ -246,6 +249,7 @@
     private Transition mSharedElementExitTransition;
     private Boolean mAllowExitTransitionOverlap;
     private Boolean mAllowEnterTransitionOverlap;
+    private long mBackgroundFadeDurationMillis = -1;
 
     static class WindowManagerHolder {
         static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface(
@@ -3419,6 +3423,12 @@
                             com.android.internal.R.styleable.
                                     Window_windowAllowExitTransitionOverlap, true);
                 }
+                if (mBackgroundFadeDurationMillis < 0) {
+                    mBackgroundFadeDurationMillis = getWindowStyle().getInteger(
+                            com.android.internal.R.styleable.
+                                    Window_windowTransitionBackgroundFadeDuration,
+                            DEFAULT_BACKGROUND_FADE_DURATION_MS);
+                }
             }
         }
     }
@@ -3825,6 +3835,20 @@
         return (mAllowExitTransitionOverlap == null) ? true : mAllowExitTransitionOverlap;
     }
 
+    @Override
+    public long getTransitionBackgroundFadeDuration() {
+        return (mBackgroundFadeDurationMillis < 0) ? DEFAULT_BACKGROUND_FADE_DURATION_MS
+                : mBackgroundFadeDurationMillis;
+    }
+
+    @Override
+    public void setTransitionBackgroundFadeDuration(long fadeDurationMillis) {
+        if (fadeDurationMillis < 0) {
+            throw new IllegalArgumentException("negative durations are not allowed");
+        }
+        mBackgroundFadeDurationMillis = fadeDurationMillis;
+    }
+
     private static final class DrawableFeatureState {
         DrawableFeatureState(int _featureId) {
             featureId = _featureId;