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

Commit 1cbef372 authored by Silvia Vinyes's avatar Silvia Vinyes Committed by Automerger Merge Worker
Browse files

Merge "Add phenotype flag for OOM_ADJ score heuristic." into sc-dev am: e596afab

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13582342

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: If33b69b8b8fcfbd232f2a42e4ca225f68c53c147
parents 6c138316 e596afab
Loading
Loading
Loading
Loading
+75 −6
Original line number Diff line number Diff line
@@ -66,6 +66,10 @@ public final class CachedAppOptimizer {
    @VisibleForTesting static final String KEY_COMPACT_THROTTLE_4 = "compact_throttle_4";
    @VisibleForTesting static final String KEY_COMPACT_THROTTLE_5 = "compact_throttle_5";
    @VisibleForTesting static final String KEY_COMPACT_THROTTLE_6 = "compact_throttle_6";
    @VisibleForTesting static final String KEY_COMPACT_THROTTLE_MIN_OOM_ADJ =
            "compact_throttle_min_oom_adj";
    @VisibleForTesting static final String KEY_COMPACT_THROTTLE_MAX_OOM_ADJ =
            "compact_throttle_max_oom_adj";
    @VisibleForTesting static final String KEY_COMPACT_STATSD_SAMPLE_RATE =
            "compact_statsd_sample_rate";
    @VisibleForTesting static final String KEY_FREEZER_STATSD_SAMPLE_RATE =
@@ -101,6 +105,10 @@ public final class CachedAppOptimizer {
    @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_4 = 10_000;
    @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_5 = 10 * 60 * 1000;
    @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_6 = 10 * 60 * 1000;
    @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ =
            ProcessList.CACHED_APP_MIN_ADJ;
    @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ =
            ProcessList.CACHED_APP_MAX_ADJ;
    // The sampling rate to push app compaction events into statsd for upload.
    @VisibleForTesting static final float DEFAULT_STATSD_SAMPLE_RATE = 0.1f;
    @VisibleForTesting static final long DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB = 12_000L;
@@ -186,6 +194,10 @@ public final class CachedAppOptimizer {
                                updateFullDeltaRssThrottle();
                            } else if (KEY_COMPACT_PROC_STATE_THROTTLE.equals(name)) {
                                updateProcStateThrottle();
                            } else if (KEY_COMPACT_THROTTLE_MIN_OOM_ADJ.equals(name)) {
                                updateMinOomAdjThrottle();
                            } else if (KEY_COMPACT_THROTTLE_MAX_OOM_ADJ.equals(name)) {
                                updateMaxOomAdjThrottle();
                            }
                        }
                    }
