Merge "Hook-up shell-transitions to DisplayChangeController rotation"

This commit is contained in:
Evan Rosky
2021-12-14 23:51:54 +00:00
committed by Android (Google) Code Review
11 changed files with 286 additions and 22 deletions

View File

@@ -17,3 +17,4 @@
package android.window;
parcelable TransitionRequestInfo;
parcelable TransitionRequestInfo.DisplayChange;

View File

@@ -18,6 +18,8 @@ package android.window;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.WindowConfiguration;
import android.graphics.Rect;
import android.os.Parcelable;
import android.view.WindowManager;
@@ -42,6 +44,194 @@ public final class TransitionRequestInfo implements Parcelable {
/** If non-null, a remote-transition associated with the source of this transition. */
private @Nullable RemoteTransition mRemoteTransition;
/**
* If non-null, this request was triggered by this display change. This will not be complete:
* The reliable parts should be flags, rotation start/end (if rotating), and start/end bounds
* (if size is changing).
*/
private @Nullable DisplayChange mDisplayChange;
/** constructor override */
public TransitionRequestInfo(
@WindowManager.TransitionType int type,
@Nullable ActivityManager.RunningTaskInfo triggerTask,
@Nullable RemoteTransition remoteTransition) {
this(type, triggerTask, remoteTransition, null /* displayChange */);
}
/** Requested change to a display. */
@DataClass(genToString = true, genSetters = true, genBuilder = false, genConstructor = false)
public static class DisplayChange implements Parcelable {
private final int mDisplayId;
@Nullable private Rect mStartAbsBounds = null;
@Nullable private Rect mEndAbsBounds = null;
private int mStartRotation = WindowConfiguration.ROTATION_UNDEFINED;
private int mEndRotation = WindowConfiguration.ROTATION_UNDEFINED;
/** Create empty display-change. */
public DisplayChange(int displayId) {
mDisplayId = displayId;
}
/** Create a display-change representing a rotation. */
public DisplayChange(int displayId, int startRotation, int endRotation) {
mDisplayId = displayId;
mStartRotation = startRotation;
mEndRotation = endRotation;
}
// Code below generated by codegen v1.0.23.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
//
// To regenerate run:
// $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/window/TransitionRequestInfo.java
//
// To exclude the generated code from IntelliJ auto-formatting enable (one-time):
// Settings > Editor > Code Style > Formatter Control
//@formatter:off
@DataClass.Generated.Member
public int getDisplayId() {
return mDisplayId;
}
@DataClass.Generated.Member
public @Nullable Rect getStartAbsBounds() {
return mStartAbsBounds;
}
@DataClass.Generated.Member
public @Nullable Rect getEndAbsBounds() {
return mEndAbsBounds;
}
@DataClass.Generated.Member
public int getStartRotation() {
return mStartRotation;
}
@DataClass.Generated.Member
public int getEndRotation() {
return mEndRotation;
}
@DataClass.Generated.Member
public @android.annotation.NonNull DisplayChange setStartAbsBounds(@android.annotation.NonNull Rect value) {
mStartAbsBounds = value;
return this;
}
@DataClass.Generated.Member
public @android.annotation.NonNull DisplayChange setEndAbsBounds(@android.annotation.NonNull Rect value) {
mEndAbsBounds = value;
return this;
}
@DataClass.Generated.Member
public @android.annotation.NonNull DisplayChange setStartRotation( int value) {
mStartRotation = value;
return this;
}
@DataClass.Generated.Member
public @android.annotation.NonNull DisplayChange setEndRotation( int value) {
mEndRotation = value;
return this;
}
@Override
@DataClass.Generated.Member
public String toString() {
// You can override field toString logic by defining methods like:
// String fieldNameToString() { ... }
return "DisplayChange { " +
"displayId = " + mDisplayId + ", " +
"startAbsBounds = " + mStartAbsBounds + ", " +
"endAbsBounds = " + mEndAbsBounds + ", " +
"startRotation = " + mStartRotation + ", " +
"endRotation = " + mEndRotation +
" }";
}
@Override
@DataClass.Generated.Member
public void writeToParcel(@android.annotation.NonNull android.os.Parcel dest, int flags) {
// You can override field parcelling by defining methods like:
// void parcelFieldName(Parcel dest, int flags) { ... }
byte flg = 0;
if (mStartAbsBounds != null) flg |= 0x2;
if (mEndAbsBounds != null) flg |= 0x4;
dest.writeByte(flg);
dest.writeInt(mDisplayId);
if (mStartAbsBounds != null) dest.writeTypedObject(mStartAbsBounds, flags);
if (mEndAbsBounds != null) dest.writeTypedObject(mEndAbsBounds, flags);
dest.writeInt(mStartRotation);
dest.writeInt(mEndRotation);
}
@Override
@DataClass.Generated.Member
public int describeContents() { return 0; }
/** @hide */
@SuppressWarnings({"unchecked", "RedundantCast"})
@DataClass.Generated.Member
protected DisplayChange(@android.annotation.NonNull android.os.Parcel in) {
// You can override field unparcelling by defining methods like:
// static FieldType unparcelFieldName(Parcel in) { ... }
byte flg = in.readByte();
int displayId = in.readInt();
Rect startAbsBounds = (flg & 0x2) == 0 ? null : (Rect) in.readTypedObject(Rect.CREATOR);
Rect endAbsBounds = (flg & 0x4) == 0 ? null : (Rect) in.readTypedObject(Rect.CREATOR);
int startRotation = in.readInt();
int endRotation = in.readInt();
this.mDisplayId = displayId;
this.mStartAbsBounds = startAbsBounds;
this.mEndAbsBounds = endAbsBounds;
this.mStartRotation = startRotation;
this.mEndRotation = endRotation;
// onConstructed(); // You can define this method to get a callback
}
@DataClass.Generated.Member
public static final @android.annotation.NonNull Parcelable.Creator<DisplayChange> CREATOR
= new Parcelable.Creator<DisplayChange>() {
@Override
public DisplayChange[] newArray(int size) {
return new DisplayChange[size];
}
@Override
public DisplayChange createFromParcel(@android.annotation.NonNull android.os.Parcel in) {
return new DisplayChange(in);
}
};
@DataClass.Generated(
time = 1639445520915L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/window/TransitionRequestInfo.java",
inputSignatures = "private final int mDisplayId\nprivate @android.annotation.Nullable android.graphics.Rect mStartAbsBounds\nprivate @android.annotation.Nullable android.graphics.Rect mEndAbsBounds\nprivate int mStartRotation\nprivate int mEndRotation\nclass DisplayChange extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genSetters=true, genBuilder=false, genConstructor=false)")
@Deprecated
private void __metadata() {}
//@formatter:on
// End of generated code
}
// Code below generated by codegen v1.0.23.
@@ -67,17 +257,23 @@ public final class TransitionRequestInfo implements Parcelable {
* finish) has caused this transition to occur.
* @param remoteTransition
* If non-null, a remote-transition associated with the source of this transition.
* @param displayChange
* If non-null, this request was triggered by this display change. This will not be complete:
* The reliable parts should be flags, rotation start/end (if rotating), and start/end bounds
* (if size is changing).
*/
@DataClass.Generated.Member
public TransitionRequestInfo(
@WindowManager.TransitionType int type,
@Nullable ActivityManager.RunningTaskInfo triggerTask,
@Nullable RemoteTransition remoteTransition) {
@Nullable RemoteTransition remoteTransition,
@Nullable DisplayChange displayChange) {
this.mType = type;
com.android.internal.util.AnnotationValidations.validate(
WindowManager.TransitionType.class, null, mType);
this.mTriggerTask = triggerTask;
this.mRemoteTransition = remoteTransition;
this.mDisplayChange = displayChange;
// onConstructed(); // You can define this method to get a callback
}
@@ -107,6 +303,16 @@ public final class TransitionRequestInfo implements Parcelable {
return mRemoteTransition;
}
/**
* If non-null, this request was triggered by this display change. This will not be complete:
* The reliable parts should be flags, rotation start/end (if rotating), and start/end bounds
* (if size is changing).
*/
@DataClass.Generated.Member
public @Nullable DisplayChange getDisplayChange() {
return mDisplayChange;
}
/**
* If non-null, If non-null, the task containing the activity whose lifecycle change (start or
* finish) has caused this transition to occur.
@@ -126,6 +332,17 @@ public final class TransitionRequestInfo implements Parcelable {
return this;
}
/**
* If non-null, this request was triggered by this display change. This will not be complete:
* The reliable parts should be flags, rotation start/end (if rotating), and start/end bounds
* (if size is changing).
*/
@DataClass.Generated.Member
public @android.annotation.NonNull TransitionRequestInfo setDisplayChange(@android.annotation.NonNull DisplayChange value) {
mDisplayChange = value;
return this;
}
@Override
@DataClass.Generated.Member
public String toString() {
@@ -135,7 +352,8 @@ public final class TransitionRequestInfo implements Parcelable {
return "TransitionRequestInfo { " +
"type = " + mType + ", " +
"triggerTask = " + mTriggerTask + ", " +
"remoteTransition = " + mRemoteTransition +
"remoteTransition = " + mRemoteTransition + ", " +
"displayChange = " + mDisplayChange +
" }";
}
@@ -148,10 +366,12 @@ public final class TransitionRequestInfo implements Parcelable {
byte flg = 0;
if (mTriggerTask != null) flg |= 0x2;
if (mRemoteTransition != null) flg |= 0x4;
if (mDisplayChange != null) flg |= 0x8;
dest.writeByte(flg);
dest.writeInt(mType);
if (mTriggerTask != null) dest.writeTypedObject(mTriggerTask, flags);
if (mRemoteTransition != null) dest.writeTypedObject(mRemoteTransition, flags);
if (mDisplayChange != null) dest.writeTypedObject(mDisplayChange, flags);
}
@Override
@@ -169,12 +389,14 @@ public final class TransitionRequestInfo implements Parcelable {
int type = in.readInt();
ActivityManager.RunningTaskInfo triggerTask = (flg & 0x2) == 0 ? null : (ActivityManager.RunningTaskInfo) in.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR);
RemoteTransition remoteTransition = (flg & 0x4) == 0 ? null : (RemoteTransition) in.readTypedObject(RemoteTransition.CREATOR);
DisplayChange displayChange = (flg & 0x8) == 0 ? null : (DisplayChange) in.readTypedObject(DisplayChange.CREATOR);
this.mType = type;
com.android.internal.util.AnnotationValidations.validate(
WindowManager.TransitionType.class, null, mType);
this.mTriggerTask = triggerTask;
this.mRemoteTransition = remoteTransition;
this.mDisplayChange = displayChange;
// onConstructed(); // You can define this method to get a callback
}
@@ -194,10 +416,10 @@ public final class TransitionRequestInfo implements Parcelable {
};
@DataClass.Generated(
time = 1629321632222L,
time = 1639445520938L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/window/TransitionRequestInfo.java",
inputSignatures = "private final @android.view.WindowManager.TransitionType int mType\nprivate @android.annotation.Nullable android.app.ActivityManager.RunningTaskInfo mTriggerTask\nprivate @android.annotation.Nullable android.window.RemoteTransition mRemoteTransition\nclass TransitionRequestInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genSetters=true, genAidl=true)")
inputSignatures = "private final @android.view.WindowManager.TransitionType int mType\nprivate @android.annotation.Nullable android.app.ActivityManager.RunningTaskInfo mTriggerTask\nprivate @android.annotation.Nullable android.window.RemoteTransition mRemoteTransition\nprivate @android.annotation.Nullable android.window.TransitionRequestInfo.DisplayChange mDisplayChange\nclass TransitionRequestInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genSetters=true, genAidl=true)")
@Deprecated
private void __metadata() {}

