Merge "Offset animation leash to the relative position" into sc-v2-dev am: 3dce047981
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15897562 Change-Id: I573a24d5b5c9cd0b7fa425b4a0ba8e601898dca4
This commit is contained in:
@@ -121,9 +121,11 @@ class TaskFragmentAnimationSpec {
|
||||
* the second one is for the end leash.
|
||||
*/
|
||||
Animation[] createChangeBoundsChangeAnimations(@NonNull RemoteAnimationTarget target) {
|
||||
// Both start bounds and end bounds are in screen coordinates. We will post translate
|
||||
// to the local coordinates in TaskFragmentAnimationAdapter#onAnimationUpdate
|
||||
final Rect startBounds = target.startBounds;
|
||||
final Rect parentBounds = target.taskInfo.configuration.windowConfiguration.getBounds();
|
||||
final Rect endBounds = target.localBounds;
|
||||
final Rect endBounds = target.screenSpaceBounds;
|
||||
float scaleX = ((float) startBounds.width()) / endBounds.width();
|
||||
float scaleY = ((float) startBounds.height()) / endBounds.height();
|
||||
// Start leash is a child of the end leash. Reverse the scale so that the start leash won't
|
||||
|
||||
@@ -1411,7 +1411,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
this.task = newTask;
|
||||
|
||||
if (shouldStartChangeTransition(newParent, oldParent)) {
|
||||
initializeChangeTransition(getBounds());
|
||||
// The new parent and old parent may be in different position. Need to offset the
|
||||
// animation surface to keep it in its original position.
|
||||
initializeChangeTransition(getBounds(), newParent.getBounds());
|
||||
}
|
||||
|
||||
super.onParentChanged(newParent, oldParent);
|
||||
@@ -9276,7 +9278,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
record.getMode(), record.mAdapter.mCapturedLeash, !fillsParent(),
|
||||
new Rect(), insets,
|
||||
getPrefixOrderIndex(), record.mAdapter.mPosition, record.mAdapter.mLocalBounds,
|
||||
record.mAdapter.mRootTaskBounds, task.getWindowConfiguration(),
|
||||
record.mAdapter.mEndBounds, task.getWindowConfiguration(),
|
||||
false /*isNotInRecents*/,
|
||||
record.mThumbnailAdapter != null ? record.mThumbnailAdapter.mCapturedLeash : null,
|
||||
record.mStartBounds, task.getTaskInfo(), checkEnterPictureInPictureAppOpsState());
|
||||
|
||||
@@ -65,7 +65,6 @@ class RemoteAnimationController implements DeathRecipient {
|
||||
new ArrayList<>();
|
||||
@VisibleForTesting
|
||||
final ArrayList<NonAppWindowAnimationAdapter> mPendingNonAppAnimations = new ArrayList<>();
|
||||
private final Rect mTmpRect = new Rect();
|
||||
private final Handler mHandler;
|
||||
private final Runnable mTimeoutRunnable = () -> cancelAnimation("timeoutRunnable");
|
||||
|
||||
@@ -85,18 +84,18 @@ class RemoteAnimationController implements DeathRecipient {
|
||||
* Creates an animation record for each individual {@link WindowContainer}.
|
||||
*
|
||||
* @param windowContainer The windows to animate.
|
||||
* @param position The position app bounds, in screen coordinates.
|
||||
* @param position The position app bounds relative to its parent.
|
||||
* @param localBounds The bounds of the app relative to its parent.
|
||||
* @param stackBounds The stack bounds of the app relative to position.
|
||||
* @param startBounds The stack bounds before the transition, in screen coordinates
|
||||
* @param endBounds The end bounds after the transition, in screen coordinates.
|
||||
* @param startBounds The start bounds before the transition, in screen coordinates.
|
||||
* @return The record representing animation(s) to run on the app.
|
||||
*/
|
||||
RemoteAnimationRecord createRemoteAnimationRecord(WindowContainer windowContainer,
|
||||
Point position, Rect localBounds, Rect stackBounds, Rect startBounds) {
|
||||
Point position, Rect localBounds, Rect endBounds, Rect startBounds) {
|
||||
ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "createAnimationAdapter(): container=%s",
|
||||
windowContainer);
|
||||
final RemoteAnimationRecord adapters = new RemoteAnimationRecord(windowContainer, position,
|
||||
localBounds, stackBounds, startBounds);
|
||||
localBounds, endBounds, startBounds);
|
||||
mPendingAnimations.add(adapters);
|
||||
return adapters;
|
||||
}
|
||||
@@ -405,16 +404,17 @@ class RemoteAnimationController implements DeathRecipient {
|
||||
mStartBounds = new Rect(startBounds);
|
||||
mAdapter = new RemoteAnimationAdapterWrapper(this, endPos, localBounds, endBounds,
|
||||
mStartBounds);
|
||||
mTmpRect.set(startBounds);
|
||||
mTmpRect.offsetTo(0, 0);
|
||||
if (mRemoteAnimationAdapter.getChangeNeedsSnapshot()) {
|
||||
mThumbnailAdapter =
|
||||
new RemoteAnimationAdapterWrapper(this, new Point(0, 0), localBounds,
|
||||
mTmpRect, new Rect());
|
||||
final Rect thumbnailLocalBounds = new Rect(startBounds);
|
||||
thumbnailLocalBounds.offsetTo(0, 0);
|
||||
// Snapshot is located at (0,0) of the animation leash. It doesn't have size
|
||||
// change, so the startBounds is its end bounds, and no start bounds for it.
|
||||
mThumbnailAdapter = new RemoteAnimationAdapterWrapper(this, new Point(0, 0),
|
||||
thumbnailLocalBounds, startBounds, new Rect());
|
||||
}
|
||||
} else {
|
||||
mAdapter = new RemoteAnimationAdapterWrapper(this, endPos, localBounds, endBounds,
|
||||
new Rect(endPos.x, endPos.y, endBounds.right, endBounds.bottom));
|
||||
new Rect());
|
||||
mStartBounds = null;
|
||||
}
|
||||
}
|
||||
@@ -458,15 +458,15 @@ class RemoteAnimationController implements DeathRecipient {
|
||||
private @AnimationType int mAnimationType;
|
||||
final Point mPosition = new Point();
|
||||
final Rect mLocalBounds;
|
||||
final Rect mRootTaskBounds = new Rect();
|
||||
final Rect mEndBounds = new Rect();
|
||||
final Rect mStartBounds = new Rect();
|
||||
|
||||
RemoteAnimationAdapterWrapper(RemoteAnimationRecord record, Point position,
|
||||
Rect localBounds, Rect rootTaskBounds, Rect startBounds) {
|
||||
Rect localBounds, Rect endBounds, Rect startBounds) {
|
||||
mRecord = record;
|
||||
mPosition.set(position.x, position.y);
|
||||
mLocalBounds = localBounds;
|
||||
mRootTaskBounds.set(rootTaskBounds);
|
||||
mEndBounds.set(endBounds);
|
||||
mStartBounds.set(startBounds);
|
||||
}
|
||||
|
||||
@@ -480,12 +480,17 @@ class RemoteAnimationController implements DeathRecipient {
|
||||
@AnimationType int type, OnAnimationFinishedCallback finishCallback) {
|
||||
ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "startAnimation");
|
||||
|
||||
// Restore position and stack crop until client has a chance to modify it.
|
||||
if (mStartBounds.isEmpty()) {
|
||||
t.setPosition(animationLeash, 0, 0);
|
||||
t.setWindowCrop(animationLeash, -1, -1);
|
||||
// Restore position and stack crop until client has a chance to modify it.
|
||||
t.setPosition(animationLeash, mPosition.x, mPosition.y);
|
||||
t.setWindowCrop(animationLeash, mEndBounds.width(), mEndBounds.height());
|
||||
} else {
|
||||
t.setPosition(animationLeash, mStartBounds.left, mStartBounds.top);
|
||||
// Offset the change animation leash to the relative start position in parent.
|
||||
// (mPosition) is the relative end position in parent container.
|
||||
// (mStartBounds - mEndBounds) is the position difference between start and end.
|
||||
// (mPosition + mStartBounds - mEndBounds) will be the relative start position.
|
||||
t.setPosition(animationLeash, mPosition.x + mStartBounds.left - mEndBounds.left,
|
||||
mPosition.y + mStartBounds.top - mEndBounds.top);
|
||||
t.setWindowCrop(animationLeash, mStartBounds.width(), mStartBounds.height());
|
||||
}
|
||||
mCapturedLeash = animationLeash;
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.graphics.GraphicBuffer;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.hardware.HardwareBuffer;
|
||||
import android.view.Surface;
|
||||
@@ -70,13 +71,14 @@ class SurfaceFreezer {
|
||||
* above the target surface) and then taking a snapshot and placing it over the target surface.
|
||||
*
|
||||
* @param startBounds The original bounds (on screen) of the surface we are snapshotting.
|
||||
* @param relativePosition The related position of the snapshot surface to its parent.
|
||||
*/
|
||||
void freeze(SurfaceControl.Transaction t, Rect startBounds) {
|
||||
void freeze(SurfaceControl.Transaction t, Rect startBounds, Point relativePosition) {
|
||||
mFreezeBounds.set(startBounds);
|
||||
|
||||
mLeash = SurfaceAnimator.createAnimationLeash(mAnimatable, mAnimatable.getSurfaceControl(),
|
||||
t, ANIMATION_TYPE_SCREEN_ROTATION, startBounds.width(), startBounds.height(),
|
||||
startBounds.left, startBounds.top, false /* hidden */,
|
||||
relativePosition.x, relativePosition.y, false /* hidden */,
|
||||
mWmService.mTransactionFactory);
|
||||
mAnimatable.onAnimationLeashCreated(t, mLeash);
|
||||
|
||||
|
||||
@@ -2623,11 +2623,20 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
* 3. {@link ActivityRecord} is reparented into an organized {@link TaskFragment}.
|
||||
*
|
||||
* This shouldn't be called on other {@link WindowContainer} unless there is a valid use case.
|
||||
*
|
||||
* @param startBounds The original bounds (on screen) of the surface we are snapshotting.
|
||||
* @param parentBounds The parent bounds (on screen) to calculate the animation surface
|
||||
* position.
|
||||
*/
|
||||
void initializeChangeTransition(Rect startBounds) {
|
||||
void initializeChangeTransition(Rect startBounds, Rect parentBounds) {
|
||||
mDisplayContent.prepareAppTransition(TRANSIT_CHANGE);
|
||||
mDisplayContent.mChangingContainers.add(this);
|
||||
mSurfaceFreezer.freeze(getSyncTransaction(), startBounds);
|
||||
mTmpPoint.set(startBounds.left - parentBounds.left, startBounds.top - parentBounds.top);
|
||||
mSurfaceFreezer.freeze(getSyncTransaction(), startBounds, mTmpPoint);
|
||||
}
|
||||
|
||||
void initializeChangeTransition(Rect startBounds) {
|
||||
initializeChangeTransition(startBounds, getParent().getBounds());
|
||||
}
|
||||
|
||||
ArraySet<WindowContainer> getAnimationSources() {
|
||||
|
||||
@@ -341,7 +341,8 @@ public class RemoteAnimationControllerTest extends WindowTestsBase {
|
||||
verify(mMockTransaction).setWindowCrop(
|
||||
mMockLeash, app.startBounds.width(), app.startBounds.height());
|
||||
verify(mMockTransaction).setPosition(mMockThumbnailLeash, 0, 0);
|
||||
verify(mMockTransaction).setWindowCrop(mMockThumbnailLeash, -1, -1);
|
||||
verify(mMockTransaction).setWindowCrop(mMockThumbnailLeash, app.startBounds.width(),
|
||||
app.startBounds.height());
|
||||
|
||||
finishedCaptor.getValue().onAnimationFinished();
|
||||
verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_WINDOW_ANIMATION),
|
||||
@@ -394,7 +395,63 @@ public class RemoteAnimationControllerTest extends WindowTestsBase {
|
||||
verify(mMockTransaction).setWindowCrop(
|
||||
mMockLeash, app.startBounds.width(), app.startBounds.height());
|
||||
verify(mMockTransaction).setPosition(mMockThumbnailLeash, 0, 0);
|
||||
verify(mMockTransaction).setWindowCrop(mMockThumbnailLeash, -1, -1);
|
||||
verify(mMockTransaction).setWindowCrop(mMockThumbnailLeash, app.startBounds.width(),
|
||||
app.startBounds.height());
|
||||
|
||||
finishedCaptor.getValue().onAnimationFinished();
|
||||
verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_WINDOW_ANIMATION),
|
||||
eq(record.mAdapter));
|
||||
verify(mThumbnailFinishedCallback).onAnimationFinished(
|
||||
eq(ANIMATION_TYPE_WINDOW_ANIMATION), eq(record.mThumbnailAdapter));
|
||||
} finally {
|
||||
mDisplayContent.mChangingContainers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeToDifferentPosition() throws Exception {
|
||||
final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
|
||||
mDisplayContent.mChangingContainers.add(win.mActivityRecord);
|
||||
try {
|
||||
final RemoteAnimationRecord record = mController.createRemoteAnimationRecord(
|
||||
win.mActivityRecord, new Point(100, 100), null, new Rect(150, 150, 400, 400),
|
||||
new Rect(50, 100, 150, 150));
|
||||
assertNotNull(record.mThumbnailAdapter);
|
||||
((AnimationAdapter) record.mAdapter)
|
||||
.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION,
|
||||
mFinishedCallback);
|
||||
((AnimationAdapter) record.mThumbnailAdapter).startAnimation(mMockThumbnailLeash,
|
||||
mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION, mThumbnailFinishedCallback);
|
||||
mController.goodToGo(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE);
|
||||
mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
|
||||
final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
|
||||
ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
|
||||
final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
|
||||
ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
|
||||
final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
|
||||
ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
|
||||
final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
|
||||
ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
|
||||
verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE),
|
||||
appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
|
||||
finishedCaptor.capture());
|
||||
assertEquals(1, appsCaptor.getValue().length);
|
||||
final RemoteAnimationTarget app = appsCaptor.getValue()[0];
|
||||
assertEquals(RemoteAnimationTarget.MODE_CHANGING, app.mode);
|
||||
assertEquals(new Point(100, 100), app.position);
|
||||
assertEquals(new Rect(150, 150, 400, 400), app.sourceContainerBounds);
|
||||
assertEquals(new Rect(50, 100, 150, 150), app.startBounds);
|
||||
assertEquals(mMockLeash, app.leash);
|
||||
assertEquals(mMockThumbnailLeash, app.startLeash);
|
||||
assertEquals(false, app.isTranslucent);
|
||||
verify(mMockTransaction).setPosition(
|
||||
mMockLeash, app.position.x + app.startBounds.left - app.screenSpaceBounds.left,
|
||||
app.position.y + app.startBounds.top - app.screenSpaceBounds.top);
|
||||
verify(mMockTransaction).setWindowCrop(
|
||||
mMockLeash, app.startBounds.width(), app.startBounds.height());
|
||||
verify(mMockTransaction).setPosition(mMockThumbnailLeash, 0, 0);
|
||||
verify(mMockTransaction).setWindowCrop(mMockThumbnailLeash, app.startBounds.width(),
|
||||
app.startBounds.height());
|
||||
|
||||
finishedCaptor.getValue().onAnimationFinished();
|
||||
verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_WINDOW_ANIMATION),
|
||||
|
||||
Reference in New Issue
Block a user