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

Commit 68a0633e authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Special handling of processes with recent tasks.

As the startup time of application processes has increased,
it is becoming more useful to try to keep around the process
for a recently used app, even if there are no longer any
actively running activities in it.  (For example, if you backed
out of the root activity.)

This change implements that behavior, keeping track of any recent
task entries that a process represents the root activity for,
and classififying them under a new cached proc state that is
managed the same as a cached activity.

Test: manual
Bug: 69386069
Change-Id: I430741646478763fd85b33a5384278ece831b2c3
parent 9352e47d
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -519,11 +519,15 @@ public class ActivityManager {
     * process that contains activities. */
    public static final int PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 16;

    /** @hide Process is being cached for later use and has an activity that corresponds
     * to an existing recent task. */
    public static final int PROCESS_STATE_CACHED_RECENT = 17;

    /** @hide Process is being cached for later use and is empty. */
    public static final int PROCESS_STATE_CACHED_EMPTY = 17;
    public static final int PROCESS_STATE_CACHED_EMPTY = 18;

    /** @hide Process does not exist. */
    public static final int PROCESS_STATE_NONEXISTENT = 18;
    public static final int PROCESS_STATE_NONEXISTENT = 19;

    // NOTE: If PROCESS_STATEs are added or changed, then new fields must be added
    // to frameworks/base/core/proto/android/app/activitymanager.proto and the following method must
+1 −0
Original line number Diff line number Diff line
@@ -102,6 +102,7 @@ public final class ProcessState {
        STATE_LAST_ACTIVITY,            // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
        STATE_CACHED_ACTIVITY,          // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
        STATE_CACHED_ACTIVITY_CLIENT,   // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
        STATE_CACHED_ACTIVITY,          // ActivityManager.PROCESS_STATE_CACHED_RECENT
        STATE_CACHED_EMPTY,             // ActivityManager.PROCESS_STATE_CACHED_EMPTY
    };

+14 −5
Original line number Diff line number Diff line
@@ -3316,7 +3316,7 @@ public class ActivityManagerService extends IActivityManager.Stub
            String what, Object obj, ProcessRecord srcApp) {
        app.lastActivityTime = now;
        if (app.activities.size() > 0) {
        if (app.activities.size() > 0 || app.recentTasks.size() > 0) {
            // Don't want to touch dependent processes that are hosting activities.
            return index;
        }
@@ -3380,7 +3380,7 @@ public class ActivityManagerService extends IActivityManager.Stub
    final void updateLruProcessLocked(ProcessRecord app, boolean activityChange,
            ProcessRecord client) {
        final boolean hasActivity = app.activities.size() > 0 || app.hasClientActivities
                || app.treatLikeActivity;
                || app.treatLikeActivity || app.recentTasks.size() > 0;
        final boolean hasService = false; // not impl yet. app.services.size() > 0;
        if (!activityChange && hasActivity) {
            // The process has activities, so we are only allowing activity-based adjustments
@@ -3484,7 +3484,8 @@ public class ActivityManagerService extends IActivityManager.Stub
        int nextIndex;
        if (hasActivity) {
            final int N = mLruProcesses.size();
            if (app.activities.size() == 0 && mLruProcessActivityStart < (N - 1)) {
            if ((app.activities.size() == 0 || app.recentTasks.size() > 0)
                    && mLruProcessActivityStart < (N - 1)) {
                // Process doesn't have activities, but has clients with
                // activities...  move it up, but one below the top (the top
                // should always have a real activity).
@@ -5321,6 +5322,8 @@ public class ActivityManagerService extends IActivityManager.Stub
        // Remove this application's activities from active lists.
        boolean hasVisibleActivities = mStackSupervisor.handleAppDiedLocked(app);
        app.clearRecentTasks();
        app.activities.clear();
        if (app.instr != null) {
@@ -20959,7 +20962,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                            + " instead of expected " + app);
                    if (r.app == null || (r.app.uid == app.uid)) {
                        // Only fix things up when they look sane
                        r.app = app;
                        r.setProcess(app);
                    } else {
                        continue;
                    }
@@ -21038,6 +21041,11 @@ public class ActivityManagerService extends IActivityManager.Stub
                adj += minLayer;
            }
        }
        if (procState > ActivityManager.PROCESS_STATE_CACHED_RECENT && app.recentTasks.size() > 0) {
            procState = ActivityManager.PROCESS_STATE_CACHED_RECENT;
            app.adjType = "cch-rec";
            if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to cached recent: " + app);
        }
        if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
                || procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
@@ -22598,6 +22606,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                    switch (app.curProcState) {
                        case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
                        case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
                        case ActivityManager.PROCESS_STATE_CACHED_RECENT:
                            // This process is a cached process holding activities...
                            // assign it the next cached value for that type, and then
                            // step that cached level.
@@ -23322,7 +23331,7 @@ public class ActivityManagerService extends IActivityManager.Stub
            // has been removed.
            for (i=mRemovedProcesses.size()-1; i>=0; i--) {
                final ProcessRecord app = mRemovedProcesses.get(i);
                if (app.activities.size() == 0
                if (app.activities.size() == 0 && app.recentTasks.size() == 0
                        && app.curReceivers.isEmpty() && app.services.size() == 0) {
                    Slog.i(
                        TAG, "Exiting empty application process "
+8 −0
Original line number Diff line number Diff line
@@ -934,6 +934,14 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
        }
    }

    void setProcess(ProcessRecord proc) {
        app = proc;
        final ActivityRecord root = task != null ? task.getRootActivity() : null;
        if (root == this) {
            task.setRootProcess(proc);
        }
    }

    AppWindowContainerController getWindowContainerController() {
        return mWindowContainerController;
    }
+1 −1
Original line number Diff line number Diff line
@@ -1270,7 +1270,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
            // schedule launch ticks to collect information about slow apps.
            r.startLaunchTickingLocked();

            r.app = app;
            r.setProcess(app);

            if (mKeyguardController.isKeyguardLocked()) {
                r.notifyUnknownVisibilityLaunched();
Loading