diff options
| author | 2020-10-27 19:51:00 +0000 | |
|---|---|---|
| committer | 2020-10-27 19:51:00 +0000 | |
| commit | 03bcb30a6f6d96fa577a32df04531ff2c93a04e9 (patch) | |
| tree | fe9bb578094660d0b22c611958ffe3623942c0b3 | |
| parent | c95fd08136b95cadc83031dad20fadf262fb8dd6 (diff) | |
| parent | 1ad98565974235219fd73a42a835779a0e931c21 (diff) | |
Merge "Apply correct memory trim levels for processes in LRU list"
4 files changed, 165 insertions, 25 deletions
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 50c992c1eb16..112814c69d9b 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -340,6 +340,7 @@ import com.android.server.SystemServiceManager; import com.android.server.ThreadPriorityBooster; import com.android.server.UserspaceRebootLogger; import com.android.server.Watchdog; +import com.android.server.am.LowMemDetector.MemFactor; import com.android.server.appop.AppOpsService; import com.android.server.compat.PlatformCompat; import com.android.server.contentcapture.ContentCaptureManagerInternal; @@ -8224,13 +8225,25 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public int getMemoryTrimLevel() { + public @MemFactor int getMemoryTrimLevel() { enforceNotIsolatedCaller("getMyMemoryState"); synchronized (this) { return mAppProfiler.getLastMemoryLevelLocked(); } } + void setMemFactorOverride(@MemFactor int level) { + synchronized (this) { + if (level == mAppProfiler.getLastMemoryLevelLocked()) { + return; + } + + mAppProfiler.setMemFactorOverrideLocked(level); + // Kick off an oom adj update since we forced a mem factor update. + updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE); + } + } + @Override public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 31e7106979f1..e3c071fe10e2 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -25,6 +25,12 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.Display.INVALID_DISPLAY; +import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_CRITICAL; +import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_LOW; +import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_MODERATE; +import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_NORMAL; +import static com.android.server.am.LowMemDetector.ADJ_MEM_FACTOR_NOTHING; + import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.ActivityTaskManager; @@ -92,6 +98,7 @@ import android.view.Display; import com.android.internal.compat.CompatibilityChangeConfig; import com.android.internal.util.HexDump; import com.android.internal.util.MemInfoReader; +import com.android.server.am.LowMemDetector.MemFactor; import com.android.server.compat.PlatformCompat; import java.io.BufferedReader; @@ -309,6 +316,8 @@ final class ActivityManagerShellCommand extends ShellCommand { return runCompat(pw); case "refresh-settings-cache": return runRefreshSettingsCache(); + case "memory-factor": + return runMemoryFactor(pw); default: return handleDefaultCommands(cmd); } @@ -3014,6 +3023,81 @@ final class ActivityManagerShellCommand extends ShellCommand { return -1; } + private int runSetMemoryFactor(PrintWriter pw) throws RemoteException { + final String levelArg = getNextArgRequired(); + @MemFactor int level = ADJ_MEM_FACTOR_NOTHING; + switch (levelArg) { + case "NORMAL": + level = ADJ_MEM_FACTOR_NORMAL; + break; + case "MODERATE": + level = ADJ_MEM_FACTOR_MODERATE; + break; + case "LOW": + level = ADJ_MEM_FACTOR_LOW; + break; + case "CRITICAL": + level = ADJ_MEM_FACTOR_CRITICAL; + break; + default: + try { + level = Integer.parseInt(levelArg); + } catch (NumberFormatException e) { + } + if (level < ADJ_MEM_FACTOR_NORMAL || level > ADJ_MEM_FACTOR_CRITICAL) { + getErrPrintWriter().println("Error: Unknown level option: " + levelArg); + return -1; + } + } + mInternal.setMemFactorOverride(level); + return 0; + } + + private int runShowMemoryFactor(PrintWriter pw) throws RemoteException { + final @MemFactor int level = mInternal.getMemoryTrimLevel(); + switch (level) { + case ADJ_MEM_FACTOR_NOTHING: + pw.println("<UNKNOWN>"); + break; + case ADJ_MEM_FACTOR_NORMAL: + pw.println("NORMAL"); + break; + case ADJ_MEM_FACTOR_MODERATE: + pw.println("MODERATE"); + break; + case ADJ_MEM_FACTOR_LOW: + pw.println("LOW"); + break; + case ADJ_MEM_FACTOR_CRITICAL: + pw.println("CRITICAL"); + break; + } + pw.flush(); + return 0; + } + + private int runResetMemoryFactor(PrintWriter pw) throws RemoteException { + mInternal.setMemFactorOverride(ADJ_MEM_FACTOR_NOTHING); + return 0; + } + + private int runMemoryFactor(PrintWriter pw) throws RemoteException { + mInternal.enforceCallingPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS, + "runMemoryFactor()"); + + final String op = getNextArgRequired(); + switch (op) { + case "set": + return runSetMemoryFactor(pw); + case "show": + return runShowMemoryFactor(pw); + case "reset": + return runResetMemoryFactor(pw); + default: + getErrPrintWriter().println("Error: unknown command '" + op + "'"); + return -1; + } + } private Resources getResources(PrintWriter pw) throws RemoteException { // system resources does not contain all the device configuration, construct it manually. @@ -3334,6 +3418,13 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println(" Removes all existing overrides for all changes for "); pw.println(" <PACKAGE_NAME> (back to default behaviour)."); pw.println(" It kills <PACKAGE_NAME> (to allow the toggle to take effect)."); + pw.println(" memory-factor [command] [...]: sub-commands for overriding memory pressure factor"); + pw.println(" set <NORMAL|MODERATE|LOW|CRITICAL>"); + pw.println(" Overrides memory pressure factor. May also supply a raw int level"); + pw.println(" show"); + pw.println(" Shows the existing memory pressure factor"); + pw.println(" reset"); + pw.println(" Removes existing override for memory pressure factor"); pw.println(); Intent.printIntentArgsHelp(pw, ""); } diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java index 31ffb35f24b3..5e59a35fc4ee 100644 --- a/services/core/java/com/android/server/am/AppProfiler.java +++ b/services/core/java/com/android/server/am/AppProfiler.java @@ -20,11 +20,16 @@ import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL; import static android.os.Process.FIRST_APPLICATION_UID; +import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_CRITICAL; +import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_LOW; +import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_MODERATE; +import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_NORMAL; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PSS; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PSS; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.am.LowMemDetector.ADJ_MEM_FACTOR_NOTHING; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; import android.annotation.BroadcastBehavior; @@ -72,6 +77,7 @@ import com.android.internal.os.ProcessCpuTracker; import com.android.internal.util.DumpUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.MemInfoReader; +import com.android.server.am.LowMemDetector.MemFactor; import com.android.server.am.ProcessList.ProcStateMemTracker; import com.android.server.utils.PriorityDump; @@ -202,7 +208,10 @@ public class AppProfiler { * processes are going away for other reasons. */ @GuardedBy("mService") - private int mLastMemoryLevel = ProcessStats.ADJ_MEM_FACTOR_NORMAL; + private @MemFactor int mLastMemoryLevel = ADJ_MEM_FACTOR_NORMAL; + + @GuardedBy("mService") + private @MemFactor int mMemFactorOverride = ADJ_MEM_FACTOR_NOTHING; /** * The last total number of process we have, to determine if changes actually look @@ -851,7 +860,7 @@ public class AppProfiler { @GuardedBy("mService") boolean isLastMemoryLevelNormal() { - return mLastMemoryLevel <= ProcessStats.ADJ_MEM_FACTOR_NORMAL; + return mLastMemoryLevel <= ADJ_MEM_FACTOR_NORMAL; } @GuardedBy("mService") @@ -868,6 +877,11 @@ public class AppProfiler { } @GuardedBy("mService") + void setMemFactorOverrideLocked(@MemFactor int factor) { + mMemFactorOverride = factor; + } + + @GuardedBy("mService") boolean updateLowMemStateLocked(int numCached, int numEmpty, int numTrimming) { final int numOfLru = mService.mProcessList.getLruSizeLocked(); final long now = SystemClock.uptimeMillis(); @@ -885,28 +899,32 @@ public class AppProfiler { && numEmpty <= mService.mConstants.CUR_TRIM_EMPTY_PROCESSES) { final int numCachedAndEmpty = numCached + numEmpty; if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) { - memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL; + memFactor = ADJ_MEM_FACTOR_CRITICAL; } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) { - memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW; + memFactor = ADJ_MEM_FACTOR_LOW; } else { - memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE; + memFactor = ADJ_MEM_FACTOR_MODERATE; } } else { - memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL; + memFactor = ADJ_MEM_FACTOR_NORMAL; } } // We always allow the memory level to go up (better). We only allow it to go // down if we are in a state where that is allowed, *and* the total number of processes // has gone down since last time. if (DEBUG_OOM_ADJ) { - Slog.d(TAG_OOM_ADJ, "oom: memFactor=" + memFactor + Slog.d(TAG_OOM_ADJ, "oom: memFactor=" + memFactor + " override=" + mMemFactorOverride + " last=" + mLastMemoryLevel + " allowLow=" + mAllowLowerMemLevel + " numProcs=" + mService.mProcessList.getLruSizeLocked() + " last=" + mLastNumProcesses); } + boolean override; + if (override = (mMemFactorOverride != ADJ_MEM_FACTOR_NOTHING)) { + memFactor = mMemFactorOverride; + } if (memFactor > mLastMemoryLevel) { - if (!mAllowLowerMemLevel - || mService.mProcessList.getLruSizeLocked() >= mLastNumProcesses) { + if (!override && (!mAllowLowerMemLevel + || mService.mProcessList.getLruSizeLocked() >= mLastNumProcesses)) { memFactor = mLastMemoryLevel; if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "Keeping last mem factor!"); } @@ -924,17 +942,17 @@ public class AppProfiler { mService.mAtmInternal == null || !mService.mAtmInternal.isSleeping(), now); trackerMemFactor = mService.mProcessStats.getMemFactorLocked(); } - if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) { + if (memFactor != ADJ_MEM_FACTOR_NORMAL) { if (mLowRamStartTime == 0) { mLowRamStartTime = now; } int step = 0; int fgTrimLevel; switch (memFactor) { - case ProcessStats.ADJ_MEM_FACTOR_CRITICAL: + case ADJ_MEM_FACTOR_CRITICAL: fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL; break; - case ProcessStats.ADJ_MEM_FACTOR_LOW: + case ADJ_MEM_FACTOR_LOW: fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW; break; default: @@ -947,7 +965,7 @@ public class AppProfiler { if (mService.mAtmInternal.getPreviousProcess() != null) minFactor++; if (factor < minFactor) factor = minFactor; int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE; - for (int i = numOfLru - 1; i >= 0; i--) { + for (int i = 0; i < numOfLru; i++) { ProcessRecord app = mService.mProcessList.mLruProcesses.get(i); if (allChanged || app.procStateChanged) { mService.setProcessTrackerStateLocked(app, trackerMemFactor, now); @@ -1032,7 +1050,7 @@ public class AppProfiler { mLowRamTimeSinceLastIdle += now - mLowRamStartTime; mLowRamStartTime = 0; } - for (int i = numOfLru - 1; i >= 0; i--) { + for (int i = 0; i < numOfLru; i++) { ProcessRecord app = mService.mProcessList.mLruProcesses.get(i); if (allChanged || app.procStateChanged) { mService.setProcessTrackerStateLocked(app, trackerMemFactor, now); @@ -1622,16 +1640,16 @@ public class AppProfiler { @GuardedBy("mService") void dumpLastMemoryLevelLocked(PrintWriter pw) { switch (mLastMemoryLevel) { - case ProcessStats.ADJ_MEM_FACTOR_NORMAL: + case ADJ_MEM_FACTOR_NORMAL: pw.println("normal)"); break; - case ProcessStats.ADJ_MEM_FACTOR_MODERATE: + case ADJ_MEM_FACTOR_MODERATE: pw.println("moderate)"); break; - case ProcessStats.ADJ_MEM_FACTOR_LOW: + case ADJ_MEM_FACTOR_LOW: pw.println("low)"); break; - case ProcessStats.ADJ_MEM_FACTOR_CRITICAL: + case ADJ_MEM_FACTOR_CRITICAL: pw.println("critical)"); break; default: diff --git a/services/core/java/com/android/server/am/LowMemDetector.java b/services/core/java/com/android/server/am/LowMemDetector.java index e82a207cdd59..8f791331f0cf 100644 --- a/services/core/java/com/android/server/am/LowMemDetector.java +++ b/services/core/java/com/android/server/am/LowMemDetector.java @@ -16,8 +16,19 @@ package com.android.server.am; +import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_CRITICAL; +import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_LOW; +import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_MODERATE; +import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_NORMAL; +import static com.android.internal.app.procstats.ProcessStats.ADJ_NOTHING; + +import android.annotation.IntDef; + import com.android.internal.annotations.GuardedBy; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Detects low memory using PSI. * @@ -32,13 +43,20 @@ public final class LowMemDetector { private final Object mPressureStateLock = new Object(); @GuardedBy("mPressureStateLock") - private int mPressureState = MEM_PRESSURE_NONE; + private int mPressureState = ADJ_MEM_FACTOR_NORMAL; + + public static final int ADJ_MEM_FACTOR_NOTHING = ADJ_NOTHING; /* getPressureState return values */ - public static final int MEM_PRESSURE_NONE = 0; - public static final int MEM_PRESSURE_LOW = 1; - public static final int MEM_PRESSURE_MEDIUM = 2; - public static final int MEM_PRESSURE_HIGH = 3; + @IntDef(prefix = { "ADJ_MEM_FACTOR_" }, value = { + ADJ_MEM_FACTOR_NOTHING, + ADJ_MEM_FACTOR_NORMAL, + ADJ_MEM_FACTOR_MODERATE, + ADJ_MEM_FACTOR_LOW, + ADJ_MEM_FACTOR_CRITICAL, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface MemFactor{} LowMemDetector(ActivityManagerService am) { mAm = am; @@ -62,7 +80,7 @@ public final class LowMemDetector { * there should be conversion performed here to translate pressure state * into memFactor. */ - public int getMemFactor() { + public @MemFactor int getMemFactor() { synchronized (mPressureStateLock) { return mPressureState; } |