Merge "Allowing leaf Task to contain both Activity and TaskFragment" into sc-v2-dev

This commit is contained in:
Louis Chang
2021-06-24 06:09:15 +00:00
committed by Android (Google) Code Review
7 changed files with 220 additions and 109 deletions

View File

@@ -1645,6 +1645,12 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
"-248761393": {
"message": "startPausing: taskFrag =%s mResumedActivity=%s",
"level": "DEBUG",
"group": "WM_DEBUG_STATES",
"at": "com\/android\/server\/wm\/TaskFragment.java"
},
"-240296576": {
"message": "handleAppTransitionReady: displayId=%d appTransition={%s} openingApps=[%s] closingApps=[%s] transit=%s",
"level": "VERBOSE",
@@ -3385,12 +3391,6 @@
"group": "WM_DEBUG_APP_TRANSITIONS",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
"1814259538": {
"message": "pauseBackTasks: taskFrag=%s mResumedActivity=%s",
"level": "DEBUG",
"group": "WM_DEBUG_STATES",
"at": "com\/android\/server\/wm\/TaskDisplayArea.java"
},
"1822314934": {
"message": "Expected target rootTask=%s to restored behind rootTask=%s but it is behind rootTask=%s",
"level": "WARN",

View File

@@ -1188,7 +1188,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
}
}
pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
pw.print(prefix); pw.print(full ? "* " : " "); pw.print(label);
pw.print(" #"); pw.print(index); pw.print(": ");
pw.println(r);
if (full) {
@@ -3071,12 +3071,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Tell window manager to prepare for this one to be removed.
setVisibility(false);
if (task.getTopPausingActivity() == null) {
if (getTaskFragment().getPausingActivity() == null) {
ProtoLog.v(WM_DEBUG_STATES, "Finish needs to pause: %s", this);
if (DEBUG_USER_LEAVING) {
Slog.v(TAG_USER_LEAVING, "finish() => pause with userLeaving=false");
}
task.startPausing(false /* userLeaving */, false /* uiSleeping */,
getTaskFragment().startPausing(false /* userLeaving */, false /* uiSleeping */,
null /* resuming */, "finish");
}
@@ -5431,7 +5431,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (!task.hasChild(this)) {
throw new IllegalStateException("Activity not found in its task");
}
return task.topRunningActivity() == this;
return getTaskFragment().topRunningActivity() == this;
}
void handleAlreadyVisible() {

View File

@@ -29,7 +29,7 @@ class EnsureActivitiesVisibleHelper {
private ActivityRecord mStarting;
private boolean mAboveTop;
private boolean mContainerShouldBeVisible;
private boolean mBehindFullscreenActivity;
private boolean mBehindFullyOccludedContainer;
private int mConfigChanges;
private boolean mPreserveWindows;
private boolean mNotifyClients;
@@ -56,7 +56,7 @@ class EnsureActivitiesVisibleHelper {
// are now visible.
mAboveTop = mTop != null;
mContainerShouldBeVisible = mTaskFragment.shouldBeVisible(mStarting);
mBehindFullscreenActivity = !mContainerShouldBeVisible;
mBehindFullyOccludedContainer = !mContainerShouldBeVisible;
mConfigChanges = configChanges;
mPreserveWindows = preserveWindows;
mNotifyClients = notifyClients;
@@ -97,9 +97,21 @@ class EnsureActivitiesVisibleHelper {
&& mTaskFragment.isTopActivityFocusable()
&& (starting == null || !starting.isDescendantOf(mTaskFragment));
mTaskFragment.forAllActivities(a -> {
setActivityVisibilityState(a, starting, resumeTopActivity);
});
for (int i = mTaskFragment.mChildren.size() - 1; i >= 0; --i) {
final WindowContainer child = mTaskFragment.mChildren.get(i);
if (child.asTaskFragment() != null) {
final TaskFragment childTaskFragment = child.asTaskFragment();
childTaskFragment.updateActivityVisibilities(starting, configChanges,
preserveWindows, notifyClients);
mBehindFullyOccludedContainer = childTaskFragment.getBounds().equals(
mTaskFragment.getBounds());
if (mAboveTop && mTop.getTaskFragment() == childTaskFragment) {
mAboveTop = false;
}
} else if (child.asActivityRecord() != null) {
setActivityVisibilityState(child.asActivityRecord(), starting, resumeTopActivity);
}
}
if (mTaskFragment.mAtmService.getTransitionController().getTransitionPlayer() != null) {
mTaskFragment.getDisplayContent().mWallpaperController.adjustWallpaperWindows();
}
@@ -113,7 +125,7 @@ class EnsureActivitiesVisibleHelper {
}
mAboveTop = false;
r.updateVisibilityIgnoringKeyguard(mBehindFullscreenActivity);
r.updateVisibilityIgnoringKeyguard(mBehindFullyOccludedContainer);
final boolean reallyVisible = r.shouldBeVisibleUnchecked();
// Check whether activity should be visible without Keyguard influence
@@ -123,11 +135,11 @@ class EnsureActivitiesVisibleHelper {
if (DEBUG_VISIBILITY) {
Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r
+ " containerVisible=" + mContainerShouldBeVisible
+ " behindFullscreen=" + mBehindFullscreenActivity);
+ " behindFullyOccluded=" + mBehindFullyOccludedContainer);
}
mBehindFullscreenActivity = true;
mBehindFullyOccludedContainer = true;
} else {
mBehindFullscreenActivity = false;
mBehindFullyOccludedContainer = false;
}
}
@@ -174,24 +186,25 @@ class EnsureActivitiesVisibleHelper {
Slog.v(TAG_VISIBILITY, "Make invisible? " + r
+ " finishing=" + r.finishing + " state=" + r.getState()
+ " containerShouldBeVisible=" + mContainerShouldBeVisible
+ " behindFullscreenActivity=" + mBehindFullscreenActivity
+ " behindFullyOccludedContainer=" + mBehindFullyOccludedContainer
+ " mLaunchTaskBehind=" + r.mLaunchTaskBehind);
}
r.makeInvisible();
}
if (!mBehindFullscreenActivity && mTaskFragment.isActivityTypeHome() && r.isRootOfTask()) {
if (!mBehindFullyOccludedContainer && mTaskFragment.isActivityTypeHome()
&& r.isRootOfTask()) {
if (DEBUG_VISIBILITY) {
Slog.v(TAG_VISIBILITY, "Home task: at " + mTaskFragment
+ " containerShouldBeVisible=" + mContainerShouldBeVisible
+ " behindFullscreenActivity=" + mBehindFullscreenActivity);
+ " behindOccludedParentContainer=" + mBehindFullyOccludedContainer);
}
// No other task in the root home task should be visible behind the home activity.
// Home activities is usually a translucent activity with the wallpaper behind
// them. However, when they don't have the wallpaper behind them, we want to
// show activities in the next application root task behind them vs. another
// task in the root home task like recents.
mBehindFullscreenActivity = true;
mBehindFullyOccludedContainer = true;
}
}

View File

@@ -2378,7 +2378,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
if (displayShouldSleep) {
rootTask.goToSleepIfPossible(false /* shuttingDown */);
} else {
rootTask.forAllLeafTaskFragments(
rootTask.forAllLeafTasksAndLeafTaskFragments(
taskFragment -> taskFragment.awakeFromSleeping(),
true /* traverseTopToBottom */);
if (rootTask.isFocusedRootTaskOnDisplay()

View File

@@ -1242,22 +1242,35 @@ class Task extends TaskFragment {
/** Returns the currently topmost resumed activity. */
@Nullable
ActivityRecord getTopResumedActivity() {
if (isLeafTask()) {
final ActivityRecord[] resumedActivity = new ActivityRecord[1];
forAllLeafTaskFragments(fragment -> {
if (fragment.getResumedActivity() != null) {
resumedActivity[0] = fragment.getResumedActivity();
return true;
if (!isLeafTask()) {
for (int i = mChildren.size() - 1; i >= 0; --i) {
ActivityRecord resumedActivity = mChildren.get(i).asTask().getTopResumedActivity();
if (resumedActivity != null) {
return resumedActivity;
}
return false;
});
return resumedActivity[0];
}
}
final ActivityRecord taskResumedActivity = getResumedActivity();
ActivityRecord topResumedActivity = null;
for (int i = mChildren.size() - 1; i >= 0; --i) {
ActivityRecord resumedActivity = mChildren.get(i).asTask().getTopResumedActivity();
if (resumedActivity != null) {
return resumedActivity;
final WindowContainer child = mChildren.get(i);
if (child.asTaskFragment() != null) {
final ActivityRecord[] resumedActivity = new ActivityRecord[1];
child.asTaskFragment().forAllLeafTaskFragments(fragment -> {
if (fragment.getResumedActivity() != null) {
resumedActivity[0] = fragment.getResumedActivity();
return true;
}
return false;
});
topResumedActivity = resumedActivity[0];
} else if (taskResumedActivity != null
&& child.asActivityRecord() == taskResumedActivity) {
topResumedActivity = taskResumedActivity;
}
if (topResumedActivity != null) {
return topResumedActivity;
}
}
return null;
@@ -1268,22 +1281,35 @@ class Task extends TaskFragment {
*/
@Nullable
ActivityRecord getTopPausingActivity() {
if (isLeafTask()) {
final ActivityRecord[] pausingActivity = new ActivityRecord[1];
forAllLeafTaskFragments(fragment -> {
if (fragment.getPausingActivity() != null) {
pausingActivity[0] = fragment.getPausingActivity();
return true;
if (!isLeafTask()) {
for (int i = mChildren.size() - 1; i >= 0; --i) {
ActivityRecord pausingActivity = mChildren.get(i).asTask().getTopPausingActivity();
if (pausingActivity != null) {
return pausingActivity;
}
return false;
});
return pausingActivity[0];
}
}
final ActivityRecord taskPausingActivity = getPausingActivity();
ActivityRecord topPausingActivity = null;
for (int i = mChildren.size() - 1; i >= 0; --i) {
ActivityRecord pausingActivity = mChildren.get(i).asTask().getTopPausingActivity();
if (pausingActivity != null) {
return pausingActivity;
final WindowContainer child = mChildren.get(i);
if (child.asTaskFragment() != null) {
final ActivityRecord[] pausingActivity = new ActivityRecord[1];
child.asTaskFragment().forAllLeafTaskFragments(fragment -> {
if (fragment.getPausingActivity() != null) {
pausingActivity[0] = fragment.getPausingActivity();
return true;
}
return false;
});
topPausingActivity = pausingActivity[0];
} else if (taskPausingActivity != null
&& child.asActivityRecord() == taskPausingActivity) {
topPausingActivity = taskPausingActivity;
}
if (topPausingActivity != null) {
return topPausingActivity;
}
}
return null;
@@ -1434,12 +1460,6 @@ class Task extends TaskFragment {
@Override
void addChild(WindowContainer child, int index) {
// If this task had any child before we added this one.
boolean hadChild = hasChild();
// getActivityType() looks at the top child, so we need to read the type before adding
// a new child in case the new child is on top and UNDEFINED.
final int activityType = getActivityType();
index = getAdjustedChildPosition(child, index);
super.addChild(child, index);
@@ -1454,11 +1474,11 @@ class Task extends TaskFragment {
// Make sure the list of display UID allowlists is updated
// now that this record is in a new task.
mRootWindowContainer.updateUIDsPresentOnDisplay();
}
final ActivityRecord r = child.asActivityRecord();
if (r == null) return;
r.inHistory = true;
/** Called when an {@link ActivityRecord} is added as a descendant */
void onDescendantActivityAdded(boolean hadChild, int activityType, ActivityRecord r) {
warnForNonLeafTask("onDescendantActivityAdded");
// Only set this based on the first activity
if (!hadChild) {
@@ -1485,10 +1505,6 @@ class Task extends TaskFragment {
updateEffectiveIntent();
}
void addChild(ActivityRecord r) {
addChild(r, Integer.MAX_VALUE /* add on top */);
}
@Override
void removeChild(WindowContainer child) {
removeChild(child, "removeChild");
@@ -3072,6 +3088,41 @@ class Task extends TaskFragment {
return false;
}
/** Iterates through all leaf task fragments and the leaf tasks. */
void forAllLeafTasksAndLeafTaskFragments(final Consumer<TaskFragment> callback,
boolean traverseTopToBottom) {
forAllLeafTasks(task -> {
if (task.isLeafTaskFragment()) {
callback.accept(task);
return;
}
// A leaf task that may contains both activities and task fragments.
boolean consumed = false;
if (traverseTopToBottom) {
for (int i = task.mChildren.size() - 1; i >= 0; --i) {
final WindowContainer child = mChildren.get(i);
if (child.asTaskFragment() != null) {
child.forAllLeafTaskFragments(callback, traverseTopToBottom);
} else if (child.asActivityRecord() != null && !consumed) {
callback.accept(task);
consumed = true;
}
}
} else {
for (int i = 0; i < task.mChildren.size(); i++) {
final WindowContainer child = mChildren.get(i);
if (child.asTaskFragment() != null) {
child.forAllLeafTaskFragments(callback, traverseTopToBottom);
} else if (child.asActivityRecord() != null && !consumed) {
callback.accept(task);
consumed = true;
}
}
}
}, traverseTopToBottom);
}
@Override
boolean forAllRootTasks(Function<Task, Boolean> callback, boolean traverseTopToBottom) {
return isRootTask() ? callback.apply(this) : false;
@@ -4602,11 +4653,11 @@ class Task extends TaskFragment {
*/
boolean goToSleepIfPossible(boolean shuttingDown) {
final int[] sleepInProgress = {0};
forAllLeafTaskFragments((f) -> {
if (!f.sleepIfPossible(shuttingDown)) {
forAllLeafTasksAndLeafTaskFragments(taskFragment -> {
if (!taskFragment.sleepIfPossible(shuttingDown)) {
sleepInProgress[0]++;
}
}, true);
}, true /* traverseTopToBottom */);
return sleepInProgress[0] == 0;
}
@@ -4661,8 +4712,8 @@ class Task extends TaskFragment {
boolean preserveWindows, boolean notifyClients) {
mTaskSupervisor.beginActivityVisibilityUpdate();
try {
forAllLeafTaskFragments(fragment -> {
fragment.updateActivityVisibilities(starting, configChanges, preserveWindows,
forAllLeafTasks(task -> {
task.updateActivityVisibilities(starting, configChanges, preserveWindows,
notifyClients);
}, true /* traverseTopToBottom */);
@@ -4829,13 +4880,20 @@ class Task extends TaskFragment {
mRootWindowContainer.cancelInitializingActivities();
if (topRunningActivity(true /* focusableOnly */) == null) {
final ActivityRecord topActivity = topRunningActivity(true /* focusableOnly */);
if (topActivity == null) {
// There are no activities left in this task, let's look somewhere else.
return resumeNextFocusableActivityWhenRootTaskIsEmpty(prev, options);
}
final boolean[] resumed = new boolean[1];
final TaskFragment topFragment = topActivity.getTaskFragment();
resumed[0] = topFragment.resumeTopActivity(prev, options, deferPause);
forAllLeafTaskFragments(f -> {
if (topFragment == f) {
return;
}
resumed[0] |= f.resumeTopActivity(prev, options, deferPause);
}, true);
return resumed[0];

View File

@@ -33,7 +33,6 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
import static com.android.server.wm.ActivityRecord.State.RESUMED;
import static com.android.server.wm.ActivityTaskManagerService.TAG_ROOT_TASK;
import static com.android.server.wm.DisplayContent.alwaysCreateRootTask;
@@ -1451,18 +1450,30 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> {
*/
boolean pauseBackTasks(ActivityRecord resuming) {
final int[] someActivityPaused = {0};
forAllLeafTaskFragments((taskFragment) -> {
final ActivityRecord resumedActivity = taskFragment.getResumedActivity();
if (resumedActivity != null
&& (taskFragment.getVisibility(resuming) != TASK_FRAGMENT_VISIBILITY_VISIBLE
|| !taskFragment.isTopActivityFocusable())) {
ProtoLog.d(WM_DEBUG_STATES, "pauseBackTasks: taskFrag=%s "
+ "mResumedActivity=%s", taskFragment, resumedActivity);
if (taskFragment.startPausing(false /* uiSleeping*/,
resuming, "pauseBackTasks")) {
someActivityPaused[0]++;
forAllLeafTasks(leafTask -> {
// Check if the direct child resumed activity in the leaf task needed to be paused if
// the leaf task is not a leaf task fragment.
if (!leafTask.isLeafTaskFragment()) {
final ActivityRecord top = topRunningActivity();
final ActivityRecord resumedActivity = leafTask.getResumedActivity();
if (resumedActivity != null && top.getTaskFragment() != leafTask) {
// Pausing the resumed activity because it is occluded by other task fragment.
if (leafTask.startPausing(false /* uiSleeping*/, resuming, "pauseBackTasks")) {
someActivityPaused[0]++;
}
}
}
leafTask.forAllLeafTaskFragments((taskFrag) -> {
final ActivityRecord resumedActivity = taskFrag.getResumedActivity();
if (resumedActivity != null
&& (taskFrag.getVisibility(resuming) != TASK_FRAGMENT_VISIBILITY_VISIBLE
|| !taskFrag.isTopActivityFocusable())) {
if (taskFrag.startPausing(false /* uiSleeping*/, resuming, "pauseBackTasks")) {
someActivityPaused[0]++;
}
}
}, true /* traverseTopToBottom */);
}, true /* traverseTopToBottom */);
return someActivityPaused[0] > 0;
}

View File

@@ -620,11 +620,10 @@ class TaskFragment extends WindowContainer<WindowContainer> {
final int windowingMode = getWindowingMode();
final boolean isAssistantType = isActivityTypeAssistant();
for (int i = parent.getChildCount() - 1; i >= 0; --i) {
final WindowContainer wc = parent.getChildAt(i);
final TaskFragment other = wc.asTaskFragment();
final WindowContainer other = parent.getChildAt(i);
if (other == null) continue;
final boolean hasRunningActivities = other.topRunningActivity() != null;
final boolean hasRunningActivities = hasRunningActivity(other);
if (other == this) {
// Should be visible if there is no other fragment occluding it, unless it doesn't
// have any running activities, not starting one and not home stack.
@@ -640,7 +639,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
final int otherWindowingMode = other.getWindowingMode();
if (otherWindowingMode == WINDOWING_MODE_FULLSCREEN) {
if (other.isTranslucent(starting)) {
if (isTranslucent(other, starting)) {
// Can be visible behind a translucent fullscreen TaskFragment.
gotTranslucentFullscreen = true;
continue;
@@ -648,7 +647,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
return TASK_FRAGMENT_VISIBILITY_INVISIBLE;
} else if (otherWindowingMode == WINDOWING_MODE_MULTI_WINDOW
&& other.matchParentBounds()) {
if (other.isTranslucent(starting)) {
if (isTranslucent(other, starting)) {
// Can be visible behind a translucent TaskFragment.
gotTranslucentFullscreen = true;
continue;
@@ -658,7 +657,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
} else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
&& !gotOpaqueSplitScreenPrimary) {
gotRootSplitScreenFragment = true;
gotTranslucentSplitScreenPrimary = other.isTranslucent(starting);
gotTranslucentSplitScreenPrimary = isTranslucent(other, starting);
gotOpaqueSplitScreenPrimary = !gotTranslucentSplitScreenPrimary;
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
&& gotOpaqueSplitScreenPrimary) {
@@ -668,7 +667,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
} else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
&& !gotOpaqueSplitScreenSecondary) {
gotRootSplitScreenFragment = true;
gotTranslucentSplitScreenSecondary = other.isTranslucent(starting);
gotTranslucentSplitScreenSecondary = isTranslucent(other, starting);
gotOpaqueSplitScreenSecondary = !gotTranslucentSplitScreenSecondary;
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
&& gotOpaqueSplitScreenSecondary) {
@@ -688,10 +687,11 @@ class TaskFragment extends WindowContainer<WindowContainer> {
return TASK_FRAGMENT_VISIBILITY_INVISIBLE;
}
if (other.mAdjacentTaskFragment != null) {
if (adjacentTaskFragments.contains(other.mAdjacentTaskFragment)) {
if (other.isTranslucent(starting)
|| other.mAdjacentTaskFragment.isTranslucent(starting)) {
final TaskFragment otherTaskFrag = other.asTaskFragment();
if (otherTaskFrag != null && otherTaskFrag.mAdjacentTaskFragment != null) {
if (adjacentTaskFragments.contains(otherTaskFrag.mAdjacentTaskFragment)) {
if (otherTaskFrag.isTranslucent(starting)
|| otherTaskFrag.mAdjacentTaskFragment.isTranslucent(starting)) {
// Can be visible behind a translucent adjacent TaskFragments.
gotTranslucentFullscreen = true;
continue;
@@ -699,7 +699,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
// Can not be visible behind adjacent TaskFragments.
return TASK_FRAGMENT_VISIBILITY_INVISIBLE;
} else {
adjacentTaskFragments.add(other);
adjacentTaskFragments.add(otherTaskFrag);
}
}
@@ -743,14 +743,28 @@ class TaskFragment extends WindowContainer<WindowContainer> {
: TASK_FRAGMENT_VISIBILITY_VISIBLE;
}
private boolean isTopActivityLaunchedBehind() {
final ActivityRecord top = topRunningActivity();
if (top != null && top.mLaunchTaskBehind) {
return true;
private static boolean hasRunningActivity(WindowContainer wc) {
if (wc.asTaskFragment() != null) {
return wc.asTaskFragment().topRunningActivity() != null;
}
return wc.asActivityRecord() != null && !wc.asActivityRecord().finishing;
}
private static boolean isTranslucent(WindowContainer wc, ActivityRecord starting) {
if (wc.asTaskFragment() != null) {
return wc.asTaskFragment().isTranslucent(starting);
} else if (wc.asActivityRecord() != null) {
return !wc.asActivityRecord().occludesParent();
}
return false;
}
private boolean isTopActivityLaunchedBehind() {
final ActivityRecord top = topRunningActivity();
return top != null && top.mLaunchTaskBehind;
}
final void updateActivityVisibilities(@Nullable ActivityRecord starting, int configChanges,
boolean preserveWindows, boolean notifyClients) {
mTaskSupervisor.beginActivityVisibilityUpdate();
@@ -838,7 +852,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);
if (mResumedActivity != null) {
ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Pausing %s", mResumedActivity);
pausing |= startPausingInner(mTaskSupervisor.mUserLeaving, false /* uiSleeping */,
pausing |= startPausing(mTaskSupervisor.mUserLeaving, false /* uiSleeping */,
next, "resumeTopActivity");
}
if (pausing) {
@@ -1146,17 +1160,6 @@ class TaskFragment extends WindowContainer<WindowContainer> {
return startPausing(mTaskSupervisor.mUserLeaving, uiSleeping, resuming, reason);
}
final boolean startPausing(boolean userLeaving, boolean uiSleeping,
ActivityRecord resuming, String reason) {
final int[] pausing = {0};
forAllLeafTaskFragments((f) -> {
if (f.startPausingInner(userLeaving, uiSleeping, resuming, reason)) {
pausing[0]++;
}
}, true /* traverseTopToBottom */);
return pausing[0] > 0;
}
/**
* Start pausing the currently resumed activity. It is an error to call this if there
* is already an activity being paused or there is no resumed activity.
@@ -1171,12 +1174,15 @@ class TaskFragment extends WindowContainer<WindowContainer> {
* @return Returns true if an activity now is in the PAUSING state, and we are waiting for
* it to tell us when it is done.
*/
private boolean startPausingInner(boolean userLeaving, boolean uiSleeping,
ActivityRecord resuming, String reason) {
boolean startPausing(boolean userLeaving, boolean uiSleeping, ActivityRecord resuming,
String reason) {
if (!hasDirectChildActivities()) {
return false;
}
ProtoLog.d(WM_DEBUG_STATES, "startPausing: taskFrag =%s " + "mResumedActivity=%s", this,
mResumedActivity);
if (mPausingActivity != null) {
Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
+ " state=" + mPausingActivity.getState());
@@ -1433,6 +1439,29 @@ class TaskFragment extends WindowContainer<WindowContainer> {
return false;
}
void addChild(ActivityRecord r) {
addChild(r, POSITION_TOP);
}
@Override
void addChild(WindowContainer child, int index) {
boolean isAddingActivity = child.asActivityRecord() != null;
final Task task = isAddingActivity ? getTask() : null;
// If this task had any child before we added this one.
boolean taskHadChild = task != null && task.hasChild();
// getActivityType() looks at the top child, so we need to read the type before adding
// a new child in case the new child is on top and UNDEFINED.
final int activityType = task != null ? task.getActivityType() : ACTIVITY_TYPE_UNDEFINED;
super.addChild(child, index);
if (isAddingActivity && task != null) {
child.asActivityRecord().inHistory = true;
task.onDescendantActivityAdded(taskHadChild, activityType, child.asActivityRecord());
}
}
void executeAppTransition(ActivityOptions options) {
// No app transition applied to the task fragment.
}