Merge "Apply correct memory trim levels for processes in LRU list"

This commit is contained in:
Jing Ji
2020-10-27 19:51:00 +00:00
committed by Android (Google) Code Review
4 changed files with 165 additions and 25 deletions

View File

@@ -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,

View File

@@ -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, "");
}

View File

@@ -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")
@@ -867,6 +876,11 @@ public class AppProfiler {
mAllowLowerMemLevel = allowLowerMemLevel;
}
@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();
@@ -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:

View File

@@ -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;
}