Merge "Ensure that windows are drawn before starting transition into PiP." into oc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
ef4e38f96f
@@ -10589,8 +10589,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
mStackSupervisor.getStack(PINNED_STACK_ID);
|
||||
if (pinnedStack != null) {
|
||||
pinnedStack.animateResizePinnedStack(null /* sourceHintBounds */,
|
||||
destBounds, animationDuration,
|
||||
false /* schedulePipModeChangedOnAnimationEnd */);
|
||||
destBounds, animationDuration, false /* fromFullscreen */);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Stack: " + stackId
|
||||
|
||||
@@ -2986,18 +2986,21 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
|
||||
mWindowManager.continueSurfaceLayout();
|
||||
}
|
||||
|
||||
// The task might have already been running and its visibility needs to be synchronized
|
||||
// with the visibility of the stack / windows.
|
||||
// Calculate the default bounds (don't use existing stack bounds as we may have just created
|
||||
// the stack, and schedule the start of the animation into PiP (the bounds animator that
|
||||
// is triggered by this is posted on another thread)
|
||||
final Rect destBounds = stack.getPictureInPictureBounds(aspectRatio,
|
||||
false /* useExistingStackBounds */);
|
||||
stack.animateResizePinnedStack(sourceHintBounds, destBounds, -1 /* animationDuration */,
|
||||
true /* fromFullscreen */);
|
||||
|
||||
// Update the visibility of all activities after the they have been reparented to the new
|
||||
// stack. This MUST run after the animation above is scheduled to ensure that the windows
|
||||
// drawn signal is scheduled after the bounds animation start call on the bounds animator
|
||||
// thread.
|
||||
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 = stack.getPictureInPictureBounds(aspectRatio,
|
||||
false /* useExistingStackBounds */);
|
||||
|
||||
stack.animateResizePinnedStack(sourceHintBounds, destBounds, -1 /* animationDuration */,
|
||||
true /* schedulePipModeChangedOnAnimationEnd */);
|
||||
mService.mTaskChangeNotificationController.notifyActivityPinned(r.packageName,
|
||||
r.getTask().taskId);
|
||||
}
|
||||
|
||||
@@ -50,12 +50,12 @@ class PinnedActivityStack extends ActivityStack<PinnedStackWindowController>
|
||||
}
|
||||
|
||||
void animateResizePinnedStack(Rect sourceHintBounds, Rect toBounds, int animationDuration,
|
||||
boolean schedulePipModeChangedOnAnimationEnd) {
|
||||
boolean fromFullscreen) {
|
||||
if (skipResizeAnimation(toBounds == null /* toFullscreen */)) {
|
||||
mService.moveTasksToFullscreenStack(mStackId, true /* onTop */);
|
||||
} else {
|
||||
getWindowContainerController().animateResizePinnedStack(toBounds, sourceHintBounds,
|
||||
animationDuration, schedulePipModeChangedOnAnimationEnd);
|
||||
animationDuration, fromFullscreen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.server.wm;
|
||||
|
||||
import static android.app.ActivityManager.StackId;
|
||||
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
|
||||
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
|
||||
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
|
||||
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
|
||||
@@ -51,6 +52,7 @@ import static com.android.server.wm.WindowManagerService.logWithStack;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Binder;
|
||||
@@ -1345,9 +1347,11 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
}
|
||||
mService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
|
||||
|
||||
final TaskStack s = getStack();
|
||||
if (s != null) {
|
||||
s.onAllWindowsDrawn();
|
||||
// Notify the pinned stack upon all windows drawn. If there was an animation in
|
||||
// progress then this signal will resume that animation.
|
||||
final TaskStack pinnedStack = mDisplayContent.getStackById(PINNED_STACK_ID);
|
||||
if (pinnedStack != null) {
|
||||
pinnedStack.onAllWindowsDrawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,8 +139,14 @@ public class BoundsAnimationController {
|
||||
private final boolean mSkipAnimationStart;
|
||||
// True if this animation was canceled by the user, not as a part of a replacing animation
|
||||
private boolean mSkipAnimationEnd;
|
||||
|
||||
// True if the animation target is animating from the fullscreen. Only one of
|
||||
// {@link mMoveToFullscreen} or {@link mMoveFromFullscreen} can be true at any time in the
|
||||
// animation.
|
||||
private boolean mMoveFromFullscreen;
|
||||
// True if the animation target should be moved to the fullscreen stack at the end of this
|
||||
// animation
|
||||
// animation. Only one of {@link mMoveToFullscreen} or {@link mMoveFromFullscreen} can be
|
||||
// true at any time in the animation.
|
||||
private boolean mMoveToFullscreen;
|
||||
|
||||
// Whether to schedule PiP mode changes on animation start/end
|
||||
@@ -151,15 +157,21 @@ public class BoundsAnimationController {
|
||||
private final int mFrozenTaskWidth;
|
||||
private final int mFrozenTaskHeight;
|
||||
|
||||
// Timeout callback to ensure we continue the animation if waiting for resuming or app
|
||||
// windows drawn fails
|
||||
private final Runnable mResumeRunnable = () -> resume();
|
||||
|
||||
BoundsAnimator(BoundsAnimationTarget target, Rect from, Rect to,
|
||||
@SchedulePipModeChangedState int schedulePipModeChangedState,
|
||||
boolean moveToFullscreen, boolean replacingExistingAnimation) {
|
||||
boolean moveFromFullscreen, boolean moveToFullscreen,
|
||||
boolean replacingExistingAnimation) {
|
||||
super();
|
||||
mTarget = target;
|
||||
mFrom.set(from);
|
||||
mTo.set(to);
|
||||
mSkipAnimationStart = replacingExistingAnimation;
|
||||
mSchedulePipModeChangedState = schedulePipModeChangedState;
|
||||
mMoveFromFullscreen = moveFromFullscreen;
|
||||
mMoveToFullscreen = moveToFullscreen;
|
||||
addUpdateListener(this);
|
||||
addListener(this);
|
||||
@@ -177,13 +189,6 @@ public class BoundsAnimationController {
|
||||
}
|
||||
}
|
||||
|
||||
final Runnable mResumeRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
resume();
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget
|
||||
@@ -199,6 +204,12 @@ public class BoundsAnimationController {
|
||||
if (!mSkipAnimationStart) {
|
||||
mTarget.onAnimationStart(mSchedulePipModeChangedState ==
|
||||
SCHEDULE_PIP_MODE_CHANGED_ON_START);
|
||||
|
||||
// When starting an animation from fullscreen, pause here and wait for the
|
||||
// windows-drawn signal before we start the rest of the transition down into PiP.
|
||||
if (mMoveFromFullscreen) {
|
||||
pause();
|
||||
}
|
||||
}
|
||||
|
||||
// Immediately update the task bounds if they have to become larger, but preserve
|
||||
@@ -213,13 +224,20 @@ public class BoundsAnimationController {
|
||||
// correct logic to make this resize seamless.
|
||||
if (mMoveToFullscreen) {
|
||||
pause();
|
||||
mHandler.postDelayed(mResumeRunnable, WAIT_FOR_DRAW_TIMEOUT_MS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pause() {
|
||||
if (DEBUG) Slog.d(TAG, "pause: waiting for windows drawn");
|
||||
super.pause();
|
||||
mHandler.postDelayed(mResumeRunnable, WAIT_FOR_DRAW_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resume() {
|
||||
if (DEBUG) Slog.d(TAG, "resume:");
|
||||
mHandler.removeCallbacks(mResumeRunnable);
|
||||
super.resume();
|
||||
}
|
||||
@@ -336,15 +354,15 @@ public class BoundsAnimationController {
|
||||
|
||||
public void animateBounds(final BoundsAnimationTarget target, Rect from, Rect to,
|
||||
int animationDuration, @SchedulePipModeChangedState int schedulePipModeChangedState,
|
||||
boolean moveToFullscreen) {
|
||||
boolean moveFromFullscreen, boolean moveToFullscreen) {
|
||||
animateBoundsImpl(target, from, to, animationDuration, schedulePipModeChangedState,
|
||||
moveToFullscreen);
|
||||
moveFromFullscreen, moveToFullscreen);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
BoundsAnimator animateBoundsImpl(final BoundsAnimationTarget target, Rect from, Rect to,
|
||||
int animationDuration, @SchedulePipModeChangedState int schedulePipModeChangedState,
|
||||
boolean moveToFullscreen) {
|
||||
boolean moveFromFullscreen, boolean moveToFullscreen) {
|
||||
final BoundsAnimator existing = mRunningAnimations.get(target);
|
||||
final boolean replacing = existing != null;
|
||||
|
||||
@@ -387,7 +405,7 @@ public class BoundsAnimationController {
|
||||
existing.cancel();
|
||||
}
|
||||
final BoundsAnimator animator = new BoundsAnimator(target, from, to,
|
||||
schedulePipModeChangedState, moveToFullscreen, replacing);
|
||||
schedulePipModeChangedState, moveFromFullscreen, moveToFullscreen, replacing);
|
||||
mRunningAnimations.put(target, animator);
|
||||
animator.setFloatValues(0f, 1f);
|
||||
animator.setDuration((animationDuration != -1 ? animationDuration
|
||||
@@ -397,14 +415,19 @@ public class BoundsAnimationController {
|
||||
return animator;
|
||||
}
|
||||
|
||||
public Handler getHandler() {
|
||||
return mHandler;
|
||||
}
|
||||
|
||||
public void onAllWindowsDrawn() {
|
||||
if (DEBUG) Slog.d(TAG, "onAllWindowsDrawn:");
|
||||
mHandler.post(this::resume);
|
||||
}
|
||||
|
||||
private void resume() {
|
||||
for (int i = 0; i < mRunningAnimations.size(); i++) {
|
||||
final BoundsAnimator b = mRunningAnimations.valueAt(i);
|
||||
b.resume();
|
||||
}
|
||||
}
|
||||
|
||||
public void onAllWindowsDrawn() {
|
||||
mHandler.post(this::resume);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ public class PinnedStackWindowController extends StackWindowController {
|
||||
* Animates the pinned stack.
|
||||
*/
|
||||
public void animateResizePinnedStack(Rect toBounds, Rect sourceHintBounds,
|
||||
int animationDuration, boolean schedulePipModeChangedOnAnimationEnd) {
|
||||
int animationDuration, boolean fromFullscreen) {
|
||||
synchronized (mWindowMap) {
|
||||
if (mContainer == null) {
|
||||
throw new IllegalArgumentException("Pinned stack container not found :(");
|
||||
@@ -98,7 +98,7 @@ public class PinnedStackWindowController extends StackWindowController {
|
||||
NO_PIP_MODE_CHANGED_CALLBACKS;
|
||||
final boolean toFullscreen = toBounds == null;
|
||||
if (toFullscreen) {
|
||||
if (schedulePipModeChangedOnAnimationEnd) {
|
||||
if (fromFullscreen) {
|
||||
throw new IllegalArgumentException("Should not defer scheduling PiP mode"
|
||||
+ " change on animation to fullscreen.");
|
||||
}
|
||||
@@ -113,7 +113,7 @@ public class PinnedStackWindowController extends StackWindowController {
|
||||
toBounds = new Rect();
|
||||
mContainer.getDisplayContent().getLogicalDisplayRect(toBounds);
|
||||
}
|
||||
} else if (schedulePipModeChangedOnAnimationEnd) {
|
||||
} else if (fromFullscreen) {
|
||||
schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_END;
|
||||
}
|
||||
|
||||
@@ -122,13 +122,13 @@ public class PinnedStackWindowController extends StackWindowController {
|
||||
final Rect finalToBounds = toBounds;
|
||||
final @SchedulePipModeChangedState int finalSchedulePipModeChangedState =
|
||||
schedulePipModeChangedState;
|
||||
UiThread.getHandler().post(() -> {
|
||||
mService.mBoundsAnimationController.getHandler().post(() -> {
|
||||
if (mContainer == null) {
|
||||
return;
|
||||
}
|
||||
mService.mBoundsAnimationController.animateBounds(mContainer, fromBounds,
|
||||
finalToBounds, animationDuration, finalSchedulePipModeChangedState,
|
||||
toFullscreen);
|
||||
fromFullscreen, toFullscreen);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -152,7 +152,7 @@ public class PinnedStackWindowController extends StackWindowController {
|
||||
if (Float.compare(aspectRatio, pinnedStackController.getAspectRatio()) != 0) {
|
||||
if (!toBounds.equals(targetBounds)) {
|
||||
animateResizePinnedStack(toBounds, null /* sourceHintBounds */,
|
||||
-1 /* duration */, false /* schedulePipModeChangedOnAnimationEnd */);
|
||||
-1 /* duration */, false /* fromFullscreen */);
|
||||
}
|
||||
pinnedStackController.setAspectRatio(
|
||||
pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)
|
||||
|
||||
@@ -1489,7 +1489,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
|
||||
}
|
||||
|
||||
void onAllWindowsDrawn() {
|
||||
if (!mBoundsAnimating) {
|
||||
if (!mBoundsAnimating && !mBoundsAnimatingRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -152,8 +152,6 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
|
||||
mAwaitingAnimationStart = false;
|
||||
mAnimationStarted = true;
|
||||
mSchedulePipModeChangedOnStart = schedulePipModeChangedCallback;
|
||||
|
||||
mController.onAllWindowsDrawn();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -207,6 +205,9 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
|
||||
throw new IllegalArgumentException("Call restart() to restart an animation");
|
||||
}
|
||||
|
||||
boolean fromFullscreen = from.equals(BOUNDS_FULL);
|
||||
boolean toFullscreen = to.equals(BOUNDS_FULL);
|
||||
|
||||
mTarget.initialize(from);
|
||||
|
||||
// Started, not running
|
||||
@@ -215,6 +216,15 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
|
||||
|
||||
startImpl(from, to);
|
||||
|
||||
// Ensure that the animator is paused for the all windows drawn signal when animating
|
||||
// to/from fullscreen
|
||||
if (fromFullscreen || toFullscreen) {
|
||||
assertTrue(mAnimator.isPaused());
|
||||
mController.onAllWindowsDrawn();
|
||||
} else {
|
||||
assertTrue(!mAnimator.isPaused());
|
||||
}
|
||||
|
||||
// Started and running
|
||||
assertTrue(!mTarget.mAwaitingAnimationStart);
|
||||
assertTrue(mTarget.mAnimationStarted);
|
||||
@@ -262,7 +272,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase {
|
||||
? SCHEDULE_PIP_MODE_CHANGED_ON_END
|
||||
: NO_PIP_MODE_CHANGED_CALLBACKS;
|
||||
mAnimator = mController.animateBoundsImpl(mTarget, from, to, DURATION,
|
||||
schedulePipModeChangedState, toFullscreen);
|
||||
schedulePipModeChangedState, fromFullscreen, toFullscreen);
|
||||
|
||||
// Original stack bounds, frozen task bounds
|
||||
assertEquals(mFrom, mTarget.mStackBounds);
|
||||
|
||||
Reference in New Issue
Block a user