Loading services/core/java/com/android/server/am/ActivityManagerService.java +5 −0 Original line number Diff line number Diff line Loading @@ -5121,6 +5121,7 @@ public class ActivityManagerService extends IActivityManager.Stub String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { synchronized (ActivityManagerService.this) { mOomAdjuster.mAppCompact.compactAllSystem(); requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false); } } Loading Loading @@ -8614,6 +8615,10 @@ public class ActivityManagerService extends IActivityManager.Stub synchronized (this) { final long now = SystemClock.uptimeMillis(); final long timeSinceLastIdle = now - mLastIdleTime; // Compact all non-zygote processes to freshen up the page cache. mOomAdjuster.mAppCompact.compactAllSystem(); final long lowRamSinceLastIdle = getLowRamTimeSinceIdle(now); mLastIdleTime = now; mLowRamTimeSinceLastIdle = 0; Loading services/core/java/com/android/server/am/AppCompactor.java +117 −24 Original line number Diff line number Diff line Loading @@ -51,6 +51,8 @@ public final class AppCompactor { @VisibleForTesting static final String KEY_COMPACT_THROTTLE_2 = "compact_throttle_2"; @VisibleForTesting static final String KEY_COMPACT_THROTTLE_3 = "compact_throttle_3"; @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_STATSD_SAMPLE_RATE = "compact_statsd_sample_rate"; Loading @@ -73,6 +75,8 @@ public final class AppCompactor { @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_2 = 10_000; @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_3 = 500; @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; // The sampling rate to push app compaction events into statsd for upload. @VisibleForTesting static final float DEFAULT_STATSD_SAMPLE_RATE = 0.1f; Loading @@ -85,7 +89,10 @@ public final class AppCompactor { // Handler constants. static final int COMPACT_PROCESS_SOME = 1; static final int COMPACT_PROCESS_FULL = 2; static final int COMPACT_PROCESS_PERSISTENT = 3; static final int COMPACT_PROCESS_BFGS = 4; static final int COMPACT_PROCESS_MSG = 1; static final int COMPACT_SYSTEM_MSG = 2; /** * This thread must be moved to the system background cpuset. Loading Loading @@ -142,6 +149,10 @@ public final class AppCompactor { @GuardedBy("mPhenotypeFlagLock") @VisibleForTesting volatile long mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4; @GuardedBy("mPhenotypeFlagLock") @VisibleForTesting volatile long mCompactThrottleBFGS = DEFAULT_COMPACT_THROTTLE_5; @GuardedBy("mPhenotypeFlagLock") @VisibleForTesting volatile long mCompactThrottlePersistent = DEFAULT_COMPACT_THROTTLE_6; @GuardedBy("mPhenotypeFlagLock") private volatile boolean mUseCompaction = DEFAULT_USE_COMPACTION; private final Random mRandom = new Random(); Loading Loading @@ -224,6 +235,46 @@ public final class AppCompactor { } @GuardedBy("mAm") void compactAppPersistent(ProcessRecord app) { app.reqCompactAction = COMPACT_PROCESS_PERSISTENT; mPendingCompactionProcesses.add(app); mCompactionHandler.sendMessage( mCompactionHandler.obtainMessage( COMPACT_PROCESS_MSG, app.curAdj, app.setProcState)); } @GuardedBy("mAm") boolean shouldCompactPersistent(ProcessRecord app, long now) { return (app.lastCompactTime == 0 || (now - app.lastCompactTime) > mCompactThrottlePersistent); } @GuardedBy("mAm") void compactAppBfgs(ProcessRecord app) { app.reqCompactAction = COMPACT_PROCESS_BFGS; mPendingCompactionProcesses.add(app); mCompactionHandler.sendMessage( mCompactionHandler.obtainMessage( COMPACT_PROCESS_MSG, app.curAdj, app.setProcState)); } @GuardedBy("mAm") boolean shouldCompactBFGS(ProcessRecord app, long now) { return (app.lastCompactTime == 0 || (now - app.lastCompactTime) > mCompactThrottleBFGS); } @GuardedBy("mAm") void compactAllSystem() { if (mUseCompaction) { mCompactionHandler.sendMessage(mCompactionHandler.obtainMessage( COMPACT_SYSTEM_MSG)); } } private native void compactSystem(); /** * Reads the flag value from DeviceConfig to determine whether app compaction * should be enabled, and starts/stops the compaction thread as needed. Loading Loading @@ -265,10 +316,18 @@ public final class AppCompactor { String throttleFullFullFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_4); String throttleBFGSFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_5); String throttlePersistentFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_6); if (TextUtils.isEmpty(throttleSomeSomeFlag) || TextUtils.isEmpty(throttleSomeFullFlag) || TextUtils.isEmpty(throttleFullSomeFlag) || TextUtils.isEmpty(throttleFullFullFlag)) { || TextUtils.isEmpty(throttleFullFullFlag) || TextUtils.isEmpty(throttleBFGSFlag) || TextUtils.isEmpty(throttlePersistentFlag)) { // Set defaults for all if any are not set. useThrottleDefaults = true; } else { Loading @@ -277,6 +336,8 @@ public final class AppCompactor { mCompactThrottleSomeFull = Integer.parseInt(throttleSomeFullFlag); mCompactThrottleFullSome = Integer.parseInt(throttleFullSomeFlag); mCompactThrottleFullFull = Integer.parseInt(throttleFullFullFlag); mCompactThrottleBFGS = Integer.parseInt(throttleBFGSFlag); mCompactThrottlePersistent = Integer.parseInt(throttlePersistentFlag); } catch (NumberFormatException e) { useThrottleDefaults = true; } Loading @@ -287,6 +348,8 @@ public final class AppCompactor { mCompactThrottleSomeFull = DEFAULT_COMPACT_THROTTLE_2; mCompactThrottleFullSome = DEFAULT_COMPACT_THROTTLE_3; mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4; mCompactThrottleBFGS = DEFAULT_COMPACT_THROTTLE_5; mCompactThrottlePersistent = DEFAULT_COMPACT_THROTTLE_6; } } Loading Loading @@ -332,14 +395,19 @@ public final class AppCompactor { synchronized (mAm) { proc = mPendingCompactionProcesses.remove(0); pendingAction = proc.reqCompactAction; // don't compact if the process has returned to perceptible if (proc.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) { // and this is only a cached/home/prev compaction if ((pendingAction == COMPACT_PROCESS_SOME || pendingAction == COMPACT_PROCESS_FULL) && (proc.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ)) { return; } pid = proc.pid; name = proc.processName; pendingAction = proc.reqCompactAction; lastCompactAction = proc.lastCompactAction; lastCompactTime = proc.lastCompactTime; } Loading @@ -356,6 +424,7 @@ public final class AppCompactor { // Note that we explicitly don't take mPhenotypeFlagLock here as the flags // should very seldom change, and taking the risk of using the wrong action is // preferable to taking the lock for every single compaction action. if (lastCompactTime != 0) { if (pendingAction == COMPACT_PROCESS_SOME) { if ((lastCompactAction == COMPACT_PROCESS_SOME && (start - lastCompactTime < mCompactThrottleSomeSome)) Loading @@ -364,7 +433,7 @@ public final class AppCompactor { < mCompactThrottleSomeFull))) { return; } } else { } else if (pendingAction == COMPACT_PROCESS_FULL) { if ((lastCompactAction == COMPACT_PROCESS_SOME && (start - lastCompactTime < mCompactThrottleFullSome)) || (lastCompactAction == COMPACT_PROCESS_FULL Loading @@ -372,15 +441,32 @@ public final class AppCompactor { < mCompactThrottleFullFull))) { return; } } else if (pendingAction == COMPACT_PROCESS_PERSISTENT) { if (start - lastCompactTime < mCompactThrottlePersistent) { return; } if (pendingAction == COMPACT_PROCESS_SOME) { } else if (pendingAction == COMPACT_PROCESS_BFGS) { if (start - lastCompactTime < mCompactThrottleBFGS) { return; } } } switch (pendingAction) { case COMPACT_PROCESS_SOME: action = mCompactActionSome; } else { break; // For the time being, treat these as equivalent. case COMPACT_PROCESS_FULL: case COMPACT_PROCESS_PERSISTENT: case COMPACT_PROCESS_BFGS: action = mCompactActionFull; break; default: action = COMPACT_ACTION_NONE; break; } if (action.equals(COMPACT_ACTION_NONE)) { if (COMPACT_ACTION_NONE.equals(action)) { return; } Loading Loading @@ -422,6 +508,13 @@ public final class AppCompactor { // nothing to do, presumably the process died Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } break; } case COMPACT_SYSTEM_MSG: { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "compactSystem"); compactSystem(); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; } } } Loading services/core/java/com/android/server/am/OomAdjuster.java +20 −3 Original line number Diff line number Diff line Loading @@ -1686,9 +1686,10 @@ public final class OomAdjuster { int changes = 0; if (app.curAdj != app.setAdj) { // don't compact during bootup if (mAppCompact.useCompaction() && mService.mBooted) { // Cached and prev/home compaction if (app.curAdj != app.setAdj) { // Perform a minor compaction when a perceptible app becomes the prev/home app // Perform a major compaction when any app enters cached // reminder: here, setAdj is previous state, curAdj is upcoming state Loading @@ -1702,7 +1703,23 @@ public final class OomAdjuster { && app.curAdj <= ProcessList.CACHED_APP_MAX_ADJ) { mAppCompact.compactAppFull(app); } } else if (mService.mWakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE && app.setAdj < ProcessList.FOREGROUND_APP_ADJ // Because these can fire independent of oom_adj/procstate changes, we need // to throttle the actual dispatch of these requests in addition to the // processing of the requests. As a result, there is throttling both here // and in AppCompactor. && mAppCompact.shouldCompactPersistent(app, now)) { mAppCompact.compactAppPersistent(app); } else if (mService.mWakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE && app.getCurProcState() == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE && mAppCompact.shouldCompactBFGS(app, now)) { mAppCompact.compactAppBfgs(app); } } if (app.curAdj != app.setAdj) { ProcessList.setOomAdj(app.pid, app.uid, app.curAdj); if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.info.uid) { String msg = "Set " + app.pid + " " + app.processName + " adj " Loading services/core/jni/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ cc_library_static { "com_android_server_VibratorService.cpp", "com_android_server_PersistentDataBlockService.cpp", "com_android_server_GraphicsStatsService.cpp", "com_android_server_am_AppCompactor.cpp", "onload.cpp", ], Loading services/core/jni/com_android_server_am_AppCompactor.cpp 0 → 100644 +88 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "AppCompactor" //#define LOG_NDEBUG 0 #include <dirent.h> #include <stddef.h> #include <stdio.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <android-base/stringprintf.h> #include <android-base/file.h> #include <nativehelper/JNIHelp.h> #include <android_runtime/AndroidRuntime.h> #include <jni.h> using android::base::StringPrintf; using android::base::WriteStringToFile; namespace android { // This performs per-process reclaim on all processes belonging to non-app UIDs. // For the most part, these are non-zygote processes like Treble HALs, but it // also includes zygote-derived processes that run in system UIDs, like bluetooth // or potentially some mainline modules. The only process that should definitely // not be compacted is system_server, since compacting system_server around the // time of BOOT_COMPLETE could result in perceptible issues. static void com_android_server_am_AppCompactor_compactSystem(JNIEnv *, jobject) { std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir); struct dirent* current; while ((current = readdir(proc.get()))) { if (current->d_type != DT_DIR) { continue; } // don't compact system_server, rely on persistent compaction during screen off // in order to avoid mmap_sem-related stalls if (atoi(current->d_name) == getpid()) { continue; } std::string status_name = StringPrintf("/proc/%s/status", current->d_name); struct stat status_info; if (stat(status_name.c_str(), &status_info) != 0) { // must be some other directory that isn't a pid continue; } // android.os.Process.FIRST_APPLICATION_UID if (status_info.st_uid >= 10000) { continue; } std::string reclaim_path = StringPrintf("/proc/%s/reclaim", current->d_name); WriteStringToFile(std::string("all"), reclaim_path); } } static const JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ {"compactSystem", "()V", (void*)com_android_server_am_AppCompactor_compactSystem}, }; int register_android_server_am_AppCompactor(JNIEnv* env) { return jniRegisterNativeMethods(env, "com/android/server/am/AppCompactor", sMethods, NELEM(sMethods)); } } Loading
services/core/java/com/android/server/am/ActivityManagerService.java +5 −0 Original line number Diff line number Diff line Loading @@ -5121,6 +5121,7 @@ public class ActivityManagerService extends IActivityManager.Stub String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { synchronized (ActivityManagerService.this) { mOomAdjuster.mAppCompact.compactAllSystem(); requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false); } } Loading Loading @@ -8614,6 +8615,10 @@ public class ActivityManagerService extends IActivityManager.Stub synchronized (this) { final long now = SystemClock.uptimeMillis(); final long timeSinceLastIdle = now - mLastIdleTime; // Compact all non-zygote processes to freshen up the page cache. mOomAdjuster.mAppCompact.compactAllSystem(); final long lowRamSinceLastIdle = getLowRamTimeSinceIdle(now); mLastIdleTime = now; mLowRamTimeSinceLastIdle = 0; Loading
services/core/java/com/android/server/am/AppCompactor.java +117 −24 Original line number Diff line number Diff line Loading @@ -51,6 +51,8 @@ public final class AppCompactor { @VisibleForTesting static final String KEY_COMPACT_THROTTLE_2 = "compact_throttle_2"; @VisibleForTesting static final String KEY_COMPACT_THROTTLE_3 = "compact_throttle_3"; @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_STATSD_SAMPLE_RATE = "compact_statsd_sample_rate"; Loading @@ -73,6 +75,8 @@ public final class AppCompactor { @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_2 = 10_000; @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_3 = 500; @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; // The sampling rate to push app compaction events into statsd for upload. @VisibleForTesting static final float DEFAULT_STATSD_SAMPLE_RATE = 0.1f; Loading @@ -85,7 +89,10 @@ public final class AppCompactor { // Handler constants. static final int COMPACT_PROCESS_SOME = 1; static final int COMPACT_PROCESS_FULL = 2; static final int COMPACT_PROCESS_PERSISTENT = 3; static final int COMPACT_PROCESS_BFGS = 4; static final int COMPACT_PROCESS_MSG = 1; static final int COMPACT_SYSTEM_MSG = 2; /** * This thread must be moved to the system background cpuset. Loading Loading @@ -142,6 +149,10 @@ public final class AppCompactor { @GuardedBy("mPhenotypeFlagLock") @VisibleForTesting volatile long mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4; @GuardedBy("mPhenotypeFlagLock") @VisibleForTesting volatile long mCompactThrottleBFGS = DEFAULT_COMPACT_THROTTLE_5; @GuardedBy("mPhenotypeFlagLock") @VisibleForTesting volatile long mCompactThrottlePersistent = DEFAULT_COMPACT_THROTTLE_6; @GuardedBy("mPhenotypeFlagLock") private volatile boolean mUseCompaction = DEFAULT_USE_COMPACTION; private final Random mRandom = new Random(); Loading Loading @@ -224,6 +235,46 @@ public final class AppCompactor { } @GuardedBy("mAm") void compactAppPersistent(ProcessRecord app) { app.reqCompactAction = COMPACT_PROCESS_PERSISTENT; mPendingCompactionProcesses.add(app); mCompactionHandler.sendMessage( mCompactionHandler.obtainMessage( COMPACT_PROCESS_MSG, app.curAdj, app.setProcState)); } @GuardedBy("mAm") boolean shouldCompactPersistent(ProcessRecord app, long now) { return (app.lastCompactTime == 0 || (now - app.lastCompactTime) > mCompactThrottlePersistent); } @GuardedBy("mAm") void compactAppBfgs(ProcessRecord app) { app.reqCompactAction = COMPACT_PROCESS_BFGS; mPendingCompactionProcesses.add(app); mCompactionHandler.sendMessage( mCompactionHandler.obtainMessage( COMPACT_PROCESS_MSG, app.curAdj, app.setProcState)); } @GuardedBy("mAm") boolean shouldCompactBFGS(ProcessRecord app, long now) { return (app.lastCompactTime == 0 || (now - app.lastCompactTime) > mCompactThrottleBFGS); } @GuardedBy("mAm") void compactAllSystem() { if (mUseCompaction) { mCompactionHandler.sendMessage(mCompactionHandler.obtainMessage( COMPACT_SYSTEM_MSG)); } } private native void compactSystem(); /** * Reads the flag value from DeviceConfig to determine whether app compaction * should be enabled, and starts/stops the compaction thread as needed. Loading Loading @@ -265,10 +316,18 @@ public final class AppCompactor { String throttleFullFullFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_4); String throttleBFGSFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_5); String throttlePersistentFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_6); if (TextUtils.isEmpty(throttleSomeSomeFlag) || TextUtils.isEmpty(throttleSomeFullFlag) || TextUtils.isEmpty(throttleFullSomeFlag) || TextUtils.isEmpty(throttleFullFullFlag)) { || TextUtils.isEmpty(throttleFullFullFlag) || TextUtils.isEmpty(throttleBFGSFlag) || TextUtils.isEmpty(throttlePersistentFlag)) { // Set defaults for all if any are not set. useThrottleDefaults = true; } else { Loading @@ -277,6 +336,8 @@ public final class AppCompactor { mCompactThrottleSomeFull = Integer.parseInt(throttleSomeFullFlag); mCompactThrottleFullSome = Integer.parseInt(throttleFullSomeFlag); mCompactThrottleFullFull = Integer.parseInt(throttleFullFullFlag); mCompactThrottleBFGS = Integer.parseInt(throttleBFGSFlag); mCompactThrottlePersistent = Integer.parseInt(throttlePersistentFlag); } catch (NumberFormatException e) { useThrottleDefaults = true; } Loading @@ -287,6 +348,8 @@ public final class AppCompactor { mCompactThrottleSomeFull = DEFAULT_COMPACT_THROTTLE_2; mCompactThrottleFullSome = DEFAULT_COMPACT_THROTTLE_3; mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4; mCompactThrottleBFGS = DEFAULT_COMPACT_THROTTLE_5; mCompactThrottlePersistent = DEFAULT_COMPACT_THROTTLE_6; } } Loading Loading @@ -332,14 +395,19 @@ public final class AppCompactor { synchronized (mAm) { proc = mPendingCompactionProcesses.remove(0); pendingAction = proc.reqCompactAction; // don't compact if the process has returned to perceptible if (proc.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) { // and this is only a cached/home/prev compaction if ((pendingAction == COMPACT_PROCESS_SOME || pendingAction == COMPACT_PROCESS_FULL) && (proc.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ)) { return; } pid = proc.pid; name = proc.processName; pendingAction = proc.reqCompactAction; lastCompactAction = proc.lastCompactAction; lastCompactTime = proc.lastCompactTime; } Loading @@ -356,6 +424,7 @@ public final class AppCompactor { // Note that we explicitly don't take mPhenotypeFlagLock here as the flags // should very seldom change, and taking the risk of using the wrong action is // preferable to taking the lock for every single compaction action. if (lastCompactTime != 0) { if (pendingAction == COMPACT_PROCESS_SOME) { if ((lastCompactAction == COMPACT_PROCESS_SOME && (start - lastCompactTime < mCompactThrottleSomeSome)) Loading @@ -364,7 +433,7 @@ public final class AppCompactor { < mCompactThrottleSomeFull))) { return; } } else { } else if (pendingAction == COMPACT_PROCESS_FULL) { if ((lastCompactAction == COMPACT_PROCESS_SOME && (start - lastCompactTime < mCompactThrottleFullSome)) || (lastCompactAction == COMPACT_PROCESS_FULL Loading @@ -372,15 +441,32 @@ public final class AppCompactor { < mCompactThrottleFullFull))) { return; } } else if (pendingAction == COMPACT_PROCESS_PERSISTENT) { if (start - lastCompactTime < mCompactThrottlePersistent) { return; } if (pendingAction == COMPACT_PROCESS_SOME) { } else if (pendingAction == COMPACT_PROCESS_BFGS) { if (start - lastCompactTime < mCompactThrottleBFGS) { return; } } } switch (pendingAction) { case COMPACT_PROCESS_SOME: action = mCompactActionSome; } else { break; // For the time being, treat these as equivalent. case COMPACT_PROCESS_FULL: case COMPACT_PROCESS_PERSISTENT: case COMPACT_PROCESS_BFGS: action = mCompactActionFull; break; default: action = COMPACT_ACTION_NONE; break; } if (action.equals(COMPACT_ACTION_NONE)) { if (COMPACT_ACTION_NONE.equals(action)) { return; } Loading Loading @@ -422,6 +508,13 @@ public final class AppCompactor { // nothing to do, presumably the process died Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } break; } case COMPACT_SYSTEM_MSG: { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "compactSystem"); compactSystem(); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; } } } Loading
services/core/java/com/android/server/am/OomAdjuster.java +20 −3 Original line number Diff line number Diff line Loading @@ -1686,9 +1686,10 @@ public final class OomAdjuster { int changes = 0; if (app.curAdj != app.setAdj) { // don't compact during bootup if (mAppCompact.useCompaction() && mService.mBooted) { // Cached and prev/home compaction if (app.curAdj != app.setAdj) { // Perform a minor compaction when a perceptible app becomes the prev/home app // Perform a major compaction when any app enters cached // reminder: here, setAdj is previous state, curAdj is upcoming state Loading @@ -1702,7 +1703,23 @@ public final class OomAdjuster { && app.curAdj <= ProcessList.CACHED_APP_MAX_ADJ) { mAppCompact.compactAppFull(app); } } else if (mService.mWakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE && app.setAdj < ProcessList.FOREGROUND_APP_ADJ // Because these can fire independent of oom_adj/procstate changes, we need // to throttle the actual dispatch of these requests in addition to the // processing of the requests. As a result, there is throttling both here // and in AppCompactor. && mAppCompact.shouldCompactPersistent(app, now)) { mAppCompact.compactAppPersistent(app); } else if (mService.mWakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE && app.getCurProcState() == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE && mAppCompact.shouldCompactBFGS(app, now)) { mAppCompact.compactAppBfgs(app); } } if (app.curAdj != app.setAdj) { ProcessList.setOomAdj(app.pid, app.uid, app.curAdj); if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.info.uid) { String msg = "Set " + app.pid + " " + app.processName + " adj " Loading
services/core/jni/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ cc_library_static { "com_android_server_VibratorService.cpp", "com_android_server_PersistentDataBlockService.cpp", "com_android_server_GraphicsStatsService.cpp", "com_android_server_am_AppCompactor.cpp", "onload.cpp", ], Loading
services/core/jni/com_android_server_am_AppCompactor.cpp 0 → 100644 +88 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "AppCompactor" //#define LOG_NDEBUG 0 #include <dirent.h> #include <stddef.h> #include <stdio.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <android-base/stringprintf.h> #include <android-base/file.h> #include <nativehelper/JNIHelp.h> #include <android_runtime/AndroidRuntime.h> #include <jni.h> using android::base::StringPrintf; using android::base::WriteStringToFile; namespace android { // This performs per-process reclaim on all processes belonging to non-app UIDs. // For the most part, these are non-zygote processes like Treble HALs, but it // also includes zygote-derived processes that run in system UIDs, like bluetooth // or potentially some mainline modules. The only process that should definitely // not be compacted is system_server, since compacting system_server around the // time of BOOT_COMPLETE could result in perceptible issues. static void com_android_server_am_AppCompactor_compactSystem(JNIEnv *, jobject) { std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir); struct dirent* current; while ((current = readdir(proc.get()))) { if (current->d_type != DT_DIR) { continue; } // don't compact system_server, rely on persistent compaction during screen off // in order to avoid mmap_sem-related stalls if (atoi(current->d_name) == getpid()) { continue; } std::string status_name = StringPrintf("/proc/%s/status", current->d_name); struct stat status_info; if (stat(status_name.c_str(), &status_info) != 0) { // must be some other directory that isn't a pid continue; } // android.os.Process.FIRST_APPLICATION_UID if (status_info.st_uid >= 10000) { continue; } std::string reclaim_path = StringPrintf("/proc/%s/reclaim", current->d_name); WriteStringToFile(std::string("all"), reclaim_path); } } static const JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ {"compactSystem", "()V", (void*)com_android_server_am_AppCompactor_compactSystem}, }; int register_android_server_am_AppCompactor(JNIEnv* env) { return jniRegisterNativeMethods(env, "com/android/server/am/AppCompactor", sMethods, NELEM(sMethods)); } }