Loading services/core/java/com/android/server/am/CachedAppOptimizer.java +75 −6 Original line number Original line 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_4 = "compact_throttle_4"; @VisibleForTesting static final String KEY_COMPACT_THROTTLE_5 = "compact_throttle_5"; @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_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 = @VisibleForTesting static final String KEY_COMPACT_STATSD_SAMPLE_RATE = "compact_statsd_sample_rate"; "compact_statsd_sample_rate"; @VisibleForTesting static final String KEY_FREEZER_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_4 = 10_000; @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_5 = 10 * 60 * 1000; @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_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. // 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 float DEFAULT_STATSD_SAMPLE_RATE = 0.1f; @VisibleForTesting static final long DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB = 12_000L; @VisibleForTesting static final long DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB = 12_000L; Loading Loading @@ -186,6 +194,10 @@ public final class CachedAppOptimizer { updateFullDeltaRssThrottle(); updateFullDeltaRssThrottle(); } else if (KEY_COMPACT_PROC_STATE_THROTTLE.equals(name)) { } else if (KEY_COMPACT_PROC_STATE_THROTTLE.equals(name)) { updateProcStateThrottle(); 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") @GuardedBy("mPhenotypeFlagLock") @VisibleForTesting volatile long mCompactThrottlePersistent = DEFAULT_COMPACT_THROTTLE_6; @VisibleForTesting volatile long mCompactThrottlePersistent = DEFAULT_COMPACT_THROTTLE_6; @GuardedBy("mPhenotypeFlagLock") @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 mUseCompaction = DEFAULT_USE_COMPACTION; private volatile boolean mUseFreezer = DEFAULT_USE_FREEZER; private volatile boolean mUseFreezer = DEFAULT_USE_FREEZER; @GuardedBy("this") @GuardedBy("this") Loading Loading @@ -282,6 +300,7 @@ public final class CachedAppOptimizer { * starts the background thread if necessary. * starts the background thread if necessary. */ */ public void init() { public void init() { // TODO: initialize flags to default and only update them if values are set in DeviceConfig DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, ActivityThread.currentApplication().getMainExecutor(), mOnFlagsChangedListener); ActivityThread.currentApplication().getMainExecutor(), mOnFlagsChangedListener); synchronized (mPhenotypeFlagLock) { synchronized (mPhenotypeFlagLock) { Loading @@ -294,6 +313,8 @@ public final class CachedAppOptimizer { updateFullDeltaRssThrottle(); updateFullDeltaRssThrottle(); updateProcStateThrottle(); updateProcStateThrottle(); updateUseFreezer(); 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_4 + "=" + mCompactThrottleFullFull); pw.println(" " + KEY_COMPACT_THROTTLE_5 + "=" + mCompactThrottleBFGS); pw.println(" " + KEY_COMPACT_THROTTLE_5 + "=" + mCompactThrottleBFGS); pw.println(" " + KEY_COMPACT_THROTTLE_6 + "=" + mCompactThrottlePersistent); 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_STATSD_SAMPLE_RATE + "=" + mCompactStatsdSampleRate); pw.println(" " + KEY_COMPACT_FULL_RSS_THROTTLE_KB + "=" pw.println(" " + KEY_COMPACT_FULL_RSS_THROTTLE_KB + "=" + mFullAnonRssThrottleKb); + mFullAnonRssThrottleKb); Loading Loading @@ -367,12 +390,23 @@ public final class CachedAppOptimizer { @GuardedBy("mProcLock") @GuardedBy("mProcLock") void compactAppFull(ProcessRecord app) { 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); app.mOptRecord.setReqCompactAction(COMPACT_PROCESS_FULL); mPendingCompactionProcesses.add(app); mPendingCompactionProcesses.add(app); mCompactionHandler.sendMessage( mCompactionHandler.sendMessage( mCompactionHandler.obtainMessage( mCompactionHandler.obtainMessage( COMPACT_PROCESS_MSG, app.mState.getSetAdj(), app.mState.getSetProcState())); 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") @GuardedBy("mProcLock") Loading Loading @@ -629,6 +663,7 @@ public final class CachedAppOptimizer { @GuardedBy("mPhenotypeFlagLock") @GuardedBy("mPhenotypeFlagLock") private void updateCompactionThrottles() { private void updateCompactionThrottles() { boolean useThrottleDefaults = false; boolean useThrottleDefaults = false; // TODO: improve efficiency by calling DeviceConfig only once for all flags. String throttleSomeSomeFlag = String throttleSomeSomeFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_1); KEY_COMPACT_THROTTLE_1); Loading @@ -647,12 +682,20 @@ public final class CachedAppOptimizer { String throttlePersistentFlag = String throttlePersistentFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_6); 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) if (TextUtils.isEmpty(throttleSomeSomeFlag) || TextUtils.isEmpty(throttleSomeFullFlag) || TextUtils.isEmpty(throttleFullSomeFlag) || TextUtils.isEmpty(throttleFullSomeFlag) || TextUtils.isEmpty(throttleFullFullFlag) || TextUtils.isEmpty(throttleFullFullFlag) || TextUtils.isEmpty(throttleBFGSFlag) || TextUtils.isEmpty(throttleBFGSFlag) || TextUtils.isEmpty(throttlePersistentFlag)) { || TextUtils.isEmpty(throttlePersistentFlag) || TextUtils.isEmpty(throttleMinOomAdjFlag) || TextUtils.isEmpty(throttleMaxOomAdjFlag)) { // Set defaults for all if any are not set. // Set defaults for all if any are not set. useThrottleDefaults = true; useThrottleDefaults = true; } else { } else { Loading @@ -663,6 +706,8 @@ public final class CachedAppOptimizer { mCompactThrottleFullFull = Integer.parseInt(throttleFullFullFlag); mCompactThrottleFullFull = Integer.parseInt(throttleFullFullFlag); mCompactThrottleBFGS = Integer.parseInt(throttleBFGSFlag); mCompactThrottleBFGS = Integer.parseInt(throttleBFGSFlag); mCompactThrottlePersistent = Integer.parseInt(throttlePersistentFlag); mCompactThrottlePersistent = Integer.parseInt(throttlePersistentFlag); mCompactThrottleMinOomAdj = Long.parseLong(throttleMinOomAdjFlag); mCompactThrottleMaxOomAdj = Long.parseLong(throttleMaxOomAdjFlag); } catch (NumberFormatException e) { } catch (NumberFormatException e) { useThrottleDefaults = true; useThrottleDefaults = true; } } Loading @@ -675,6 +720,8 @@ public final class CachedAppOptimizer { mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4; mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4; mCompactThrottleBFGS = DEFAULT_COMPACT_THROTTLE_5; mCompactThrottleBFGS = DEFAULT_COMPACT_THROTTLE_5; mCompactThrottlePersistent = DEFAULT_COMPACT_THROTTLE_6; 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) { private boolean parseProcStateThrottle(String procStateThrottleString) { String[] procStates = TextUtils.split(procStateThrottleString, ","); String[] procStates = TextUtils.split(procStateThrottleString, ","); mProcStateThrottle.clear(); mProcStateThrottle.clear(); Loading services/core/java/com/android/server/am/OomAdjuster.java +1 −3 Original line number Original line Diff line number Diff line Loading @@ -2541,9 +2541,7 @@ public final class OomAdjuster { && (state.getCurAdj() == ProcessList.PREVIOUS_APP_ADJ && (state.getCurAdj() == ProcessList.PREVIOUS_APP_ADJ || state.getCurAdj() == ProcessList.HOME_APP_ADJ)) { || state.getCurAdj() == ProcessList.HOME_APP_ADJ)) { mCachedAppOptimizer.compactAppSome(app); mCachedAppOptimizer.compactAppSome(app); } else if ((state.getSetAdj() < ProcessList.CACHED_APP_MIN_ADJ } else if (state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ || state.getSetAdj() > ProcessList.CACHED_APP_MAX_ADJ) && state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ && state.getCurAdj() <= ProcessList.CACHED_APP_MAX_ADJ) { && state.getCurAdj() <= ProcessList.CACHED_APP_MAX_ADJ) { mCachedAppOptimizer.compactAppFull(app); mCachedAppOptimizer.compactAppFull(app); } } Loading services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java +81 −6 Original line number Original line Diff line number Diff line Loading @@ -139,7 +139,8 @@ public final class CachedAppOptimizerTest { app.info.uid = packageUid; app.info.uid = packageUid; // Exact value does not mater, it can be any state for which compaction is allowed. // 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.setSetProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE); app.mState.setSetAdj(905); app.mState.setSetAdj(899); app.mState.setCurAdj(940); return app; return app; } } Loading @@ -164,8 +165,6 @@ public final class CachedAppOptimizerTest { CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE); CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE); assertThat(mCachedAppOptimizerUnderTest.mFreezerStatsdSampleRate).isEqualTo( assertThat(mCachedAppOptimizerUnderTest.mFreezerStatsdSampleRate).isEqualTo( CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE); CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE); assertThat(mCachedAppOptimizerUnderTest.mFullAnonRssThrottleKb).isEqualTo( CachedAppOptimizer.DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB); assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleBFGS).isEqualTo( assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleBFGS).isEqualTo( CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5); CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5); assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo( assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo( Loading @@ -176,6 +175,11 @@ public final class CachedAppOptimizerTest { CachedAppOptimizer.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB); CachedAppOptimizer.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB); assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isEqualTo( assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isEqualTo( CachedAppOptimizer.DEFAULT_USE_FREEZER); 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<>(); Set<Integer> expected = new HashSet<>(); for (String s : TextUtils.split( for (String s : TextUtils.split( Loading Loading @@ -230,6 +234,14 @@ public final class CachedAppOptimizerTest { CachedAppOptimizer.KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB, CachedAppOptimizer.KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB, Long.toString( Long.toString( CachedAppOptimizer.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB + 1), false); 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, DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, CachedAppOptimizer.KEY_COMPACT_PROC_STATE_THROTTLE, "1,2,3", false); CachedAppOptimizer.KEY_COMPACT_PROC_STATE_THROTTLE, "1,2,3", false); assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isEqualTo( assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isEqualTo( Loading Loading @@ -261,6 +273,12 @@ public final class CachedAppOptimizerTest { CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5 + 1); CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5 + 1); assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo( assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo( CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_6 + 1); 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( assertThat(mCachedAppOptimizerUnderTest.mCompactStatsdSampleRate).isEqualTo( CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE + 0.1f); CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE + 0.1f); assertThat(mCachedAppOptimizerUnderTest.mFreezerStatsdSampleRate).isEqualTo( assertThat(mCachedAppOptimizerUnderTest.mFreezerStatsdSampleRate).isEqualTo( Loading Loading @@ -437,7 +455,7 @@ public final class CachedAppOptimizerTest { mCachedAppOptimizerUnderTest.init(); mCachedAppOptimizerUnderTest.init(); // When we override new reasonable throttle values after init... // When we override new reasonable throttle values after init... mCountDown = new CountDownLatch(6); mCountDown = new CountDownLatch(8); DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, CachedAppOptimizer.KEY_COMPACT_THROTTLE_1, CachedAppOptimizer.KEY_COMPACT_THROTTLE_1, Long.toString(CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_1 + 1), false); Long.toString(CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_1 + 1), false); Loading @@ -456,7 +474,13 @@ public final class CachedAppOptimizerTest { DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, CachedAppOptimizer.KEY_COMPACT_THROTTLE_6, CachedAppOptimizer.KEY_COMPACT_THROTTLE_6, Long.toString(CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_6 + 1), false); 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. // Then those flags values are reflected in the compactor. assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleSomeSome).isEqualTo( assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleSomeSome).isEqualTo( Loading @@ -471,6 +495,10 @@ public final class CachedAppOptimizerTest { CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5 + 1); CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5 + 1); assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo( assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo( CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_6 + 1); 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 @Test Loading Loading @@ -902,7 +930,6 @@ public final class CachedAppOptimizerTest { valuesAfter = mCachedAppOptimizerUnderTest.mLastCompactionStats.get( valuesAfter = mCachedAppOptimizerUnderTest.mLastCompactionStats.get( pid).getRssAfterCompaction(); pid).getRssAfterCompaction(); assertThat(valuesAfter).isEqualTo(rssAfter3); assertThat(valuesAfter).isEqualTo(rssAfter3); } } @Test @Test Loading Loading @@ -954,6 +981,54 @@ public final class CachedAppOptimizerTest { assertThat(valuesAfter).isEqualTo(rssAboveThresholdAfter); 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 { private void setFlag(String key, String value, boolean defaultValue) throws Exception { mCountDown = new CountDownLatch(1); mCountDown = new CountDownLatch(1); Loading Loading
services/core/java/com/android/server/am/CachedAppOptimizer.java +75 −6 Original line number Original line 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_4 = "compact_throttle_4"; @VisibleForTesting static final String KEY_COMPACT_THROTTLE_5 = "compact_throttle_5"; @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_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 = @VisibleForTesting static final String KEY_COMPACT_STATSD_SAMPLE_RATE = "compact_statsd_sample_rate"; "compact_statsd_sample_rate"; @VisibleForTesting static final String KEY_FREEZER_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_4 = 10_000; @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_5 = 10 * 60 * 1000; @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_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. // 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 float DEFAULT_STATSD_SAMPLE_RATE = 0.1f; @VisibleForTesting static final long DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB = 12_000L; @VisibleForTesting static final long DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB = 12_000L; Loading Loading @@ -186,6 +194,10 @@ public final class CachedAppOptimizer { updateFullDeltaRssThrottle(); updateFullDeltaRssThrottle(); } else if (KEY_COMPACT_PROC_STATE_THROTTLE.equals(name)) { } else if (KEY_COMPACT_PROC_STATE_THROTTLE.equals(name)) { updateProcStateThrottle(); 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") @GuardedBy("mPhenotypeFlagLock") @VisibleForTesting volatile long mCompactThrottlePersistent = DEFAULT_COMPACT_THROTTLE_6; @VisibleForTesting volatile long mCompactThrottlePersistent = DEFAULT_COMPACT_THROTTLE_6; @GuardedBy("mPhenotypeFlagLock") @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 mUseCompaction = DEFAULT_USE_COMPACTION; private volatile boolean mUseFreezer = DEFAULT_USE_FREEZER; private volatile boolean mUseFreezer = DEFAULT_USE_FREEZER; @GuardedBy("this") @GuardedBy("this") Loading Loading @@ -282,6 +300,7 @@ public final class CachedAppOptimizer { * starts the background thread if necessary. * starts the background thread if necessary. */ */ public void init() { public void init() { // TODO: initialize flags to default and only update them if values are set in DeviceConfig DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, ActivityThread.currentApplication().getMainExecutor(), mOnFlagsChangedListener); ActivityThread.currentApplication().getMainExecutor(), mOnFlagsChangedListener); synchronized (mPhenotypeFlagLock) { synchronized (mPhenotypeFlagLock) { Loading @@ -294,6 +313,8 @@ public final class CachedAppOptimizer { updateFullDeltaRssThrottle(); updateFullDeltaRssThrottle(); updateProcStateThrottle(); updateProcStateThrottle(); updateUseFreezer(); 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_4 + "=" + mCompactThrottleFullFull); pw.println(" " + KEY_COMPACT_THROTTLE_5 + "=" + mCompactThrottleBFGS); pw.println(" " + KEY_COMPACT_THROTTLE_5 + "=" + mCompactThrottleBFGS); pw.println(" " + KEY_COMPACT_THROTTLE_6 + "=" + mCompactThrottlePersistent); 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_STATSD_SAMPLE_RATE + "=" + mCompactStatsdSampleRate); pw.println(" " + KEY_COMPACT_FULL_RSS_THROTTLE_KB + "=" pw.println(" " + KEY_COMPACT_FULL_RSS_THROTTLE_KB + "=" + mFullAnonRssThrottleKb); + mFullAnonRssThrottleKb); Loading Loading @@ -367,12 +390,23 @@ public final class CachedAppOptimizer { @GuardedBy("mProcLock") @GuardedBy("mProcLock") void compactAppFull(ProcessRecord app) { 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); app.mOptRecord.setReqCompactAction(COMPACT_PROCESS_FULL); mPendingCompactionProcesses.add(app); mPendingCompactionProcesses.add(app); mCompactionHandler.sendMessage( mCompactionHandler.sendMessage( mCompactionHandler.obtainMessage( mCompactionHandler.obtainMessage( COMPACT_PROCESS_MSG, app.mState.getSetAdj(), app.mState.getSetProcState())); 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") @GuardedBy("mProcLock") Loading Loading @@ -629,6 +663,7 @@ public final class CachedAppOptimizer { @GuardedBy("mPhenotypeFlagLock") @GuardedBy("mPhenotypeFlagLock") private void updateCompactionThrottles() { private void updateCompactionThrottles() { boolean useThrottleDefaults = false; boolean useThrottleDefaults = false; // TODO: improve efficiency by calling DeviceConfig only once for all flags. String throttleSomeSomeFlag = String throttleSomeSomeFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_1); KEY_COMPACT_THROTTLE_1); Loading @@ -647,12 +682,20 @@ public final class CachedAppOptimizer { String throttlePersistentFlag = String throttlePersistentFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_6); 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) if (TextUtils.isEmpty(throttleSomeSomeFlag) || TextUtils.isEmpty(throttleSomeFullFlag) || TextUtils.isEmpty(throttleFullSomeFlag) || TextUtils.isEmpty(throttleFullSomeFlag) || TextUtils.isEmpty(throttleFullFullFlag) || TextUtils.isEmpty(throttleFullFullFlag) || TextUtils.isEmpty(throttleBFGSFlag) || TextUtils.isEmpty(throttleBFGSFlag) || TextUtils.isEmpty(throttlePersistentFlag)) { || TextUtils.isEmpty(throttlePersistentFlag) || TextUtils.isEmpty(throttleMinOomAdjFlag) || TextUtils.isEmpty(throttleMaxOomAdjFlag)) { // Set defaults for all if any are not set. // Set defaults for all if any are not set. useThrottleDefaults = true; useThrottleDefaults = true; } else { } else { Loading @@ -663,6 +706,8 @@ public final class CachedAppOptimizer { mCompactThrottleFullFull = Integer.parseInt(throttleFullFullFlag); mCompactThrottleFullFull = Integer.parseInt(throttleFullFullFlag); mCompactThrottleBFGS = Integer.parseInt(throttleBFGSFlag); mCompactThrottleBFGS = Integer.parseInt(throttleBFGSFlag); mCompactThrottlePersistent = Integer.parseInt(throttlePersistentFlag); mCompactThrottlePersistent = Integer.parseInt(throttlePersistentFlag); mCompactThrottleMinOomAdj = Long.parseLong(throttleMinOomAdjFlag); mCompactThrottleMaxOomAdj = Long.parseLong(throttleMaxOomAdjFlag); } catch (NumberFormatException e) { } catch (NumberFormatException e) { useThrottleDefaults = true; useThrottleDefaults = true; } } Loading @@ -675,6 +720,8 @@ public final class CachedAppOptimizer { mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4; mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4; mCompactThrottleBFGS = DEFAULT_COMPACT_THROTTLE_5; mCompactThrottleBFGS = DEFAULT_COMPACT_THROTTLE_5; mCompactThrottlePersistent = DEFAULT_COMPACT_THROTTLE_6; 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) { private boolean parseProcStateThrottle(String procStateThrottleString) { String[] procStates = TextUtils.split(procStateThrottleString, ","); String[] procStates = TextUtils.split(procStateThrottleString, ","); mProcStateThrottle.clear(); mProcStateThrottle.clear(); Loading
services/core/java/com/android/server/am/OomAdjuster.java +1 −3 Original line number Original line Diff line number Diff line Loading @@ -2541,9 +2541,7 @@ public final class OomAdjuster { && (state.getCurAdj() == ProcessList.PREVIOUS_APP_ADJ && (state.getCurAdj() == ProcessList.PREVIOUS_APP_ADJ || state.getCurAdj() == ProcessList.HOME_APP_ADJ)) { || state.getCurAdj() == ProcessList.HOME_APP_ADJ)) { mCachedAppOptimizer.compactAppSome(app); mCachedAppOptimizer.compactAppSome(app); } else if ((state.getSetAdj() < ProcessList.CACHED_APP_MIN_ADJ } else if (state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ || state.getSetAdj() > ProcessList.CACHED_APP_MAX_ADJ) && state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ && state.getCurAdj() <= ProcessList.CACHED_APP_MAX_ADJ) { && state.getCurAdj() <= ProcessList.CACHED_APP_MAX_ADJ) { mCachedAppOptimizer.compactAppFull(app); mCachedAppOptimizer.compactAppFull(app); } } Loading
services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java +81 −6 Original line number Original line Diff line number Diff line Loading @@ -139,7 +139,8 @@ public final class CachedAppOptimizerTest { app.info.uid = packageUid; app.info.uid = packageUid; // Exact value does not mater, it can be any state for which compaction is allowed. // 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.setSetProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE); app.mState.setSetAdj(905); app.mState.setSetAdj(899); app.mState.setCurAdj(940); return app; return app; } } Loading @@ -164,8 +165,6 @@ public final class CachedAppOptimizerTest { CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE); CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE); assertThat(mCachedAppOptimizerUnderTest.mFreezerStatsdSampleRate).isEqualTo( assertThat(mCachedAppOptimizerUnderTest.mFreezerStatsdSampleRate).isEqualTo( CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE); CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE); assertThat(mCachedAppOptimizerUnderTest.mFullAnonRssThrottleKb).isEqualTo( CachedAppOptimizer.DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB); assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleBFGS).isEqualTo( assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleBFGS).isEqualTo( CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5); CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5); assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo( assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo( Loading @@ -176,6 +175,11 @@ public final class CachedAppOptimizerTest { CachedAppOptimizer.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB); CachedAppOptimizer.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB); assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isEqualTo( assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isEqualTo( CachedAppOptimizer.DEFAULT_USE_FREEZER); 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<>(); Set<Integer> expected = new HashSet<>(); for (String s : TextUtils.split( for (String s : TextUtils.split( Loading Loading @@ -230,6 +234,14 @@ public final class CachedAppOptimizerTest { CachedAppOptimizer.KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB, CachedAppOptimizer.KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB, Long.toString( Long.toString( CachedAppOptimizer.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB + 1), false); 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, DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, CachedAppOptimizer.KEY_COMPACT_PROC_STATE_THROTTLE, "1,2,3", false); CachedAppOptimizer.KEY_COMPACT_PROC_STATE_THROTTLE, "1,2,3", false); assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isEqualTo( assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isEqualTo( Loading Loading @@ -261,6 +273,12 @@ public final class CachedAppOptimizerTest { CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5 + 1); CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5 + 1); assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo( assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo( CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_6 + 1); 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( assertThat(mCachedAppOptimizerUnderTest.mCompactStatsdSampleRate).isEqualTo( CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE + 0.1f); CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE + 0.1f); assertThat(mCachedAppOptimizerUnderTest.mFreezerStatsdSampleRate).isEqualTo( assertThat(mCachedAppOptimizerUnderTest.mFreezerStatsdSampleRate).isEqualTo( Loading Loading @@ -437,7 +455,7 @@ public final class CachedAppOptimizerTest { mCachedAppOptimizerUnderTest.init(); mCachedAppOptimizerUnderTest.init(); // When we override new reasonable throttle values after init... // When we override new reasonable throttle values after init... mCountDown = new CountDownLatch(6); mCountDown = new CountDownLatch(8); DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, CachedAppOptimizer.KEY_COMPACT_THROTTLE_1, CachedAppOptimizer.KEY_COMPACT_THROTTLE_1, Long.toString(CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_1 + 1), false); Long.toString(CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_1 + 1), false); Loading @@ -456,7 +474,13 @@ public final class CachedAppOptimizerTest { DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, CachedAppOptimizer.KEY_COMPACT_THROTTLE_6, CachedAppOptimizer.KEY_COMPACT_THROTTLE_6, Long.toString(CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_6 + 1), false); 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. // Then those flags values are reflected in the compactor. assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleSomeSome).isEqualTo( assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleSomeSome).isEqualTo( Loading @@ -471,6 +495,10 @@ public final class CachedAppOptimizerTest { CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5 + 1); CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5 + 1); assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo( assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo( CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_6 + 1); 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 @Test Loading Loading @@ -902,7 +930,6 @@ public final class CachedAppOptimizerTest { valuesAfter = mCachedAppOptimizerUnderTest.mLastCompactionStats.get( valuesAfter = mCachedAppOptimizerUnderTest.mLastCompactionStats.get( pid).getRssAfterCompaction(); pid).getRssAfterCompaction(); assertThat(valuesAfter).isEqualTo(rssAfter3); assertThat(valuesAfter).isEqualTo(rssAfter3); } } @Test @Test Loading Loading @@ -954,6 +981,54 @@ public final class CachedAppOptimizerTest { assertThat(valuesAfter).isEqualTo(rssAboveThresholdAfter); 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 { private void setFlag(String key, String value, boolean defaultValue) throws Exception { mCountDown = new CountDownLatch(1); mCountDown = new CountDownLatch(1); Loading