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

Commit 6a6c1dc7 authored by Tim Murray's avatar Tim Murray Committed by Android (Google) Code Review
Browse files

Merge changes I5bab7728,Ie386672c,I04940599 into udc-dev

* changes:
  Freezer: release AM lock while checking /proc/locks
  OomAdjuster: use oom_adj_score tiers for cached apps
  Reland OomAdjuster: demote previous process to cached after configurable timeout
parents ab677c71 f760f7f1
Loading
Loading
Loading
Loading
+48 −0
Original line number Diff line number Diff line
@@ -129,6 +129,7 @@ final class ActivityManagerConstants extends ContentObserver {
    static final String KEY_KILL_BG_RESTRICTED_CACHED_IDLE = "kill_bg_restricted_cached_idle";
    static final String KEY_KILL_BG_RESTRICTED_CACHED_IDLE_SETTLE_TIME =
            "kill_bg_restricted_cached_idle_settle_time";
    static final String KEY_MAX_PREVIOUS_TIME = "max_previous_time";
    /**
     * Note this key is on {@link DeviceConfig#NAMESPACE_ACTIVITY_MANAGER_COMPONENT_ALIAS}.
     * @see #mEnableComponentAlias
@@ -145,6 +146,9 @@ final class ActivityManagerConstants extends ContentObserver {
     */
    static final String KEY_NETWORK_ACCESS_TIMEOUT_MS = "network_access_timeout_ms";

    static final String KEY_USE_TIERED_CACHED_ADJ = "use_tiered_cached_adj";
    static final String KEY_TIERED_CACHED_ADJ_DECAY_TIME = "tiered_cached_adj_decay_time";

    private static final int DEFAULT_MAX_CACHED_PROCESSES = 32;
    private static final boolean DEFAULT_PRIORITIZE_ALARM_BROADCASTS = true;
    private static final long DEFAULT_FGSERVICE_MIN_SHOWN_TIME = 2*1000;
@@ -192,6 +196,7 @@ final class ActivityManagerConstants extends ContentObserver {
    private static final float DEFAULT_FGS_START_DENIED_LOG_SAMPLE_RATE = 1; // 100%
    private static final long DEFAULT_PROCESS_KILL_TIMEOUT_MS = 10 * 1000;
    private static final long DEFAULT_NETWORK_ACCESS_TIMEOUT_MS = 200; // 0.2 sec
    private static final long DEFAULT_MAX_PREVIOUS_TIME = 60 * 1000; // 60s

    static final long DEFAULT_BACKGROUND_SETTLE_TIME = 60 * 1000;
    static final long DEFAULT_KILL_BG_RESTRICTED_CACHED_IDLE_SETTLE_TIME_MS = 60 * 1000;
@@ -199,6 +204,9 @@ final class ActivityManagerConstants extends ContentObserver {

    static final int DEFAULT_MAX_SERVICE_CONNECTIONS_PER_PROCESS = 3000;

    private static final boolean DEFAULT_USE_TIERED_CACHED_ADJ = false;
    private static final long DEFAULT_TIERED_CACHED_ADJ_DECAY_TIME = 60 * 1000;

    /**
     * Same as {@link TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED}
     */
@@ -534,6 +542,9 @@ final class ActivityManagerConstants extends ContentObserver {
    public long TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION =
            DEFAULT_TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION;

    // How long a process can remain at previous oom_adj before dropping to cached
    public static long MAX_PREVIOUS_TIME = DEFAULT_MAX_PREVIOUS_TIME;

    /**
     * The minimum time we allow between crashes, for us to consider this
     * application to be bad and stop its services and reject broadcasts.
@@ -1006,6 +1017,12 @@ final class ActivityManagerConstants extends ContentObserver {
    public volatile long mShortFgsAnrExtraWaitDuration =
            DEFAULT_SHORT_FGS_ANR_EXTRA_WAIT_DURATION;

    /** @see #KEY_USE_TIERED_CACHED_ADJ */
    public boolean USE_TIERED_CACHED_ADJ = DEFAULT_USE_TIERED_CACHED_ADJ;

    /** @see #KEY_TIERED_CACHED_ADJ_DECAY_TIME */
    public long TIERED_CACHED_ADJ_DECAY_TIME = DEFAULT_TIERED_CACHED_ADJ_DECAY_TIME;

    private final OnPropertiesChangedListener mOnDeviceConfigChangedListener =
            new OnPropertiesChangedListener() {
                @Override
@@ -1171,6 +1188,13 @@ final class ActivityManagerConstants extends ContentObserver {
                            case KEY_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION:
                                updateEnableWaitForFinishAttachApplication();
                                break;
                            case KEY_MAX_PREVIOUS_TIME:
                                updateMaxPreviousTime();
                                break;
                            case KEY_USE_TIERED_CACHED_ADJ:
                            case KEY_TIERED_CACHED_ADJ_DECAY_TIME:
                                updateUseTieredCachedAdj();
                                break;
                            default:
                                break;
                        }
@@ -1825,6 +1849,7 @@ final class ActivityManagerConstants extends ContentObserver {
                DEFAULT_LOW_SWAP_THRESHOLD_PERCENT);
    }


    private void updateTopToFgsGraceDuration() {
        TOP_TO_FGS_GRACE_DURATION = DeviceConfig.getLong(
                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
@@ -1832,6 +1857,13 @@ final class ActivityManagerConstants extends ContentObserver {
                DEFAULT_TOP_TO_FGS_GRACE_DURATION);
    }

    private void updateMaxPreviousTime() {
        MAX_PREVIOUS_TIME = DeviceConfig.getLong(
                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                KEY_MAX_PREVIOUS_TIME,
                DEFAULT_MAX_PREVIOUS_TIME);
    }

    private void updateMinAssocLogDuration() {
        MIN_ASSOC_LOG_DURATION = DeviceConfig.getLong(
                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_MIN_ASSOC_LOG_DURATION,
@@ -1908,6 +1940,17 @@ final class ActivityManagerConstants extends ContentObserver {
                DEFAULT_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION);
    }

    private void updateUseTieredCachedAdj() {
        USE_TIERED_CACHED_ADJ = DeviceConfig.getBoolean(
            DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
            KEY_USE_TIERED_CACHED_ADJ,
            DEFAULT_USE_TIERED_CACHED_ADJ);
        TIERED_CACHED_ADJ_DECAY_TIME = DeviceConfig.getLong(
            DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
            KEY_TIERED_CACHED_ADJ_DECAY_TIME,
            DEFAULT_TIERED_CACHED_ADJ_DECAY_TIME);
    }

    @NeverCompile // Avoid size overhead of debugging code.
    void dump(PrintWriter pw) {
        pw.println("ACTIVITY MANAGER SETTINGS (dumpsys activity settings) "
@@ -2092,6 +2135,11 @@ final class ActivityManagerConstants extends ContentObserver {
        pw.print("  "); pw.print(KEY_SHORT_FGS_ANR_EXTRA_WAIT_DURATION);
        pw.print("="); pw.println(mShortFgsAnrExtraWaitDuration);

        pw.print("  "); pw.print(KEY_USE_TIERED_CACHED_ADJ);
        pw.print("="); pw.println(USE_TIERED_CACHED_ADJ);
        pw.print("  "); pw.print(KEY_TIERED_CACHED_ADJ_DECAY_TIME);
        pw.print("="); pw.println(TIERED_CACHED_ADJ_DECAY_TIME);

        pw.println();
        if (mOverrideMaxCachedProcesses >= 0) {
            pw.print("  mOverrideMaxCachedProcesses="); pw.println(mOverrideMaxCachedProcesses);
+37 −27
Original line number Diff line number Diff line
@@ -1921,8 +1921,25 @@ public final class CachedAppOptimizer {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case SET_FROZEN_PROCESS_MSG:
                {
                    ProcessRecord proc = (ProcessRecord) msg.obj;
                    int pid = proc.getPid();
                    final String name = proc.processName;
                    synchronized (mAm) {
                        freezeProcess(proc);
                    }
                    try {
                        // post-check to prevent deadlock
                        mProcLocksReader.handleBlockingFileLocks(this);
                    } catch (Exception e) {
                        Slog.e(TAG_AM, "Unable to check file locks for "
                                + name + "(" + pid + "): " + e);
                        synchronized (mAm) {
                        freezeProcess((ProcessRecord) msg.obj);
                            synchronized (mProcLock) {
                                unfreezeAppLSP(proc, OomAdjuster.OOM_ADJ_REASON_NONE);
                            }
                        }
                    }
                }
                    break;
                case REPORT_UNFREEZE_MSG:
@@ -2057,16 +2074,6 @@ public final class CachedAppOptimizer {
                    }
                });
            }

            try {
                // post-check to prevent deadlock
                mProcLocksReader.handleBlockingFileLocks(this);
            } catch (Exception e) {
                Slog.e(TAG_AM, "Unable to check file locks for " + name + "(" + pid + "): " + e);
                synchronized (mProcLock) {
                    unfreezeAppLSP(proc, OomAdjuster.OOM_ADJ_REASON_NONE);
                }
            }
        }

        private void reportUnfreeze(int pid, int frozenDuration, String processName,
@@ -2123,6 +2130,7 @@ public final class CachedAppOptimizer {
            if (DEBUG_FREEZER) {
                Slog.d(TAG_AM, "Blocking file lock found: " + pids);
            }
            synchronized (mAm) {
                synchronized (mProcLock) {
                    int pid = pids.get(0);
                    ProcessRecord app = mFrozenProcesses.get(pid);
@@ -2133,7 +2141,8 @@ public final class CachedAppOptimizer {
                            synchronized (mAm.mPidsSelfLocked) {
                                pr = mAm.mPidsSelfLocked.get(blocked);
                            }
                        if (pr != null && pr.mState.getCurAdj() < ProcessList.CACHED_APP_MIN_ADJ) {
                            if (pr != null
                                    && pr.mState.getCurAdj() < ProcessList.CACHED_APP_MIN_ADJ) {
                                Slog.d(TAG_AM, app.processName + " (" + pid + ") blocks "
                                        + pr.processName + " (" + blocked + ")");
                                // Found at least one blocked non-cached process
@@ -2145,6 +2154,7 @@ public final class CachedAppOptimizer {
                }
            }
        }
    }

    /**
     * Default implementation for ProcessDependencies, public vor visibility to OomAdjuster class.
+172 −130
Original line number Diff line number Diff line
@@ -1073,7 +1073,34 @@ public class OomAdjuster {
    @GuardedBy({"mService", "mProcLock"})
    private void assignCachedAdjIfNecessary(ArrayList<ProcessRecord> lruList) {
        final int numLru = lruList.size();

        if (mConstants.USE_TIERED_CACHED_ADJ) {
            final long now = SystemClock.uptimeMillis();
            for (int i = numLru - 1; i >= 0; i--) {
                ProcessRecord app = lruList.get(i);
                final ProcessStateRecord state = app.mState;
                final ProcessCachedOptimizerRecord opt = app.mOptRecord;
                if (!app.isKilledByAm() && app.getThread() != null && state.getCurAdj()
                        >= UNKNOWN_ADJ) {
                    final ProcessServiceRecord psr = app.mServices;
                    int targetAdj = CACHED_APP_MIN_ADJ;

                    if (opt != null && opt.isFreezeExempt()) {
                        // BIND_WAIVE_PRIORITY and the like get oom_adj 900
                        targetAdj += 0;
                    } else if ((state.getSetAdj() >= CACHED_APP_MIN_ADJ)
                            && (state.getLastStateTime()
                                    + mConstants.TIERED_CACHED_ADJ_DECAY_TIME) < now) {
                        // Older cached apps get 950
                        targetAdj += 50;
                    } else {
                        // Newer cached apps get 910
                        targetAdj += 10;
                    }
                    state.setCurRawAdj(targetAdj);
                    state.setCurAdj(psr.modifyRawOomAdj(targetAdj));
                }
            }
        } else {
            // First update the OOM adjustment for each of the
            // application processes based on their current state.
            int curCachedAdj = CACHED_APP_MIN_ADJ;
@@ -1099,7 +1126,8 @@ public class OomAdjuster {
                // instead of a gazillion empty processes.
                numEmptyProcs = cachedProcessLimit;
            }
        int cachedFactor = (mNumCachedHiddenProcs > 0 ? (mNumCachedHiddenProcs + mNumSlots - 1) : 1)
            int cachedFactor = (mNumCachedHiddenProcs > 0
                    ? (mNumCachedHiddenProcs + mNumSlots - 1) : 1)
                               / mNumSlots;
            if (cachedFactor < 1) cachedFactor = 1;

@@ -1112,6 +1140,7 @@ public class OomAdjuster {
            int lastCachedGroupImportance = 0;
            int lastCachedGroupUid = 0;


            for (int i = numLru - 1; i >= 0; i--) {
                ProcessRecord app = lruList.get(i);
                final ProcessStateRecord state = app.mState;
@@ -1193,7 +1222,8 @@ public class OomAdjuster {
                            state.setCurAdj(psr.modifyRawOomAdj(curEmptyAdj));
                            if (DEBUG_LRU) {
                                Slog.d(TAG_LRU, "Assigning empty LRU #" + i
                                    + " adj: " + state.getCurAdj() + " (curEmptyAdj=" + curEmptyAdj
                                        + " adj: " + state.getCurAdj()
                                        + " (curEmptyAdj=" + curEmptyAdj
                                        + ")");
                            }
                            break;
@@ -1201,7 +1231,7 @@ public class OomAdjuster {
                }
            }
        }

    }
    private long mNextNoKillDebugMessageTime;

    private double mLastFreeSwapPercent = 1.00;
@@ -2018,12 +2048,23 @@ public class OomAdjuster {
                }
            }
        }

        if (state.getCachedIsPreviousProcess() && state.getCachedHasActivities()) {
            // This was the previous process that showed UI to the user.  We want to
            // try to keep it around more aggressively, to give a good experience
            // around switching between two apps. However, we don't want to keep the
            // process in this privileged state indefinitely. Eventually, allow the
            // app to be demoted to cached.
            if ((state.getSetProcState() == PROCESS_STATE_LAST_ACTIVITY
                    && (state.getLastStateTime() + mConstants.MAX_PREVIOUS_TIME) < now)) {
                procState = PROCESS_STATE_LAST_ACTIVITY;
                schedGroup = SCHED_GROUP_BACKGROUND;
                state.setAdjType("previous-expired");
                adj = CACHED_APP_MIN_ADJ;
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Expire prev adj: " + app);
                }
            } else {
                if (adj > PREVIOUS_APP_ADJ) {
                // This was the previous process that showed UI to the user.
                // We want to try to keep it around more aggressively, to give
                // a good experience around switching between two apps.
                    adj = PREVIOUS_APP_ADJ;
                    schedGroup = SCHED_GROUP_BACKGROUND;
                    state.setCached(false);
@@ -2040,6 +2081,7 @@ public class OomAdjuster {
                    }
                }
            }
        }

        if (false) Slog.i(TAG, "OOM " + app + ": initial adj=" + adj
                + " reason=" + state.getAdjType());
+15 −8
Original line number Diff line number Diff line
@@ -143,7 +143,7 @@ public class MockingOomAdjusterTests {
    private static final String MOCKAPP5_PROCESSNAME = "test #5";
    private static final String MOCKAPP5_PACKAGENAME = "com.android.test.test5";
    private static final int MOCKAPP2_UID_OTHER = MOCKAPP2_UID + UserHandle.PER_USER_RANGE;
    private static final int FIRST_CACHED_ADJ = ProcessList.CACHED_APP_MIN_ADJ
    private static int sFirstCachedAdj = ProcessList.CACHED_APP_MIN_ADJ
                                          + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
    private static Context sContext;
    private static PackageManagerInternal sPackageManagerInternal;
@@ -208,6 +208,9 @@ public class MockingOomAdjusterTests {
                new ActiveUids(sService, false));
        sService.mOomAdjuster.mAdjSeq = 10000;
        sService.mWakefulness = new AtomicInteger(PowerManagerInternal.WAKEFULNESS_AWAKE);
        if (sService.mConstants.USE_TIERED_CACHED_ADJ) {
            sFirstCachedAdj = ProcessList.CACHED_APP_MIN_ADJ + 10;
        }
    }

    @AfterClass
@@ -834,7 +837,7 @@ public class MockingOomAdjusterTests {
        updateOomAdj(client, app);
        doReturn(null).when(sService).getTopApp();

        assertProcStates(app, PROCESS_STATE_SERVICE, FIRST_CACHED_ADJ, SCHED_GROUP_BACKGROUND);
        assertProcStates(app, PROCESS_STATE_SERVICE, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
    }

    @SuppressWarnings("GuardedBy")
@@ -882,7 +885,7 @@ public class MockingOomAdjusterTests {
        sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
        updateOomAdj(app);

        assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, FIRST_CACHED_ADJ, SCHED_GROUP_BACKGROUND);
        assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
    }

    @SuppressWarnings("GuardedBy")
@@ -1286,7 +1289,7 @@ public class MockingOomAdjusterTests {
        bindProvider(app, app, null, null, false);
        updateOomAdj(app);

        assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, FIRST_CACHED_ADJ, SCHED_GROUP_BACKGROUND);
        assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
    }

    @SuppressWarnings("GuardedBy")
@@ -1301,7 +1304,7 @@ public class MockingOomAdjusterTests {
        sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
        updateOomAdj(app, client);

        assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, FIRST_CACHED_ADJ, SCHED_GROUP_BACKGROUND);
        assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
    }

    @SuppressWarnings("GuardedBy")
@@ -2378,8 +2381,12 @@ public class MockingOomAdjusterTests {
                MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
        final int userOwner = 0;
        final int userOther = 1;
        final int cachedAdj1 = CACHED_APP_MIN_ADJ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
        final int cachedAdj2 = cachedAdj1 + ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
        final int cachedAdj1 = sService.mConstants.USE_TIERED_CACHED_ADJ
                               ? CACHED_APP_MIN_ADJ + 10
                               : CACHED_APP_MIN_ADJ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
        final int cachedAdj2 = sService.mConstants.USE_TIERED_CACHED_ADJ
                               ? CACHED_APP_MIN_ADJ + 10
                               : cachedAdj1 + ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
        doReturn(userOwner).when(sService.mUserController).getCurrentUserId();

        final ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();