Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a38654fc authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Change Task to have generic WindowContainer children (73/n)

- Step towards Tasks containing other Tasks.
- There are several places where we want to perform an operation on all
activities in a branch of the hierarchy. We end up looping based on
the parent knowing what type of children is in the sub-branch.
Instead use forAllActivities() to perfrom the operation on all
activities in the sub-branch.

Bug: 80414790
Test: Existing tests pass
Change-Id: I3dd08784e82b3eceac9aacacd4d1f1bd85ef8c02
parent 3ef13e04
Loading
Loading
Loading
Loading
+24 −25
Original line number Diff line number Diff line
@@ -73,7 +73,9 @@ import android.util.proto.ProtoOutputStream;
import android.view.Display;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.util.function.pooled.PooledPredicate;
import com.android.server.protolog.common.ProtoLog;

import java.io.PrintWriter;
@@ -617,7 +619,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
                continue;
            }

            stack.findTaskLocked(r, mTmpFindTaskResult);
            mTmpFindTaskResult.process(r, stack);
            // It is possible to have tasks in multiple stacks with the same root affinity, so
            // we should keep looking after finding an affinity match to see if there is a
            // better match in another stack. Also, task affinity isn't a good enough reason
@@ -1190,12 +1192,11 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
    }

    boolean isUidPresent(int uid) {
        for (ActivityStack stack : mStacks) {
            if (stack.isUidPresent(uid)) {
                return true;
            }
        }
        return false;
        final PooledPredicate p = PooledLambda.obtainPredicate(
                ActivityRecord::isUid, PooledLambda.__(ActivityRecord.class), uid);
        final boolean isUidPresent = mDisplayContent.getActivity(p) != null;
        p.recycle();
        return isUidPresent;
    }

    /**
@@ -1291,12 +1292,16 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
    /** Update and get all UIDs that are present on the display and have access to it. */
    IntArray getPresentUIDs() {
        mDisplayAccessUIDs.clear();
        for (ActivityStack stack : mStacks) {
            stack.getPresentUIDs(mDisplayAccessUIDs);
        }
        final PooledConsumer c = PooledLambda.obtainConsumer(ActivityDisplay::addActivityUid,
                PooledLambda.__(ActivityRecord.class), mDisplayAccessUIDs);
        mDisplayContent.forAllActivities(c);
        c.recycle();
        return mDisplayAccessUIDs;
    }

    private static void addActivityUid(ActivityRecord r, IntArray uids) {
        uids.add(r.getUid());
    }
    /**
     * Checks if system decorations should be shown on this display.
     *
@@ -1449,22 +1454,16 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
            return null;
        }

        final ArrayList<Task> tasks = mHomeStack.getAllTasks();
        for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
            final Task task = tasks.get(taskNdx);
            if (!task.isActivityTypeHome()) {
                continue;
            }

            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
                final ActivityRecord r = task.getChildAt(activityNdx);
                if (r.isActivityTypeHome()
                        && ((userId == UserHandle.USER_ALL) || (r.mUserId == userId))) {
        final PooledPredicate p = PooledLambda.obtainPredicate(
                ActivityDisplay::isHomeActivityForUser, PooledLambda.__(ActivityRecord.class),
                userId);
        final ActivityRecord r = mHomeStack.getActivity(p);
        p.recycle();
        return r;
    }
            }
        }
        return null;

    private static boolean isHomeActivityForUser(ActivityRecord r, int userId) {
        return r.isActivityTypeHome() && (userId == UserHandle.USER_ALL || r.mUserId == userId);
    }

    boolean isSleeping() {
+1 −7
Original line number Diff line number Diff line
@@ -546,13 +546,7 @@ class ActivityMetricsLogger {

    /** @return {@code true} if the given task has an activity will be drawn. */
    private static boolean hasActivityToBeDrawn(Task t) {
        for (int i = t.getChildCount() - 1; i >= 0; --i) {
            final ActivityRecord r = t.getChildAt(i);
            if (r.mVisibleRequested && !r.mDrawn && !r.finishing) {
                return true;
            }
        }
        return false;
        return t.forAllActivities((r) -> r.mVisibleRequested && !r.mDrawn && !r.finishing);
    }

    private void checkVisibility(Task t, ActivityRecord r) {
+84 −79
Original line number Diff line number Diff line
@@ -301,6 +301,9 @@ import com.android.internal.app.ResolverActivity;
import com.android.internal.content.ReferrerIntent;
import com.android.internal.util.ToBooleanFunction;
import com.android.internal.util.XmlUtils;
import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledFunction;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.AttributeCache;
import com.android.server.LocalServices;
import com.android.server.am.AppTimeTracker;
@@ -695,12 +698,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        }
    }

    void dump(PrintWriter pw, String prefix) {
    }

    /**
     * Copied from old AppWindowToken.
     */
    @Override
    void dump(PrintWriter pw, String prefix, boolean dumpAll) {
        final long now = SystemClock.uptimeMillis();
@@ -940,6 +937,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        }
    }

    void setAppTimeTracker(AppTimeTracker att) {
        appTimeTracker = att;
    }

    /** Update the saved state of an activity. */
    void setSavedState(@Nullable Bundle savedState) {
        mIcicle = savedState;
@@ -1167,6 +1168,15 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

        super.onParentChanged(newParent, oldParent);

        if (isPersistable()) {
            if (oldTask != null) {
                mAtmService.notifyTaskPersisterLocked(oldTask, false);
            }
            if (newTask != null) {
                mAtmService.notifyTaskPersisterLocked(newTask, false);
            }
        }

        if (oldParent == null && newParent != null) {
            // First time we are adding the activity to the system.
            mVoiceInteraction = newTask.voiceSession != null;
@@ -1261,14 +1271,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

        if (prevDc.mFocusedApp == this) {
            prevDc.setFocusedApp(null);
            final ActivityStack stack = dc.getTopStack();
            if (stack != null) {
                final Task task = stack.getTopChild();
                if (task != null && task.getTopChild() == this) {
            if (dc.getTopMostActivity() == this) {
                dc.setFocusedApp(this);
            }
        }
        }

        if (mLetterbox != null) {
            mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
@@ -2206,7 +2212,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                OP_PICTURE_IN_PICTURE, info.applicationInfo.uid, packageName) == MODE_ALLOWED;
    }

    boolean isAlwaysFocusable() {
    private boolean isAlwaysFocusable() {
        return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
    }

@@ -2263,23 +2269,28 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        return true;
    }

    /** Finish all activities in the task with the same affinity as this one. */
    void finishActivityAffinity() {
        final ArrayList<ActivityRecord> activities = task.mChildren;
        for (int index = activities.indexOf(this); index >= 0; --index) {
            final ActivityRecord cur = activities.get(index);
            if (!Objects.equals(cur.taskAffinity, taskAffinity)) {
                break;
            }
            cur.finishIfPossible("request-affinity", true /* oomAdj */);
    void finishIfSubActivity(ActivityRecord parent, String otherResultWho, int otherRequestCode) {
        if (resultTo != parent
                || requestCode != otherRequestCode
                || !Objects.equals(resultWho, otherResultWho)) return;

        finishIfPossible("request-sub", false /* oomAdj */);
    }

    /** Finish all activities in the task with the same affinity as this one. */
    boolean finishIfSameAffinity(ActivityRecord r) {
        // End search once we get to the activity that doesn't have the same affinity.
        if (!Objects.equals(r.taskAffinity, taskAffinity)) return true;

        r.finishIfPossible("request-affinity", true /* oomAdj */);
        return false;
    }

    /**
     * Sets the result for activity that started this one, clears the references to activities
     * started for result from this one, and clears new intents.
     */
    void finishActivityResults(int resultCode, Intent resultData) {
    private void finishActivityResults(int resultCode, Intent resultData) {
        // Send the result if needed
        if (resultTo != null) {
            if (DEBUG_RESULTS) {
@@ -2378,14 +2389,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
            final Task task = getTask();
            EventLogTags.writeWmFinishActivity(mUserId, System.identityHashCode(this),
                    task.mTaskId, shortComponentName, reason);
            final ArrayList<ActivityRecord> activities = task.mChildren;
            final int index = activities.indexOf(this);
            if (index < (task.getChildCount() - 1)) {
            ActivityRecord next = task.getActivityAbove(this);
            if (next != null) {
                if ((intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
                    // If the caller asked that this activity (and all above it)
                    // be cleared when the task is reset, don't lose that information,
                    // but propagate it up to the next activity.
                    final ActivityRecord next = task.getChildAt(index + 1);
                    next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
                }
            }
@@ -2403,7 +2412,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                } else {
                    // Only move the next stack to top in its display.
                    final ActivityDisplay display = stack.getDisplay();
                    final ActivityRecord next = display.topRunningActivity();
                    next = display.topRunningActivity();
                    if (next != null) {
                        display.positionChildAtTop(next.getActivityStack(),
                                false /* includingParents */, "finish-display-top");
@@ -2413,7 +2422,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

            finishActivityResults(resultCode, resultData);

            final boolean endTask = index <= 0 && !task.isClearingToReuseTask();
            final boolean endTask = task.getActivityBelow(this) == null
                    && !task.isClearingToReuseTask();
            final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
            if (isState(RESUMED)) {
                if (endTask) {
@@ -2473,16 +2483,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                // sync with the activity visibility being set for this finishing activity above.
                // In this case, we can set the visibility of all the task overlay activities when
                // we detect the last one is finishing to keep them in sync.
                if (task.onlyHasTaskOverlayActivities(true /* excludeFinishing */)) {
                    for (int i = task.getChildCount() - 1; i >= 0 ; --i) {
                        final ActivityRecord taskOverlay = task.getChildAt(i);
                        if (!taskOverlay.mTaskOverlay) {
                            continue;
                        }
                        taskOverlay.prepareActivityHideTransitionAnimation(transit);
                    }
                if (task.onlyHasTaskOverlayActivities(false /* includeFinishing */)) {
                    final PooledConsumer c = PooledLambda.obtainConsumer(
                            ActivityRecord::prepareActivityHideTransitionAnimationIfOvarlay,
                            PooledLambda.__(ActivityRecord.class), transit);
                    task.forAllActivities(c);
                    c.recycle();
                }

                return removedActivity ? FINISH_RESULT_REMOVED : FINISH_RESULT_REQUESTED;
            } else {
                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + this);
@@ -2494,6 +2501,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        }
    }

    private void prepareActivityHideTransitionAnimationIfOvarlay(int transit) {
        if (mTaskOverlay) {
            prepareActivityHideTransitionAnimation(transit);
        }
    }

    private void prepareActivityHideTransitionAnimation(int transit) {
        final DisplayContent dc = getDisplay().mDisplayContent;
        dc.prepareAppTransition(transit, false);
@@ -3265,15 +3278,16 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
     * immediately finishes after, so we have to transfer T to M.
     */
    void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
        for (int i = task.mChildren.size() - 1; i >= 0; i--) {
            final ActivityRecord fromActivity = task.mChildren.get(i);
            if (fromActivity == this) {
                return;
            }
            if (!fromActivity.mVisibleRequested && transferStartingWindow(fromActivity.token)) {
                return;
            }
        final PooledFunction p = PooledLambda.obtainFunction(ActivityRecord::transferStartingWindow,
                this, PooledLambda.__(ActivityRecord.class));
        task.forAllActivities(p);
        p.recycle();
    }

    private boolean transferStartingWindow(ActivityRecord fromActivity) {
        if (fromActivity == this) return true;

        return !fromActivity.mVisibleRequested && transferStartingWindow(fromActivity.token);
    }

    void checkKeyguardFlagsChanged() {
@@ -3345,7 +3359,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        if (!inPinnedWindowingMode() && (mShowWhenLocked || containsShowWhenLockedWindow())) {
            return true;
        } else if (mInheritShownWhenLocked) {
            final ActivityRecord r = getActivityBelow();
            final ActivityRecord r = task.getActivityBelow(this);
            return r != null && !r.inPinnedWindowingMode() && (r.mShowWhenLocked
                    || r.containsShowWhenLockedWindow());
        } else {
@@ -3370,19 +3384,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                true /* topToBottom */);
    }

    /**
     * @return an {@link ActivityRecord} of the activity below this activity, or {@code null} if no
     * such activity exists.
     */
    @Nullable
    private ActivityRecord getActivityBelow() {
        final int pos = task.mChildren.indexOf(this);
        if (pos == -1) {
            throw new IllegalStateException("Activity not found in its task");
        }
        return pos == 0 ? null : task.getChildAt(pos - 1);
    }

    WindowState getImeTargetBelowWindow(WindowState w) {
        final int index = mChildren.indexOf(w);
        if (index > 0) {
@@ -3426,7 +3427,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
    }

    @Override
    boolean forAllActivities(Function<ActivityRecord, Boolean> callback) {
    boolean forAllActivities(
            Function<ActivityRecord, Boolean> callback, boolean traverseTopToBottom) {
        return callback.apply(this);
    }

@@ -3603,7 +3605,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                clearOptionsLocked(false /* withAbort */);
            } else {
                // This will clear the options for all the ActivityRecords for this Task.
                task.clearAllPendingOptions();
                task.forAllActivities((r) -> {
                    r.clearOptionsLocked(false /* withAbort */);
                });
            }
        }
    }
@@ -4596,16 +4600,15 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        }

        // Check if position in task allows to become paused
        final int positionInTask = task.mChildren.indexOf(this);
        if (positionInTask == -1) {
        if (!task.hasChild(this)) {
            throw new IllegalStateException("Activity not found in its task");
        }
        if (positionInTask == task.getChildCount() - 1) {
        final ActivityRecord activityAbove = task.getActivityAbove(this);
        if (activityAbove == null) {
            // It's the topmost activity in the task - should become resumed now
            return true;
        }
        // Check if activity above is finishing now and this one becomes the topmost in task.
        final ActivityRecord activityAbove = task.getChildAt(positionInTask + 1);
        if (activityAbove.finishing) {
            return true;
        }
@@ -4661,7 +4664,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        stopped = false;

        if (isActivityTypeHome()) {
            mStackSupervisor.updateHomeProcess(task.getChildAt(0).app);
            mStackSupervisor.updateHomeProcess(task.getBottomMostActivity().app);
        }

        if (nowVisible) {
@@ -5288,6 +5291,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                && mAtmService.mAmInternal.isUserRunning(mUserId, 0 /* flags */));
    }

    boolean canBeTopRunning() {
        return !finishing && okToShowLocked();
    }

    /**
     * This method will return true if the activity is either visible, is becoming visible, is
     * currently pausing, or is resumed.
@@ -5319,13 +5326,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

    static int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
        if (r == null) {
        if (r == null || r.getParent() == null) {
            return INVALID_TASK_ID;
        }
        final Task task = r.task;
        final int activityNdx = task.mChildren.indexOf(r);
        if (activityNdx < 0
                || (onlyRoot && activityNdx > task.findRootIndex(true /* effectiveRoot */))) {
        if (onlyRoot && r.compareTo(task.getRootActivity(
                false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/)) > 0) {
            return INVALID_TASK_ID;
        }
        return task.mTaskId;
@@ -7216,6 +7222,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        return info.applicationInfo.uid;
    }

    boolean isUid(int uid) {
        return info.applicationInfo.uid == uid;
    }

    int getPid() {
        return app != null ? app.getPid() : 0;
    }
@@ -7279,14 +7289,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        if (task == null) {
            return false;
        }
        final ActivityRecord rootActivity = task.getRootActivity();
        if (rootActivity != null) {
        final ActivityRecord rootActivity = task.getRootActivity(true);
        return this == rootActivity;
    }
        // No non-finishing activity found. In this case the bottom-most activity is considered to
        // be the root.
        return task.getChildAt(0) == this;
    }

    @Override
    public String toString() {
+444 −821

File changed.

Preview size limit exceeded, changes collapsed.

+36 −25
Original line number Diff line number Diff line
@@ -138,6 +138,7 @@ import com.android.internal.content.ReferrerIntent;
import com.android.internal.os.TransferPipe;
import com.android.internal.os.logging.MetricsLoggerWrapper;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.am.ActivityManagerService;
import com.android.server.am.UserState;
@@ -825,7 +826,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
                        task.mTaskId, r.shortComponentName);
                if (r.isActivityTypeHome()) {
                    // Home process is the root process of the task.
                    updateHomeProcess(task.getChildAt(0).app);
                    updateHomeProcess(task.getBottomMostActivity().app);
                }
                mService.getPackageManagerInternalLocked().notifyPackageUse(
                        r.intent.getComponent().getPackageName(), NOTIFY_PACKAGE_USE_ACTIVITY);
@@ -1688,7 +1689,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
                }
            }
            if (!deferResume) {
                stack.ensureVisibleActivitiesConfigurationLocked(r, preserveWindows);
                stack.ensureVisibleActivitiesConfiguration(r, preserveWindows);
            }
        } finally {
            mAllowDockedStackResize = true;
@@ -2485,18 +2486,23 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
            return;
        }

        for (int i = task.getChildCount() - 1; i >= 0; i--) {
            final ActivityRecord r = task.getChildAt(i);
            if (r.attachedToProcess()) {
                mMultiWindowModeChangedActivities.add(r);
            }
        }
        final PooledConsumer c = PooledLambda.obtainConsumer(
                ActivityStackSupervisor::addToMultiWindowModeChangedList, this,
                PooledLambda.__(ActivityRecord.class));
        task.forAllActivities(c);
        c.recycle();

        if (!mHandler.hasMessages(REPORT_MULTI_WINDOW_MODE_CHANGED_MSG)) {
            mHandler.sendEmptyMessage(REPORT_MULTI_WINDOW_MODE_CHANGED_MSG);
        }
    }

    private void addToMultiWindowModeChangedList(ActivityRecord r) {
        if (r.attachedToProcess()) {
            mMultiWindowModeChangedActivities.add(r);
        }
    }

    void scheduleUpdatePictureInPictureModeIfNeeded(Task task, ActivityStack prevStack) {
        final ActivityStack stack = task.getStack();
        if (prevStack == null || prevStack == stack
@@ -2507,17 +2513,13 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
        scheduleUpdatePictureInPictureModeIfNeeded(task, stack.getRequestedOverrideBounds());
    }

    void scheduleUpdatePictureInPictureModeIfNeeded(Task task, Rect targetStackBounds) {
        for (int i = task.getChildCount() - 1; i >= 0; i--) {
            final ActivityRecord r = task.getChildAt(i);
            if (r.attachedToProcess()) {
                mPipModeChangedActivities.add(r);
                // If we are scheduling pip change, then remove this activity from multi-window
                // change list as the processing of pip change will make sure multi-window changed
                // message is processed in the right order relative to pip changed.
                mMultiWindowModeChangedActivities.remove(r);
            }
        }
    private void scheduleUpdatePictureInPictureModeIfNeeded(Task task, Rect targetStackBounds) {
        final PooledConsumer c = PooledLambda.obtainConsumer(
                ActivityStackSupervisor::addToPipModeChangedList, this,
                PooledLambda.__(ActivityRecord.class));
        task.forAllActivities(c);
        c.recycle();

        mPipModeChangedTargetStackBounds = targetStackBounds;

        if (!mHandler.hasMessages(REPORT_PIP_MODE_CHANGED_MSG)) {
@@ -2525,14 +2527,23 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
        }
    }

    private void addToPipModeChangedList(ActivityRecord r) {
        if (!r.attachedToProcess()) return;

        mPipModeChangedActivities.add(r);
        // If we are scheduling pip change, then remove this activity from multi-window
        // change list as the processing of pip change will make sure multi-window changed
        // message is processed in the right order relative to pip changed.
        mMultiWindowModeChangedActivities.remove(r);
    }

    void updatePictureInPictureMode(Task task, Rect targetStackBounds, boolean forceUpdate) {
        mHandler.removeMessages(REPORT_PIP_MODE_CHANGED_MSG);
        for (int i = task.getChildCount() - 1; i >= 0; i--) {
            final ActivityRecord r = task.getChildAt(i);
            if (r.attachedToProcess()) {
                r.updatePictureInPictureMode(targetStackBounds, forceUpdate);
            }
        }
        final PooledConsumer c = PooledLambda.obtainConsumer(
                ActivityRecord::updatePictureInPictureMode,
                PooledLambda.__(ActivityRecord.class), targetStackBounds, forceUpdate);
        task.forAllActivities(c);
        c.recycle();
    }

    void wakeUp(String reason) {
Loading