diff options
7 files changed, 21 insertions, 365 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index f38394e2a259..1a658902c2c5 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -659,8 +659,6 @@ final class ActivityRecord extends WindowToken { private RemoteAnimationDefinition mRemoteAnimationDefinition; - AnimatingActivityRegistry mAnimatingActivityRegistry; - // Set to the previous Task parent of the ActivityRecord when it is reparented to a new Task // due to picture-in-picture. This gets cleared whenever this activity or the Task // it references to gets removed. This should also be cleared when we move out of pip. @@ -1596,9 +1594,6 @@ final class ActivityRecord extends WindowToken { } } final Task rootTask = getRootTask(); - - updateAnimatingActivityRegistry(); - if (task == mLastParentBeforePip && task != null) { // Notify the TaskFragmentOrganizer that the activity is reparented back from pip. mAtmService.mWindowOrganizerController.mTaskFragmentOrganizerController @@ -1700,20 +1695,6 @@ final class ActivityRecord extends WindowToken { return !organizedTaskFragment.isAllowedToEmbedActivityInTrustedMode(this); } - void updateAnimatingActivityRegistry() { - final Task rootTask = getRootTask(); - final AnimatingActivityRegistry registry = rootTask != null - ? rootTask.getAnimatingActivityRegistry() - : null; - - // If we reparent, make sure to remove ourselves from the old animation registry. - if (mAnimatingActivityRegistry != null && mAnimatingActivityRegistry != registry) { - mAnimatingActivityRegistry.notifyFinished(this); - } - - mAnimatingActivityRegistry = registry; - } - boolean canAutoEnterPip() { // beforeStopping=false since the actual pip-ing will take place after startPausing() final boolean activityCanPip = checkEnterPictureInPictureState( @@ -7648,13 +7629,6 @@ final class ActivityRecord extends WindowToken { } @Override - public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) { - return mAnimatingActivityRegistry != null - && mAnimatingActivityRegistry.notifyAboutToFinish( - this, endDeferFinishCallback); - } - - @Override boolean isWaitingForTransitionStart() { final DisplayContent dc = getDisplayContent(); return dc != null && dc.mAppTransition.isTransitionSet() @@ -7675,10 +7649,6 @@ final class ActivityRecord extends WindowToken { @Override public void onLeashAnimationStarting(Transaction t, SurfaceControl leash) { - if (mAnimatingActivityRegistry != null) { - mAnimatingActivityRegistry.notifyStarting(this); - } - if (mNeedsLetterboxedAnimation) { updateLetterboxSurfaceIfNeeded(findMainWindow(), t); mNeedsAnimationBoundsLayer = true; @@ -7855,10 +7825,6 @@ final class ActivityRecord extends WindowToken { mNeedsLetterboxedAnimation = false; updateLetterboxSurfaceIfNeeded(findMainWindow(), t); } - - if (mAnimatingActivityRegistry != null) { - mAnimatingActivityRegistry.notifyFinished(this); - } } @Override diff --git a/services/core/java/com/android/server/wm/AnimatingActivityRegistry.java b/services/core/java/com/android/server/wm/AnimatingActivityRegistry.java deleted file mode 100644 index 18ec96c38264..000000000000 --- a/services/core/java/com/android/server/wm/AnimatingActivityRegistry.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.server.wm; - -import android.util.ArrayMap; -import android.util.ArraySet; - -import java.io.PrintWriter; -import java.util.ArrayList; - -/** - * Keeps track of all {@link ActivityRecord} that are animating and makes sure all animations are - * finished at the same time such that we don't run into issues with z-ordering: An activity A - * that has a shorter animation that is above another activity B with a longer animation in the same - * task, the animation layer would put the B on top of A, but from the hierarchy, A needs to be on - * top of B. Thus, we defer reparenting A to the original hierarchy such that it stays on top of B - * until B finishes animating. - */ -class AnimatingActivityRegistry { - - private ArraySet<ActivityRecord> mAnimatingActivities = new ArraySet<>(); - private ArrayMap<ActivityRecord, Runnable> mFinishedTokens = new ArrayMap<>(); - - private ArrayList<Runnable> mTmpRunnableList = new ArrayList<>(); - - private boolean mEndingDeferredFinish; - - /** - * Notifies that an {@link ActivityRecord} has started animating. - */ - void notifyStarting(ActivityRecord token) { - mAnimatingActivities.add(token); - } - - /** - * Notifies that an {@link ActivityRecord} has finished animating. - */ - void notifyFinished(ActivityRecord activity) { - mAnimatingActivities.remove(activity); - mFinishedTokens.remove(activity); - - // If we were the last activity, make sure the end all deferred finishes. - if (mAnimatingActivities.isEmpty()) { - endDeferringFinished(); - } - } - - /** - * Called when an {@link ActivityRecord} is about to finish animating. - * - * @param endDeferFinishCallback Callback to run when defer finish should be ended. - * @return {@code true} if finishing the animation should be deferred, {@code false} otherwise. - */ - boolean notifyAboutToFinish(ActivityRecord activity, Runnable endDeferFinishCallback) { - final boolean removed = mAnimatingActivities.remove(activity); - if (!removed) { - return false; - } - - if (mAnimatingActivities.isEmpty()) { - - // If no animations are animating anymore, finish all others. - endDeferringFinished(); - return false; - } else { - - // Otherwise let's put it into the pending list of to be finished animations. - mFinishedTokens.put(activity, endDeferFinishCallback); - return true; - } - } - - private void endDeferringFinished() { - - // Don't start recursing. Running the finished listener invokes notifyFinished, which may - // invoked us again. - if (mEndingDeferredFinish) { - return; - } - try { - mEndingDeferredFinish = true; - - // Copy it into a separate temp list to avoid modifying the collection while iterating - // as calling the callback may call back into notifyFinished. - for (int i = mFinishedTokens.size() - 1; i >= 0; i--) { - mTmpRunnableList.add(mFinishedTokens.valueAt(i)); - } - mFinishedTokens.clear(); - for (int i = mTmpRunnableList.size() - 1; i >= 0; i--) { - mTmpRunnableList.get(i).run(); - } - mTmpRunnableList.clear(); - } finally { - mEndingDeferredFinish = false; - } - } - - void dump(PrintWriter pw, String header, String prefix) { - if (!mAnimatingActivities.isEmpty() || !mFinishedTokens.isEmpty()) { - pw.print(prefix); pw.println(header); - prefix = prefix + " "; - pw.print(prefix); pw.print("mAnimatingActivities="); pw.println(mAnimatingActivities); - pw.print(prefix); pw.print("mFinishedTokens="); pw.println(mFinishedTokens); - } - } -} diff --git a/services/core/java/com/android/server/wm/AnimationAdapter.java b/services/core/java/com/android/server/wm/AnimationAdapter.java index 3dc377dbc14c..4458ed76dcba 100644 --- a/services/core/java/com/android/server/wm/AnimationAdapter.java +++ b/services/core/java/com/android/server/wm/AnimationAdapter.java @@ -109,15 +109,6 @@ public interface AnimationAdapter { * Gets called when the animation is about to finish and gives the client the opportunity to * defer finishing the animation, i.e. it keeps the leash around until the client calls * endDeferFinishCallback. - * <p> - * This has the same effect as - * {@link com.android.server.wm.SurfaceAnimator.Animatable#shouldDeferAnimationFinish(Runnable)} - * . The later will be evaluated first and has precedence over this method if it returns true, - * which means that if the {@link com.android.server.wm.SurfaceAnimator.Animatable} requests to - * defer its finish, this method won't be called so this adapter will never have access to the - * finish callback. On the other hand, if the - * {@link com.android.server.wm.SurfaceAnimator.Animatable}, doesn't request to defer, this - * {@link AnimationAdapter} is responsible for ending the animation. * * @param endDeferFinishCallback The callback to call when defer finishing should be ended. * @return Whether the client would like to defer the animation finish. diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java index 3dfff39e9b68..c5425fedf2ac 100644 --- a/services/core/java/com/android/server/wm/SurfaceAnimator.java +++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java @@ -132,10 +132,7 @@ public class SurfaceAnimator { animationFinishCallback.onAnimationFinished(type, anim); } }; - // If both the Animatable and AnimationAdapter requests to be deferred, only the - // first one will be called. - if (!(mAnimatable.shouldDeferAnimationFinish(resetAndInvokeFinish) - || anim.shouldDeferAnimationFinish(resetAndInvokeFinish))) { + if (!anim.shouldDeferAnimationFinish(resetAndInvokeFinish)) { resetAndInvokeFinish.run(); } mAnimationFinished = true; @@ -639,23 +636,5 @@ public class SurfaceAnimator { * @return The height of the surface to be animated. */ int getSurfaceHeight(); - - /** - * Gets called when the animation is about to finish and gives the client the opportunity to - * defer finishing the animation, i.e. it keeps the leash around until the client calls - * {@link #cancelAnimation}. - * <p> - * {@link AnimationAdapter} has a similar method which is called only if this method returns - * false. This mean that if both this {@link Animatable} and the {@link AnimationAdapter} - * request to be deferred, this method is the sole responsible to call - * endDeferFinishCallback. On the other hand, the animation finish might still be deferred - * if this method return false and the one from the {@link AnimationAdapter} returns true. - * - * @param endDeferFinishCallback The callback to call when defer finishing should be ended. - * @return Whether the client would like to defer the animation finish. - */ - default boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) { - return false; - } } } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index f75e7175b4d2..2edf4db1ae1a 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -508,9 +508,6 @@ class Task extends TaskFragment { */ boolean mAllowForceResizeOverride = true; - private final AnimatingActivityRegistry mAnimatingActivityRegistry = - new AnimatingActivityRegistry(); - private static final int TRANSLUCENT_TIMEOUT_MSG = FIRST_ACTIVITY_TASK_MSG + 1; private final Handler mHandler; @@ -1185,9 +1182,6 @@ class Task extends TaskFragment { } mRootWindowContainer.updateUIDsPresentOnDisplay(); - - // Ensure all animations are finished at same time in split-screen mode. - forAllActivities(ActivityRecord::updateAnimatingActivityRegistry); } @Override @@ -3345,13 +3339,6 @@ class Task extends TaskFragment { mLastSurfaceShowing = show; } - @Override - void dump(PrintWriter pw, String prefix, boolean dumpAll) { - super.dump(pw, prefix, dumpAll); - mAnimatingActivityRegistry.dump(pw, "AnimatingApps:", prefix); - } - - /** * Fills in a {@link TaskInfo} with information from this task. Note that the base intent in the * task info will not include any extras or clip data. @@ -6313,10 +6300,6 @@ class Task extends TaskFragment { return mDisplayContent.getDisplayInfo(); } - AnimatingActivityRegistry getAnimatingActivityRegistry() { - return mAnimatingActivityRegistry; - } - private Rect getRawBounds() { return super.getBounds(); } diff --git a/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java b/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java deleted file mode 100644 index 8871056988ef..000000000000 --- a/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wm; - -import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; - -import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyZeroInteractions; -import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; -import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import android.platform.test.annotations.Presubmit; - -import androidx.test.filters.SmallTest; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * Tests for the {@link ActivityStack} class. - * - * Build/Install/Run: - * atest WmTests:AnimatingActivityRegistryTest - */ -@SmallTest -@Presubmit -@RunWith(WindowTestRunner.class) -public class AnimatingActivityRegistryTest extends WindowTestsBase { - - @Mock - AnimationAdapter mAdapter; - - @Mock - Runnable mMockEndDeferFinishCallback1; - @Mock - Runnable mMockEndDeferFinishCallback2; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testDeferring() { - final ActivityRecord activity1 = createActivityRecord(mDisplayContent); - final ActivityRecord activity2 = createAppWindow(activity1.getTask(), ACTIVITY_TYPE_STANDARD, - "activity2").mActivityRecord; - final AnimatingActivityRegistry registry = - activity1.getRootTask().getAnimatingActivityRegistry(); - - activity1.startAnimation(activity1.getPendingTransaction(), mAdapter, false /* hidden */, - ANIMATION_TYPE_APP_TRANSITION); - activity2.startAnimation(activity1.getPendingTransaction(), mAdapter, false /* hidden */, - ANIMATION_TYPE_APP_TRANSITION); - assertTrue(activity1.isAnimating(TRANSITION)); - assertTrue(activity2.isAnimating(TRANSITION)); - - // Make sure that first animation finish is deferred, second one is not deferred, and first - // one gets cancelled. - assertTrue(registry.notifyAboutToFinish(activity1, mMockEndDeferFinishCallback1)); - assertFalse(registry.notifyAboutToFinish(activity2, mMockEndDeferFinishCallback2)); - verify(mMockEndDeferFinishCallback1).run(); - verifyZeroInteractions(mMockEndDeferFinishCallback2); - } - - @Test - public void testContainerRemoved() { - final ActivityRecord window1 = createActivityRecord(mDisplayContent); - final ActivityRecord window2 = createAppWindow(window1.getTask(), ACTIVITY_TYPE_STANDARD, - "window2").mActivityRecord; - final AnimatingActivityRegistry registry = - window1.getRootTask().getAnimatingActivityRegistry(); - - window1.startAnimation(window1.getPendingTransaction(), mAdapter, false /* hidden */, - ANIMATION_TYPE_APP_TRANSITION); - window2.startAnimation(window1.getPendingTransaction(), mAdapter, false /* hidden */, - ANIMATION_TYPE_APP_TRANSITION); - assertTrue(window1.isAnimating(TRANSITION)); - assertTrue(window2.isAnimating(TRANSITION)); - - // Make sure that first animation finish is deferred, and removing the second window stops - // finishes all pending deferred finishings. - registry.notifyAboutToFinish(window1, mMockEndDeferFinishCallback1); - window2.setParent(null); - verify(mMockEndDeferFinishCallback1).run(); - } -} diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java index 7dba1422d61d..2544550120d4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java @@ -22,6 +22,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.never; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; +import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -69,7 +70,6 @@ public class SurfaceAnimatorTest extends WindowTestsBase { private MyAnimatable mAnimatable; private MyAnimatable mAnimatable2; - private DeferFinishAnimatable mDeferFinishAnimatable; @Before public void setUp() throws Exception { @@ -77,14 +77,12 @@ public class SurfaceAnimatorTest extends WindowTestsBase { mAnimatable = new MyAnimatable(mWm, mTransaction); mAnimatable2 = new MyAnimatable(mWm, mTransaction); - mDeferFinishAnimatable = new DeferFinishAnimatable(mWm, mTransaction); } @After public void tearDown() { mAnimatable = null; mAnimatable2 = null; - mDeferFinishAnimatable = null; } @Test @@ -202,41 +200,33 @@ public class SurfaceAnimatorTest extends WindowTestsBase { } @Test - public void testDeferFinish() { - - // Start animation - final OnAnimationFinishedCallback onFinishedCallback = startDeferFinishAnimatable(mSpec); - - // Finish the animation but then make sure we are deferring. - onFinishedCallback.onAnimationFinished(ANIMATION_TYPE_APP_TRANSITION, mSpec); - assertAnimating(mDeferFinishAnimatable); - - // Now end defer finishing. - mDeferFinishAnimatable.mEndDeferFinishCallback.run(); - assertNotAnimating(mAnimatable2); - assertTrue(mDeferFinishAnimatable.mFinishedCallbackCalled); - assertEquals(ANIMATION_TYPE_APP_TRANSITION, mDeferFinishAnimatable.mFinishedAnimationType); - verify(mTransaction).remove(eq(mDeferFinishAnimatable.mLeash)); - } - - @Test public void testDeferFinishDoNotFinishNextAnimation() { + final DeferredFinishAdapter deferredFinishAdapter = new DeferredFinishAdapter(); + spyOn(deferredFinishAdapter); // Start the first animation. - final OnAnimationFinishedCallback onFinishedCallback = startDeferFinishAnimatable(mSpec); - onFinishedCallback.onAnimationFinished(ANIMATION_TYPE_APP_TRANSITION, mSpec); + mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, deferredFinishAdapter, + true /* hidden */, ANIMATION_TYPE_WINDOW_ANIMATION); + assertAnimating(mAnimatable); + final ArgumentCaptor<OnAnimationFinishedCallback> callbackCaptor = ArgumentCaptor.forClass( + OnAnimationFinishedCallback.class); + verify(deferredFinishAdapter).startAnimation(any(), any(), + eq(ANIMATION_TYPE_WINDOW_ANIMATION), callbackCaptor.capture()); + final OnAnimationFinishedCallback onFinishedCallback = callbackCaptor.getValue(); + onFinishedCallback.onAnimationFinished(ANIMATION_TYPE_APP_TRANSITION, + deferredFinishAdapter); // The callback is the resetAndInvokeFinish in {@link SurfaceAnimator#getFinishedCallback}. - final Runnable firstDeferFinishCallback = mDeferFinishAnimatable.mEndDeferFinishCallback; + final Runnable firstDeferFinishCallback = deferredFinishAdapter.mEndDeferFinishCallback; // Start the second animation. - mDeferFinishAnimatable.mSurfaceAnimator.cancelAnimation(); - startDeferFinishAnimatable(mSpec2); - mDeferFinishAnimatable.mFinishedCallbackCalled = false; + mAnimatable.mSurfaceAnimator.cancelAnimation(); + mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec2, + true /* hidden */, ANIMATION_TYPE_WINDOW_ANIMATION); + mAnimatable.mFinishedCallbackCalled = false; - // Simulate the first deferred callback is executed from - // {@link AnimatingActivityRegistry#endDeferringFinished}. + // Simulate the first deferred callback is executed. firstDeferFinishCallback.run(); // The second animation should not be finished. - assertFalse(mDeferFinishAnimatable.mFinishedCallbackCalled); + assertFalse(mAnimatable.mFinishedCallbackCalled); } @Test @@ -260,17 +250,6 @@ public class SurfaceAnimatorTest extends WindowTestsBase { verify(mTransaction).remove(eq(deferredFinishAdapter.mAnimationLeash)); } - private OnAnimationFinishedCallback startDeferFinishAnimatable(AnimationAdapter anim) { - mDeferFinishAnimatable.mSurfaceAnimator.startAnimation(mTransaction, anim, - true /* hidden */, ANIMATION_TYPE_APP_TRANSITION); - final ArgumentCaptor<OnAnimationFinishedCallback> callbackCaptor = ArgumentCaptor.forClass( - OnAnimationFinishedCallback.class); - assertAnimating(mDeferFinishAnimatable); - verify(anim).startAnimation(any(), any(), eq(ANIMATION_TYPE_APP_TRANSITION), - callbackCaptor.capture()); - return callbackCaptor.getValue(); - } - private void assertAnimating(MyAnimatable animatable) { assertTrue(animatable.mSurfaceAnimator.isAnimating()); assertNotNull(animatable.mSurfaceAnimator.getAnimation()); @@ -370,21 +349,6 @@ public class SurfaceAnimatorTest extends WindowTestsBase { }; } - private static class DeferFinishAnimatable extends MyAnimatable { - - Runnable mEndDeferFinishCallback; - - DeferFinishAnimatable(WindowManagerService wm, Transaction transaction) { - super(wm, transaction); - } - - @Override - public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) { - mEndDeferFinishCallback = endDeferFinishCallback; - return true; - } - } - private static class DeferredFinishAdapter implements AnimationAdapter { private Runnable mEndDeferFinishCallback; |