Merge "Offset animation leash to the relative position" into sc-v2-dev
This commit is contained in:
@@ -121,9 +121,11 @@ class TaskFragmentAnimationSpec {
|
|||||||
* the second one is for the end leash.
|
* the second one is for the end leash.
|
||||||
*/
|
*/
|
||||||
Animation[] createChangeBoundsChangeAnimations(@NonNull RemoteAnimationTarget target) {
|
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 startBounds = target.startBounds;
|
||||||
final Rect parentBounds = target.taskInfo.configuration.windowConfiguration.getBounds();
|
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 scaleX = ((float) startBounds.width()) / endBounds.width();
|
||||||
float scaleY = ((float) startBounds.height()) / endBounds.height();
|
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
|
// 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;
|
this.task = newTask;
|
||||||
|
|
||||||
if (shouldStartChangeTransition(newParent, oldParent)) {
|
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);
|
super.onParentChanged(newParent, oldParent);
|
||||||
@@ -9276,7 +9278,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
|||||||
record.getMode(), record.mAdapter.mCapturedLeash, !fillsParent(),
|
record.getMode(), record.mAdapter.mCapturedLeash, !fillsParent(),
|
||||||
new Rect(), insets,
|
new Rect(), insets,
|
||||||
getPrefixOrderIndex(), record.mAdapter.mPosition, record.mAdapter.mLocalBounds,
|
getPrefixOrderIndex(), record.mAdapter.mPosition, record.mAdapter.mLocalBounds,
|
||||||
record.mAdapter.mRootTaskBounds, task.getWindowConfiguration(),
|
record.mAdapter.mEndBounds, task.getWindowConfiguration(),
|
||||||
false /*isNotInRecents*/,
|
false /*isNotInRecents*/,
|
||||||
record.mThumbnailAdapter != null ? record.mThumbnailAdapter.mCapturedLeash : null,
|
record.mThumbnailAdapter != null ? record.mThumbnailAdapter.mCapturedLeash : null,
|
||||||
record.mStartBounds, task.getTaskInfo(), checkEnterPictureInPictureAppOpsState());
|
record.mStartBounds, task.getTaskInfo(), checkEnterPictureInPictureAppOpsState());
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ class RemoteAnimationController implements DeathRecipient {
|
|||||||
new ArrayList<>();
|
new ArrayList<>();
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
final ArrayList<NonAppWindowAnimationAdapter> mPendingNonAppAnimations = new ArrayList<>();
|
final ArrayList<NonAppWindowAnimationAdapter> mPendingNonAppAnimations = new ArrayList<>();
|
||||||
private final Rect mTmpRect = new Rect();
|
|
||||||
private final Handler mHandler;
|
private final Handler mHandler;
|
||||||
private final Runnable mTimeoutRunnable = () -> cancelAnimation("timeoutRunnable");
|
private final Runnable mTimeoutRunnable = () -> cancelAnimation("timeoutRunnable");
|
||||||
|
|
||||||
@@ -85,18 +84,18 @@ class RemoteAnimationController implements DeathRecipient {
|
|||||||
* Creates an animation record for each individual {@link WindowContainer}.
|
* Creates an animation record for each individual {@link WindowContainer}.
|
||||||
*
|
*
|
||||||
* @param windowContainer The windows to animate.
|
* @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 localBounds The bounds of the app relative to its parent.
|
||||||
* @param stackBounds The stack bounds of the app relative to position.
|
* @param endBounds The end bounds after the transition, in screen coordinates.
|
||||||
* @param startBounds The stack bounds before 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.
|
* @return The record representing animation(s) to run on the app.
|
||||||
*/
|
*/
|
||||||
RemoteAnimationRecord createRemoteAnimationRecord(WindowContainer windowContainer,
|
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",
|
ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "createAnimationAdapter(): container=%s",
|
||||||
windowContainer);
|
windowContainer);
|
||||||
final RemoteAnimationRecord adapters = new RemoteAnimationRecord(windowContainer, position,
|
final RemoteAnimationRecord adapters = new RemoteAnimationRecord(windowContainer, position,
|
||||||
localBounds, stackBounds, startBounds);
|
localBounds, endBounds, startBounds);
|
||||||
mPendingAnimations.add(adapters);
|
mPendingAnimations.add(adapters);
|
||||||
return adapters;
|
return adapters;
|
||||||
}
|
}
|
||||||
@@ -405,16 +404,17 @@ class RemoteAnimationController implements DeathRecipient {
|
|||||||
mStartBounds = new Rect(startBounds);
|
mStartBounds = new Rect(startBounds);
|
||||||
mAdapter = new RemoteAnimationAdapterWrapper(this, endPos, localBounds, endBounds,
|
mAdapter = new RemoteAnimationAdapterWrapper(this, endPos, localBounds, endBounds,
|
||||||
mStartBounds);
|
mStartBounds);
|
||||||
mTmpRect.set(startBounds);
|
|
||||||
mTmpRect.offsetTo(0, 0);
|
|
||||||
if (mRemoteAnimationAdapter.getChangeNeedsSnapshot()) {
|
if (mRemoteAnimationAdapter.getChangeNeedsSnapshot()) {
|
||||||
mThumbnailAdapter =
|
final Rect thumbnailLocalBounds = new Rect(startBounds);
|
||||||
new RemoteAnimationAdapterWrapper(this, new Point(0, 0), localBounds,
|
thumbnailLocalBounds.offsetTo(0, 0);
|
||||||
mTmpRect, new Rect());
|
// 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 {
|
} else {
|
||||||
mAdapter = new RemoteAnimationAdapterWrapper(this, endPos, localBounds, endBounds,
|
mAdapter = new RemoteAnimationAdapterWrapper(this, endPos, localBounds, endBounds,
|
||||||
new Rect(endPos.x, endPos.y, endBounds.right, endBounds.bottom));
|
new Rect());
|
||||||
mStartBounds = null;
|
mStartBounds = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -458,15 +458,15 @@ class RemoteAnimationController implements DeathRecipient {
|
|||||||
private @AnimationType int mAnimationType;
|
private @AnimationType int mAnimationType;
|
||||||
final Point mPosition = new Point();
|
final Point mPosition = new Point();
|
||||||
final Rect mLocalBounds;
|
final Rect mLocalBounds;
|
||||||
final Rect mRootTaskBounds = new Rect();
|
final Rect mEndBounds = new Rect();
|
||||||
final Rect mStartBounds = new Rect();
|
final Rect mStartBounds = new Rect();
|
||||||
|
|
||||||
RemoteAnimationAdapterWrapper(RemoteAnimationRecord record, Point position,
|
RemoteAnimationAdapterWrapper(RemoteAnimationRecord record, Point position,
|
||||||
Rect localBounds, Rect rootTaskBounds, Rect startBounds) {
|
Rect localBounds, Rect endBounds, Rect startBounds) {
|
||||||
mRecord = record;
|
mRecord = record;
|
||||||
mPosition.set(position.x, position.y);
|
mPosition.set(position.x, position.y);
|
||||||
mLocalBounds = localBounds;
|
mLocalBounds = localBounds;
|
||||||
mRootTaskBounds.set(rootTaskBounds);
|
mEndBounds.set(endBounds);
|
||||||
mStartBounds.set(startBounds);
|
mStartBounds.set(startBounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -480,12 +480,17 @@ class RemoteAnimationController implements DeathRecipient {
|
|||||||
@AnimationType int type, OnAnimationFinishedCallback finishCallback) {
|
@AnimationType int type, OnAnimationFinishedCallback finishCallback) {
|
||||||
ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "startAnimation");
|
ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "startAnimation");
|
||||||
|
|
||||||
// Restore position and stack crop until client has a chance to modify it.
|
|
||||||
if (mStartBounds.isEmpty()) {
|
if (mStartBounds.isEmpty()) {
|
||||||
t.setPosition(animationLeash, 0, 0);
|
// Restore position and stack crop until client has a chance to modify it.
|
||||||
t.setWindowCrop(animationLeash, -1, -1);
|
t.setPosition(animationLeash, mPosition.x, mPosition.y);
|
||||||
|
t.setWindowCrop(animationLeash, mEndBounds.width(), mEndBounds.height());
|
||||||
} else {
|
} 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());
|
t.setWindowCrop(animationLeash, mStartBounds.width(), mStartBounds.height());
|
||||||
}
|
}
|
||||||
mCapturedLeash = animationLeash;
|
mCapturedLeash = animationLeash;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import android.annotation.NonNull;
|
|||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.graphics.GraphicBuffer;
|
import android.graphics.GraphicBuffer;
|
||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
|
import android.graphics.Point;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.hardware.HardwareBuffer;
|
import android.hardware.HardwareBuffer;
|
||||||
import android.view.Surface;
|
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.
|
* 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 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);
|
mFreezeBounds.set(startBounds);
|
||||||
|
|
||||||
mLeash = SurfaceAnimator.createAnimationLeash(mAnimatable, mAnimatable.getSurfaceControl(),
|
mLeash = SurfaceAnimator.createAnimationLeash(mAnimatable, mAnimatable.getSurfaceControl(),
|
||||||
t, ANIMATION_TYPE_SCREEN_ROTATION, startBounds.width(), startBounds.height(),
|
t, ANIMATION_TYPE_SCREEN_ROTATION, startBounds.width(), startBounds.height(),
|
||||||
startBounds.left, startBounds.top, false /* hidden */,
|
relativePosition.x, relativePosition.y, false /* hidden */,
|
||||||
mWmService.mTransactionFactory);
|
mWmService.mTransactionFactory);
|
||||||
mAnimatable.onAnimationLeashCreated(t, mLeash);
|
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}.
|
* 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.
|
* 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.prepareAppTransition(TRANSIT_CHANGE);
|
||||||
mDisplayContent.mChangingContainers.add(this);
|
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() {
|
ArraySet<WindowContainer> getAnimationSources() {
|
||||||
|
|||||||
@@ -341,7 +341,8 @@ public class RemoteAnimationControllerTest extends WindowTestsBase {
|
|||||||
verify(mMockTransaction).setWindowCrop(
|
verify(mMockTransaction).setWindowCrop(
|
||||||
mMockLeash, app.startBounds.width(), app.startBounds.height());
|
mMockLeash, app.startBounds.width(), app.startBounds.height());
|
||||||
verify(mMockTransaction).setPosition(mMockThumbnailLeash, 0, 0);
|
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();
|
finishedCaptor.getValue().onAnimationFinished();
|
||||||
verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_WINDOW_ANIMATION),
|
verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_WINDOW_ANIMATION),
|
||||||
@@ -394,7 +395,63 @@ public class RemoteAnimationControllerTest extends WindowTestsBase {
|
|||||||
verify(mMockTransaction).setWindowCrop(
|
verify(mMockTransaction).setWindowCrop(
|
||||||
mMockLeash, app.startBounds.width(), app.startBounds.height());
|
mMockLeash, app.startBounds.width(), app.startBounds.height());
|
||||||
verify(mMockTransaction).setPosition(mMockThumbnailLeash, 0, 0);
|
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();
|
finishedCaptor.getValue().onAnimationFinished();
|
||||||
verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_WINDOW_ANIMATION),
|
verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_WINDOW_ANIMATION),
|
||||||
|
|||||||
Reference in New Issue
Block a user