Loading services/core/java/com/android/server/wm/ActivityRecord.java +0 −34 Original line number Diff line number Diff line Loading @@ -657,8 +657,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. Loading Loading @@ -1579,9 +1577,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 Loading Loading @@ -1683,20 +1678,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( Loading Loading @@ -7534,13 +7515,6 @@ final class ActivityRecord extends WindowToken { return boundsLayer; } @Override public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) { return mAnimatingActivityRegistry != null && mAnimatingActivityRegistry.notifyAboutToFinish( this, endDeferFinishCallback); } @Override boolean isWaitingForTransitionStart() { final DisplayContent dc = getDisplayContent(); Loading @@ -7562,10 +7536,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; Loading Loading @@ -7732,10 +7702,6 @@ final class ActivityRecord extends WindowToken { mNeedsLetterboxedAnimation = false; updateLetterboxSurfaceIfNeeded(findMainWindow(), t); } if (mAnimatingActivityRegistry != null) { mAnimatingActivityRegistry.notifyFinished(this); } } @Override Loading services/core/java/com/android/server/wm/AnimatingActivityRegistry.javadeleted 100644 → 0 +0 −120 Original line number Diff line number Diff line /* * 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); } } } services/core/java/com/android/server/wm/AnimationAdapter.java +0 −9 Original line number Diff line number Diff line Loading @@ -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. Loading services/core/java/com/android/server/wm/SurfaceAnimator.java +1 −22 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } } } services/core/java/com/android/server/wm/Task.java +0 −17 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -1174,9 +1171,6 @@ class Task extends TaskFragment { } mRootWindowContainer.updateUIDsPresentOnDisplay(); // Ensure all animations are finished at same time in split-screen mode. forAllActivities(ActivityRecord::updateAnimatingActivityRegistry); } @Override Loading Loading @@ -3335,13 +3329,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. Loading Loading @@ -6303,10 +6290,6 @@ class Task extends TaskFragment { return mDisplayContent.getDisplayInfo(); } AnimatingActivityRegistry getAnimatingActivityRegistry() { return mAnimatingActivityRegistry; } private Rect getRawBounds() { return super.getBounds(); } Loading Loading
services/core/java/com/android/server/wm/ActivityRecord.java +0 −34 Original line number Diff line number Diff line Loading @@ -657,8 +657,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. Loading Loading @@ -1579,9 +1577,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 Loading Loading @@ -1683,20 +1678,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( Loading Loading @@ -7534,13 +7515,6 @@ final class ActivityRecord extends WindowToken { return boundsLayer; } @Override public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) { return mAnimatingActivityRegistry != null && mAnimatingActivityRegistry.notifyAboutToFinish( this, endDeferFinishCallback); } @Override boolean isWaitingForTransitionStart() { final DisplayContent dc = getDisplayContent(); Loading @@ -7562,10 +7536,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; Loading Loading @@ -7732,10 +7702,6 @@ final class ActivityRecord extends WindowToken { mNeedsLetterboxedAnimation = false; updateLetterboxSurfaceIfNeeded(findMainWindow(), t); } if (mAnimatingActivityRegistry != null) { mAnimatingActivityRegistry.notifyFinished(this); } } @Override Loading
services/core/java/com/android/server/wm/AnimatingActivityRegistry.javadeleted 100644 → 0 +0 −120 Original line number Diff line number Diff line /* * 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); } } }
services/core/java/com/android/server/wm/AnimationAdapter.java +0 −9 Original line number Diff line number Diff line Loading @@ -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. Loading
services/core/java/com/android/server/wm/SurfaceAnimator.java +1 −22 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } } }
services/core/java/com/android/server/wm/Task.java +0 −17 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -1174,9 +1171,6 @@ class Task extends TaskFragment { } mRootWindowContainer.updateUIDsPresentOnDisplay(); // Ensure all animations are finished at same time in split-screen mode. forAllActivities(ActivityRecord::updateAnimatingActivityRegistry); } @Override Loading Loading @@ -3335,13 +3329,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. Loading Loading @@ -6303,10 +6290,6 @@ class Task extends TaskFragment { return mDisplayContent.getDisplayInfo(); } AnimatingActivityRegistry getAnimatingActivityRegistry() { return mAnimatingActivityRegistry; } private Rect getRawBounds() { return super.getBounds(); } Loading