Ensure that participated activities are not omitted by ancestor
... when preparing transition targets.
Previously, the first step of the calculation finds the top participant
if possible, and once there is one, only the level above task will be
added. Because it assumes that the parent of participant can represent
it. But there are more than one participants belong to an ancestor, the
descendants may have individual changes, so they should be still in the
transition targets. Otherwise the animation may have nothing to do.
Now all valid participants are added into the target lists, and then
combine the targets from bottom to up based on depth. So it can be
done in 1 pass (originally it requires 3 passes when launching a new
task from home, 4 passes when starting recents).
The population of ChangeInfo#mParent is moved after tryPromo so it
can skip the targets which were removed, and the parent info can
be updated in a single place.
Bug: 213867980
Test: TransitionTests#testOpenActivityInTheSameTaskWithDisplayChange
Test: adb shell setprop persist.debug.shell_transit 1; reboot
Start a landscape activity from a portrait activity in the
same task. The animation should not jump cut.
Change-Id: I23a3326611dcb5664b204748280ae15b2377f318
This commit is contained in:
@@ -355,6 +355,12 @@
|
||||
"group": "WM_DEBUG_ORIENTATION",
|
||||
"at": "com\/android\/server\/wm\/DisplayRotation.java"
|
||||
},
|
||||
"-1728919185": {
|
||||
"message": " unrelated invisible sibling %s",
|
||||
"level": "VERBOSE",
|
||||
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/Transition.java"
|
||||
},
|
||||
"-1715268616": {
|
||||
"message": "Last window, removing starting window %s",
|
||||
"level": "VERBOSE",
|
||||
@@ -451,12 +457,6 @@
|
||||
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
|
||||
"at": "com\/android\/server\/wm\/RemoteAnimationController.java"
|
||||
},
|
||||
"-1587921395": {
|
||||
"message": " Top targets: %s",
|
||||
"level": "VERBOSE",
|
||||
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/Transition.java"
|
||||
},
|
||||
"-1585311008": {
|
||||
"message": "Bring to front target: %s from %s",
|
||||
"level": "DEBUG",
|
||||
@@ -709,12 +709,6 @@
|
||||
"group": "WM_DEBUG_TASKS",
|
||||
"at": "com\/android\/server\/wm\/RootWindowContainer.java"
|
||||
},
|
||||
"-1375751630": {
|
||||
"message": " --- Start combine pass ---",
|
||||
"level": "VERBOSE",
|
||||
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/Transition.java"
|
||||
},
|
||||
"-1364754753": {
|
||||
"message": "Task vanished taskId=%d",
|
||||
"level": "VERBOSE",
|
||||
@@ -1177,12 +1171,6 @@
|
||||
"group": "WM_DEBUG_IME",
|
||||
"at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java"
|
||||
},
|
||||
"-855366859": {
|
||||
"message": " merging children in from %s: %s",
|
||||
"level": "VERBOSE",
|
||||
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/Transition.java"
|
||||
},
|
||||
"-853404763": {
|
||||
"message": "\twallpaper=%s",
|
||||
"level": "DEBUG",
|
||||
@@ -1243,6 +1231,12 @@
|
||||
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/Transition.java"
|
||||
},
|
||||
"-779095785": {
|
||||
"message": " sibling is a participant with mode %s",
|
||||
"level": "VERBOSE",
|
||||
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/Transition.java"
|
||||
},
|
||||
"-775004869": {
|
||||
"message": "Not a match: %s",
|
||||
"level": "DEBUG",
|
||||
@@ -1555,12 +1549,6 @@
|
||||
"group": "WM_DEBUG_CONFIGURATION",
|
||||
"at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
|
||||
},
|
||||
"-446752714": {
|
||||
"message": " SKIP: sibling contains top target %s",
|
||||
"level": "VERBOSE",
|
||||
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/Transition.java"
|
||||
},
|
||||
"-445944810": {
|
||||
"message": "finish(%b): mCanceled=%b",
|
||||
"level": "DEBUG",
|
||||
@@ -1729,12 +1717,6 @@
|
||||
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
|
||||
"at": "com\/android\/server\/wm\/RecentsAnimation.java"
|
||||
},
|
||||
"-302335479": {
|
||||
"message": " remove from topTargets %s",
|
||||
"level": "VERBOSE",
|
||||
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/Transition.java"
|
||||
},
|
||||
"-292790591": {
|
||||
"message": "Attempted to set IME policy to a display that does not exist: %d",
|
||||
"level": "WARN",
|
||||
@@ -2077,6 +2059,12 @@
|
||||
"group": "WM_DEBUG_STARTING_WINDOW",
|
||||
"at": "com\/android\/server\/wm\/ActivityRecord.java"
|
||||
},
|
||||
"112145970": {
|
||||
"message": " SKIP: its sibling was rejected",
|
||||
"level": "VERBOSE",
|
||||
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/Transition.java"
|
||||
},
|
||||
"114070759": {
|
||||
"message": "New wallpaper target: %s prevTarget: %s caller=%s",
|
||||
"level": "VERBOSE",
|
||||
@@ -2413,6 +2401,12 @@
|
||||
"group": "WM_SHOW_SURFACE_ALLOC",
|
||||
"at": "com\/android\/server\/wm\/RootWindowContainer.java"
|
||||
},
|
||||
"405146734": {
|
||||
"message": " Final targets: %s",
|
||||
"level": "VERBOSE",
|
||||
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/Transition.java"
|
||||
},
|
||||
"416924848": {
|
||||
"message": "InsetsSource Control %s for target %s",
|
||||
"level": "DEBUG",
|
||||
@@ -2437,12 +2431,6 @@
|
||||
"group": "WM_ERROR",
|
||||
"at": "com\/android\/server\/wm\/WindowManagerService.java"
|
||||
},
|
||||
"430260320": {
|
||||
"message": " sibling is a top target with mode %s",
|
||||
"level": "VERBOSE",
|
||||
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/Transition.java"
|
||||
},
|
||||
"431715812": {
|
||||
"message": "Launch on display check: allow launch any on display",
|
||||
"level": "DEBUG",
|
||||
@@ -2761,12 +2749,6 @@
|
||||
"group": "WM_SHOW_SURFACE_ALLOC",
|
||||
"at": "com\/android\/server\/wm\/WindowStateAnimator.java"
|
||||
},
|
||||
"751854538": {
|
||||
"message": "DisplayArea keep clear rects changed name =%s",
|
||||
"level": "VERBOSE",
|
||||
"group": "WM_DEBUG_WINDOW_ORGANIZER",
|
||||
"at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java"
|
||||
},
|
||||
"765395228": {
|
||||
"message": "onAnimationFinished(): controller=%s reorderMode=%d",
|
||||
"level": "DEBUG",
|
||||
@@ -3097,12 +3079,6 @@
|
||||
"group": "WM_DEBUG_WALLPAPER",
|
||||
"at": "com\/android\/server\/wm\/WallpaperController.java"
|
||||
},
|
||||
"1186730970": {
|
||||
"message": " no common mode yet, so set it",
|
||||
"level": "VERBOSE",
|
||||
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/Transition.java"
|
||||
},
|
||||
"1191587912": {
|
||||
"message": "Moved rootTask=%s behind rootTask=%s",
|
||||
"level": "DEBUG",
|
||||
|
||||
@@ -37,7 +37,6 @@ import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHA
|
||||
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
|
||||
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;
|
||||
import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
|
||||
import static android.view.WindowManager.TRANSIT_NONE;
|
||||
import static android.view.WindowManager.TRANSIT_OPEN;
|
||||
import static android.view.WindowManager.TRANSIT_TO_BACK;
|
||||
import static android.view.WindowManager.TRANSIT_TO_FRONT;
|
||||
@@ -72,6 +71,7 @@ import android.os.Trace;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.WindowManager;
|
||||
import android.view.animation.Animation;
|
||||
@@ -156,7 +156,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
final ArraySet<WindowContainer> mParticipants = new ArraySet<>();
|
||||
|
||||
/** The final animation targets derived from participants after promotion. */
|
||||
private ArraySet<WindowContainer> mTargets = null;
|
||||
private ArrayList<WindowContainer> mTargets;
|
||||
|
||||
/** The main display running this transition. */
|
||||
private DisplayContent mTargetDisplay;
|
||||
@@ -385,7 +385,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
// usually only size 1
|
||||
final ArraySet<DisplayContent> displays = new ArraySet<>();
|
||||
for (int i = mTargets.size() - 1; i >= 0; --i) {
|
||||
final WindowContainer target = mTargets.valueAt(i);
|
||||
final WindowContainer target = mTargets.get(i);
|
||||
if (target.getParent() != null) {
|
||||
final SurfaceControl targetLeash = getLeashSurface(target);
|
||||
final SurfaceControl origParent = getOrigParentSurface(target);
|
||||
@@ -818,7 +818,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
// Search for the home task. If it is supposed to be visible, then the navbar is not at
|
||||
// the bottom of the screen, so we need to animate it.
|
||||
for (int i = 0; i < mTargets.size(); ++i) {
|
||||
final Task task = mTargets.valueAt(i).asTask();
|
||||
final Task task = mTargets.get(i).asTask();
|
||||
if (task == null || !task.isHomeOrRecentsRootTask()) continue;
|
||||
animate = task.isVisibleRequested();
|
||||
break;
|
||||
@@ -901,23 +901,8 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
private static boolean reportIfNotTop(WindowContainer wc) {
|
||||
// Organized tasks need to be reported anyways because Core won't show() their surfaces
|
||||
// and we can't rely on onTaskAppeared because it isn't in sync.
|
||||
// Also report wallpaper so it can be handled properly during display change/rotation.
|
||||
// TODO(shell-transitions): switch onTaskAppeared usage over to transitions OPEN.
|
||||
return wc.isOrganized() || isWallpaper(wc);
|
||||
}
|
||||
|
||||
/** @return the depth of child within ancestor, 0 if child == ancestor, or -1 if not a child. */
|
||||
private static int getChildDepth(WindowContainer child, WindowContainer ancestor) {
|
||||
WindowContainer parent = child;
|
||||
int depth = 0;
|
||||
while (parent != null) {
|
||||
if (parent == ancestor) {
|
||||
return depth;
|
||||
}
|
||||
parent = parent.getParent();
|
||||
++depth;
|
||||
}
|
||||
return -1;
|
||||
return wc.isOrganized();
|
||||
}
|
||||
|
||||
private static boolean isWallpaper(WindowContainer wc) {
|
||||
@@ -947,61 +932,48 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
*
|
||||
* @return {@code true} if transition in target can be promoted to its parent.
|
||||
*/
|
||||
private static boolean canPromote(WindowContainer target, ArraySet<WindowContainer> topTargets,
|
||||
private static boolean canPromote(WindowContainer<?> target, Targets targets,
|
||||
ArrayMap<WindowContainer, ChangeInfo> changes) {
|
||||
final WindowContainer parent = target.getParent();
|
||||
final ChangeInfo parentChanges = parent != null ? changes.get(parent) : null;
|
||||
if (parent == null || !parent.canCreateRemoteAnimationTarget()
|
||||
|| parentChanges == null || !parentChanges.hasChanged(parent)) {
|
||||
final WindowContainer<?> parent = target.getParent();
|
||||
final ChangeInfo parentChange = changes.get(parent);
|
||||
if (!parent.canCreateRemoteAnimationTarget()
|
||||
|| parentChange == null || !parentChange.hasChanged(parent)) {
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " SKIP: %s",
|
||||
parent == null ? "no parent" : ("parent can't be target " + parent));
|
||||
"parent can't be target " + parent);
|
||||
return false;
|
||||
}
|
||||
if (isWallpaper(target)) {
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " SKIP: is wallpaper");
|
||||
return false;
|
||||
}
|
||||
@TransitionInfo.TransitionMode int mode = TRANSIT_NONE;
|
||||
// Go through all siblings of this target to see if any of them would prevent
|
||||
// the target from promoting.
|
||||
siblingLoop:
|
||||
|
||||
final @TransitionInfo.TransitionMode int mode = changes.get(target).getTransitMode(target);
|
||||
for (int i = parent.getChildCount() - 1; i >= 0; --i) {
|
||||
final WindowContainer sibling = parent.getChildAt(i);
|
||||
final WindowContainer<?> sibling = parent.getChildAt(i);
|
||||
if (target == sibling) continue;
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " check sibling %s",
|
||||
sibling);
|
||||
// Check if any topTargets are the sibling or within it
|
||||
for (int j = topTargets.size() - 1; j >= 0; --j) {
|
||||
final int depth = getChildDepth(topTargets.valueAt(j), sibling);
|
||||
if (depth < 0) continue;
|
||||
if (depth == 0) {
|
||||
final int siblingMode = changes.get(sibling).getTransitMode(sibling);
|
||||
final ChangeInfo siblingChange = changes.get(sibling);
|
||||
if (siblingChange == null || !targets.wasParticipated(sibling)) {
|
||||
if (sibling.isVisibleRequested()) {
|
||||
// Sibling is visible but not animating, so no promote.
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
|
||||
" sibling is a top target with mode %s",
|
||||
TransitionInfo.modeToString(siblingMode));
|
||||
if (mode == TRANSIT_NONE) {
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
|
||||
" no common mode yet, so set it");
|
||||
mode = siblingMode;
|
||||
} else if (mode != siblingMode) {
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
|
||||
" SKIP: common mode mismatch. was %s",
|
||||
TransitionInfo.modeToString(mode));
|
||||
return false;
|
||||
}
|
||||
continue siblingLoop;
|
||||
} else {
|
||||
// Sibling subtree may not be promotable.
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
|
||||
" SKIP: sibling contains top target %s",
|
||||
topTargets.valueAt(j));
|
||||
" SKIP: sibling is visible but not part of transition");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// No other animations are playing in this sibling
|
||||
if (sibling.isVisibleRequested()) {
|
||||
// Sibling is visible but not animating, so no promote.
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
|
||||
" SKIP: sibling is visible but not part of transition");
|
||||
" unrelated invisible sibling %s", sibling);
|
||||
continue;
|
||||
}
|
||||
|
||||
final int siblingMode = siblingChange.getTransitMode(sibling);
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
|
||||
" sibling is a participant with mode %s",
|
||||
TransitionInfo.modeToString(siblingMode));
|
||||
if (mode != siblingMode) {
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
|
||||
" SKIP: common mode mismatch. was %s",
|
||||
TransitionInfo.modeToString(mode));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1011,58 +983,40 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
/**
|
||||
* Go through topTargets and try to promote (see {@link #canPromote}) one of them.
|
||||
*
|
||||
* @param topTargets set of just the top-most targets in the hierarchy of participants.
|
||||
* @param targets all targets that will be sent to the player.
|
||||
* @return {@code true} if something was promoted.
|
||||
*/
|
||||
private static boolean tryPromote(ArraySet<WindowContainer> topTargets,
|
||||
ArraySet<WindowContainer> targets, ArrayMap<WindowContainer, ChangeInfo> changes) {
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " --- Start combine pass ---");
|
||||
// Go through each target until we find one that can be promoted.
|
||||
for (WindowContainer targ : topTargets) {
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " checking %s", targ);
|
||||
if (!canPromote(targ, topTargets, changes)) {
|
||||
private static void tryPromote(Targets targets, ArrayMap<WindowContainer, ChangeInfo> changes) {
|
||||
WindowContainer<?> lastNonPromotableParent = null;
|
||||
// Go through from the deepest target.
|
||||
for (int i = targets.mArray.size() - 1; i >= 0; --i) {
|
||||
final WindowContainer<?> target = targets.mArray.valueAt(i);
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " checking %s", target);
|
||||
final WindowContainer<?> parent = target.getParent();
|
||||
if (parent == lastNonPromotableParent) {
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
|
||||
" SKIP: its sibling was rejected");
|
||||
continue;
|
||||
}
|
||||
// No obstructions found to promotion, so promote
|
||||
final WindowContainer parent = targ.getParent();
|
||||
final ChangeInfo parentInfo = changes.get(parent);
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
|
||||
" CAN PROMOTE: promoting to parent %s", parent);
|
||||
targets.add(parent);
|
||||
|
||||
// Go through all children of newly-promoted container and remove them from the
|
||||
// top-targets.
|
||||
for (int i = parent.getChildCount() - 1; i >= 0; --i) {
|
||||
final WindowContainer child = parent.getChildAt(i);
|
||||
int idx = targets.indexOf(child);
|
||||
if (idx >= 0) {
|
||||
final ChangeInfo childInfo = changes.get(child);
|
||||
if (reportIfNotTop(child)) {
|
||||
childInfo.mParent = parent;
|
||||
parentInfo.addChild(child);
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
|
||||
" keep as target %s", child);
|
||||
} else {
|
||||
if (childInfo.mChildren != null) {
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
|
||||
" merging children in from %s: %s", child,
|
||||
childInfo.mChildren);
|
||||
parentInfo.addChildren(childInfo.mChildren);
|
||||
}
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
|
||||
" remove from targets %s", child);
|
||||
targets.removeAt(idx);
|
||||
}
|
||||
}
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
|
||||
" remove from topTargets %s", child);
|
||||
topTargets.remove(child);
|
||||
if (!canPromote(target, targets, changes)) {
|
||||
lastNonPromotableParent = parent;
|
||||
continue;
|
||||
}
|
||||
if (reportIfNotTop(target)) {
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
|
||||
" keep as target %s", target);
|
||||
} else {
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
|
||||
" remove from targets %s", target);
|
||||
targets.remove(i, target);
|
||||
}
|
||||
if (targets.mArray.indexOfValue(parent) < 0) {
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
|
||||
" CAN PROMOTE: promoting to parent %s", parent);
|
||||
// The parent has lower depth, so it will be checked in the later iteration.
|
||||
i++;
|
||||
targets.add(parent);
|
||||
}
|
||||
topTargets.add(parent);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1071,22 +1025,15 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
*/
|
||||
@VisibleForTesting
|
||||
@NonNull
|
||||
static ArraySet<WindowContainer> calculateTargets(ArraySet<WindowContainer> participants,
|
||||
static ArrayList<WindowContainer> calculateTargets(ArraySet<WindowContainer> participants,
|
||||
ArrayMap<WindowContainer, ChangeInfo> changes) {
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
|
||||
"Start calculating TransitionInfo based on participants: %s", participants);
|
||||
|
||||
final ArraySet<WindowContainer> topTargets = new ArraySet<>();
|
||||
// The final animation targets which cannot promote to higher level anymore.
|
||||
final ArraySet<WindowContainer> targets = new ArraySet<>();
|
||||
|
||||
final ArrayList<WindowContainer> tmpList = new ArrayList<>();
|
||||
|
||||
// Build initial set of top-level participants by removing any participants that are no-ops
|
||||
// or children of other participants or are otherwise invalid; however, keep around a list
|
||||
// of participants that should always be reported even if they aren't top.
|
||||
for (WindowContainer wc : participants) {
|
||||
// Don't include detached windows.
|
||||
// Add all valid participants to the target container.
|
||||
final Targets targets = new Targets();
|
||||
for (int i = participants.size() - 1; i >= 0; --i) {
|
||||
final WindowContainer<?> wc = participants.valueAt(i);
|
||||
if (!wc.isAttached()) {
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
|
||||
" Rejecting as detached: %s", wc);
|
||||
@@ -1101,70 +1048,62 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
" Rejecting as no-op: %s", wc);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Search through ancestors to find the top-most participant (if one exists)
|
||||
WindowContainer topParent = null;
|
||||
tmpList.clear();
|
||||
if (reportIfNotTop(wc)) {
|
||||
tmpList.add(wc);
|
||||
}
|
||||
// Wallpaper must be the top (regardless of how nested it is in DisplayAreas).
|
||||
boolean skipIntermediateReports = isWallpaper(wc);
|
||||
for (WindowContainer p = wc.getParent(); p != null; p = p.getParent()) {
|
||||
if (!p.isAttached() || changes.get(p) == null || !changes.get(p).hasChanged(p)) {
|
||||
// Again, we're skipping no-ops
|
||||
break;
|
||||
}
|
||||
if (participants.contains(p)) {
|
||||
topParent = p;
|
||||
break;
|
||||
} else if (isWallpaper(p)) {
|
||||
skipIntermediateReports = true;
|
||||
} else if (reportIfNotTop(p) && !skipIntermediateReports) {
|
||||
tmpList.add(p);
|
||||
}
|
||||
}
|
||||
if (topParent != null) {
|
||||
// There was an ancestor participant, so don't add wc to targets unless always-
|
||||
// report. Similarly, add any always-report parents along the way.
|
||||
for (int i = 0; i < tmpList.size(); ++i) {
|
||||
targets.add(tmpList.get(i));
|
||||
final ChangeInfo info = changes.get(tmpList.get(i));
|
||||
info.mParent = i < tmpList.size() - 1 ? tmpList.get(i + 1) : topParent;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// No ancestors in participant-list, so wc is a top target.
|
||||
targets.add(wc);
|
||||
topTargets.add(wc);
|
||||
targets.mValidParticipants.add(wc);
|
||||
}
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " Initial targets: %s",
|
||||
targets.mArray);
|
||||
// Combine the targets from bottom to top if possible.
|
||||
tryPromote(targets, changes);
|
||||
// Establish the relationship between the targets and their top changes.
|
||||
populateParentChanges(targets, changes);
|
||||
|
||||
// Populate children lists
|
||||
for (int i = targets.size() - 1; i >= 0; --i) {
|
||||
if (changes.get(targets.valueAt(i)).mParent != null) {
|
||||
changes.get(changes.get(targets.valueAt(i)).mParent).addChild(targets.valueAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " Initial targets: %s", targets);
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " Top targets: %s", topTargets);
|
||||
|
||||
// Combine targets by repeatedly going through the topTargets to see if they can be
|
||||
// promoted until there aren't any promotions possible.
|
||||
while (tryPromote(topTargets, targets, changes)) {
|
||||
// Empty on purpose
|
||||
}
|
||||
return targets;
|
||||
final ArrayList<WindowContainer> targetList = targets.getListSortedByZ();
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " Final targets: %s", targetList);
|
||||
return targetList;
|
||||
}
|
||||
|
||||
/** Add any of `members` within `root` to `out` in top-to-bottom z-order. */
|
||||
private static void addMembersInOrder(WindowContainer root, ArraySet<WindowContainer> members,
|
||||
ArrayList<WindowContainer> out) {
|
||||
for (int i = root.getChildCount() - 1; i >= 0; --i) {
|
||||
final WindowContainer child = root.getChildAt(i);
|
||||
addMembersInOrder(child, members, out);
|
||||
if (members.contains(child)) {
|
||||
out.add(child);
|
||||
/** Populates parent to the change info and collects intermediate targets. */
|
||||
private static void populateParentChanges(Targets targets,
|
||||
ArrayMap<WindowContainer, ChangeInfo> changes) {
|
||||
final ArrayList<WindowContainer<?>> intermediates = new ArrayList<>();
|
||||
for (int i = targets.mValidParticipants.size() - 1; i >= 0; --i) {
|
||||
WindowContainer<?> wc = targets.mValidParticipants.get(i);
|
||||
// Go up if the participant has been represented by its parent.
|
||||
while (targets.mArray.indexOfValue(wc) < 0 && wc.getParent() != null) {
|
||||
wc = wc.getParent();
|
||||
}
|
||||
// Wallpaper must belong to the top (regardless of how nested it is in DisplayAreas).
|
||||
final boolean skipIntermediateReports = isWallpaper(wc);
|
||||
intermediates.clear();
|
||||
// Collect the intermediate parents between target and top changed parent.
|
||||
for (WindowContainer<?> p = wc.getParent(); p != null; p = p.getParent()) {
|
||||
final ChangeInfo parentChange = changes.get(p);
|
||||
if (parentChange == null || !parentChange.hasChanged(p)) break;
|
||||
if (parentChange.mParent != null && !skipIntermediateReports) {
|
||||
changes.get(wc).mParent = p;
|
||||
// The chain above the parent was processed.
|
||||
break;
|
||||
}
|
||||
if (targets.mValidParticipants.contains(p)) {
|
||||
if (skipIntermediateReports) {
|
||||
changes.get(wc).mParent = p;
|
||||
} else {
|
||||
intermediates.add(p);
|
||||
}
|
||||
// The parent reaches a participant.
|
||||
break;
|
||||
} else if (reportIfNotTop(p) && !skipIntermediateReports) {
|
||||
intermediates.add(p);
|
||||
}
|
||||
}
|
||||
if (intermediates.isEmpty()) continue;
|
||||
// Add any always-report parents along the way.
|
||||
changes.get(wc).mParent = intermediates.get(0);
|
||||
for (int j = 0; j < intermediates.size() - 1; j++) {
|
||||
final WindowContainer<?> intermediate = intermediates.get(j);
|
||||
changes.get(intermediate).mParent = intermediates.get(j + 1);
|
||||
targets.add(intermediate);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1201,32 +1140,36 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
/**
|
||||
* Construct a TransitionInfo object from a set of targets and changes. Also populates the
|
||||
* root surface.
|
||||
* @param sortedTargets The targets sorted by z-order from top (index 0) to bottom.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
@NonNull
|
||||
static TransitionInfo calculateTransitionInfo(@TransitionType int type, int flags,
|
||||
ArraySet<WindowContainer> targets, ArrayMap<WindowContainer, ChangeInfo> changes) {
|
||||
ArrayList<WindowContainer> sortedTargets,
|
||||
ArrayMap<WindowContainer, ChangeInfo> changes) {
|
||||
final TransitionInfo out = new TransitionInfo(type, flags);
|
||||
|
||||
final ArraySet<WindowContainer> appTargets = new ArraySet<>();
|
||||
final ArraySet<WindowContainer> wallpapers = new ArraySet<>();
|
||||
for (int i = targets.size() - 1; i >= 0; --i) {
|
||||
(isWallpaper(targets.valueAt(i)) ? wallpapers : appTargets).add(targets.valueAt(i));
|
||||
WindowContainer<?> topApp = null;
|
||||
for (int i = 0; i < sortedTargets.size(); i++) {
|
||||
final WindowContainer<?> wc = sortedTargets.get(i);
|
||||
if (!isWallpaper(wc)) {
|
||||
topApp = wc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the top-most shared ancestor of app targets
|
||||
if (appTargets.isEmpty()) {
|
||||
if (topApp == null) {
|
||||
out.setRootLeash(new SurfaceControl(), 0, 0);
|
||||
return out;
|
||||
}
|
||||
WindowContainer ancestor = appTargets.valueAt(appTargets.size() - 1).getParent();
|
||||
|
||||
// Find the top-most shared ancestor of app targets.
|
||||
WindowContainer<?> ancestor = topApp.getParent();
|
||||
// Go up ancestor parent chain until all targets are descendants.
|
||||
ancestorLoop:
|
||||
while (ancestor != null) {
|
||||
for (int i = appTargets.size() - 1; i >= 0; --i) {
|
||||
final WindowContainer wc = appTargets.valueAt(i);
|
||||
if (!wc.isDescendantOf(ancestor)) {
|
||||
for (int i = sortedTargets.size() - 1; i >= 0; --i) {
|
||||
final WindowContainer wc = sortedTargets.get(i);
|
||||
if (!isWallpaper(wc) && !wc.isDescendantOf(ancestor)) {
|
||||
ancestor = ancestor.getParent();
|
||||
continue ancestorLoop;
|
||||
}
|
||||
@@ -1234,11 +1177,6 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
break;
|
||||
}
|
||||
|
||||
// Sort targets top-to-bottom in Z. Check ALL targets here in case the display area itself
|
||||
// is animating: then we want to include wallpapers at the right position.
|
||||
ArrayList<WindowContainer> sortedTargets = new ArrayList<>();
|
||||
addMembersInOrder(ancestor, targets, sortedTargets);
|
||||
|
||||
// make leash based on highest (z-order) direct child of ancestor with a participant.
|
||||
WindowContainer leashReference = sortedTargets.get(0);
|
||||
while (leashReference.getParent() != ancestor) {
|
||||
@@ -1252,14 +1190,6 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
t.close();
|
||||
out.setRootLeash(rootLeash, ancestor.getBounds().left, ancestor.getBounds().top);
|
||||
|
||||
// add the wallpapers at the bottom
|
||||
for (int i = wallpapers.size() - 1; i >= 0; --i) {
|
||||
final WindowContainer wc = wallpapers.valueAt(i);
|
||||
// If the displayarea itself is animating, then the wallpaper was already added.
|
||||
if (wc.isDescendantOf(ancestor)) break;
|
||||
sortedTargets.add(wc);
|
||||
}
|
||||
|
||||
// Convert all the resolved ChangeInfos into TransactionInfo.Change objects in order.
|
||||
final int count = sortedTargets.size();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
@@ -1403,7 +1333,6 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
static class ChangeInfo {
|
||||
// Usually "post" change state.
|
||||
WindowContainer mParent;
|
||||
ArraySet<WindowContainer> mChildren;
|
||||
|
||||
// State tracking
|
||||
boolean mExistenceChanged = false;
|
||||
@@ -1498,19 +1427,6 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
void addChild(@NonNull WindowContainer wc) {
|
||||
if (mChildren == null) {
|
||||
mChildren = new ArraySet<>();
|
||||
}
|
||||
mChildren.add(wc);
|
||||
}
|
||||
void addChildren(@NonNull ArraySet<WindowContainer> wcs) {
|
||||
if (mChildren == null) {
|
||||
mChildren = new ArraySet<>();
|
||||
}
|
||||
mChildren.addAll(wcs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1603,4 +1519,64 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
return b.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The container to represent the depth relation for calculating transition targets. The window
|
||||
* container with larger depth is put at larger index. For the same depth, higher z-order has
|
||||
* larger index.
|
||||
*/
|
||||
private static class Targets {
|
||||
/** All targets. Its keys (depth) are sorted in ascending order naturally. */
|
||||
final SparseArray<WindowContainer<?>> mArray = new SparseArray<>();
|
||||
/** The initial participants which have changes. */
|
||||
final ArrayList<WindowContainer<?>> mValidParticipants = new ArrayList<>();
|
||||
/** The targets which were represented by their parent. */
|
||||
private ArrayList<WindowContainer<?>> mRemovedTargets;
|
||||
private int mDepthFactor;
|
||||
|
||||
void add(WindowContainer<?> target) {
|
||||
// The number of slots per depth is larger than the total number of window container,
|
||||
// so the depth score (key) won't have collision.
|
||||
if (mDepthFactor == 0) {
|
||||
mDepthFactor = target.mWmService.mRoot.getTreeWeight() + 1;
|
||||
}
|
||||
int score = target.getPrefixOrderIndex();
|
||||
WindowContainer<?> wc = target;
|
||||
while (wc != null) {
|
||||
final WindowContainer<?> parent = wc.getParent();
|
||||
if (parent != null) {
|
||||
score += mDepthFactor;
|
||||
}
|
||||
wc = parent;
|
||||
}
|
||||
mArray.put(score, target);
|
||||
}
|
||||
|
||||
void remove(int index, WindowContainer<?> removingTarget) {
|
||||
mArray.removeAt(index);
|
||||
if (mRemovedTargets == null) {
|
||||
mRemovedTargets = new ArrayList<>();
|
||||
}
|
||||
mRemovedTargets.add(removingTarget);
|
||||
}
|
||||
|
||||
boolean wasParticipated(WindowContainer<?> wc) {
|
||||
return mArray.indexOfValue(wc) >= 0
|
||||
|| (mRemovedTargets != null && mRemovedTargets.contains(wc));
|
||||
}
|
||||
|
||||
/** Returns the target list sorted by z-order in ascending order (index 0 is top). */
|
||||
ArrayList<WindowContainer> getListSortedByZ() {
|
||||
final SparseArray<WindowContainer<?>> arrayByZ = new SparseArray<>(mArray.size());
|
||||
for (int i = mArray.size() - 1; i >= 0; --i) {
|
||||
final int zOrder = mArray.keyAt(i) % mDepthFactor;
|
||||
arrayByZ.put(zOrder, mArray.valueAt(i));
|
||||
}
|
||||
final ArrayList<WindowContainer> sortedTargets = new ArrayList<>(arrayByZ.size());
|
||||
for (int i = arrayByZ.size() - 1; i >= 0; --i) {
|
||||
sortedTargets.add(arrayByZ.valueAt(i));
|
||||
}
|
||||
return sortedTargets;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -661,6 +661,11 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the total number of descendants, including self. */
|
||||
int getTreeWeight() {
|
||||
return mTreeWeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The index of this element in the hierarchy tree in prefix order.
|
||||
*/
|
||||
|
||||
@@ -50,6 +50,7 @@ import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.TransactionCommittedListener;
|
||||
import android.window.IDisplayAreaOrganizer;
|
||||
import android.window.ITaskOrganizer;
|
||||
import android.window.ITransitionPlayer;
|
||||
import android.window.TransitionInfo;
|
||||
@@ -60,6 +61,8 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -106,7 +109,7 @@ public class TransitionTests extends WindowTestsBase {
|
||||
// Check basic both tasks participating
|
||||
participants.add(oldTask);
|
||||
participants.add(newTask);
|
||||
ArraySet<WindowContainer> targets = Transition.calculateTargets(participants, changes);
|
||||
ArrayList<WindowContainer> targets = Transition.calculateTargets(participants, changes);
|
||||
TransitionInfo info = Transition.calculateTransitionInfo(transit, flags, targets, changes);
|
||||
assertEquals(2, info.getChanges().size());
|
||||
assertEquals(transit, info.getType());
|
||||
@@ -171,7 +174,7 @@ public class TransitionTests extends WindowTestsBase {
|
||||
participants.add(oldTask);
|
||||
participants.add(opening);
|
||||
participants.add(opening2);
|
||||
ArraySet<WindowContainer> targets = Transition.calculateTargets(participants, changes);
|
||||
ArrayList<WindowContainer> targets = Transition.calculateTargets(participants, changes);
|
||||
TransitionInfo info = Transition.calculateTransitionInfo(transit, flags, targets, changes);
|
||||
assertEquals(2, info.getChanges().size());
|
||||
assertEquals(transit, info.getType());
|
||||
@@ -217,15 +220,14 @@ public class TransitionTests extends WindowTestsBase {
|
||||
// Check promotion to DisplayArea
|
||||
participants.add(showing);
|
||||
participants.add(showing2);
|
||||
ArraySet<WindowContainer> targets = Transition.calculateTargets(participants, changes);
|
||||
ArrayList<WindowContainer> targets = Transition.calculateTargets(participants, changes);
|
||||
TransitionInfo info = Transition.calculateTransitionInfo(transit, flags, targets, changes);
|
||||
assertEquals(1, info.getChanges().size());
|
||||
assertEquals(transit, info.getType());
|
||||
assertNotNull(info.getChange(tda.mRemoteToken.toWindowContainerToken()));
|
||||
|
||||
ITaskOrganizer mockOrg = mock(ITaskOrganizer.class);
|
||||
// Check that organized tasks get reported even if not top
|
||||
showTask.mTaskOrganizer = mockOrg;
|
||||
makeTaskOrganized(showTask);
|
||||
targets = Transition.calculateTargets(participants, changes);
|
||||
info = Transition.calculateTransitionInfo(transit, flags, targets, changes);
|
||||
assertEquals(2, info.getChanges().size());
|
||||
@@ -255,7 +257,7 @@ public class TransitionTests extends WindowTestsBase {
|
||||
opening.mVisibleRequested = true;
|
||||
closing.mVisibleRequested = false;
|
||||
|
||||
ArraySet<WindowContainer> targets = Transition.calculateTargets(
|
||||
ArrayList<WindowContainer> targets = Transition.calculateTargets(
|
||||
transition.mParticipants, transition.mChanges);
|
||||
TransitionInfo info = Transition.calculateTransitionInfo(
|
||||
0, 0, targets, transition.mChanges);
|
||||
@@ -292,7 +294,7 @@ public class TransitionTests extends WindowTestsBase {
|
||||
tasks[i].getTopMostActivity().mVisibleRequested = (i % 2) != 0;
|
||||
}
|
||||
|
||||
ArraySet<WindowContainer> targets = Transition.calculateTargets(
|
||||
ArrayList<WindowContainer> targets = Transition.calculateTargets(
|
||||
transition.mParticipants, transition.mChanges);
|
||||
TransitionInfo info = Transition.calculateTransitionInfo(
|
||||
0, 0, targets, transition.mChanges);
|
||||
@@ -341,7 +343,7 @@ public class TransitionTests extends WindowTestsBase {
|
||||
tasks[i].getTopMostActivity().mVisibleRequested = (i % 2) != 0;
|
||||
}
|
||||
|
||||
ArraySet<WindowContainer> targets = Transition.calculateTargets(
|
||||
ArrayList<WindowContainer> targets = Transition.calculateTargets(
|
||||
transition.mParticipants, transition.mChanges);
|
||||
TransitionInfo info = Transition.calculateTransitionInfo(
|
||||
0, 0, targets, transition.mChanges);
|
||||
@@ -363,13 +365,7 @@ public class TransitionTests extends WindowTestsBase {
|
||||
mock(IBinder.class), true, mDisplayContent, true /* ownerCanManageAppTokens */);
|
||||
// Make DA organized so we can check that they don't get included.
|
||||
WindowContainer parent = wallpaperWindowToken.getParent();
|
||||
while (parent != null && parent != mDisplayContent) {
|
||||
if (parent.asDisplayArea() != null) {
|
||||
parent.asDisplayArea().setOrganizer(
|
||||
mock(android.window.IDisplayAreaOrganizer.class), true /* skipAppear */);
|
||||
}
|
||||
parent = parent.getParent();
|
||||
}
|
||||
makeDisplayAreaOrganized(parent, mDisplayContent);
|
||||
final WindowState wallpaperWindow = createWindow(null, TYPE_WALLPAPER, wallpaperWindowToken,
|
||||
"wallpaperWindow");
|
||||
wallpaperWindowToken.setVisibleRequested(false);
|
||||
@@ -381,7 +377,7 @@ public class TransitionTests extends WindowTestsBase {
|
||||
mDisplayContent.getWindowConfiguration().setRotation(
|
||||
(mDisplayContent.getWindowConfiguration().getRotation() + 1) % 4);
|
||||
|
||||
ArraySet<WindowContainer> targets = Transition.calculateTargets(
|
||||
ArrayList<WindowContainer> targets = Transition.calculateTargets(
|
||||
transition.mParticipants, transition.mChanges);
|
||||
TransitionInfo info = Transition.calculateTransitionInfo(
|
||||
0, 0, targets, transition.mChanges);
|
||||
@@ -393,12 +389,38 @@ public class TransitionTests extends WindowTestsBase {
|
||||
info.getChanges().get(0).getParent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenActivityInTheSameTaskWithDisplayChange() {
|
||||
final ActivityRecord closing = createActivityRecord(mDisplayContent);
|
||||
closing.mVisibleRequested = true;
|
||||
final Task task = closing.getTask();
|
||||
makeTaskOrganized(task);
|
||||
final ActivityRecord opening = createActivityRecord(task);
|
||||
opening.mVisibleRequested = false;
|
||||
makeDisplayAreaOrganized(mDisplayContent.getDefaultTaskDisplayArea(), mDisplayContent);
|
||||
final WindowContainer<?>[] wcs = { closing, opening, task, mDisplayContent };
|
||||
final Transition transition = createTestTransition(TRANSIT_OPEN);
|
||||
for (WindowContainer<?> wc : wcs) {
|
||||
transition.collect(wc);
|
||||
}
|
||||
closing.mVisibleRequested = false;
|
||||
opening.mVisibleRequested = true;
|
||||
final int newRotation = mDisplayContent.getWindowConfiguration().getRotation() + 1;
|
||||
for (WindowContainer<?> wc : wcs) {
|
||||
wc.getWindowConfiguration().setRotation(newRotation);
|
||||
}
|
||||
|
||||
final ArrayList<WindowContainer> targets = Transition.calculateTargets(
|
||||
transition.mParticipants, transition.mChanges);
|
||||
// Especially the activities must be in the targets.
|
||||
assertTrue(targets.containsAll(Arrays.asList(wcs)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIndependent() {
|
||||
final Transition transition = createTestTransition(TRANSIT_OPEN);
|
||||
ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges;
|
||||
ArraySet<WindowContainer> participants = transition.mParticipants;
|
||||
ITaskOrganizer mockOrg = mock(ITaskOrganizer.class);
|
||||
|
||||
final Task openTask = createTask(mDisplayContent);
|
||||
final Task openInOpenTask = createTaskInRootTask(openTask, 0);
|
||||
@@ -410,10 +432,8 @@ public class TransitionTests extends WindowTestsBase {
|
||||
final ActivityRecord changeInChange = createActivityRecord(changeInChangeTask);
|
||||
final ActivityRecord openInChange = createActivityRecord(openInChangeTask);
|
||||
// set organizer for everything so that they all get added to transition info
|
||||
for (Task t : new Task[]{
|
||||
openTask, openInOpenTask, changeTask, changeInChangeTask, openInChangeTask}) {
|
||||
t.mTaskOrganizer = mockOrg;
|
||||
}
|
||||
makeTaskOrganized(openTask, openInOpenTask, changeTask, changeInChangeTask,
|
||||
openInChangeTask);
|
||||
|
||||
// Start states.
|
||||
changes.put(openTask, new Transition.ChangeInfo(false /* vis */, true /* exChg */));
|
||||
@@ -440,7 +460,8 @@ public class TransitionTests extends WindowTestsBase {
|
||||
participants.add(openInChange);
|
||||
// Explicitly add changeTask (to test independence with parents)
|
||||
participants.add(changeTask);
|
||||
ArraySet<WindowContainer> targets = Transition.calculateTargets(participants, changes);
|
||||
final ArrayList<WindowContainer> targets =
|
||||
Transition.calculateTargets(participants, changes);
|
||||
TransitionInfo info = Transition.calculateTransitionInfo(transit, flags, targets, changes);
|
||||
// Root changes should always be considered independent
|
||||
assertTrue(isIndependent(
|
||||
@@ -581,17 +602,15 @@ public class TransitionTests extends WindowTestsBase {
|
||||
final TransitionController controller = new TransitionController(mAtm, snapshotController);
|
||||
final ITransitionPlayer player = new ITransitionPlayer.Default();
|
||||
controller.registerTransitionPlayer(player, null /* appThread */);
|
||||
ITaskOrganizer mockOrg = mock(ITaskOrganizer.class);
|
||||
final Transition openTransition = controller.createTransition(TRANSIT_OPEN);
|
||||
|
||||
// Start out with task2 visible and set up a transition that closes task2 and opens task1
|
||||
final Task task1 = createTask(mDisplayContent);
|
||||
task1.mTaskOrganizer = mockOrg;
|
||||
final ActivityRecord activity1 = createActivityRecord(task1);
|
||||
activity1.mVisibleRequested = false;
|
||||
activity1.setVisible(false);
|
||||
final Task task2 = createTask(mDisplayContent);
|
||||
task2.mTaskOrganizer = mockOrg;
|
||||
makeTaskOrganized(task1, task2);
|
||||
final ActivityRecord activity2 = createActivityRecord(task1);
|
||||
activity2.mVisibleRequested = true;
|
||||
activity2.setVisible(true);
|
||||
@@ -647,17 +666,15 @@ public class TransitionTests extends WindowTestsBase {
|
||||
final TransitionController controller = new TransitionController(mAtm, snapshotController);
|
||||
final ITransitionPlayer player = new ITransitionPlayer.Default();
|
||||
controller.registerTransitionPlayer(player, null /* appThread */);
|
||||
ITaskOrganizer mockOrg = mock(ITaskOrganizer.class);
|
||||
final Transition openTransition = controller.createTransition(TRANSIT_OPEN);
|
||||
|
||||
// Start out with task2 visible and set up a transition that closes task2 and opens task1
|
||||
final Task task1 = createTask(mDisplayContent);
|
||||
task1.mTaskOrganizer = mockOrg;
|
||||
final ActivityRecord activity1 = createActivityRecord(task1);
|
||||
activity1.mVisibleRequested = false;
|
||||
activity1.setVisible(false);
|
||||
final Task task2 = createTask(mDisplayContent);
|
||||
task2.mTaskOrganizer = mockOrg;
|
||||
makeTaskOrganized(task1, task2);
|
||||
final ActivityRecord activity2 = createActivityRecord(task2);
|
||||
activity2.mVisibleRequested = true;
|
||||
activity2.setVisible(true);
|
||||
@@ -706,6 +723,24 @@ public class TransitionTests extends WindowTestsBase {
|
||||
verify(snapshotController, times(1)).recordTaskSnapshot(eq(task1), eq(false));
|
||||
}
|
||||
|
||||
private static void makeTaskOrganized(Task... tasks) {
|
||||
final ITaskOrganizer organizer = mock(ITaskOrganizer.class);
|
||||
for (Task t : tasks) {
|
||||
t.mTaskOrganizer = organizer;
|
||||
}
|
||||
}
|
||||
|
||||
private static void makeDisplayAreaOrganized(WindowContainer<?> from,
|
||||
WindowContainer<?> end) {
|
||||
final IDisplayAreaOrganizer organizer = mock(IDisplayAreaOrganizer.class);
|
||||
while (from != null && from != end) {
|
||||
if (from.asDisplayArea() != null) {
|
||||
from.asDisplayArea().mOrganizer = organizer;
|
||||
}
|
||||
from = from.getParent();
|
||||
}
|
||||
}
|
||||
|
||||
/** Fill the change map with all the parents of top. Change maps are usually fully populated */
|
||||
private static void fillChangeMap(ArrayMap<WindowContainer, Transition.ChangeInfo> changes,
|
||||
WindowContainer top) {
|
||||
|
||||
Reference in New Issue
Block a user