Fix issue #3222014: Dragging items around home screen is unresponsive

Also make the dim fade duration configurable, with a configured value
that more closely matches what UX wants.

Change-Id: Id32e2de14a2a2003d8fade6331377d8d723ac397
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index a91574e..b3ea836 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -59,6 +59,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
 import android.graphics.Paint;
@@ -200,10 +201,6 @@
      */
     static final int DEFAULT_FADE_IN_OUT_DURATION = 400;
 
-    /** Adjustment to time to perform a dim, to make it more dramatic.
-     */
-    static final int DIM_DURATION_MULTIPLIER = 6;
-    
     // Maximum number of milliseconds to wait for input event injection.
     // FIXME is this value reasonable?
     private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000;
@@ -6627,6 +6624,7 @@
         final Rect mContainingFrame = new Rect();
         final Rect mDisplayFrame = new Rect();
         final Rect mContentFrame = new Rect();
+        final Rect mParentFrame = new Rect();
         final Rect mVisibleFrame = new Rect();
 
         boolean mContentChanged;
@@ -6832,8 +6830,12 @@
                 h = mAttrs.height== mAttrs.MATCH_PARENT ? ph : mRequestedHeight;
             }
 
+            if (!mParentFrame.equals(pf)) {
+                mParentFrame.set(pf);
+                mContentChanged = true;
+            }
+
             final Rect content = mContentFrame;
-            mContentChanged |= !content.equals(cf);
             content.set(cf);
 
             final Rect visible = mVisibleFrame;
@@ -7699,6 +7701,21 @@
                     && !mDrawPending && !mCommitDrawPending;
         }
 
+        /**
+         * Return whether this window is wanting to have a translation
+         * animation applied to it for an in-progress move.  (Only makes
+         * sense to call from performLayoutAndPlaceSurfacesLockedInner().)
+         */
+        boolean shouldAnimateMove() {
+            return mContentChanged && !mAnimating && !mLastHidden && !mDisplayFrozen
+                    && (mFrame.top != mLastFrame.top
+                            || mFrame.left != mLastFrame.left)
+                    && (mAttachedWindow == null
+                            || (mAttachedWindow.mAnimation == null
+                                    && !mAttachedWindow.shouldAnimateMove()))
+                    && mPolicy.isScreenOn();
+        }
+
         boolean needsBackgroundFiller(int screenWidth, int screenHeight) {
             return
                  // only if the application is requesting compatible window
@@ -7925,6 +7942,8 @@
                     pw.println();
             pw.print(prefix); pw.print("mContainingFrame=");
                     mContainingFrame.printShortString(pw);
+                    pw.print(" mParentFrame=");
+                    mParentFrame.printShortString(pw);
                     pw.print(" mDisplayFrame=");
                     mDisplayFrame.printShortString(pw);
                     pw.println();
@@ -9157,11 +9176,11 @@
                     || win.mAttachedHidden
                     || win.mExiting || win.mDestroying;
 
-            if (!win.mLayoutAttached) {
-                if (DEBUG_LAYOUT) Slog.v(TAG, "First pass " + win
+            if (DEBUG_LAYOUT && !win.mLayoutAttached) {
+                Slog.v(TAG, "First pass " + win
                         + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
                         + " mLayoutAttached=" + win.mLayoutAttached);
-                if (DEBUG_LAYOUT && gone) Slog.v(TAG, "  (mViewVisibility="
+                if (gone) Slog.v(TAG, "  (mViewVisibility="
                         + win.mViewVisibility + " mRelayoutCalled="
                         + win.mRelayoutCalled + " hidden="
                         + win.mRootToken.hidden + " hiddenRequested="
@@ -9198,16 +9217,16 @@
         for (i = topAttached; i >= 0; i--) {
             WindowState win = mWindows.get(i);
 
-            // If this view is GONE, then skip it -- keep the current
-            // frame, and let the caller know so they can ignore it
-            // if they want.  (We do the normal layout for INVISIBLE
-            // windows, since that means "perform layout as normal,
-            // just don't display").
             if (win.mLayoutAttached) {
                 if (DEBUG_LAYOUT) Slog.v(TAG, "Second pass " + win
                         + " mHaveFrame=" + win.mHaveFrame
                         + " mViewVisibility=" + win.mViewVisibility
                         + " mRelayoutCalled=" + win.mRelayoutCalled);
+                // If this view is GONE, then skip it -- keep the current
+                // frame, and let the caller know so they can ignore it
+                // if they want.  (We do the normal layout for INVISIBLE
+                // windows, since that means "perform layout as normal,
+                // just don't display").
                 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
                         || !win.mHaveFrame) {
                     if (initial) {
@@ -9390,10 +9409,7 @@
                         // content frame changing, then we'd like to animate
                         // it.  The checks here are ordered by what is least
                         // likely to be true first.
-                        if (w.mContentChanged && !wasAnimating && !w.mLastHidden && !mDisplayFrozen
-                                && (w.mFrame.top != w.mLastFrame.top
-                                        || w.mFrame.left != w.mLastFrame.left)
-                                && mPolicy.isScreenOn()) {
+                        if (w.shouldAnimateMove()) {
                             // Frame has moved, containing content frame
                             // has also moved, and we're not currently animating...
                             // let's do something.
@@ -9402,6 +9418,7 @@
                             w.setAnimation(a);
                             animDw = w.mLastFrame.left - w.mFrame.left;
                             animDh = w.mLastFrame.top - w.mFrame.top;
+                            w.mContentChanged = false;
                         }
 
                         // Execute animation.
@@ -10265,7 +10282,8 @@
                                     mDimAnimator = new DimAnimator(mFxSession);
                                 }
                                 mDimAnimator.show(dw, dh);
-                                mDimAnimator.updateParameters(w, currentTime);
+                                mDimAnimator.updateParameters(mContext.getResources(),
+                                        w, currentTime);
                             }
                         }
                         if ((attrFlags&FLAG_BLUR_BEHIND) != 0) {
@@ -11327,7 +11345,7 @@
          * Set's the dim surface's layer and update dim parameters that will be used in
          * {@link updateSurface} after all windows are examined.
          */
-        void updateParameters(WindowState w, long currentTime) {
+        void updateParameters(Resources res, WindowState w, long currentTime) {
             mDimSurface.setLayer(w.mAnimLayer-1);
 
             final float target = w.mExiting ? 0 : w.mAttrs.dimAmount;
@@ -11341,11 +11359,15 @@
                         ? w.mAnimation.computeDurationHint()
                         : DEFAULT_DIM_DURATION;
                 if (target > mDimTargetAlpha) {
-                    // This is happening behind the activity UI,
-                    // so we can make it run a little longer to
-                    // give a stronger impression without disrupting
-                    // the user.
-                    duration *= DIM_DURATION_MULTIPLIER;
+                    TypedValue tv = new TypedValue();
+                    res.getValue(com.android.internal.R.fraction.config_dimBehindFadeDuration,
+                            tv, true);
+                    if (tv.type == TypedValue.TYPE_FRACTION) {
+                        duration = (long)tv.getFraction((float)duration, (float)duration);
+                    } else if (tv.type >= TypedValue.TYPE_FIRST_INT
+                            && tv.type <= TypedValue.TYPE_LAST_INT) {
+                        duration = tv.data;
+                    }
                 }
                 if (duration < 1) {
                     // Don't divide by zero