OSDN Git Service

Add animation to running animation list before starting.
authorchaviw <chaviw@google.com>
Fri, 25 May 2018 23:18:42 +0000 (16:18 -0700)
committerchaviw <chaviw@google.com>
Fri, 25 May 2018 23:34:58 +0000 (16:34 -0700)
The animation needs to be added to the animation list before starting
to ensure it's in the list before onAnimationEnd is called. Specifically,
this can happen if the duration is 0 since the animation will complete
very quickly. If that occurs, the animation will be added to the list
after it's been "removed" which means there will continue to be a reference
to that animation even after it's completed.

Also fix a few other issues:
1. Don't create a dim layer if stopDim is called. This causes excess
layers to be created, just so they can be destroyed.
2. Add try/catch to dim layer create so the system doesn't crash if the
layer fails to create.

Test: Enter split screen and move divider so dim layers are show and
hidden. There are no longer excess dim layers being created and leashes
are being properly dereferenced.
Fixes: 80206408

Change-Id: I7198bd5e972fce32633869697a4d26f51e675d48

services/core/java/com/android/server/wm/Dimmer.java
services/core/java/com/android/server/wm/SurfaceAnimationRunner.java

index b8431b1..65c8e96 100644 (file)
@@ -22,7 +22,9 @@ import static com.android.server.wm.AlphaAnimationSpecProto.TO;
 import static com.android.server.wm.AnimationSpecProto.ALPHA;
 
 import android.graphics.Rect;
+import android.util.Log;
 import android.util.proto.ProtoOutputStream;
+import android.view.Surface;
 import android.view.SurfaceControl;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -171,14 +173,18 @@ class Dimmer {
      */
     private DimState getDimState(WindowContainer container) {
         if (mDimState == null) {
-            final SurfaceControl ctl = makeDimLayer();
-            mDimState = new DimState(ctl);
-            /**
-             * See documentation on {@link #dimAbove} to understand lifecycle management of Dim's
-             * via state resetting for Dim's with containers.
-             */
-            if (container == null) {
-                mDimState.mDontReset = true;
+            try {
+                final SurfaceControl ctl = makeDimLayer();
+                mDimState = new DimState(ctl);
+                /**
+                 * See documentation on {@link #dimAbove} to understand lifecycle management of
+                 * Dim's via state resetting for Dim's with containers.
+                 */
+                if (container == null) {
+                    mDimState.mDontReset = true;
+                }
+            } catch (Surface.OutOfResourcesException e) {
+                Log.w(TAG, "OutOfResourcesException creating dim surface");
             }
         }
 
@@ -189,6 +195,11 @@ class Dimmer {
     private void dim(SurfaceControl.Transaction t, WindowContainer container, int relativeLayer,
             float alpha) {
         final DimState d = getDimState(container);
+
+        if (d == null) {
+            return;
+        }
+
         if (container != null) {
             // The dim method is called from WindowState.prepareSurfaces(), which is always called
             // in the correct Z from lowest Z to highest. This ensures that the dim layer is always
@@ -208,10 +219,11 @@ class Dimmer {
      * @param t A Transaction in which to finish the dim.
      */
     void stopDim(SurfaceControl.Transaction t) {
-        DimState d = getDimState(null);
-        t.hide(d.mDimLayer);
-        d.isVisible = false;
-        d.mDontReset = false;
+        if (mDimState != null) {
+            t.hide(mDimState.mDimLayer);
+            mDimState.isVisible = false;
+            mDimState.mDontReset = false;
+        }
     }
 
     /**
index 7211533..2bfff26 100644 (file)
@@ -206,6 +206,9 @@ class SurfaceAnimationRunner {
                 }
             }
         });
+        a.mAnim = anim;
+        mRunningAnimations.put(a.mLeash, a);
+
         anim.start();
         if (a.mAnimSpec.canSkipFirstFrame()) {
             // If we can skip the first frame, we start one frame later.
@@ -215,8 +218,6 @@ class SurfaceAnimationRunner {
         // Immediately start the animation by manually applying an animation frame. Otherwise, the
         // start time would only be set in the next frame, leading to a delay.
         anim.doAnimationFrame(mChoreographer.getFrameTime());
-        a.mAnim = anim;
-        mRunningAnimations.put(a.mLeash, a);
     }
 
     private void applyTransformation(RunningAnimation a, Transaction t, long currentPlayTime) {