Merge "Add multi-display support to shell transitions" into sc-v2-dev

This commit is contained in:
Evan Rosky
2021-07-14 17:13:07 +00:00
committed by Android (Google) Code Review
10 changed files with 187 additions and 31 deletions

View File

@@ -181,6 +181,12 @@
"group": "WM_DEBUG_STARTING_WINDOW", "group": "WM_DEBUG_STARTING_WINDOW",
"at": "com\/android\/server\/wm\/ActivityRecord.java" "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": { "-1918702467": {
"message": "onSyncFinishedDrawing %s", "message": "onSyncFinishedDrawing %s",
"level": "VERBOSE", "level": "VERBOSE",
@@ -607,6 +613,12 @@
"group": "WM_ERROR", "group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java" "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": { "-1438175584": {
"message": "Input focus has changed to %s display=%d", "message": "Input focus has changed to %s display=%d",
"level": "VERBOSE", "level": "VERBOSE",
@@ -2209,6 +2221,12 @@
"group": "WM_DEBUG_ADD_REMOVE", "group": "WM_DEBUG_ADD_REMOVE",
"at": "com\/android\/server\/wm\/ActivityRecord.java" "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": { "355720268": {
"message": "stopFreezingDisplayLocked: Unfreezing now", "message": "stopFreezingDisplayLocked: Unfreezing now",
"level": "DEBUG", "level": "DEBUG",
@@ -3277,6 +3295,12 @@
"group": "WM_DEBUG_IME", "group": "WM_DEBUG_IME",
"at": "com\/android\/server\/wm\/InsetsStateController.java" "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": { "1671994402": {
"message": "Nulling last startingData", "message": "Nulling last startingData",
"level": "VERBOSE", "level": "VERBOSE",

View File

@@ -1620,7 +1620,7 @@ class ActivityStarter {
mTargetTask, remoteTransition); mTargetTask, remoteTransition);
} else if (started) { } else if (started) {
// Make the collecting transition wait until this request is ready. // Make the collecting transition wait until this request is ready.
mService.getTransitionController().setReady(false); mService.getTransitionController().setReady(r, false);
} }
} }
} }

View File

@@ -1359,7 +1359,8 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
} }
mService.getTransitionController().requestTransitionIfNeeded(TRANSIT_TO_FRONT, 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"; reason = reason + " findTaskToMoveToFront";
boolean reparented = false; boolean reparented = false;
if (task.isResizeable() && canUseActivityOptionsLaunchBounds(options)) { if (task.isResizeable() && canUseActivityOptionsLaunchBounds(options)) {

View File

@@ -2987,7 +2987,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
@Override @Override
void removeIfPossible() { 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; mDeferredRemoval = true;
return; return;
} }
@@ -4989,7 +4992,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
@WindowManager.TransitionFlags int flags) { @WindowManager.TransitionFlags int flags) {
prepareAppTransition(transit, flags); prepareAppTransition(transit, flags);
mAtmService.getTransitionController().requestTransitionIfNeeded(transit, flags, mAtmService.getTransitionController().requestTransitionIfNeeded(transit, flags,
null /* trigger */); null /* trigger */, this);
} }
/** @see #requestTransitionAndLegacyPrepare(int, int) */ /** @see #requestTransitionAndLegacyPrepare(int, int) */
@@ -4997,11 +5000,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
@Nullable WindowContainer trigger) { @Nullable WindowContainer trigger) {
prepareAppTransition(transit); prepareAppTransition(transit);
mAtmService.getTransitionController().requestTransitionIfNeeded(transit, 0 /* flags */, mAtmService.getTransitionController().requestTransitionIfNeeded(transit, 0 /* flags */,
trigger); trigger, this);
} }
void executeAppTransition() { void executeAppTransition() {
mAtmService.getTransitionController().setReady(); mAtmService.getTransitionController().setReady(this);
if (mAppTransition.isTransitionSet()) { if (mAppTransition.isTransitionSet()) {
ProtoLog.w(WM_DEBUG_APP_TRANSITIONS, ProtoLog.w(WM_DEBUG_APP_TRANSITIONS,
"Execute app transition: %s, displayId: %d Callers=%s", "Execute app transition: %s, displayId: %d Callers=%s",

View File

@@ -508,6 +508,11 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
mTaskSupervisor.updateTopResumedActivityIfNeeded(); mTaskSupervisor.updateTopResumedActivityIfNeeded();
} }
@Override
boolean isAttached() {
return true;
}
/** /**
* Called when DisplayWindowSettings values may change. * Called when DisplayWindowSettings values may change.
*/ */

View File

@@ -132,7 +132,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
private TransitionInfo.AnimationOptions mOverrideOptions; private TransitionInfo.AnimationOptions mOverrideOptions;
private @TransitionState int mState = STATE_COLLECTING; private @TransitionState int mState = STATE_COLLECTING;
private boolean mReadyCalled = false; private final ReadyTracker mReadyTracker = new ReadyTracker();
// TODO(b/188595497): remove when not needed. // TODO(b/188595497): remove when not needed.
/** @see RecentsAnimationController#mNavigationBarAttachedToApp */ /** @see RecentsAnimationController#mNavigationBarAttachedToApp */
@@ -169,9 +169,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
mState = STATE_STARTED; mState = STATE_STARTED;
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Starting Transition %d", ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Starting Transition %d",
mSyncId); mSyncId);
if (mReadyCalled) { applyReady();
setReady();
}
} }
/** /**
@@ -186,6 +184,11 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
for (WindowContainer curr = wc.getParent(); curr != null && !mChanges.containsKey(curr); for (WindowContainer curr = wc.getParent(); curr != null && !mChanges.containsKey(curr);
curr = curr.getParent()) { curr = curr.getParent()) {
mChanges.put(curr, new ChangeInfo(curr)); 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; if (mParticipants.contains(wc)) return;
mSyncEngine.addToSyncSet(mSyncId, wc); 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. * 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. * 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 (mSyncId < 0) return;
if (mState < STATE_STARTED) { mReadyTracker.setReadyFrom(wc, ready);
mReadyCalled = ready; applyReady();
return; }
}
private void applyReady() {
if (mState < STATE_STARTED) return;
final boolean ready = mReadyTracker.allReady();
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
"Set transition ready=%b %d", ready, mSyncId); "Set transition ready=%b %d", ready, mSyncId);
mSyncEngine.setReady(mSyncId, ready); mSyncEngine.setReady(mSyncId, ready);
} }
/** @see #setReady . This calls with parameter true. */ /**
void setReady() { * Sets all possible ready groups to ready.
setReady(true); * @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(); 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 * Construct a TransitionInfo object from a set of targets and changes. Also populates the
* root surface. * root surface.
@@ -1092,4 +1116,95 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
mChildren.addAll(wcs); 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();
}
}
} }

View File

@@ -192,8 +192,8 @@ class TransitionController {
*/ */
@Nullable @Nullable
Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type, Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type,
@Nullable WindowContainer trigger) { @NonNull WindowContainer trigger) {
return requestTransitionIfNeeded(type, 0 /* flags */, trigger); return requestTransitionIfNeeded(type, 0 /* flags */, trigger, trigger /* readyGroupRef */);
} }
/** /**
@@ -201,8 +201,10 @@ class TransitionController {
*/ */
@Nullable @Nullable
Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type, Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type,
@WindowManager.TransitionFlags int flags, @Nullable WindowContainer trigger) { @WindowManager.TransitionFlags int flags, @Nullable WindowContainer trigger,
return requestTransitionIfNeeded(type, flags, trigger, null /* remote */); @NonNull WindowContainer readyGroupRef) {
return requestTransitionIfNeeded(type, flags, trigger, readyGroupRef,
null /* remoteTransition */);
} }
private static boolean isExistenceType(@WindowManager.TransitionType int type) { 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 * If a transition isn't requested yet, creates one and asks the TransitionPlayer (Shell) to
* start it. Collection can start immediately. * start it. Collection can start immediately.
* @param trigger if non-null, this is the first container that will be collected * @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. * @return the created transition if created or null otherwise.
*/ */
@Nullable @Nullable
Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type, Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type,
@WindowManager.TransitionFlags int flags, @Nullable WindowContainer trigger, @WindowManager.TransitionFlags int flags, @Nullable WindowContainer trigger,
@Nullable IRemoteTransition remoteTransition) { @NonNull WindowContainer readyGroupRef, @Nullable IRemoteTransition remoteTransition) {
if (mTransitionPlayer == null) { if (mTransitionPlayer == null) {
return null; return null;
} }
Transition newTransition = null; Transition newTransition = null;
if (isCollecting()) { if (isCollecting()) {
// Make the collecting transition wait until this request is ready. // Make the collecting transition wait until this request is ready.
mCollectingTransition.setReady(false); mCollectingTransition.setReady(readyGroupRef, false);
} else { } else {
newTransition = requestStartTransition(createTransition(type, flags), newTransition = requestStartTransition(createTransition(type, flags),
trigger != null ? trigger.asTask() : null, remoteTransition); trigger != null ? trigger.asTask() : null, remoteTransition);
@@ -280,14 +283,14 @@ class TransitionController {
} }
/** @see Transition#setReady */ /** @see Transition#setReady */
void setReady(boolean ready) { void setReady(WindowContainer wc, boolean ready) {
if (mCollectingTransition == null) return; if (mCollectingTransition == null) return;
mCollectingTransition.setReady(ready); mCollectingTransition.setReady(wc, ready);
} }
/** @see Transition#setReady */ /** @see Transition#setReady */
void setReady() { void setReady(WindowContainer wc) {
setReady(true); setReady(wc, true);
} }
/** @see Transition#finishTransition */ /** @see Transition#finishTransition */

View File

@@ -851,7 +851,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
} }
boolean isAttached() { boolean isAttached() {
return getDisplayArea() != null; WindowContainer parent = getParent();
return parent != null && parent.isAttached();
} }
void setWaitingForDrawnIfResizingChanged() { void setWaitingForDrawnIfResizingChanged() {

View File

@@ -8123,7 +8123,11 @@ public class WindowManagerService extends IWindowManager.Stub
boolean isAnimating = mAnimator.isAnimationScheduled() boolean isAnimating = mAnimator.isAnimationScheduled()
|| mRoot.isAnimating(TRANSITION | CHILDREN, ANIMATION_TYPE_ALL); || mRoot.isAnimating(TRANSITION | CHILDREN, ANIMATION_TYPE_ALL);
if (!isAnimating) { 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(); long startTime = System.currentTimeMillis();
try { try {

View File

@@ -227,7 +227,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
} }
applyTransaction(t, -1 /*syncId*/, transition, caller); applyTransaction(t, -1 /*syncId*/, transition, caller);
if (needsSetReady) { if (needsSetReady) {
transition.setReady(); transition.setAllReady();
} }
return transition; return transition;
} }