Loading services/core/java/com/android/server/am/CachedAppOptimizer.java +75 −6 Original line number Diff line number Diff line Loading @@ -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 = Loading Loading @@ -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; Loading Loading @@ -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(); } } } Loading Loading @@ -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") Loading Loading @@ -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) { Loading @@ -294,6 +313,8 @@ public final class CachedAppOptimizer { updateFullDeltaRssThrottle(); updateProcStateThrottle(); updateUseFreezer(); updateMinOomAdjThrottle(); updateMaxOomAdjThrottle(); } } Loading Loading @@ -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); Loading Loading @@ -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") Loading Loading @@ -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); Loading @@ -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 { Loading @@ -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; } Loading @@ -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; } } Loading Loading @@ -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(); Loading services/core/java/com/android/server/am/OomAdjuster.java +1 −3 Original line number Diff line number Diff line Loading @@ -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); } Loading services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java +81 −6 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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( Loading @@ -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( Loading Loading @@ -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( Loading Loading @@ -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( Loading Loading @@ -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); Loading @@ -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( Loading @@ -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 Loading Loading @@ -902,7 +930,6 @@ public final class CachedAppOptimizerTest { valuesAfter = mCachedAppOptimizerUnderTest.mLastCompactionStats.get( pid).getRssAfterCompaction(); assertThat(valuesAfter).isEqualTo(rssAfter3); } @Test Loading Loading @@ -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); Loading Loading
services/core/java/com/android/server/am/CachedAppOptimizer.java +75 −6 Original line number Diff line number Diff line Loading @@ -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 = Loading Loading @@ -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; Loading Loading @@ -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(); } } } Loading Loading @@ -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") Loading Loading @@ -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) { Loading @@ -294,6 +313,8 @@ public final class CachedAppOptimizer { updateFullDeltaRssThrottle(); updateProcStateThrottle(); updateUseFreezer(); updateMinOomAdjThrottle(); updateMaxOomAdjThrottle(); } } Loading Loading @@ -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); Loading Loading @@ -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") Loading Loading @@ -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); Loading @@ -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 { Loading @@ -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; } Loading @@ -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; } } Loading Loading @@ -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(); Loading
services/core/java/com/android/server/am/OomAdjuster.java +1 −3 Original line number Diff line number Diff line Loading @@ -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); } Loading
services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java +81 −6 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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( Loading @@ -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( Loading Loading @@ -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( Loading Loading @@ -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( Loading Loading @@ -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); Loading @@ -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( Loading @@ -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 Loading Loading @@ -902,7 +930,6 @@ public final class CachedAppOptimizerTest { valuesAfter = mCachedAppOptimizerUnderTest.mLastCompactionStats.get( pid).getRssAfterCompaction(); assertThat(valuesAfter).isEqualTo(rssAfter3); } @Test Loading Loading @@ -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); Loading