View File

@@ -27,7 +27,6 @@ import androidx.annotation.BinderThread;
import com.android.wm.shell.common.annotations.ShellMainThread;
import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;
/**
@@ -71,12 +70,18 @@ public class DisplayChangeController {
mRotationListener.remove(listener);
}
/** Query all listeners for changes that should happen on rotation. */
public void dispatchOnRotateDisplay(WindowContainerTransaction outWct, int displayId,
final int fromRotation, final int toRotation) {
for (OnDisplayChangingListener c : mRotationListener) {
c.onRotateDisplay(displayId, fromRotation, toRotation, outWct);
}
}
private void onRotateDisplay(int displayId, final int fromRotation, final int toRotation,
IDisplayWindowRotationCallback callback) {
WindowContainerTransaction t = new WindowContainerTransaction();
for (OnDisplayChangingListener c : mRotationListener) {
c.onRotateDisplay(displayId, fromRotation, toRotation, t);
}
dispatchOnRotateDisplay(t, displayId, fromRotation, toRotation);
try {
callback.continueRotateDisplay(toRotation, t);
} catch (RemoteException e) {

View File

@@ -76,6 +76,11 @@ public class DisplayController {
}
}
/** Get the DisplayChangeController. */
public DisplayChangeController getChangeController() {
return mChangeController;
}
/**
* Gets a display by id from DisplayManager.
*/

View File

@@ -95,6 +95,7 @@ public class Transitions implements RemoteCallable<Transitions> {
private final ShellExecutor mAnimExecutor;
private final TransitionPlayerImpl mPlayerImpl;
private final RemoteTransitionHandler mRemoteTransitionHandler;
private final DisplayController mDisplayController;
private final ShellTransitionImpl mImpl = new ShellTransitionImpl();
/** List of possible handlers. Ordered by specificity (eg. tapped back to front). */
@@ -122,6 +123,7 @@ public class Transitions implements RemoteCallable<Transitions> {
mContext = context;
mMainExecutor = mainExecutor;
mAnimExecutor = animExecutor;
mDisplayController = displayController;
mPlayerImpl = new TransitionPlayerImpl();
// The very last handler (0 in the list) should be the default one.
mHandlers.add(new DefaultTransitionHandler(displayController, pool, context, mainExecutor,
@@ -147,6 +149,7 @@ public class Transitions implements RemoteCallable<Transitions> {
mContext = null;
mMainExecutor = null;
mAnimExecutor = null;
mDisplayController = null;
mPlayerImpl = null;
mRemoteTransitionHandler = null;
}
@@ -547,6 +550,17 @@ public class Transitions implements RemoteCallable<Transitions> {
break;
}
}
if (request.getDisplayChange() != null) {
TransitionRequestInfo.DisplayChange change = request.getDisplayChange();
if (change.getEndRotation() != change.getStartRotation()) {
// Is a rotation, so dispatch to all displayChange listeners
if (wct == null) {
wct = new WindowContainerTransaction();
}
mDisplayController.getChangeController().dispatchOnRotateDisplay(wct,
change.getDisplayId(), change.getStartRotation(), change.getEndRotation());
}
}
active.mToken = mOrganizer.startTransition(
request.getType(), transitionToken, wct);
mActiveTransitions.add(active);

View File

@@ -1672,7 +1672,7 @@ class ActivityStarter {
}
if (newTransition != null) {
transitionController.requestStartTransition(newTransition,
mTargetTask, remoteTransition);
mTargetTask, remoteTransition, null /* displayChange */);
} else if (started) {
// Make the collecting transition wait until this request is ready.
transitionController.setReady(r, false);

View File

@@ -1387,7 +1387,8 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
task.mTransitionController.requestTransitionIfNeeded(TRANSIT_TO_FRONT,
0 /* flags */, task, task /* readyGroupRef */,
options != null ? options.getRemoteTransition() : null);
options != null ? options.getRemoteTransition() : null,
null /* displayChange */);
reason = reason + " findTaskToMoveToFront";
boolean reparented = false;
if (task.isResizeable() && canUseActivityOptionsLaunchBounds(options)) {

View File

@@ -224,6 +224,7 @@ import android.view.WindowManager.DisplayImePolicy;
import android.view.WindowManagerPolicyConstants.PointerEventListener;
import android.window.DisplayWindowPolicyController;
import android.window.IDisplayAreaOrganizer;
import android.window.TransitionRequestInfo;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
@@ -1422,7 +1423,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
if (configChanged) {
mWaitingForConfig = true;
if (mTransitionController.isShellTransitionsEnabled()) {
requestChangeTransitionIfNeeded(changes);
requestChangeTransitionIfNeeded(changes, null /* displayChange */);
} else {
mWmService.startFreezingDisplay(0 /* exitAnim */, 0 /* enterAnim */, this);
}
@@ -3217,15 +3218,20 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
* Requests to start a transition for the display configuration change. The given changes must
* be non-zero. This method is no-op if the display has been collected.
*/
void requestChangeTransitionIfNeeded(@ActivityInfo.Config int changes) {
void requestChangeTransitionIfNeeded(@ActivityInfo.Config int changes,
@Nullable TransitionRequestInfo.DisplayChange displayChange) {
final TransitionController controller = mTransitionController;
if (controller.isCollecting()) {
if (displayChange != null) {
throw new IllegalArgumentException("Provided displayChange for non-new transition");
}
if (!controller.isCollecting(this)) {
controller.collect(this);
}
return;
}
final Transition t = controller.requestTransitionIfNeeded(TRANSIT_CHANGE, this);
final Transition t = controller.requestTransitionIfNeeded(TRANSIT_CHANGE, 0 /* flags */,
this, this, null /* remoteTransition */, displayChange);
if (t != null) {
mAtmService.startLaunchPowerMode(POWER_MODE_REASON_CHANGE_DISPLAY);
if (getRotation() != getWindowConfiguration().getRotation()) {
@@ -5692,7 +5698,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
mWmService.mDisplayNotificationController.dispatchDisplayChanged(
this, getConfiguration());
if (isReady() && mTransitionController.isShellTransitionsEnabled()) {
requestChangeTransitionIfNeeded(changes);
requestChangeTransitionIfNeeded(changes, null /* displayChange */);
}
}
return changes;

View File

@@ -62,6 +62,7 @@ import android.util.proto.ProtoOutputStream;
import android.view.IDisplayWindowRotationCallback;
import android.view.IWindowManager;
import android.view.Surface;
import android.window.TransitionRequestInfo;
import android.window.WindowContainerTransaction;
import com.android.internal.R;
@@ -509,8 +510,11 @@ public class DisplayRotation {
if (useShellTransitions) {
final boolean wasCollecting = mDisplayContent.mTransitionController.isCollecting();
final TransitionRequestInfo.DisplayChange change = wasCollecting ? null
: new TransitionRequestInfo.DisplayChange(mDisplayContent.getDisplayId(),
oldRotation, mRotation);
mDisplayContent.requestChangeTransitionIfNeeded(
ActivityInfo.CONFIG_WINDOW_CONFIGURATION);
ActivityInfo.CONFIG_WINDOW_CONFIGURATION, change);
if (wasCollecting) {
// Use remote-rotation infra since the transition has already been requested
// TODO(shell-transitions): Remove this once lifecycle management can cover all

View File

@@ -247,7 +247,7 @@ class TransitionController {
@WindowManager.TransitionFlags int flags, @Nullable WindowContainer trigger,
@NonNull WindowContainer readyGroupRef) {
return requestTransitionIfNeeded(type, flags, trigger, readyGroupRef,
null /* remoteTransition */);
null /* remoteTransition */, null /* displayChange */);
}
private static boolean isExistenceType(@WindowManager.TransitionType int type) {
@@ -264,12 +264,16 @@ class TransitionController {
@Nullable
Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type,
@WindowManager.TransitionFlags int flags, @Nullable WindowContainer trigger,
@NonNull WindowContainer readyGroupRef, @Nullable RemoteTransition remoteTransition) {
@NonNull WindowContainer readyGroupRef, @Nullable RemoteTransition remoteTransition,
@Nullable TransitionRequestInfo.DisplayChange displayChange) {
if (mTransitionPlayer == null) {
return null;
}
Transition newTransition = null;
if (isCollecting()) {
if (displayChange != null) {
throw new IllegalArgumentException("Provided displayChange for a non-new request");
}
// Make the collecting transition wait until this request is ready.
mCollectingTransition.setReady(readyGroupRef, false);
if ((flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0) {
@@ -278,7 +282,7 @@ class TransitionController {
}
} else {
newTransition = requestStartTransition(createTransition(type, flags),
trigger != null ? trigger.asTask() : null, remoteTransition);
trigger != null ? trigger.asTask() : null, remoteTransition, displayChange);
}
if (trigger != null) {
if (isExistenceType(type)) {
@@ -293,7 +297,8 @@ class TransitionController {
/** Asks the transition player (shell) to start a created but not yet started transition. */
@NonNull
Transition requestStartTransition(@NonNull Transition transition, @Nullable Task startTask,
@Nullable RemoteTransition remoteTransition) {
@Nullable RemoteTransition remoteTransition,
@Nullable TransitionRequestInfo.DisplayChange displayChange) {
try {
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
"Requesting StartTransition: %s", transition);
@@ -303,7 +308,7 @@ class TransitionController {
startTask.fillTaskInfo(info);
}
mTransitionPlayer.requestStartTransition(transition, new TransitionRequestInfo(
transition.mType, info, remoteTransition));
transition.mType, info, remoteTransition, displayChange));
} catch (RemoteException e) {
Slog.e(TAG, "Error requesting transition", e);
transition.start();
@@ -317,7 +322,7 @@ class TransitionController {
if (wc.isVisibleRequested()) {
if (!isCollecting()) {
requestStartTransition(createTransition(TRANSIT_CLOSE, 0 /* flags */),
wc.asTask(), null /* remoteTransition */);
wc.asTask(), null /* remoteTransition */, null /* displayChange */);
}
collectExistenceChange(wc);
} else {

View File

@@ -488,7 +488,8 @@ public class TransitionTests extends WindowTestsBase {
final TestTransitionPlayer player = registerTestTransitionPlayer();
mDisplayContent.getDisplayRotation().setRotation(mDisplayContent.getRotation() + 1);
mDisplayContent.requestChangeTransitionIfNeeded(1 /* any changes */);
mDisplayContent.requestChangeTransitionIfNeeded(1 /* any changes */,
null /* displayChange */);
final FadeRotationAnimationController fadeController =
mDisplayContent.getFadeRotationAnimationController();
assertNotNull(fadeController);