@@ -217,6 +229,12 @@ public final class CachedAppOptimizer {
    @GuardedBy("mPhenotypeFlagLock")
    @VisibleForTesting volatile long mCompactThrottlePersistent = DEFAULT_COMPACT_THROTTLE_6;
    @GuardedBy("mPhenotypeFlagLock")
    @VisibleForTesting volatile long mCompactThrottleMinOomAdj =
            DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ;
    @GuardedBy("mPhenotypeFlagLock")
    @VisibleForTesting volatile long mCompactThrottleMaxOomAdj =
            DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ;
    @GuardedBy("mPhenotypeFlagLock")
    private volatile boolean mUseCompaction = DEFAULT_USE_COMPACTION;
    private volatile boolean mUseFreezer = DEFAULT_USE_FREEZER;
    @GuardedBy("this")
@@ -282,6 +300,7 @@ public final class CachedAppOptimizer {
     * starts the background thread if necessary.
     */
    public void init() {
        // TODO: initialize flags to default and only update them if values are set in DeviceConfig
        DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                ActivityThread.currentApplication().getMainExecutor(), mOnFlagsChangedListener);
        synchronized (mPhenotypeFlagLock) {
@@ -294,6 +313,8 @@ public final class CachedAppOptimizer {
            updateFullDeltaRssThrottle();
            updateProcStateThrottle();
            updateUseFreezer();
            updateMinOomAdjThrottle();
            updateMaxOomAdjThrottle();
        }
    }

@@ -328,6 +349,8 @@ public final class CachedAppOptimizer {
            pw.println("  " + KEY_COMPACT_THROTTLE_4 + "=" + mCompactThrottleFullFull);
            pw.println("  " + KEY_COMPACT_THROTTLE_5 + "=" + mCompactThrottleBFGS);
            pw.println("  " + KEY_COMPACT_THROTTLE_6 + "=" + mCompactThrottlePersistent);
            pw.println("  " + KEY_COMPACT_THROTTLE_MIN_OOM_ADJ + "=" + mCompactThrottleMinOomAdj);
            pw.println("  " + KEY_COMPACT_THROTTLE_MAX_OOM_ADJ + "=" + mCompactThrottleMaxOomAdj);
            pw.println("  " + KEY_COMPACT_STATSD_SAMPLE_RATE + "=" + mCompactStatsdSampleRate);
            pw.println("  " + KEY_COMPACT_FULL_RSS_THROTTLE_KB + "="
                    + mFullAnonRssThrottleKb);
@@ -367,12 +390,23 @@ public final class CachedAppOptimizer {

    @GuardedBy("mProcLock")
    void compactAppFull(ProcessRecord app) {
        // Apply OOM adj score throttle for Full App Compaction.
        if ((app.mState.getSetAdj() < mCompactThrottleMinOomAdj
                || app.mState.getSetAdj() > mCompactThrottleMaxOomAdj)
                && app.mState.getCurAdj() >= mCompactThrottleMinOomAdj
                && app.mState.getCurAdj() <= mCompactThrottleMaxOomAdj) {
            app.mOptRecord.setReqCompactAction(COMPACT_PROCESS_FULL);
            mPendingCompactionProcesses.add(app);
            mCompactionHandler.sendMessage(
                mCompactionHandler.obtainMessage(
                    COMPACT_PROCESS_MSG, app.mState.getSetAdj(), app.mState.getSetProcState()));

        } else {
            if (DEBUG_COMPACTION) {
                Slog.d(TAG_AM, "Skipping full compaction for " + app.processName
                        + " oom adj score changed from " + app.mState.getSetAdj()
                        + " to " + app.mState.getCurAdj());
            }
        }
    }

    @GuardedBy("mProcLock")
@@ -629,6 +663,7 @@ public final class CachedAppOptimizer {
    @GuardedBy("mPhenotypeFlagLock")
    private void updateCompactionThrottles() {
        boolean useThrottleDefaults = false;
        // TODO: improve efficiency by calling DeviceConfig only once for all flags.
        String throttleSomeSomeFlag =
                DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    KEY_COMPACT_THROTTLE_1);
@@ -647,12 +682,20 @@ public final class CachedAppOptimizer {
        String throttlePersistentFlag =
                DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    KEY_COMPACT_THROTTLE_6);
        String throttleMinOomAdjFlag =
                DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    KEY_COMPACT_THROTTLE_MIN_OOM_ADJ);
        String throttleMaxOomAdjFlag =
                DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    KEY_COMPACT_THROTTLE_MAX_OOM_ADJ);

        if (TextUtils.isEmpty(throttleSomeSomeFlag) || TextUtils.isEmpty(throttleSomeFullFlag)
                || TextUtils.isEmpty(throttleFullSomeFlag)
                || TextUtils.isEmpty(throttleFullFullFlag)
                || TextUtils.isEmpty(throttleBFGSFlag)
                || TextUtils.isEmpty(throttlePersistentFlag)) {
                || TextUtils.isEmpty(throttlePersistentFlag)
                || TextUtils.isEmpty(throttleMinOomAdjFlag)
                || TextUtils.isEmpty(throttleMaxOomAdjFlag)) {
            // Set defaults for all if any are not set.
            useThrottleDefaults = true;
        } else {
@@ -663,6 +706,8 @@ public final class CachedAppOptimizer {
                mCompactThrottleFullFull = Integer.parseInt(throttleFullFullFlag);
                mCompactThrottleBFGS = Integer.parseInt(throttleBFGSFlag);
                mCompactThrottlePersistent = Integer.parseInt(throttlePersistentFlag);
                mCompactThrottleMinOomAdj = Long.parseLong(throttleMinOomAdjFlag);
                mCompactThrottleMaxOomAdj = Long.parseLong(throttleMaxOomAdjFlag);
            } catch (NumberFormatException e) {
                useThrottleDefaults = true;
            }
@@ -675,6 +720,8 @@ public final class CachedAppOptimizer {
            mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4;
            mCompactThrottleBFGS = DEFAULT_COMPACT_THROTTLE_5;
            mCompactThrottlePersistent = DEFAULT_COMPACT_THROTTLE_6;
            mCompactThrottleMinOomAdj = DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ;
            mCompactThrottleMaxOomAdj = DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ;
        }
    }

@@ -729,6 +776,28 @@ public final class CachedAppOptimizer {
        }
    }

    @GuardedBy("mPhenotypeFlagLock")
    private void updateMinOomAdjThrottle() {
        mCompactThrottleMinOomAdj = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
            KEY_COMPACT_THROTTLE_MIN_OOM_ADJ, DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ);

        // Should only compact cached processes.
        if (mCompactThrottleMinOomAdj < ProcessList.CACHED_APP_MIN_ADJ) {
            mCompactThrottleMinOomAdj = DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ;
        }
    }

    @GuardedBy("mPhenotypeFlagLock")
    private void updateMaxOomAdjThrottle() {
        mCompactThrottleMaxOomAdj = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
            KEY_COMPACT_THROTTLE_MAX_OOM_ADJ, DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ);

        // Should only compact cached processes.
        if (mCompactThrottleMaxOomAdj > ProcessList.CACHED_APP_MAX_ADJ) {
            mCompactThrottleMaxOomAdj = DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ;
        }
    }

    private boolean parseProcStateThrottle(String procStateThrottleString) {
        String[] procStates = TextUtils.split(procStateThrottleString, ",");
        mProcStateThrottle.clear();
+1 −3
Original line number Diff line number Diff line
@@ -2541,9 +2541,7 @@ public final class OomAdjuster {
                        && (state.getCurAdj() == ProcessList.PREVIOUS_APP_ADJ
                            || state.getCurAdj() == ProcessList.HOME_APP_ADJ)) {
                    mCachedAppOptimizer.compactAppSome(app);
                } else if ((state.getSetAdj() < ProcessList.CACHED_APP_MIN_ADJ
                                || state.getSetAdj() > ProcessList.CACHED_APP_MAX_ADJ)
                        && state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ
                } else if (state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ
                        && state.getCurAdj() <= ProcessList.CACHED_APP_MAX_ADJ) {
                    mCachedAppOptimizer.compactAppFull(app);
                }
+81 −6
Original line number Diff line number Diff line
@@ -139,7 +139,8 @@ public final class CachedAppOptimizerTest {
        app.info.uid = packageUid;
        // Exact value does not mater, it can be any state for which compaction is allowed.
        app.mState.setSetProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
        app.mState.setSetAdj(905);
        app.mState.setSetAdj(899);
        app.mState.setCurAdj(940);
        return app;
    }

@@ -164,8 +165,6 @@ public final class CachedAppOptimizerTest {
                CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE);
        assertThat(mCachedAppOptimizerUnderTest.mFreezerStatsdSampleRate).isEqualTo(
                CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE);
        assertThat(mCachedAppOptimizerUnderTest.mFullAnonRssThrottleKb).isEqualTo(
                CachedAppOptimizer.DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB);
        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleBFGS).isEqualTo(
                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5);
        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo(
@@ -176,6 +175,11 @@ public final class CachedAppOptimizerTest {
                CachedAppOptimizer.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB);
        assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isEqualTo(
                CachedAppOptimizer.DEFAULT_USE_FREEZER);
        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleMinOomAdj).isEqualTo(
                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ);
        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleMaxOomAdj).isEqualTo(
                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ);


        Set<Integer> expected = new HashSet<>();
        for (String s : TextUtils.split(
@@ -230,6 +234,14 @@ public final class CachedAppOptimizerTest {
                CachedAppOptimizer.KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB,
                Long.toString(
                        CachedAppOptimizer.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB + 1), false);
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                CachedAppOptimizer.KEY_COMPACT_THROTTLE_MIN_OOM_ADJ,
                Long.toString(
                        CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ + 10), false);
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                CachedAppOptimizer.KEY_COMPACT_THROTTLE_MAX_OOM_ADJ,
                Long.toString(
                    CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ - 10), false);
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                CachedAppOptimizer.KEY_COMPACT_PROC_STATE_THROTTLE, "1,2,3", false);
        assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isEqualTo(
@@ -261,6 +273,12 @@ public final class CachedAppOptimizerTest {
                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5 + 1);
        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo(
                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_6 + 1);
        assertThat(mCachedAppOptimizerUnderTest.mFullDeltaRssThrottleKb).isEqualTo(
                CachedAppOptimizer.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB + 1);
        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleMinOomAdj).isEqualTo(
                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ + 10);
        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleMaxOomAdj).isEqualTo(
                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ - 10);
        assertThat(mCachedAppOptimizerUnderTest.mCompactStatsdSampleRate).isEqualTo(
                CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE + 0.1f);
        assertThat(mCachedAppOptimizerUnderTest.mFreezerStatsdSampleRate).isEqualTo(
@@ -437,7 +455,7 @@ public final class CachedAppOptimizerTest {
        mCachedAppOptimizerUnderTest.init();

        // When we override new reasonable throttle values after init...
        mCountDown = new CountDownLatch(6);
        mCountDown = new CountDownLatch(8);
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                CachedAppOptimizer.KEY_COMPACT_THROTTLE_1,
                Long.toString(CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_1 + 1), false);
@@ -456,7 +474,13 @@ public final class CachedAppOptimizerTest {
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                CachedAppOptimizer.KEY_COMPACT_THROTTLE_6,
                Long.toString(CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_6 + 1), false);
        assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                CachedAppOptimizer.KEY_COMPACT_THROTTLE_MIN_OOM_ADJ,
                Long.toString(CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ + 1), false);
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                CachedAppOptimizer.KEY_COMPACT_THROTTLE_MAX_OOM_ADJ,
                Long.toString(CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ - 1), false);
        assertThat(mCountDown.await(7, TimeUnit.SECONDS)).isTrue();

        // Then those flags values are reflected in the compactor.
        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleSomeSome).isEqualTo(
@@ -471,6 +495,10 @@ public final class CachedAppOptimizerTest {
                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5 + 1);
        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo(
                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_6 + 1);
        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleMinOomAdj).isEqualTo(
                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ + 1);
        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleMaxOomAdj).isEqualTo(
                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ - 1);
    }

    @Test
