Reuse stack as task for single task stacks (90/n)
Stacks and tasks are now the same object instance, so for cases were we
have a 1to1 relationship between the stack and task, just go ahead and
use one stack/task object instead of having the extra level.
- Helps us tryout the task hierarchy at a different depth than 2
to see what bugs needs to be fixed.
- Makes it easier to switch "tiles" into the hierarchy.
Bug: 80414790
Test: Existing tests pass.
Change-Id: I9796a149f5ca689b7000819085d4ed8e156b618c
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 4cc4851..04fae97 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1163,8 +1163,12 @@
// An activity is considered to be in multi-window mode if its task isn't fullscreen.
final boolean inMultiWindowMode = inMultiWindowMode();
if (inMultiWindowMode != mLastReportedMultiWindowMode) {
- mLastReportedMultiWindowMode = inMultiWindowMode;
- scheduleMultiWindowModeChanged(getConfiguration());
+ if (!inMultiWindowMode && mLastReportedPictureInPictureMode) {
+ updatePictureInPictureMode(null, false);
+ } else {
+ mLastReportedMultiWindowMode = inMultiWindowMode;
+ scheduleMultiWindowModeChanged(getConfiguration());
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 688f474..5b75004 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -658,8 +658,8 @@
}
@Override
- public void resolveOverrideConfiguration(Configuration newParentConfig) {
- super.resolveOverrideConfiguration(newParentConfig);
+ public void resolveTileOverrideConfiguration(Configuration newParentConfig) {
+ super.resolveTileOverrideConfiguration(newParentConfig);
if (mTile != null) {
// If this is a virtual child of a tile, simulate the parent-child relationship
mTile.updateResolvedConfig(getResolvedOverrideConfiguration());
@@ -1118,20 +1118,15 @@
return r.getTask().mTaskId != taskId && r.appToken != notTop && r.canBeTopRunning();
}
- ActivityRecord isInStackLocked(IBinder token) {
- final ActivityRecord r = ActivityRecord.forTokenLocked(token);
- return isInStackLocked(r);
- }
-
ActivityRecord isInStackLocked(ActivityRecord r) {
if (r == null) {
return null;
}
- final Task task = r.getTask();
- final ActivityStack stack = r.getRootTask();
- if (stack != null && task.mChildren.contains(r) && mChildren.contains(task)) {
- if (stack != this) Slog.w(TAG,
- "Illegal state! task does not point to stack it is in.");
+ final Task task = r.getRootTask();
+ if (task != null && r.isDescendantOf(task)) {
+ if (task != this) Slog.w(TAG, "Illegal state! task does not point to stack it is in. "
+ + "stack=" + this + " task=" + task + " r=" + r
+ + " callers=" + Debug.getCallers(15, "\n"));
return r;
}
return null;
@@ -1207,7 +1202,7 @@
}
getDisplay().positionStackAtBottom(this, reason);
- if (task != null) {
+ if (task != null && task != this) {
positionChildAtBottom(task);
}
@@ -1251,12 +1246,12 @@
mCurrentUser = userId;
super.switchUser(userId);
- forAllTasks((t) -> {
- if (t.showToCurrentUser()) {
+ forAllLeafTasks((t) -> {
+ if (t.showToCurrentUser() && t != this) {
mChildren.remove(t);
mChildren.add(t);
}
- }, true /* traverseTopToBottom */, this);
+ }, true /* traverseTopToBottom */);
}
void minimalResumeActivityLocked(ActivityRecord r) {
@@ -2450,16 +2445,16 @@
boolean newTask, boolean keepCurTransition, ActivityOptions options) {
Task rTask = r.getTask();
final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront();
- final boolean hasTask = hasChild(rTask);
+ final boolean isOrhasTask = rTask == this || hasChild(rTask);
// mLaunchTaskBehind tasks get placed at the back of the task stack.
- if (!r.mLaunchTaskBehind && allowMoveToFront && (!hasTask || newTask)) {
+ if (!r.mLaunchTaskBehind && allowMoveToFront && (!isOrhasTask || newTask)) {
// Last activity in task had been removed or ActivityManagerService is reusing task.
// Insert or replace.
// Might not even be in.
positionChildAtTop(rTask);
}
Task task = null;
- if (!newTask && hasTask) {
+ if (!newTask && isOrhasTask) {
final ActivityRecord occludingActivity = getActivity(
(ar) -> !ar.finishing && ar.occludesParent(), true, rTask);
if (occludingActivity != null) {
@@ -2717,7 +2712,7 @@
void finishVoiceTask(IVoiceInteractionSession session) {
final PooledConsumer c = PooledLambda.obtainConsumer(ActivityStack::finishIfVoiceTask,
PooledLambda.__(Task.class), session.asBinder());
- forAllTasks(c, true /* traverseTopToBottom */, this);
+ forAllLeafTasks(c, true /* traverseTopToBottom */);
c.recycle();
}
@@ -2818,8 +2813,7 @@
return false;
}
final Task task = srec.getTask();
-
- if (!mChildren.contains(task) || !task.hasChild(srec)) {
+ if (!srec.isDescendantOf(this)) {
return false;
}
@@ -2932,20 +2926,20 @@
getDisplay().mDisplayContent.prepareAppTransition(transit, false);
}
- final void moveTaskToFrontLocked(Task tr, boolean noAnimation, ActivityOptions options,
+ final void moveTaskToFront(Task tr, boolean noAnimation, ActivityOptions options,
AppTimeTracker timeTracker, String reason) {
- moveTaskToFrontLocked(tr, noAnimation, options, timeTracker, !DEFER_RESUME, reason);
+ moveTaskToFront(tr, noAnimation, options, timeTracker, !DEFER_RESUME, reason);
}
- final void moveTaskToFrontLocked(Task tr, boolean noAnimation, ActivityOptions options,
+ final void moveTaskToFront(Task tr, boolean noAnimation, ActivityOptions options,
AppTimeTracker timeTracker, boolean deferResume, String reason) {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
final ActivityStack topStack = getDisplay().getTopStack();
- final ActivityRecord topActivity = topStack != null ? topStack.getTopNonFinishingActivity() : null;
- final int numTasks = getChildCount();
- final int index = mChildren.indexOf(tr);
- if (numTasks == 0 || index < 0) {
+ final ActivityRecord topActivity = topStack != null
+ ? topStack.getTopNonFinishingActivity() : null;
+
+ if (tr != this && !tr.isDescendantOf(this)) {
// nothing to do!
if (noAnimation) {
ActivityOptions.abort(options);
@@ -3113,7 +3107,7 @@
final PooledConsumer c = PooledLambda.obtainConsumer(
ActivityStack::processTaskResizeBounds, PooledLambda.__(Task.class),
taskBounds, tempTaskInsetBounds);
- forAllTasks(c, true /* traverseTopToBottom */, this);
+ forAllLeafTasks(c, true /* traverseTopToBottom */);
c.recycle();
setBounds(bounds);
@@ -3150,7 +3144,7 @@
final PooledConsumer c = PooledLambda.obtainConsumer(ActivityStack::setTaskBounds,
PooledLambda.__(Task.class), bounds);
- forAllTasks(c, true /* traverseTopToBottom */, this);
+ forAllLeafTasks(c, true /* traverseTopToBottom */);
c.recycle();
}
@@ -3166,7 +3160,7 @@
final PooledConsumer c = PooledLambda.obtainConsumer(ActivityStack::setTaskDisplayedBounds,
PooledLambda.__(Task.class), bounds);
- forAllTasks(c, true /* traverseTopToBottom */, this);
+ forAllLeafTasks(c, true /* traverseTopToBottom */);
c.recycle();
}
@@ -3262,7 +3256,7 @@
return false;
}
final String prefix = " ";
- forAllTasks((task) -> {
+ forAllLeafTasks((task) -> {
if (needSep) {
pw.println("");
}
@@ -3280,7 +3274,7 @@
false /* traverseTopToBottom */);
dumpHistoryList(fd, pw, activities, prefix, "Hist", true, !dumpAll, dumpClient,
dumpPackage, false, null, task);
- }, true /* traverseTopToBottom */, this);
+ }, true /* traverseTopToBottom */);
return true;
}
@@ -3331,19 +3325,33 @@
}
}
- Task createTask(int taskId, ActivityInfo info, Intent intent, boolean toTop) {
- return createTask(taskId, info, intent, null /*voiceSession*/, null /*voiceInteractor*/,
+ Task reuseOrCreateTask(ActivityInfo info, Intent intent, boolean toTop) {
+ return reuseOrCreateTask(info, intent, null /*voiceSession*/, null /*voiceInteractor*/,
toTop, null /*activity*/, null /*source*/, null /*options*/);
}
+ // TODO: Can be removed once we change callpoints creating stacks to be creating tasks.
+ /** Either returns this current task to be re-used or creates a new child task. */
+ Task reuseOrCreateTask(ActivityInfo info, Intent intent, IVoiceInteractionSession voiceSession,
+ IVoiceInteractor voiceInteractor, boolean toTop, ActivityRecord activity,
+ ActivityRecord source, ActivityOptions options) {
- Task createTask(int taskId, ActivityInfo info, Intent intent,
- IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
- boolean toTop, ActivityRecord activity, ActivityRecord source,
- ActivityOptions options) {
- final Task task = Task.create(
- mAtmService, taskId, info, intent, voiceSession, voiceInteractor, this);
- // add the task to stack first, mTaskPositioner might need the stack association
- addChild(task, toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
+ Task task;
+ if (DisplayContent.alwaysCreateStack(getWindowingMode(), getActivityType())) {
+ // This stack will only contain one task, so just return itself since all stacks ara now
+ // tasks and all tasks are now stacks.
+ task = reuseAsLeafTask(voiceSession, voiceInteractor, info, activity);
+ } else {
+ // Create child task since this stack can contain multiple tasks.
+ final int taskId = activity != null
+ ? mStackSupervisor.getNextTaskIdForUser(activity.mUserId)
+ : mStackSupervisor.getNextTaskIdForUser();
+ task = Task.create(
+ mAtmService, taskId, info, intent, voiceSession, voiceInteractor, this);
+
+ // add the task to stack first, mTaskPositioner might need the stack association
+ addChild(task, toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
+ }
+
int displayId = getDisplayId();
if (displayId == INVALID_DISPLAY) displayId = DEFAULT_DISPLAY;
final boolean isLockscreenShown = mAtmService.mStackSupervisor.getKeyguardController()
@@ -3353,6 +3361,7 @@
&& !matchParentBounds() && task.isResizeable() && !isLockscreenShown) {
task.setBounds(getRequestedOverrideBounds());
}
+
return task;
}
@@ -3559,10 +3568,6 @@
"Can't exit pinned mode if it's not pinned already.");
}
- if (mChildren.size() != 1) {
- throw new RuntimeException("There should be only one task in a pinned stack.");
- }
-
// give pinned stack a chance to save current bounds, this should happen before reparent.
final ActivityRecord top = topRunningNonOverlayTaskActivity();
if (top != null && top.isVisible()) {
@@ -3592,12 +3597,12 @@
final PooledConsumer c = PooledLambda.obtainConsumer(
ActivityStackSupervisor::updatePictureInPictureMode, mStackSupervisor,
PooledLambda.__(Task.class), targetStackBounds, forceUpdate);
- forAllTasks(c, true /* traverseTopToBottom */, this);
+ forAllLeafTasks(c, true /* traverseTopToBottom */);
c.recycle();
}
void prepareFreezingTaskBounds() {
- forAllTasks(Task::prepareFreezingBounds, true /* traverseTopToBottom */, this);
+ forAllLeafTasks(Task::prepareFreezingBounds, true /* traverseTopToBottom */);
}
/**
@@ -3629,7 +3634,7 @@
final PooledConsumer c = PooledLambda.obtainConsumer(Task::alignToAdjustedBounds,
PooledLambda.__(Task.class), adjusted ? mAdjustedBounds : getRawBounds(),
insetBounds, alignBottom);
- forAllTasks(c, true /* traverseTopToBottom */, this);
+ forAllLeafTasks(c, true /* traverseTopToBottom */);
c.recycle();
}
@@ -3902,6 +3907,12 @@
return;
}
+ if (child == this) {
+ // TODO: Fix call-points
+ moveToFront("positionChildAtTop");
+ return;
+ }
+
positionChildAt(POSITION_TOP, child, true /* includingParents */);
child.updateTaskMovement(true);
@@ -4316,19 +4327,19 @@
* to the list of to be drawn windows the service is waiting for.
*/
void beginImeAdjustAnimation() {
- forAllTasks((t) -> {
+ forAllLeafTasks((t) -> {
if (t.hasContentToDisplay()) {
t.setDragResizing(true, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
t.setWaitingForDrawnIfResizingChanged();
}
- }, true /* traverseTopToBottom */, this);
+ }, true /* traverseTopToBottom */);
}
/** Resets the resizing state of all windows. */
void endImeAdjustAnimation() {
- forAllTasks((t) -> {
+ forAllLeafTasks((t) -> {
t.setDragResizing(false, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
- }, true /* traverseTopToBottom */, this);
+ }, true /* traverseTopToBottom */);
}
private int getMinTopStackBottom(final Rect displayContentRect, int originalStackBottom) {
@@ -4730,7 +4741,7 @@
/** Called immediately prior to resizing the tasks at the end of the pinned stack animation. */
void onPipAnimationEndResize() {
mBoundsAnimating = false;
- forAllTasks(Task::clearPreserveNonFloatingState, false /* traverseTopToBottom */, this);
+ forAllLeafTasks(Task::clearPreserveNonFloatingState, false /* traverseTopToBottom */);
mWmService.requestTraversal();
}
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 70cd01b..3468820 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -419,14 +419,29 @@
mTopTask = fromStack.getTopMostTask();
final PooledConsumer c = PooledLambda.obtainConsumer(
- MoveTaskToFullscreenHelper::processTask, this, PooledLambda.__(Task.class));
- fromStack.forAllTasks(c, false /* traverseTopToBottom */, fromStack);
+ MoveTaskToFullscreenHelper::processLeafTask, this, PooledLambda.__(Task.class));
+ fromStack.forAllLeafTasks(c, false /* traverseTopToBottom */);
c.recycle();
mToDisplay = null;
mTopTask = null;
}
- private void processTask(Task task) {
+ private void processLeafTask(Task task) {
+ // This is a one level task that we don't need to create stack for reparenting to.
+ if (task.isRootTask() && DisplayContent.alwaysCreateStack(WINDOWING_MODE_FULLSCREEN,
+ task.getActivityType())) {
+ final ActivityStack stack = (ActivityStack) task;
+ stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ if (mToDisplay.getDisplayId() != stack.getDisplayId()) {
+ mToDisplay.moveStackToDisplay(stack, mOnTop);
+ } else if (mOnTop) {
+ mToDisplay.positionStackAtTop(stack, false /* includingParents */);
+ } else {
+ mToDisplay.positionStackAtBottom(stack);
+ }
+ return;
+ }
+
final ActivityStack toStack = mToDisplay.getOrCreateStack(
null, mTmpOptions, task, task.getActivityType(), mOnTop);
@@ -1443,7 +1458,7 @@
}
final ActivityRecord r = task.getTopNonFinishingActivity();
- currentStack.moveTaskToFrontLocked(task, false /* noAnimation */, options,
+ currentStack.moveTaskToFront(task, false /* noAnimation */, options,
r == null ? null : r.appTimeTracker, reason);
if (DEBUG_STACK) Slog.d(TAG_STACK,
@@ -1742,7 +1757,7 @@
} else {
final PooledConsumer c = PooledLambda.obtainConsumer(
ActivityStackSupervisor::processRemoveTask, this, PooledLambda.__(Task.class));
- stack.forAllTasks(c, true /* traverseTopToBottom */, stack);
+ stack.forAllLeafTasks(c, true /* traverseTopToBottom */);
c.recycle();
}
}
@@ -2755,6 +2770,10 @@
deferUpdateRecentsHomeStackBounds();
// TODO(multi-display): currently recents animation only support default display.
mWindowManager.prepareAppTransition(TRANSIT_DOCK_TASK_FROM_RECENTS, false);
+ // TODO(task-hierarchy): Remove when tiles are in hierarchy.
+ // Unset launching windowing mode to prevent creating split-screen-primary stack
+ // in RWC#anyTaskForId() below.
+ activityOptions.setLaunchWindowingMode(WINDOWING_MODE_UNDEFINED);
}
task = mRootWindowContainer.anyTaskForId(taskId,
@@ -2764,6 +2783,9 @@
mWindowManager.executeAppTransition();
throw new IllegalArgumentException(
"startActivityFromRecents: Task " + taskId + " not found.");
+ } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+ && task.getWindowingMode() != windowingMode) {
+ mService.moveTaskToSplitScreenPrimaryTile(task, true /* toTop */);
}
if (windowingMode != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 2a2ab4b..600a125 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -2366,7 +2366,7 @@
// task on top there.
// Defer resuming the top activity while moving task to top, since the
// current task-top activity may not be the activity that should be resumed.
- mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
+ mTargetStack.moveTaskToFront(intentTask, mNoAnimation, mOptions,
mStartActivity.appTimeTracker, DEFER_RESUME,
"bringingFoundTaskToFront");
mMovedToFront = !isSplitScreenTopStack;
@@ -2396,8 +2396,7 @@
private void setNewTask(Task taskToAffiliate) {
final boolean toTop = !mLaunchTaskBehind && !mAvoidMoveToFront;
- final Task task = mTargetStack.createTask(
- mSupervisor.getNextTaskIdForUser(mStartActivity.mUserId),
+ final Task task = mTargetStack.reuseOrCreateTask(
mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
mVoiceInteractor, toTop, mStartActivity, mSourceRecord, mOptions);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 882d5c7..d5ffa1a 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2760,9 +2760,17 @@
throw new IllegalArgumentException("setTaskWindowingMode: Attempt to move"
+ " non-standard task " + taskId + " to split-screen windowing mode");
}
+ if (!task.supportsSplitScreenWindowingMode()) {
+ return false;
+ }
final int prevMode = task.getWindowingMode();
- final ActivityStack stack = task.getStack();
+ moveTaskToSplitScreenPrimaryTile(task, toTop);
+ return prevMode != task.getWindowingMode();
+ }
+
+ void moveTaskToSplitScreenPrimaryTile(Task task, boolean toTop) {
+ ActivityStack stack = task.getStack();
TaskTile tile = null;
for (int i = stack.getDisplay().getStackCount() - 1; i >= 0; --i) {
tile = stack.getDisplay().getStackAt(i).asTile();
@@ -2776,7 +2784,6 @@
WindowContainerTransaction wct = new WindowContainerTransaction();
wct.reparent(stack.mRemoteToken, tile.mRemoteToken, toTop);
mTaskOrganizerController.applyContainerTransaction(wct, null);
- return prevMode != task.getWindowingMode();
}
/**
@@ -3247,8 +3254,9 @@
}
final ActivityStack stack = r.getRootTask();
- final Task task = stack.createTask(
- mStackSupervisor.getNextTaskIdForUser(r.mUserId), ainfo, intent, !ON_TOP);
+ final Task task = stack.getDisplay().createStack(stack.getWindowingMode(),
+ stack.getActivityType(), !ON_TOP, ainfo, intent);
+
if (!mRecentTasks.addToBottom(task)) {
// The app has too many tasks already and we can't add any more
stack.removeChild(task, "addAppTask");
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index e60ab3f..0029dc8 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -4415,7 +4415,7 @@
ArrayList<Task> getVisibleTasks() {
final ArrayList<Task> visibleTasks = new ArrayList<>();
forAllTasks(task -> {
- if (!task.isRootTask() && task.isVisible()) {
+ if (task.isLeafTask() && task.isVisible()) {
visibleTasks.add(task);
}
});
@@ -4537,6 +4537,8 @@
true /* includingParents */);
}
+ child.updateTaskMovement(moveToTop);
+
setLayoutNeeded();
}
@@ -5790,7 +5792,7 @@
return null;
}
- boolean alwaysCreateStack(int windowingMode, int activityType) {
+ static boolean alwaysCreateStack(int windowingMode, int activityType) {
// Always create a stack for fullscreen, freeform, and split-screen-secondary windowing
// modes so that we can manage visual ordering and return types correctly.
return activityType == ACTIVITY_TYPE_STANDARD
diff --git a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
index 9d985d7..c92de2b 100644
--- a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
+++ b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
@@ -76,7 +76,7 @@
// to be visible (such as performing Recents animation).
final boolean resumeTopActivity = mTop != null && !mTop.mLaunchTaskBehind
&& mContiner.isTopActivityFocusable()
- && mContiner.isInStackLocked(starting) == null;
+ && (starting == null || !starting.isDescendantOf(mContiner));
final PooledConsumer f = PooledLambda.obtainConsumer(
EnsureActivitiesVisibleHelper::setActivityVisibilityState, this,
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index b0492be..e92bbaa 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -334,7 +334,7 @@
if (sendUserLeaveHint) {
// Setting this allows the previous app to PiP.
mStackSupervisor.mUserLeaving = true;
- targetStack.moveTaskToFrontLocked(targetActivity.getTask(),
+ targetStack.moveTaskToFront(targetActivity.getTask(),
true /* noAnimation */, null /* activityOptions */,
targetActivity.appTimeTracker,
"RecentsAnimation.onAnimationFinished()");
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index e923e64..57c877f 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -376,7 +376,7 @@
final PooledConsumer c = PooledLambda.obtainConsumer((t, outList) ->
{ if (!outList.contains(t)) outList.add(t); }, PooledLambda.__(Task.class),
visibleTasks);
- targetStack.forAllTasks(c, true /* traverseTopToBottom */, targetStack);
+ targetStack.forAllLeafTasks(c, true /* traverseTopToBottom */);
c.recycle();
}
diff --git a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
index 63346b9..45f8a15 100644
--- a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
+++ b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
@@ -67,7 +67,7 @@
final PooledConsumer c = PooledLambda.obtainConsumer(
ResetTargetTaskHelper::processTask, this, PooledLambda.__(Task.class));
- targetTask.mWmService.mRoot.forAllTasks(c, true /*traverseTopToBottom*/, mTargetStack);
+ targetTask.mWmService.mRoot.forAllLeafTasks(c, true /*traverseTopToBottom*/);
c.recycle();
processPendingReparentActivities();
@@ -245,9 +245,8 @@
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity "
+ r + " out to bottom task " + targetTask);
} else {
- targetTask = mTargetStack.createTask(
- atmService.mStackSupervisor.getNextTaskIdForUser(r.mUserId), r.info,
- null /* intent */, false /* toTop */);
+ targetTask = mTargetStack.reuseOrCreateTask(
+ r.info, null /*intent*/, false /*toTop*/);
targetTask.affinityIntent = r.intent;
createdTasks.add(targetTask);
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity "
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 2596452..aa6bdfd 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2137,10 +2137,7 @@
r.getActivityType(), ON_TOP, r.info, r.intent);
// There are multiple activities in the task and moving the top activity should
// reveal/leave the other activities in their original task.
-
- Task newTask = stack.createTask(mStackSupervisor.getNextTaskIdForUser(r.mUserId),
- r.info, r.intent, true);
- r.reparent(newTask, MAX_VALUE, "moveActivityToStack");
+ r.reparent(stack, MAX_VALUE, "moveActivityToStack");
}
stack.setWindowingMode(WINDOWING_MODE_PINNED);
@@ -2407,7 +2404,7 @@
final PooledConsumer c = PooledLambda.obtainConsumer(
RootWindowContainer::processTaskForStackInfo, PooledLambda.__(Task.class), info,
currentIndex);
- stack.forAllTasks(c, false /* traverseTopToBottom */, stack);
+ stack.forAllLeafTasks(c, false /* traverseTopToBottom */);
c.recycle();
final ActivityRecord top = stack.topRunningActivity();
@@ -3302,7 +3299,7 @@
final PooledConsumer c = PooledLambda.obtainConsumer(
RootWindowContainer::taskTopActivityIsUser, this, PooledLambda.__(Task.class),
userId);
- forAllTasks(c);
+ forAllLeafTasks(c, true /* traverseTopToBottom */);
c.recycle();
} finally {
mService.continueWindowLayout();
@@ -3321,14 +3318,6 @@
* @return {@code true} if the top activity looks like it belongs to {@param userId}.
*/
private void taskTopActivityIsUser(Task task, @UserIdInt int userId) {
- // TODO(b/80414790): having utilities to loop for all leaf tasks from caller vs. checking
- // leaf tasks here.
- if (!task.isLeafTask()) {
- // No op if not a leaf task since we don't want to report root tasks to
- // TaskStackListeners.
- return;
- }
-
// To handle the case that work app is in the task but just is not the top one.
final ActivityRecord activityRecord = task.getTopNonFinishingActivity();
final ActivityRecord resultTo = (activityRecord != null ? activityRecord.resultTo : null);
@@ -3430,18 +3419,8 @@
}
ActivityRecord isInAnyStack(IBinder token) {
- int numDisplays = getChildCount();
- for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final DisplayContent display = getChildAt(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- final ActivityRecord r = stack.isInStackLocked(token);
- if (r != null) {
- return r;
- }
- }
- }
- return null;
+ final ActivityRecord r = ActivityRecord.forTokenLocked(token);
+ return (r != null && r.isDescendantOf(this)) ? r : null;
}
@VisibleForTesting
diff --git a/services/core/java/com/android/server/wm/RunningTasks.java b/services/core/java/com/android/server/wm/RunningTasks.java
index 6ebbf77..9593ea0 100644
--- a/services/core/java/com/android/server/wm/RunningTasks.java
+++ b/services/core/java/com/android/server/wm/RunningTasks.java
@@ -76,7 +76,7 @@
final PooledConsumer c = PooledLambda.obtainConsumer(RunningTasks::processTask, this,
PooledLambda.__(Task.class));
- root.forAllTasks(c, false);
+ root.forAllLeafTasks(c, false);
c.recycle();
// Take the first {@param maxNum} tasks and create running task infos for them
@@ -93,9 +93,6 @@
}
private void processTask(Task task) {
- if (task.isRootTask()) {
- return;
- }
if (task.getTopNonFinishingActivity() == null) {
// Skip if there are no activities in the task
return;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index c7f2cc7..238bd44 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -225,8 +225,8 @@
String affinity; // The affinity name for this task, or null; may change identity.
String rootAffinity; // Initial base affinity, or null; does not change from initial root.
- final IVoiceInteractionSession voiceSession; // Voice interaction session driving task
- final IVoiceInteractor voiceInteractor; // Associated interactor to provide to app
+ IVoiceInteractionSession voiceSession; // Voice interaction session driving task
+ IVoiceInteractor voiceInteractor; // Associated interactor to provide to app
Intent intent; // The original intent that started the task. Note that this value can
// be null.
Intent affinityIntent; // Intent of affinity-moved activity that started this task.
@@ -571,6 +571,15 @@
mAtmService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
}
+ Task reuseAsLeafTask(IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
+ ActivityInfo info, ActivityRecord activity) {
+ voiceSession = _voiceSession;
+ voiceInteractor = _voiceInteractor;
+ setIntent(activity);
+ setMinDimensions(info);
+ return this;
+ }
+
private void cleanUpResourcesForDestroy(ConfigurationContainer oldParent) {
if (hasChild()) {
return;
@@ -1004,7 +1013,7 @@
}
/** Sets the original minimal width and height. */
- private void setMinDimensions(ActivityInfo info) {
+ void setMinDimensions(ActivityInfo info) {
if (info != null && info.windowLayout != null) {
mMinWidth = info.windowLayout.minWidth;
mMinHeight = info.windowLayout.minHeight;
@@ -2176,16 +2185,20 @@
return Configuration.reduceScreenLayout(sourceScreenLayout, longSize, shortSize);
}
+ void resolveTileOverrideConfiguration(Configuration newParentConfig) {
+ super.resolveOverrideConfiguration(newParentConfig);
+ }
+
@Override
void resolveOverrideConfiguration(Configuration newParentConfig) {
- if (isRootTask()) {
- super.resolveOverrideConfiguration(newParentConfig);
+ if (!isLeafTask()) {
+ resolveTileOverrideConfiguration(newParentConfig);
return;
}
mTmpBounds.set(getResolvedOverrideConfiguration().windowConfiguration.getBounds());
- super.resolveOverrideConfiguration(newParentConfig);
+ resolveTileOverrideConfiguration(newParentConfig);
int windowingMode =
- getRequestedOverrideConfiguration().windowConfiguration.getWindowingMode();
+ getResolvedOverrideConfiguration().windowConfiguration.getWindowingMode();
if (windowingMode == WINDOWING_MODE_UNDEFINED) {
windowingMode = newParentConfig.windowConfiguration.getWindowingMode();
}
@@ -2392,7 +2405,7 @@
final int[] currentCount = {0};
final PooledConsumer c = PooledLambda.obtainConsumer((t, count) -> { count[0]++; },
PooledLambda.__(Task.class), currentCount);
- forAllTasks(c, false /* traverseTopToBottom */, this);
+ forAllLeafTasks(c, false /* traverseTopToBottom */);
c.recycle();
return currentCount[0];
}
@@ -3074,16 +3087,33 @@
}
@Override
- void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom, Task excludedTask) {
- super.forAllTasks(callback, traverseTopToBottom, excludedTask);
- if (excludedTask != this) {
- callback.accept(this);
+ void forAllLeafTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
+ final int count = mChildren.size();
+ boolean isLeafTask = true;
+ if (traverseTopToBottom) {
+ for (int i = count - 1; i >= 0; --i) {
+ final Task child = mChildren.get(i).asTask();
+ if (child != null) {
+ isLeafTask = false;
+ child.forAllLeafTasks(callback, traverseTopToBottom);
+ }
+ }
+ } else {
+ for (int i = 0; i < count; i++) {
+ final Task child = mChildren.get(i).asTask();
+ if (child != null) {
+ isLeafTask = false;
+ child.forAllLeafTasks(callback, traverseTopToBottom);
+ }
+ }
}
+ if (isLeafTask) callback.accept(this);
}
@Override
void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
- forAllTasks(callback, traverseTopToBottom, null /* excludedTask */);
+ super.forAllTasks(callback, traverseTopToBottom);
+ callback.accept(this);
}
@Override
@@ -3265,7 +3295,7 @@
pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
pw.print(" mUserSetupComplete="); pw.print(mUserSetupComplete);
- pw.print(" mCallingPackage="); pw.println(mCallingPackage);
+ pw.print(" mCallingPackage="); pw.print(mCallingPackage);
pw.print(" mCallingFeatureId="); pw.println(mCallingFeatureId);
if (affinity != null || rootAffinity != null) {
pw.print(prefix); pw.print("affinity="); pw.print(affinity);
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index da996dc..7a4d0b0 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -615,7 +615,7 @@
void positionChildAt(int position, E child, boolean includingParents) {
if (child.getParent() != this) {
- throw new IllegalArgumentException("removeChild: container=" + child.getName()
+ throw new IllegalArgumentException("positionChildAt: container=" + child.getName()
+ " is not a child of container=" + getName()
+ " current parent=" + child.getParent());
}
@@ -1459,15 +1459,15 @@
}
}
- void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom, Task excludedTask) {
+ void forAllLeafTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
final int count = mChildren.size();
if (traverseTopToBottom) {
for (int i = count - 1; i >= 0; --i) {
- mChildren.get(i).forAllTasks(callback, traverseTopToBottom, excludedTask);
+ mChildren.get(i).forAllLeafTasks(callback, traverseTopToBottom);
}
} else {
for (int i = 0; i < count; i++) {
- mChildren.get(i).forAllTasks(callback, traverseTopToBottom, excludedTask);
+ mChildren.get(i).forAllLeafTasks(callback, traverseTopToBottom);
}
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index a0ea729..c9c3649 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -1025,9 +1025,9 @@
public void testDestroyIfPossible_lastActivityAboveEmptyHomeStack() {
// Empty the home stack.
final ActivityStack homeStack = mActivity.getDisplay().getRootHomeTask();
- homeStack.forAllTasks((t) -> {
+ homeStack.forAllLeafTasks((t) -> {
homeStack.removeChild(t, "test");
- }, true /* traverseTopToBottom */, homeStack);
+ }, true /* traverseTopToBottom */);
mActivity.finishing = true;
doReturn(false).when(mRootWindowContainer).resumeFocusedStacksTopActivities();
spyOn(mStack);
@@ -1051,9 +1051,9 @@
public void testCompleteFinishing_lastActivityAboveEmptyHomeStack() {
// Empty the home stack.
final ActivityStack homeStack = mActivity.getDisplay().getRootHomeTask();
- homeStack.forAllTasks((t) -> {
+ homeStack.forAllLeafTasks((t) -> {
homeStack.removeChild(t, "test");
- }, true /* traverseTopToBottom */, homeStack);
+ }, true /* traverseTopToBottom */);
mActivity.finishing = true;
spyOn(mStack);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
index cd53ece..45b51cf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
@@ -28,6 +28,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
@@ -300,6 +301,7 @@
Rect newSize = new Rect(10, 10, 300, 300);
Configuration c = new Configuration(tile1.getRequestedOverrideConfiguration());
c.windowConfiguration.setBounds(newSize);
+ doNothing().when(stack).adjustForMinimalTaskDimensions(any(), any());
tile1.onRequestedOverrideConfigurationChanged(c);
assertEquals(newSize, stack.getBounds());