Merge "Ensure that windows are drawn before starting transition into PiP." into oc-dev

This commit is contained in:
TreeHugger Robot
2017-05-25 20:30:21 +00:00
committed by Android (Google) Code Review
8 changed files with 83 additions and 44 deletions

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}
}

View File

@@ -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);
}
}

View File

@@ -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)

View File

@@ -1489,7 +1489,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
}
void onAllWindowsDrawn() {
if (!mBoundsAnimating) {
if (!mBoundsAnimating && !mBoundsAnimatingRequested) {
return;
}

View File

@@ -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);