OSDN Git Service

Fixing crash in recents window transition. (Bug 18246975, 18159006)
authorWinson Chung <winsonc@google.com>
Wed, 5 Nov 2014 00:15:22 +0000 (16:15 -0800)
committerWinson Chung <winsonc@google.com>
Wed, 5 Nov 2014 02:04:09 +0000 (18:04 -0800)
The recents transition requires synchronizing the thumbnail header (the bar
that animates on top of the window that is being scaled/cropped) and the
application window.  This change simplifies the code and removes the notion
of having another animator manage the same surface, and instead ensures that
the thumbnail animation has the same duration and that the thumbnail animation
is deferred and cleaned up one frame after the app transition is complete.

Change-Id: If8f348afccf59327187e8498eb451ba066600a41

services/core/java/com/android/server/wm/AppTransition.java
services/core/java/com/android/server/wm/AppWindowAnimator.java
services/core/java/com/android/server/wm/WindowManagerService.java
services/core/java/com/android/server/wm/WindowStateAnimator.java

index bfc7659..eeb007c 100644 (file)
@@ -691,8 +691,10 @@ public class AppTransition implements Dump {
                 throw new RuntimeException("Invalid thumbnail transition state");
         }
 
-        return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight,
-                THUMBNAIL_APP_TRANSITION_DURATION, mThumbnailFastOutSlowInInterpolator);
+        int duration = Math.max(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION,
+                THUMBNAIL_APP_TRANSITION_DURATION);
+        return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, duration,
+                mThumbnailFastOutSlowInInterpolator);
     }
 
     /**
index 69c9144..bf96ea5 100644 (file)
@@ -58,7 +58,9 @@ public class AppWindowAnimator {
     // the state changes.
     boolean allDrawn;
 
-    // Special surface for thumbnail animation.
+    // Special surface for thumbnail animation.  If deferThumbnailDestruction is enabled, then we
+    // will make sure that the thumbnail is destroyed after the other surface is completed.  This
+    // requires that the duration of the two animations are the same.
     SurfaceControl thumbnail;
     int thumbnailTransactionSeq;
     int thumbnailX;
@@ -68,13 +70,12 @@ public class AppWindowAnimator {
     Animation thumbnailAnimation;
     final Transformation thumbnailTransformation = new Transformation();
     // This flag indicates that the destruction of the thumbnail surface is synchronized with
-    // another animation, so do not pre-emptively destroy the thumbnail surface when the animation
-    // completes
+    // another animation, so defer the destruction of this thumbnail surface for a single frame
+    // after the secondary animation completes.
     boolean deferThumbnailDestruction;
-    // This is the thumbnail surface that has been bestowed upon this animator, and when the
-    // surface for this animator's animation is complete, we will destroy the thumbnail surface
-    // as well.  Do not animate or do anything with this surface.
-    SurfaceControl deferredThumbnail;
+    // This flag is set if the animator has deferThumbnailDestruction set and has reached the final
+    // frame of animation.  It will extend the animation by one frame and then clean up afterwards.
+    boolean deferFinalFrameCleanup;
 
     /** WindowStateAnimator from mAppAnimator.allAppWindows as of last performLayout */
     ArrayList<WindowStateAnimator> mAllAppWinAnimators = new ArrayList<WindowStateAnimator>();
@@ -134,9 +135,7 @@ public class AppWindowAnimator {
             animation = null;
             animating = true;
         }
-        if (!deferThumbnailDestruction) {
-            clearThumbnail();
-        }
+        clearThumbnail();
         if (mAppToken.deferClearAllDrawn) {
             mAppToken.allDrawn = false;
             mAppToken.deferClearAllDrawn = false;
@@ -148,13 +147,7 @@ public class AppWindowAnimator {
             thumbnail.destroy();
             thumbnail = null;
         }
-    }
-
-    public void clearDeferredThumbnail() {
-        if (deferredThumbnail != null) {
-            deferredThumbnail.destroy();
-            deferredThumbnail = null;
-        }
+        deferThumbnailDestruction = false;
     }
 
     void updateLayers() {
@@ -223,19 +216,26 @@ public class AppWindowAnimator {
             return false;
         }
         transformation.clear();
-        final boolean more = animation.getTransformation(currentTime, transformation);
-        if (false && WindowManagerService.DEBUG_ANIM) Slog.v(
-            TAG, "Stepped animation in " + mAppToken + ": more=" + more + ", xform=" + transformation);
-        if (!more) {
-            animation = null;
-            if (!deferThumbnailDestruction) {
+        boolean hasMoreFrames = animation.getTransformation(currentTime, transformation);
+        if (!hasMoreFrames) {
+            if (deferThumbnailDestruction && !deferFinalFrameCleanup) {
+                // We are deferring the thumbnail destruction, so extend the animation for one more
+                // (dummy) frame before we clean up
+                deferFinalFrameCleanup = true;
+                hasMoreFrames = true;
+            } else {
+                if (false && WindowManagerService.DEBUG_ANIM) Slog.v(
+                        TAG, "Stepped animation in " + mAppToken + ": more=" + hasMoreFrames +
+                                ", xform=" + transformation);
+                deferFinalFrameCleanup = false;
+                animation = null;
                 clearThumbnail();
+                if (WindowManagerService.DEBUG_ANIM) Slog.v(
+                        TAG, "Finished animation in " + mAppToken + " @ " + currentTime);
             }
-            if (WindowManagerService.DEBUG_ANIM) Slog.v(
-                TAG, "Finished animation in " + mAppToken + " @ " + currentTime);
         }
-        hasTransformation = more;
-        return more;
+        hasTransformation = hasMoreFrames;
+        return hasMoreFrames;
     }
 
     // This must be called while inside a transaction.
index 3fee608..9be82a1 100644 (file)
@@ -9196,12 +9196,6 @@ public class WindowManagerService extends IWindowManager.Stub
                                 topClosingLayer);
                         openingAppAnimator.deferThumbnailDestruction =
                                 !mAppTransition.isNextThumbnailTransitionScaleUp();
-                        if (openingAppAnimator.deferThumbnailDestruction) {
-                            if (closingAppAnimator != null &&
-                                    closingAppAnimator.animation != null) {
-                                closingAppAnimator.deferredThumbnail = surfaceControl;
-                            }
-                        }
                     } else {
                         anim = mAppTransition.createThumbnailScaleAnimationLocked(
                                 displayInfo.appWidth, displayInfo.appHeight, transit);
index 0c727f3..196158a 100644 (file)
@@ -962,11 +962,6 @@ class WindowStateAnimator {
             mWin.mHasSurface = false;
             mDrawState = NO_SURFACE;
         }
-
-        // Destroy any deferred thumbnail surfaces
-        if (mAppAnimator != null) {
-            mAppAnimator.clearDeferredThumbnail();
-        }
     }
 
     void destroyDeferredSurfaceLocked() {