Loading packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +1 −0 Original line number Diff line number Diff line Loading @@ -86,6 +86,7 @@ public class PipManager implements BasePipManager { ComponentName topPipActivity = PipUtils.getTopPinnedActivity(mContext, mActivityManager); mMenuController.hideMenu(); mNotificationController.onActivityUnpinned(topPipActivity); SystemServicesProxy.getInstance(mContext).setPipVisibility(topPipActivity != null); Loading services/core/java/com/android/server/am/ActivityManagerService.java +2 −4 Original line number Diff line number Diff line Loading @@ -7864,9 +7864,7 @@ public class ActivityManagerService extends IActivityManager.Stub final float aspectRatio = r.pictureInPictureArgs.getAspectRatio(); final List<RemoteAction> actions = r.pictureInPictureArgs.getActions(); final Rect sourceBounds = r.pictureInPictureArgs.getSourceRectHint(); final Rect destBounds = mWindowManager.getPictureInPictureBounds(DEFAULT_DISPLAY, aspectRatio); mStackSupervisor.moveActivityToPinnedStackLocked(r, sourceBounds, destBounds, mStackSupervisor.moveActivityToPinnedStackLocked(r, sourceBounds, aspectRatio, true /* moveHomeStackToFront */, "enterPictureInPictureMode"); final PinnedActivityStack stack = mStackSupervisor.getStack(PINNED_STACK_ID); stack.setPictureInPictureAspectRatio(aspectRatio); Loading Loading @@ -7927,7 +7925,7 @@ public class ActivityManagerService extends IActivityManager.Stub // if it is not already expanding to fullscreen. Otherwise, the arguments will // be used the next time the activity enters PiP final PinnedActivityStack stack = r.getStack(); if (!stack.isBoundsAnimatingToFullscreen()) { if (!stack.isAnimatingBoundsToFullscreen()) { stack.setPictureInPictureAspectRatio( r.pictureInPictureArgs.getAspectRatio()); stack.setPictureInPictureActions(r.pictureInPictureArgs.getActions()); services/core/java/com/android/server/am/ActivityStackSupervisor.java +19 −3 Original line number Diff line number Diff line Loading @@ -174,6 +174,7 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.widget.LockPatternUtils; import com.android.server.LocalServices; import com.android.server.am.ActivityStack.ActivityState; import com.android.server.wm.PinnedStackWindowController; import com.android.server.wm.WindowManagerService; import java.io.FileDescriptor; Loading Loading @@ -2492,11 +2493,21 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } void resizePinnedStackLocked(Rect pinnedBounds, Rect tempPinnedTaskBounds) { final ActivityStack stack = getStack(PINNED_STACK_ID); final PinnedActivityStack stack = getStack(PINNED_STACK_ID); if (stack == null) { Slog.w(TAG, "resizePinnedStackLocked: pinned stack not found"); return; } // It is possible for the bounds animation from the WM to call this but be delayed by // another AM call that is holding the AMS lock. In such a case, the pinnedBounds may be // incorrect if AMS.resizeStackWithBoundsFromWindowManager() is already called while waiting // for the AMS lock to be freed. So check and make sure these bounds are still good. final PinnedStackWindowController stackController = stack.getWindowContainerController(); if (stackController.pinnedStackResizeAllowed()) { return; } Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizePinnedStack"); mWindowManager.deferSurfaceLayout(); try { Loading Loading @@ -2857,12 +2868,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return false; } moveActivityToPinnedStackLocked(r, null /* sourceBounds */, destBounds, moveActivityToPinnedStackLocked(r, null /* sourceBounds */, 0f /* aspectRatio */, true /* moveHomeStackToFront */, "moveTopActivityToPinnedStack"); return true; } void moveActivityToPinnedStackLocked(ActivityRecord r, Rect sourceBounds, Rect destBounds, void moveActivityToPinnedStackLocked(ActivityRecord r, Rect sourceBounds, float aspectRatio, boolean moveHomeStackToFront, String reason) { mWindowManager.deferSurfaceLayout(); Loading Loading @@ -2932,6 +2943,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); resumeFocusedStackTopActivityLocked(); // Calculate the default bounds (don't use existing stack bounds as we may have just created // the stack final Rect destBounds = mWindowManager.getPictureInPictureBounds(DEFAULT_DISPLAY, aspectRatio, false /* useExistingStackBounds */); // TODO(b/36099777): Schedule the PiP mode change here immediately until we can defer all // callbacks until after the bounds animation scheduleUpdatePictureInPictureModeIfNeeded(r.getTask(), destBounds, true /* immediate */); Loading services/core/java/com/android/server/am/PinnedActivityStack.java +5 −4 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ import android.graphics.Rect; import com.android.server.am.ActivityStackSupervisor.ActivityContainer; import com.android.server.wm.PinnedStackWindowController; import com.android.server.wm.StackWindowController; import com.android.server.wm.PinnedStackWindowListener; import java.util.ArrayList; import java.util.List; Loading @@ -29,7 +29,8 @@ import java.util.List; /** * State and management of the pinned stack of activities. */ class PinnedActivityStack extends ActivityStack<PinnedStackWindowController> { class PinnedActivityStack extends ActivityStack<PinnedStackWindowController> implements PinnedStackWindowListener { PinnedActivityStack(ActivityContainer activityContainer, RecentTasks recentTasks, boolean onTop) { Loading @@ -55,8 +56,8 @@ class PinnedActivityStack extends ActivityStack<PinnedStackWindowController> { getWindowContainerController().setPictureInPictureActions(actions); } boolean isBoundsAnimatingToFullscreen() { return getWindowContainerController().isBoundsAnimatingToFullscreen(); boolean isAnimatingBoundsToFullscreen() { return getWindowContainerController().isAnimatingBoundsToFullscreen(); } @Override Loading services/core/java/com/android/server/wm/BoundsAnimationController.java +52 −23 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; import android.view.WindowManagerInternal; import com.android.internal.annotations.VisibleForTesting; /** * Enables animating bounds of objects. * Loading Loading @@ -103,7 +105,8 @@ public class BoundsAnimationController { com.android.internal.R.interpolator.fast_out_slow_in); } private final class BoundsAnimator extends ValueAnimator @VisibleForTesting final class BoundsAnimator extends ValueAnimator implements ValueAnimator.AnimatorUpdateListener, ValueAnimator.AnimatorListener { private final AnimateBoundsUser mTarget; private final Rect mFrom = new Rect(); Loading @@ -113,10 +116,12 @@ public class BoundsAnimationController { private final boolean mMoveToFullScreen; // True if this this animation was cancelled and will be replaced the another animation from // the same {@link #AnimateBoundsUser} target. private boolean mSkipAnimationEnd; private boolean mSkipFinalResize; // True if this animation replaced a previous animation of the same // {@link #AnimateBoundsUser} target. private final boolean mSkipAnimationStart; // True if this animation was cancelled by the user, not as a part of a replacing animation private boolean mSkipAnimationEnd; // True if this animation is not replacing a previous animation, or if the previous // animation is animating to a different fullscreen state than the current animation. // We use this to ensure that we always provide a consistent set/order of callbacks when we Loading Loading @@ -200,7 +205,11 @@ public class BoundsAnimationController { // Whoops, the target doesn't feel like animating anymore. Let's immediately finish // any further animation. if (DEBUG) Slog.d(TAG, "animateUpdate: cancelled"); animation.cancel(); // Since we are cancelling immediately without a replacement animation, send the // animation end to maintain callback parity, but also skip any further resizes prepareCancel(false /* skipAnimationEnd */, true /* skipFinalResize */); cancel(); } } Loading @@ -208,7 +217,7 @@ public class BoundsAnimationController { public void onAnimationEnd(Animator animation) { if (DEBUG) Slog.d(TAG, "onAnimationEnd: mTarget=" + mTarget + " mMoveToFullScreen=" + mMoveToFullScreen + " mSkipAnimationEnd=" + mSkipAnimationEnd + " mSkipFinalResize=" + mSkipFinalResize + " mFinishAnimationAfterTransition=" + mFinishAnimationAfterTransition + " mAppTransitionIsRunning=" + mAppTransition.isRunning()); Loading @@ -222,10 +231,15 @@ public class BoundsAnimationController { return; } if (!mSkipFinalResize) { // If not cancelled, resize the pinned stack to the final size. All calls to // setPinnedStackSize() must be done between onAnimationStart() and onAnimationEnd() mTarget.setPinnedStackSize(mTo, null); } finishAnimation(); mTarget.setPinnedStackSize(mTo, null); if (mMoveToFullScreen && !mSkipAnimationEnd) { if (mMoveToFullScreen && !mSkipFinalResize) { mTarget.moveToFullscreen(); } } Loading @@ -235,10 +249,16 @@ public class BoundsAnimationController { finishAnimation(); } public void prepareCancel(boolean skipAnimationEnd, boolean skipFinalResize) { if (DEBUG) Slog.d(TAG, "prepareCancel: skipAnimationEnd=" + skipAnimationEnd + " skipFinalResize=" + skipFinalResize); mSkipAnimationEnd = skipAnimationEnd; mSkipFinalResize = skipFinalResize; } @Override public void cancel() { mSkipAnimationEnd = true; if (DEBUG) Slog.d(TAG, "cancel: willReplace mTarget=" + mTarget); if (DEBUG) Slog.d(TAG, "cancel: mTarget=" + mTarget); super.cancel(); } Loading Loading @@ -273,19 +293,15 @@ public class BoundsAnimationController { public interface AnimateBoundsUser { /** * Asks the target to directly (without any intermediate steps, like scheduling animation) * resize its bounds. * * @return Whether the target still wants to be animated and successfully finished the * operation. If it returns false, the animation will immediately be cancelled. The target * should return false when something abnormal happened, e.g. it was completely removed * from the hierarchy and is not valid anymore. */ boolean setSize(Rect bounds); /** * Behaves as setSize, but freezes the bounds of any tasks in the target at taskBounds, * Sets the size of the target (without any intermediate steps, like scheduling animation) * but freezes the bounds of any tasks in the target at taskBounds, * to allow for more flexibility during resizing. Only works for the pinned stack at the * moment. * * @return Whether the target should continue to be animated and this call was successful. * If false, the animation will be cancelled because the user has determined that the * animation is now invalid and not required. In such a case, the cancel will trigger the * animation end callback as well, but will not send any further size changes. */ boolean setPinnedStackSize(Rect bounds, Rect taskBounds); Loading @@ -310,11 +326,20 @@ public class BoundsAnimationController { */ void onAnimationEnd(); /** * Callback for the target to inform it to reparent to the fullscreen stack. */ void moveToFullscreen(); } void animateBounds(final AnimateBoundsUser target, Rect from, Rect to, int animationDuration, boolean moveToFullscreen) { public void animateBounds(final AnimateBoundsUser target, Rect from, Rect to, int animationDuration, boolean moveToFullscreen) { animateBoundsImpl(target, from, to, animationDuration, moveToFullscreen); } @VisibleForTesting BoundsAnimator animateBoundsImpl(final AnimateBoundsUser target, Rect from, Rect to, int animationDuration, boolean moveToFullscreen) { final BoundsAnimator existing = mRunningAnimations.get(target); final boolean replacing = existing != null; final boolean animatingToNewFullscreenState = (existing == null) || Loading @@ -326,12 +351,15 @@ public class BoundsAnimationController { if (replacing) { if (existing.isAnimatingTo(to)) { // Just les the current animation complete if it has the same destination as the // Just let the current animation complete if it has the same destination as the // one we are trying to start. if (DEBUG) Slog.d(TAG, "animateBounds: same destination as existing=" + existing + " ignoring..."); return; return existing; } // Since we are replacing, we skip both animation start and end callbacks, and don't // animate to the final bounds when cancelling existing.prepareCancel(true /* skipAnimationEnd */, true /* skipFinalResize */); existing.cancel(); } final BoundsAnimator animator = new BoundsAnimator(target, from, to, moveToFullscreen, Loading @@ -342,5 +370,6 @@ public class BoundsAnimationController { : DEFAULT_TRANSITION_DURATION) * DEBUG_ANIMATION_SLOW_DOWN_FACTOR); animator.setInterpolator(mFastOutSlowInInterpolator); animator.start(); return animator; } } Loading
packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +1 −0 Original line number Diff line number Diff line Loading @@ -86,6 +86,7 @@ public class PipManager implements BasePipManager { ComponentName topPipActivity = PipUtils.getTopPinnedActivity(mContext, mActivityManager); mMenuController.hideMenu(); mNotificationController.onActivityUnpinned(topPipActivity); SystemServicesProxy.getInstance(mContext).setPipVisibility(topPipActivity != null); Loading
services/core/java/com/android/server/am/ActivityManagerService.java +2 −4 Original line number Diff line number Diff line Loading @@ -7864,9 +7864,7 @@ public class ActivityManagerService extends IActivityManager.Stub final float aspectRatio = r.pictureInPictureArgs.getAspectRatio(); final List<RemoteAction> actions = r.pictureInPictureArgs.getActions(); final Rect sourceBounds = r.pictureInPictureArgs.getSourceRectHint(); final Rect destBounds = mWindowManager.getPictureInPictureBounds(DEFAULT_DISPLAY, aspectRatio); mStackSupervisor.moveActivityToPinnedStackLocked(r, sourceBounds, destBounds, mStackSupervisor.moveActivityToPinnedStackLocked(r, sourceBounds, aspectRatio, true /* moveHomeStackToFront */, "enterPictureInPictureMode"); final PinnedActivityStack stack = mStackSupervisor.getStack(PINNED_STACK_ID); stack.setPictureInPictureAspectRatio(aspectRatio); Loading Loading @@ -7927,7 +7925,7 @@ public class ActivityManagerService extends IActivityManager.Stub // if it is not already expanding to fullscreen. Otherwise, the arguments will // be used the next time the activity enters PiP final PinnedActivityStack stack = r.getStack(); if (!stack.isBoundsAnimatingToFullscreen()) { if (!stack.isAnimatingBoundsToFullscreen()) { stack.setPictureInPictureAspectRatio( r.pictureInPictureArgs.getAspectRatio()); stack.setPictureInPictureActions(r.pictureInPictureArgs.getActions());
services/core/java/com/android/server/am/ActivityStackSupervisor.java +19 −3 Original line number Diff line number Diff line Loading @@ -174,6 +174,7 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.widget.LockPatternUtils; import com.android.server.LocalServices; import com.android.server.am.ActivityStack.ActivityState; import com.android.server.wm.PinnedStackWindowController; import com.android.server.wm.WindowManagerService; import java.io.FileDescriptor; Loading Loading @@ -2492,11 +2493,21 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } void resizePinnedStackLocked(Rect pinnedBounds, Rect tempPinnedTaskBounds) { final ActivityStack stack = getStack(PINNED_STACK_ID); final PinnedActivityStack stack = getStack(PINNED_STACK_ID); if (stack == null) { Slog.w(TAG, "resizePinnedStackLocked: pinned stack not found"); return; } // It is possible for the bounds animation from the WM to call this but be delayed by // another AM call that is holding the AMS lock. In such a case, the pinnedBounds may be // incorrect if AMS.resizeStackWithBoundsFromWindowManager() is already called while waiting // for the AMS lock to be freed. So check and make sure these bounds are still good. final PinnedStackWindowController stackController = stack.getWindowContainerController(); if (stackController.pinnedStackResizeAllowed()) { return; } Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizePinnedStack"); mWindowManager.deferSurfaceLayout(); try { Loading Loading @@ -2857,12 +2868,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return false; } moveActivityToPinnedStackLocked(r, null /* sourceBounds */, destBounds, moveActivityToPinnedStackLocked(r, null /* sourceBounds */, 0f /* aspectRatio */, true /* moveHomeStackToFront */, "moveTopActivityToPinnedStack"); return true; } void moveActivityToPinnedStackLocked(ActivityRecord r, Rect sourceBounds, Rect destBounds, void moveActivityToPinnedStackLocked(ActivityRecord r, Rect sourceBounds, float aspectRatio, boolean moveHomeStackToFront, String reason) { mWindowManager.deferSurfaceLayout(); Loading Loading @@ -2932,6 +2943,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); resumeFocusedStackTopActivityLocked(); // Calculate the default bounds (don't use existing stack bounds as we may have just created // the stack final Rect destBounds = mWindowManager.getPictureInPictureBounds(DEFAULT_DISPLAY, aspectRatio, false /* useExistingStackBounds */); // TODO(b/36099777): Schedule the PiP mode change here immediately until we can defer all // callbacks until after the bounds animation scheduleUpdatePictureInPictureModeIfNeeded(r.getTask(), destBounds, true /* immediate */); Loading
services/core/java/com/android/server/am/PinnedActivityStack.java +5 −4 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ import android.graphics.Rect; import com.android.server.am.ActivityStackSupervisor.ActivityContainer; import com.android.server.wm.PinnedStackWindowController; import com.android.server.wm.StackWindowController; import com.android.server.wm.PinnedStackWindowListener; import java.util.ArrayList; import java.util.List; Loading @@ -29,7 +29,8 @@ import java.util.List; /** * State and management of the pinned stack of activities. */ class PinnedActivityStack extends ActivityStack<PinnedStackWindowController> { class PinnedActivityStack extends ActivityStack<PinnedStackWindowController> implements PinnedStackWindowListener { PinnedActivityStack(ActivityContainer activityContainer, RecentTasks recentTasks, boolean onTop) { Loading @@ -55,8 +56,8 @@ class PinnedActivityStack extends ActivityStack<PinnedStackWindowController> { getWindowContainerController().setPictureInPictureActions(actions); } boolean isBoundsAnimatingToFullscreen() { return getWindowContainerController().isBoundsAnimatingToFullscreen(); boolean isAnimatingBoundsToFullscreen() { return getWindowContainerController().isAnimatingBoundsToFullscreen(); } @Override Loading
services/core/java/com/android/server/wm/BoundsAnimationController.java +52 −23 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; import android.view.WindowManagerInternal; import com.android.internal.annotations.VisibleForTesting; /** * Enables animating bounds of objects. * Loading Loading @@ -103,7 +105,8 @@ public class BoundsAnimationController { com.android.internal.R.interpolator.fast_out_slow_in); } private final class BoundsAnimator extends ValueAnimator @VisibleForTesting final class BoundsAnimator extends ValueAnimator implements ValueAnimator.AnimatorUpdateListener, ValueAnimator.AnimatorListener { private final AnimateBoundsUser mTarget; private final Rect mFrom = new Rect(); Loading @@ -113,10 +116,12 @@ public class BoundsAnimationController { private final boolean mMoveToFullScreen; // True if this this animation was cancelled and will be replaced the another animation from // the same {@link #AnimateBoundsUser} target. private boolean mSkipAnimationEnd; private boolean mSkipFinalResize; // True if this animation replaced a previous animation of the same // {@link #AnimateBoundsUser} target. private final boolean mSkipAnimationStart; // True if this animation was cancelled by the user, not as a part of a replacing animation private boolean mSkipAnimationEnd; // True if this animation is not replacing a previous animation, or if the previous // animation is animating to a different fullscreen state than the current animation. // We use this to ensure that we always provide a consistent set/order of callbacks when we Loading Loading @@ -200,7 +205,11 @@ public class BoundsAnimationController { // Whoops, the target doesn't feel like animating anymore. Let's immediately finish // any further animation. if (DEBUG) Slog.d(TAG, "animateUpdate: cancelled"); animation.cancel(); // Since we are cancelling immediately without a replacement animation, send the // animation end to maintain callback parity, but also skip any further resizes prepareCancel(false /* skipAnimationEnd */, true /* skipFinalResize */); cancel(); } } Loading @@ -208,7 +217,7 @@ public class BoundsAnimationController { public void onAnimationEnd(Animator animation) { if (DEBUG) Slog.d(TAG, "onAnimationEnd: mTarget=" + mTarget + " mMoveToFullScreen=" + mMoveToFullScreen + " mSkipAnimationEnd=" + mSkipAnimationEnd + " mSkipFinalResize=" + mSkipFinalResize + " mFinishAnimationAfterTransition=" + mFinishAnimationAfterTransition + " mAppTransitionIsRunning=" + mAppTransition.isRunning()); Loading @@ -222,10 +231,15 @@ public class BoundsAnimationController { return; } if (!mSkipFinalResize) { // If not cancelled, resize the pinned stack to the final size. All calls to // setPinnedStackSize() must be done between onAnimationStart() and onAnimationEnd() mTarget.setPinnedStackSize(mTo, null); } finishAnimation(); mTarget.setPinnedStackSize(mTo, null); if (mMoveToFullScreen && !mSkipAnimationEnd) { if (mMoveToFullScreen && !mSkipFinalResize) { mTarget.moveToFullscreen(); } } Loading @@ -235,10 +249,16 @@ public class BoundsAnimationController { finishAnimation(); } public void prepareCancel(boolean skipAnimationEnd, boolean skipFinalResize) { if (DEBUG) Slog.d(TAG, "prepareCancel: skipAnimationEnd=" + skipAnimationEnd + " skipFinalResize=" + skipFinalResize); mSkipAnimationEnd = skipAnimationEnd; mSkipFinalResize = skipFinalResize; } @Override public void cancel() { mSkipAnimationEnd = true; if (DEBUG) Slog.d(TAG, "cancel: willReplace mTarget=" + mTarget); if (DEBUG) Slog.d(TAG, "cancel: mTarget=" + mTarget); super.cancel(); } Loading Loading @@ -273,19 +293,15 @@ public class BoundsAnimationController { public interface AnimateBoundsUser { /** * Asks the target to directly (without any intermediate steps, like scheduling animation) * resize its bounds. * * @return Whether the target still wants to be animated and successfully finished the * operation. If it returns false, the animation will immediately be cancelled. The target * should return false when something abnormal happened, e.g. it was completely removed * from the hierarchy and is not valid anymore. */ boolean setSize(Rect bounds); /** * Behaves as setSize, but freezes the bounds of any tasks in the target at taskBounds, * Sets the size of the target (without any intermediate steps, like scheduling animation) * but freezes the bounds of any tasks in the target at taskBounds, * to allow for more flexibility during resizing. Only works for the pinned stack at the * moment. * * @return Whether the target should continue to be animated and this call was successful. * If false, the animation will be cancelled because the user has determined that the * animation is now invalid and not required. In such a case, the cancel will trigger the * animation end callback as well, but will not send any further size changes. */ boolean setPinnedStackSize(Rect bounds, Rect taskBounds); Loading @@ -310,11 +326,20 @@ public class BoundsAnimationController { */ void onAnimationEnd(); /** * Callback for the target to inform it to reparent to the fullscreen stack. */ void moveToFullscreen(); } void animateBounds(final AnimateBoundsUser target, Rect from, Rect to, int animationDuration, boolean moveToFullscreen) { public void animateBounds(final AnimateBoundsUser target, Rect from, Rect to, int animationDuration, boolean moveToFullscreen) { animateBoundsImpl(target, from, to, animationDuration, moveToFullscreen); } @VisibleForTesting BoundsAnimator animateBoundsImpl(final AnimateBoundsUser target, Rect from, Rect to, int animationDuration, boolean moveToFullscreen) { final BoundsAnimator existing = mRunningAnimations.get(target); final boolean replacing = existing != null; final boolean animatingToNewFullscreenState = (existing == null) || Loading @@ -326,12 +351,15 @@ public class BoundsAnimationController { if (replacing) { if (existing.isAnimatingTo(to)) { // Just les the current animation complete if it has the same destination as the // Just let the current animation complete if it has the same destination as the // one we are trying to start. if (DEBUG) Slog.d(TAG, "animateBounds: same destination as existing=" + existing + " ignoring..."); return; return existing; } // Since we are replacing, we skip both animation start and end callbacks, and don't // animate to the final bounds when cancelling existing.prepareCancel(true /* skipAnimationEnd */, true /* skipFinalResize */); existing.cancel(); } final BoundsAnimator animator = new BoundsAnimator(target, from, to, moveToFullscreen, Loading @@ -342,5 +370,6 @@ public class BoundsAnimationController { : DEFAULT_TRANSITION_DURATION) * DEBUG_ANIMATION_SLOW_DOWN_FACTOR); animator.setInterpolator(mFastOutSlowInInterpolator); animator.start(); return animator; } }