Merge "Apply the whole auto pip transaction in recents animation" into sc-dev am: 660008c5c2

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13922011

Change-Id: Ia5d47d94f0259f26f6c225e261a52d57a19f5556
This commit is contained in:
Hongwei Wang
2021-03-30 19:48:35 +00:00
committed by Automerger Merge Worker
7 changed files with 230 additions and 62 deletions

View File

@@ -20,6 +20,7 @@ import android.app.ActivityManager;
import android.view.IRemoteAnimationFinishedCallback;
import android.graphics.GraphicBuffer;
import android.graphics.Rect;
import android.window.PictureInPictureSurfaceTransaction;
import android.window.TaskSnapshot;
/**
@@ -43,11 +44,10 @@ interface IRecentsAnimationController {
* accordingly. This should be called before `finish`
* @param taskId for which the leash should be updated
* @param destinationBounds bounds of the final PiP window
* @param windowCrop bounds to crop as part of final transform.
* @param float9 An array of 9 floats to be used as matrix transform.
* @param finishTransaction leash operations for the final transform.
*/
void setFinishTaskBounds(int taskId, in Rect destinationBounds, in Rect windowCrop,
in float[] float9);
void setFinishTaskBounds(int taskId, in Rect destinationBounds,
in PictureInPictureSurfaceTransaction finishTransaction);
/**
* Notifies to the system that the animation into Recents should end, and all leashes associated

View File

@@ -0,0 +1,19 @@
/**
* Copyright (c) 2021, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.window;
parcelable PictureInPictureSurfaceTransaction;

View File

@@ -0,0 +1,140 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.window;
import android.annotation.Nullable;
import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Objects;
/**
* Represents a set of {@link android.view.SurfaceControl.Transaction} operations used to
* operate on the {@link android.view.SurfaceControl} for picture-in-picture.
*
* @hide
*/
public final class PictureInPictureSurfaceTransaction implements Parcelable {
public final float mPositionX;
public final float mPositionY;
public final float mScaleX;
public final float mScaleY;
public final float mRotation;
public final float mCornerRadius;
private final Rect mWindowCrop = new Rect();
public PictureInPictureSurfaceTransaction(Parcel in) {
mPositionX = in.readFloat();
mPositionY = in.readFloat();
mScaleX = in.readFloat();
mScaleY = in.readFloat();
mRotation = in.readFloat();
mCornerRadius = in.readFloat();
mWindowCrop.set(Objects.requireNonNull(in.readTypedObject(Rect.CREATOR)));
}
public PictureInPictureSurfaceTransaction(float positionX, float positionY,
float scaleX, float scaleY,
float rotation, float cornerRadius,
@Nullable Rect windowCrop) {
mPositionX = positionX;
mPositionY = positionY;
mScaleX = scaleX;
mScaleY = scaleY;
mRotation = rotation;
mCornerRadius = cornerRadius;
if (windowCrop != null) {
mWindowCrop.set(windowCrop);
}
}
public PictureInPictureSurfaceTransaction(PictureInPictureSurfaceTransaction other) {
this(other.mPositionX, other.mPositionY,
other.mScaleX, other.mScaleY,
other.mRotation, other.mCornerRadius,
other.mWindowCrop);
}
public Rect getWindowCrop() {
return new Rect(mWindowCrop);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PictureInPictureSurfaceTransaction)) return false;
PictureInPictureSurfaceTransaction that = (PictureInPictureSurfaceTransaction) o;
return Objects.equals(mPositionX, that.mPositionX)
&& Objects.equals(mPositionY, that.mPositionY)
&& Objects.equals(mScaleX, that.mScaleX)
&& Objects.equals(mScaleY, that.mScaleY)
&& Objects.equals(mRotation, that.mRotation)
&& Objects.equals(mCornerRadius, that.mCornerRadius)
&& Objects.equals(mWindowCrop, that.mWindowCrop);
}
@Override
public int hashCode() {
return Objects.hash(mPositionX, mPositionY, mScaleX, mScaleY,
mRotation, mCornerRadius, mWindowCrop);
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeFloat(mPositionX);
out.writeFloat(mPositionY);
out.writeFloat(mScaleX);
out.writeFloat(mScaleY);
out.writeFloat(mRotation);
out.writeFloat(mCornerRadius);
out.writeTypedObject(mWindowCrop, 0 /* flags */);
}
@Override
public String toString() {
return "PictureInPictureSurfaceTransaction("
+ " posX=" + mPositionX
+ " posY=" + mPositionY
+ " scaleX=" + mScaleX
+ " scaleY=" + mScaleY
+ " rotation=" + mRotation
+ " cornerRadius=" + mCornerRadius
+ " crop=" + mWindowCrop
+ ")";
}
public static final @android.annotation.NonNull Creator<PictureInPictureSurfaceTransaction>
CREATOR =
new Creator<PictureInPictureSurfaceTransaction>() {
public PictureInPictureSurfaceTransaction createFromParcel(Parcel in) {
return new PictureInPictureSurfaceTransaction(in);
}
public PictureInPictureSurfaceTransaction[] newArray(int size) {
return new PictureInPictureSurfaceTransaction[size];
}
};
}