@@ -902,7 +930,6 @@ public final class CachedAppOptimizerTest {
        valuesAfter = mCachedAppOptimizerUnderTest.mLastCompactionStats.get(
                pid).getRssAfterCompaction();
        assertThat(valuesAfter).isEqualTo(rssAfter3);

    }

    @Test
@@ -954,6 +981,54 @@ public final class CachedAppOptimizerTest {
        assertThat(valuesAfter).isEqualTo(rssAboveThresholdAfter);
    }

    @Test
    public void processWithOomAdjTooSmall_notFullCompacted() throws Exception {
        // Initialize CachedAppOptimizer and set flags to (1) enable compaction, (2) set Min and
        // Max OOM_Adj throttles.
        mCachedAppOptimizerUnderTest.init();
        setFlag(CachedAppOptimizer.KEY_USE_COMPACTION, "true", true);
        setFlag(CachedAppOptimizer.KEY_COMPACT_THROTTLE_MIN_OOM_ADJ, Long.toString(920), true);
        setFlag(CachedAppOptimizer.KEY_COMPACT_THROTTLE_MAX_OOM_ADJ, Long.toString(950), true);
        initActivityManagerService();

        // Simulate RSS memory for which compaction should occur.
        long[] rssBefore =
            new long[]{/*Total RSS*/ 15000, /*File RSS*/ 15000, /*Anon RSS*/ 15000,
                /*Swap*/ 10000};
        long[] rssAfter =
            new long[]{/*Total RSS*/ 8000, /*File RSS*/ 9000, /*Anon RSS*/ 6000, /*Swap*/5000};
        // Process that passes properties.
        int pid = 1;
        ProcessRecord processRecord =
                makeProcessRecord(pid, 2, 3, "p1", "app1");
        mProcessDependencies.setRss(rssBefore);
        mProcessDependencies.setRssAfterCompaction(rssAfter);

        // Compaction should occur if (setAdj < min for process || setAdj > max for process) &&
        // (MIN < curAdj <  MAX)
        // GIVEN OomAdj score below threshold.
        processRecord.mState.setSetAdj(899);
        processRecord.mState.setCurAdj(970);
        // WHEN we try to run compaction
        mCachedAppOptimizerUnderTest.compactAppFull(processRecord);
        waitForHandler();
        // THEN process IS NOT compacted.
        assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNull();

        // GIVEN (setAdj < MIN || setAdj > MAX) && (MIN < curAdj <  MAX)
        processRecord.mState.setSetAdj(910);
        processRecord.mState.setCurAdj(930);
        // WHEN we try to run compaction
        mCachedAppOptimizerUnderTest.compactAppFull(processRecord);
        waitForHandler();
        // THEN process IS compacted.
        assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNotNull();
        long[] valuesAfter = mCachedAppOptimizerUnderTest.mLastCompactionStats
            .get(pid)
            .getRssAfterCompaction();
        assertThat(valuesAfter).isEqualTo(rssAfter);
    }


    private void setFlag(String key, String value, boolean defaultValue) throws Exception {
        mCountDown = new CountDownLatch(1);