Merge "Add multi-display support to shell transitions" into sc-v2-dev am: 2f7eef8248
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14950060 Change-Id: Ied16a3d99c7c7d031f77f12907889e303b167ec2
This commit is contained in:
@@ -181,6 +181,12 @@
|
||||
"group": "WM_DEBUG_STARTING_WINDOW",
|
||||
"at": "com\/android\/server\/wm\/ActivityRecord.java"
|
||||
},
|
||||
"-1924376693": {
|
||||
"message": " Setting Ready-group to %b. group=%s from %s",
|
||||
"level": "VERBOSE",
|
||||
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/Transition.java"
|
||||
},
|
||||
"-1918702467": {
|
||||
"message": "onSyncFinishedDrawing %s",
|
||||
"level": "VERBOSE",
|
||||
@@ -607,6 +613,12 @@
|
||||
"group": "WM_ERROR",
|
||||
"at": "com\/android\/server\/wm\/WindowManagerService.java"
|
||||
},
|
||||
"-1442613680": {
|
||||
"message": " Creating Ready-group for Transition %d with root=%s",
|
||||
"level": "VERBOSE",
|
||||
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/Transition.java"
|
||||
},
|
||||
"-1438175584": {
|
||||
"message": "Input focus has changed to %s display=%d",
|
||||
"level": "VERBOSE",
|
||||
@@ -2209,6 +2221,12 @@
|
||||
"group": "WM_DEBUG_ADD_REMOVE",
|
||||
"at": "com\/android\/server\/wm\/ActivityRecord.java"
|
||||
},
|
||||
"352982444": {
|
||||
"message": " allReady query: used=%b override=%b states=[%s]",
|
||||
"level": "VERBOSE",
|
||||
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/Transition.java"
|
||||
},
|
||||
"355720268": {
|
||||
"message": "stopFreezingDisplayLocked: Unfreezing now",
|
||||
"level": "DEBUG",
|
||||
@@ -3277,6 +3295,12 @@
|
||||
"group": "WM_DEBUG_IME",
|
||||
"at": "com\/android\/server\/wm\/InsetsStateController.java"
|
||||
},
|
||||
"1670933628": {
|
||||
"message": " Setting allReady override",
|
||||
"level": "VERBOSE",
|
||||
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/Transition.java"
|
||||
},
|
||||
"1671994402": {
|
||||
"message": "Nulling last startingData",
|
||||
"level": "VERBOSE",
|
||||
|
||||
@@ -1620,7 +1620,7 @@ class ActivityStarter {
|
||||
mTargetTask, remoteTransition);
|
||||
} else if (started) {
|
||||
// Make the collecting transition wait until this request is ready.
|
||||
mService.getTransitionController().setReady(false);
|
||||
mService.getTransitionController().setReady(r, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1359,7 +1359,8 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
|
||||
}
|
||||
|
||||
mService.getTransitionController().requestTransitionIfNeeded(TRANSIT_TO_FRONT,
|
||||
0 /* flags */, task, options != null ? options.getRemoteTransition() : null);
|
||||
0 /* flags */, task, task /* readyGroupRef */,
|
||||
options != null ? options.getRemoteTransition() : null);
|
||||
reason = reason + " findTaskToMoveToFront";
|
||||
boolean reparented = false;
|
||||
if (task.isResizeable() && canUseActivityOptionsLaunchBounds(options)) {
|
||||
|
||||
@@ -2987,7 +2987,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
|
||||
@Override
|
||||
void removeIfPossible() {
|
||||
if (isAnimating(TRANSITION | PARENTS)) {
|
||||
if (isAnimating(TRANSITION | PARENTS)
|
||||
// isAnimating is a legacy transition query and will be removed, so also add a
|
||||
// check for whether this is in a shell-transition when not using legacy.
|
||||
|| mAtmService.getTransitionController().inTransition()) {
|
||||
mDeferredRemoval = true;
|
||||
return;
|
||||
}
|
||||
@@ -4989,7 +4992,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
@WindowManager.TransitionFlags int flags) {
|
||||
prepareAppTransition(transit, flags);
|
||||
mAtmService.getTransitionController().requestTransitionIfNeeded(transit, flags,
|
||||
null /* trigger */);
|
||||
null /* trigger */, this);
|
||||
}
|
||||
|
||||
/** @see #requestTransitionAndLegacyPrepare(int, int) */
|
||||
@@ -4997,11 +5000,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
@Nullable WindowContainer trigger) {
|
||||
prepareAppTransition(transit);
|
||||
mAtmService.getTransitionController().requestTransitionIfNeeded(transit, 0 /* flags */,
|
||||
trigger);
|
||||
trigger, this);
|
||||
}
|
||||
|
||||
void executeAppTransition() {
|
||||
mAtmService.getTransitionController().setReady();
|
||||
mAtmService.getTransitionController().setReady(this);
|
||||
if (mAppTransition.isTransitionSet()) {
|
||||
ProtoLog.w(WM_DEBUG_APP_TRANSITIONS,
|
||||
"Execute app transition: %s, displayId: %d Callers=%s",
|
||||
|
||||
@@ -508,6 +508,11 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
|
||||
mTaskSupervisor.updateTopResumedActivityIfNeeded();
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isAttached() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when DisplayWindowSettings values may change.
|
||||
*/
|
||||
|
||||
@@ -132,7 +132,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
private TransitionInfo.AnimationOptions mOverrideOptions;
|
||||
|
||||
private @TransitionState int mState = STATE_COLLECTING;
|
||||
private boolean mReadyCalled = false;
|
||||
private final ReadyTracker mReadyTracker = new ReadyTracker();
|
||||
|
||||
// TODO(b/188595497): remove when not needed.
|
||||
/** @see RecentsAnimationController#mNavigationBarAttachedToApp */
|
||||
@@ -169,9 +169,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
mState = STATE_STARTED;
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Starting Transition %d",
|
||||
mSyncId);
|
||||
if (mReadyCalled) {
|
||||
setReady();
|
||||
}
|
||||
applyReady();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,6 +184,11 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
for (WindowContainer curr = wc.getParent(); curr != null && !mChanges.containsKey(curr);
|
||||
curr = curr.getParent()) {
|
||||
mChanges.put(curr, new ChangeInfo(curr));
|
||||
if (isReadyGroup(curr)) {
|
||||
mReadyTracker.addGroup(curr);
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " Creating Ready-group for"
|
||||
+ " Transition %d with root=%s", mSyncId, curr);
|
||||
}
|
||||
}
|
||||
if (mParticipants.contains(wc)) return;
|
||||
mSyncEngine.addToSyncSet(mSyncId, wc);
|
||||
@@ -236,21 +239,33 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
* all participants have finished drawing, the transition can still collect participants.
|
||||
*
|
||||
* If this is called before the transition is started, it will be deferred until start.
|
||||
*
|
||||
* @param wc A reference point to determine which ready-group to update. For now, each display
|
||||
* has its own ready-group, so this is used to look-up which display to mark ready.
|
||||
* The transition will wait for all groups to be ready.
|
||||
*/
|
||||
void setReady(boolean ready) {
|
||||
void setReady(WindowContainer wc, boolean ready) {
|
||||
if (mSyncId < 0) return;
|
||||
if (mState < STATE_STARTED) {
|
||||
mReadyCalled = ready;
|
||||
return;
|
||||
}
|
||||
mReadyTracker.setReadyFrom(wc, ready);
|
||||
applyReady();
|
||||
}
|
||||
|
||||
private void applyReady() {
|
||||
if (mState < STATE_STARTED) return;
|
||||
final boolean ready = mReadyTracker.allReady();
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
|
||||
"Set transition ready=%b %d", ready, mSyncId);
|
||||
mSyncEngine.setReady(mSyncId, ready);
|
||||
}
|
||||
|
||||
/** @see #setReady . This calls with parameter true. */
|
||||
void setReady() {
|
||||
setReady(true);
|
||||
/**
|
||||
* Sets all possible ready groups to ready.
|
||||
* @see ReadyTracker#setAllReady.
|
||||
*/
|
||||
void setAllReady() {
|
||||
if (mSyncId < 0) return;
|
||||
mReadyTracker.setAllReady();
|
||||
applyReady();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -890,6 +905,15 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
return wc.getParent().getSurfaceControl();
|
||||
}
|
||||
|
||||
/**
|
||||
* A ready group is defined by a root window-container where all transitioning windows under
|
||||
* it are expected to animate together as a group. At the moment, this treats each display as
|
||||
* a ready-group to match the existing legacy transition behavior.
|
||||
*/
|
||||
private static boolean isReadyGroup(WindowContainer wc) {
|
||||
return wc instanceof DisplayContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a TransitionInfo object from a set of targets and changes. Also populates the
|
||||
* root surface.
|
||||
@@ -1092,4 +1116,95 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
mChildren.addAll(wcs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The transition sync mechanism has 2 parts:
|
||||
* 1. Whether all WM operations for a particular transition are "ready" (eg. did the app
|
||||
* launch or stop or get a new configuration?).
|
||||
* 2. Whether all the windows involved have finished drawing their final-state content.
|
||||
*
|
||||
* A transition animation can play once both parts are complete. This ready-tracker keeps track
|
||||
* of part (1). Currently, WM code assumes that "readiness" (part 1) is grouped. This means that
|
||||
* even if the WM operations in one group are ready, the whole transition itself may not be
|
||||
* ready if there are WM operations still pending in another group. This class helps keep track
|
||||
* of readiness across the multiple groups. Currently, we assume that each display is a group
|
||||
* since that is how it has been until now.
|
||||
*/
|
||||
private static class ReadyTracker {
|
||||
private final ArrayMap<WindowContainer, Boolean> mReadyGroups = new ArrayMap<>();
|
||||
|
||||
/**
|
||||
* Ensures that this doesn't report as allReady before it has been used. This is needed
|
||||
* in very niche cases where a transition is a no-op (nothing has been collected) but we
|
||||
* still want to be marked ready (via. setAllReady).
|
||||
*/
|
||||
private boolean mUsed = false;
|
||||
|
||||
/**
|
||||
* If true, this overrides all ready groups and reports ready. Used by shell-initiated
|
||||
* transitions via {@link #setAllReady()}.
|
||||
*/
|
||||
private boolean mReadyOverride = false;
|
||||
|
||||
/**
|
||||
* Adds a ready-group. Any setReady calls in this subtree will be tracked together. For
|
||||
* now these are only DisplayContents.
|
||||
*/
|
||||
void addGroup(WindowContainer wc) {
|
||||
if (mReadyGroups.containsKey(wc)) {
|
||||
Slog.e(TAG, "Trying to add a ready-group twice: " + wc);
|
||||
return;
|
||||
}
|
||||
mReadyGroups.put(wc, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a group's ready state.
|
||||
* @param wc Any container within a group's subtree. Used to identify the ready-group.
|
||||
*/
|
||||
void setReadyFrom(WindowContainer wc, boolean ready) {
|
||||
mUsed = true;
|
||||
WindowContainer current = wc;
|
||||
while (current != null) {
|
||||
if (isReadyGroup(current)) {
|
||||
mReadyGroups.put(current, ready);
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " Setting Ready-group to"
|
||||
+ " %b. group=%s from %s", ready, current, wc);
|
||||
break;
|
||||
}
|
||||
current = current.getParent();
|
||||
}
|
||||
}
|
||||
|
||||
/** Marks this as ready regardless of individual groups. */
|
||||
void setAllReady() {
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " Setting allReady override");
|
||||
mUsed = true;
|
||||
mReadyOverride = true;
|
||||
}
|
||||
|
||||
/** @return true if all tracked subtrees are ready. */
|
||||
boolean allReady() {
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " allReady query: used=%b "
|
||||
+ "override=%b states=[%s]", mUsed, mReadyOverride, groupsToString());
|
||||
if (!mUsed) return false;
|
||||
if (mReadyOverride) return true;
|
||||
for (int i = mReadyGroups.size() - 1; i >= 0; --i) {
|
||||
final WindowContainer wc = mReadyGroups.keyAt(i);
|
||||
if (!wc.isAttached() || !wc.isVisibleRequested()) continue;
|
||||
if (!mReadyGroups.valueAt(i)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private String groupsToString() {
|
||||
StringBuilder b = new StringBuilder();
|
||||
for (int i = 0; i < mReadyGroups.size(); ++i) {
|
||||
if (i != 0) b.append(',');
|
||||
b.append(mReadyGroups.keyAt(i)).append(':')
|
||||
.append(mReadyGroups.valueAt(i));
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,8 +192,8 @@ class TransitionController {
|
||||
*/
|
||||
@Nullable
|
||||
Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type,
|
||||
@Nullable WindowContainer trigger) {
|
||||
return requestTransitionIfNeeded(type, 0 /* flags */, trigger);
|
||||
@NonNull WindowContainer trigger) {
|
||||
return requestTransitionIfNeeded(type, 0 /* flags */, trigger, trigger /* readyGroupRef */);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,8 +201,10 @@ class TransitionController {
|
||||
*/
|
||||
@Nullable
|
||||
Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type,
|
||||
@WindowManager.TransitionFlags int flags, @Nullable WindowContainer trigger) {
|
||||
return requestTransitionIfNeeded(type, flags, trigger, null /* remote */);
|
||||
@WindowManager.TransitionFlags int flags, @Nullable WindowContainer trigger,
|
||||
@NonNull WindowContainer readyGroupRef) {
|
||||
return requestTransitionIfNeeded(type, flags, trigger, readyGroupRef,
|
||||
null /* remoteTransition */);
|
||||
}
|
||||
|
||||
private static boolean isExistenceType(@WindowManager.TransitionType int type) {
|
||||
@@ -213,19 +215,20 @@ class TransitionController {
|
||||
* If a transition isn't requested yet, creates one and asks the TransitionPlayer (Shell) to
|
||||
* start it. Collection can start immediately.
|
||||
* @param trigger if non-null, this is the first container that will be collected
|
||||
* @param readyGroupRef Used to identify which ready-group this request is for.
|
||||
* @return the created transition if created or null otherwise.
|
||||
*/
|
||||
@Nullable
|
||||
Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type,
|
||||
@WindowManager.TransitionFlags int flags, @Nullable WindowContainer trigger,
|
||||
@Nullable IRemoteTransition remoteTransition) {
|
||||
@NonNull WindowContainer readyGroupRef, @Nullable IRemoteTransition remoteTransition) {
|
||||
if (mTransitionPlayer == null) {
|
||||
return null;
|
||||
}
|
||||
Transition newTransition = null;
|
||||
if (isCollecting()) {
|
||||
// Make the collecting transition wait until this request is ready.
|
||||
mCollectingTransition.setReady(false);
|
||||
mCollectingTransition.setReady(readyGroupRef, false);
|
||||
} else {
|
||||
newTransition = requestStartTransition(createTransition(type, flags),
|
||||
trigger != null ? trigger.asTask() : null, remoteTransition);
|
||||
@@ -280,14 +283,14 @@ class TransitionController {
|
||||
}
|
||||
|
||||
/** @see Transition#setReady */
|
||||
void setReady(boolean ready) {
|
||||
void setReady(WindowContainer wc, boolean ready) {
|
||||
if (mCollectingTransition == null) return;
|
||||
mCollectingTransition.setReady(ready);
|
||||
mCollectingTransition.setReady(wc, ready);
|
||||
}
|
||||
|
||||
/** @see Transition#setReady */
|
||||
void setReady() {
|
||||
setReady(true);
|
||||
void setReady(WindowContainer wc) {
|
||||
setReady(wc, true);
|
||||
}
|
||||
|
||||
/** @see Transition#finishTransition */
|
||||
|
||||
@@ -851,7 +851,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
}
|
||||
|
||||
boolean isAttached() {
|
||||
return getDisplayArea() != null;
|
||||
WindowContainer parent = getParent();
|
||||
return parent != null && parent.isAttached();
|
||||
}
|
||||
|
||||
void setWaitingForDrawnIfResizingChanged() {
|
||||
|
||||
@@ -8123,7 +8123,11 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
boolean isAnimating = mAnimator.isAnimationScheduled()
|
||||
|| mRoot.isAnimating(TRANSITION | CHILDREN, ANIMATION_TYPE_ALL);
|
||||
if (!isAnimating) {
|
||||
break;
|
||||
// isAnimating is a legacy transition query and will be removed, so also add
|
||||
// a check for whether this is in a shell-transition when not using legacy.
|
||||
if (!mAtmService.getTransitionController().inTransition()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
long startTime = System.currentTimeMillis();
|
||||
try {
|
||||
|
||||
@@ -227,7 +227,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
|
||||
}
|
||||
applyTransaction(t, -1 /*syncId*/, transition, caller);
|
||||
if (needsSetReady) {
|
||||
transition.setReady();
|
||||
transition.setAllReady();
|
||||
}
|
||||
return transition;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user