View File

@@ -16,11 +16,15 @@
package com.android.systemui.shared.pip;
import static android.graphics.Matrix.MSCALE_X;
import static android.graphics.Matrix.MSCALE_Y;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.view.Choreographer;
import android.view.SurfaceControl;
import android.window.PictureInPictureSurfaceTransaction;
/**
* TODO(b/171721389): unify this class with
@@ -28,22 +32,32 @@ import android.view.SurfaceControl;
* source of truth on enabling/disabling and the actual value of corner radius.
*/
public class PipSurfaceTransactionHelper {
/** corner radius is currently disabled. */
private final float mCornerRadius = 0f;
private final Matrix mTmpTransform = new Matrix();
private final float[] mTmpFloat9 = new float[9];
private final RectF mTmpSourceRectF = new RectF();
private final RectF mTmpDestinationRectF = new RectF();
private final Rect mTmpDestinationRect = new Rect();
public void scale(SurfaceControl.Transaction tx, SurfaceControl leash,
public PictureInPictureSurfaceTransaction scale(
SurfaceControl.Transaction tx, SurfaceControl leash,
Rect sourceBounds, Rect destinationBounds) {
mTmpSourceRectF.set(sourceBounds);
mTmpDestinationRectF.set(destinationBounds);
mTmpTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL);
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
.setPosition(leash, mTmpDestinationRectF.left, mTmpDestinationRectF.top);
.setPosition(leash, mTmpDestinationRectF.left, mTmpDestinationRectF.top)
.setCornerRadius(leash, mCornerRadius);
return new PictureInPictureSurfaceTransaction(
mTmpDestinationRectF.left, mTmpDestinationRectF.top,
mTmpFloat9[MSCALE_X], mTmpFloat9[MSCALE_Y],
0 /* rotation*/, mCornerRadius, sourceBounds);
}
public void scale(SurfaceControl.Transaction tx, SurfaceControl leash,
public PictureInPictureSurfaceTransaction scale(
SurfaceControl.Transaction tx, SurfaceControl leash,
Rect sourceBounds, Rect destinationBounds,
float degree, float positionX, float positionY) {
mTmpSourceRectF.set(sourceBounds);
@@ -51,10 +65,16 @@ public class PipSurfaceTransactionHelper {
mTmpTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL);
mTmpTransform.postRotate(degree, 0, 0);
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
.setPosition(leash, positionX, positionY);
.setPosition(leash, positionX, positionY)
.setCornerRadius(leash, mCornerRadius);
return new PictureInPictureSurfaceTransaction(
positionX, positionY,
mTmpFloat9[MSCALE_X], mTmpFloat9[MSCALE_Y],
degree, mCornerRadius, sourceBounds);
}
public void scaleAndCrop(SurfaceControl.Transaction tx, SurfaceControl leash,
public PictureInPictureSurfaceTransaction scaleAndCrop(
SurfaceControl.Transaction tx, SurfaceControl leash,
Rect sourceBounds, Rect destinationBounds, Rect insets) {
mTmpSourceRectF.set(sourceBounds);
mTmpDestinationRect.set(sourceBounds);
@@ -69,10 +89,14 @@ public class PipSurfaceTransactionHelper {
mTmpTransform.setScale(scale, scale);
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
.setWindowCrop(leash, mTmpDestinationRect)
.setPosition(leash, left, top);
.setPosition(leash, left, top)
.setCornerRadius(leash, mCornerRadius);
return new PictureInPictureSurfaceTransaction(
left, top, scale, scale, 0 /* rotation */, mCornerRadius, mTmpDestinationRect);
}
public void scaleAndRotate(SurfaceControl.Transaction tx, SurfaceControl leash,
public PictureInPictureSurfaceTransaction scaleAndRotate(
SurfaceControl.Transaction tx, SurfaceControl leash,
Rect sourceBounds, Rect destinationBounds, Rect insets,
float degree, float positionX, float positionY) {
mTmpSourceRectF.set(sourceBounds);
@@ -87,17 +111,10 @@ public class PipSurfaceTransactionHelper {
mTmpTransform.postScale(scale, scale);
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
.setWindowCrop(leash, mTmpDestinationRect)
.setPosition(leash, positionX, positionY);
}
public void resetCornerRadius(SurfaceControl.Transaction tx, SurfaceControl leash) {
tx.setCornerRadius(leash, 0);
}
public void crop(SurfaceControl.Transaction tx, SurfaceControl leash,
Rect destinationBounds) {
tx.setWindowCrop(leash, destinationBounds.width(), destinationBounds.height())
.setPosition(leash, destinationBounds.left, destinationBounds.top);
.setPosition(leash, positionX, positionY)
.setCornerRadius(leash, mCornerRadius);
return new PictureInPictureSurfaceTransaction(
positionX, positionY, scale, scale, degree, mCornerRadius, mTmpDestinationRect);
}
/** @return {@link SurfaceControl.Transaction} instance with vsync-id */

View File

@@ -20,6 +20,7 @@ import android.graphics.Rect;
import android.os.RemoteException;
import android.util.Log;
import android.view.IRecentsAnimationController;
import android.window.PictureInPictureSurfaceTransaction;
import android.window.TaskSnapshot;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -76,14 +77,12 @@ public class RecentsAnimationControllerCompat {
* accordingly. This should be called before `finish`
* @param taskId Task id of the Activity in PiP mode.
* @param destinationBounds Bounds of the PiP window on home.
* @param windowCrop bounds to crop as part of final transform.
* @param float9 An array of 9 floats to be used as matrix transform.
* @param finishTransaction leash operations for the final transform.
*/
public void setFinishTaskBounds(int taskId, Rect destinationBounds, Rect windowCrop,
float[] float9) {
public void setFinishTaskBounds(int taskId, Rect destinationBounds,
PictureInPictureSurfaceTransaction finishTransaction) {
try {
mAnimationController.setFinishTaskBounds(taskId, destinationBounds, windowCrop,
float9);
mAnimationController.setFinishTaskBounds(taskId, destinationBounds, finishTransaction);
} catch (RemoteException e) {
Log.d(TAG, "Failed to set finish task bounds", e);
}
@@ -152,4 +151,4 @@ public class RecentsAnimationControllerCompat {
Log.e(TAG, "Failed to detach the navigation bar from app", e);
}
}
}
}

View File

@@ -32,6 +32,7 @@ import android.view.IRecentsAnimationController;
import android.view.SurfaceControl;
import android.window.IRemoteTransition;
import android.window.IRemoteTransitionFinishedCallback;
import android.window.PictureInPictureSurfaceTransaction;
import android.window.TransitionFilter;
import android.window.TransitionInfo;
import android.window.WindowContainerToken;
@@ -138,9 +139,9 @@ public class RemoteTransitionCompat implements Parcelable {
}
@Override public void setFinishTaskBounds(int taskId, Rect destinationBounds,
Rect windowCrop, float[] float9) {
PictureInPictureSurfaceTransaction finishTransaction) {
if (mWrapped != null) {
mWrapped.setFinishTaskBounds(taskId, destinationBounds, windowCrop, float9);
mWrapped.setFinishTaskBounds(taskId, destinationBounds, finishTransaction);
}
}

View File

@@ -20,10 +20,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.graphics.Matrix.MSCALE_X;
import static android.graphics.Matrix.MSCALE_Y;
import static android.graphics.Matrix.MSKEW_X;
import static android.graphics.Matrix.MSKEW_Y;
import static android.view.RemoteAnimationTarget.MODE_CLOSING;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
@@ -40,6 +36,7 @@ import static com.android.server.wm.WindowManagerInternal.AppTransitionListener;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.app.WindowConfiguration;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Binder;
@@ -59,6 +56,7 @@ import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.WindowInsets.Type;
import android.window.PictureInPictureSurfaceTransaction;
import android.window.TaskSnapshot;
import com.android.internal.annotations.VisibleForTesting;
@@ -233,8 +231,8 @@ public class RecentsAnimationController implements DeathRecipient {
}
@Override
public void setFinishTaskBounds(int taskId, Rect destinationBounds, Rect windowCrop,
float[] float9) {
public void setFinishTaskBounds(int taskId, Rect destinationBounds,
PictureInPictureSurfaceTransaction finishTransaction) {
ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
"setFinishTaskBounds(%d): bounds=%s", taskId, destinationBounds);
final long token = Binder.clearCallingIdentity();
@@ -244,8 +242,7 @@ public class RecentsAnimationController implements DeathRecipient {
final TaskAnimationAdapter taskAdapter = mPendingAnimations.get(i);
if (taskAdapter.mTask.mTaskId == taskId) {
taskAdapter.mFinishBounds.set(destinationBounds);
taskAdapter.mFinishWindowCrop.set(windowCrop);
taskAdapter.mFinishTransform = float9;
taskAdapter.mFinishTransaction = finishTransaction;
break;
}
}
@@ -1098,8 +1095,7 @@ public class RecentsAnimationController implements DeathRecipient {
// The bounds of the target when animation is finished
private final Rect mFinishBounds = new Rect();
// Bounds and transform for the final transaction.
private final Rect mFinishWindowCrop = new Rect();
private float[] mFinishTransform;
private PictureInPictureSurfaceTransaction mFinishTransaction;
TaskAnimationAdapter(Task task, boolean isRecentTaskInvisible) {
mTask = task;
@@ -1138,29 +1134,25 @@ public class RecentsAnimationController implements DeathRecipient {
if (!mFinishBounds.isEmpty()) {
final SurfaceControl taskSurface = mTask.mSurfaceControl;
final Transaction pendingTransaction = mTask.getPendingTransaction();
if (mFinishTransform != null) {
pendingTransaction
.setMatrix(taskSurface,
mFinishTransform[MSCALE_X], mFinishTransform[MSKEW_Y],
mFinishTransform[MSKEW_X], mFinishTransform[MSCALE_Y]);
}
float left = mFinishBounds.left;
float top = mFinishBounds.top;
if (!mFinishWindowCrop.isEmpty()) {
pendingTransaction.setWindowCrop(taskSurface, mFinishWindowCrop);
if (mFinishTransform != null) {
// adjust the position for insets.
left -= mFinishWindowCrop.left * mFinishTransform[MSCALE_X];
top -= mFinishWindowCrop.top * mFinishTransform[MSCALE_Y];
if (mFinishTransaction != null) {
final Matrix matrix = new Matrix();
matrix.setScale(mFinishTransaction.mScaleX, mFinishTransaction.mScaleY);
if (mFinishTransaction.mRotation != 0) {
matrix.postRotate(mFinishTransaction.mRotation);
}
pendingTransaction.setMatrix(taskSurface, matrix, new float[9])
.setPosition(taskSurface,
mFinishTransaction.mPositionX, mFinishTransaction.mPositionY)
.setWindowCrop(taskSurface, mFinishTransaction.getWindowCrop())
.setCornerRadius(taskSurface, mFinishTransaction.mCornerRadius);
mTask.mLastRecentsAnimationBounds.set(mFinishBounds);
mFinishTransaction = null;
} else {
pendingTransaction
.setPosition(taskSurface, mFinishBounds.left, mFinishBounds.top)
.setWindowCrop(taskSurface, mFinishBounds);
}
pendingTransaction
.setPosition(taskSurface, left, top)
.apply();
mTask.mLastRecentsAnimationBounds.set(mFinishBounds);
// reset the variables
mFinishTransform = null;
mFinishWindowCrop.setEmpty();
pendingTransaction.apply();
mFinishBounds.setEmpty();
} else if (!mTask.isAttached()) {
// Apply the task's pending transaction in case it is detached and its transaction