diff options
4 files changed, 105 insertions, 3 deletions
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index 26aa0535d43e..2c048831ccab 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -169,6 +169,11 @@ final class ActivityManagerConstants extends ContentObserver { */ static final String KEY_ENABLE_NEW_OOMADJ = "enable_new_oom_adj"; + /** + * Whether or not to enable the batching of OOM adjuster calls to LMKD + */ + static final String KEY_ENABLE_BATCHING_OOM_ADJ = "enable_batching_oom_adj"; + private static final int DEFAULT_MAX_CACHED_PROCESSES = 1024; private static final boolean DEFAULT_PRIORITIZE_ALARM_BROADCASTS = true; private static final long DEFAULT_FGSERVICE_MIN_SHOWN_TIME = 2*1000; @@ -244,6 +249,11 @@ final class ActivityManagerConstants extends ContentObserver { private static final boolean DEFAULT_ENABLE_NEW_OOM_ADJ = Flags.oomadjusterCorrectnessRewrite(); /** + * The default value to {@link #KEY_ENABLE_BATCHING_OOM_ADJ}. + */ + private static final boolean DEFAULT_ENABLE_BATCHING_OOM_ADJ = Flags.batchingOomAdj(); + + /** * Same as {@link TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED} */ private static final int @@ -1136,6 +1146,9 @@ final class ActivityManagerConstants extends ContentObserver { /** @see #KEY_ENABLE_NEW_OOMADJ */ public boolean ENABLE_NEW_OOMADJ = DEFAULT_ENABLE_NEW_OOM_ADJ; + /** @see #KEY_ENABLE_BATCHING_OOM_ADJ */ + public boolean ENABLE_BATCHING_OOM_ADJ = DEFAULT_ENABLE_BATCHING_OOM_ADJ; + /** * Indicates whether PSS profiling in AppProfiler is disabled or not. */ @@ -1479,6 +1492,8 @@ final class ActivityManagerConstants extends ContentObserver { private void loadNativeBootDeviceConfigConstants() { ENABLE_NEW_OOMADJ = getDeviceConfigBoolean(KEY_ENABLE_NEW_OOMADJ, DEFAULT_ENABLE_NEW_OOM_ADJ); + ENABLE_BATCHING_OOM_ADJ = getDeviceConfigBoolean(KEY_ENABLE_BATCHING_OOM_ADJ, + DEFAULT_ENABLE_BATCHING_OOM_ADJ); } public void setOverrideMaxCachedProcesses(int value) { @@ -2248,6 +2263,13 @@ final class ActivityManagerConstants extends ContentObserver { mDefaultPssToRssThresholdModifier); } + private void updateEnableBatchingOomAdj() { + ENABLE_BATCHING_OOM_ADJ = DeviceConfig.getBoolean( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT, + KEY_ENABLE_BATCHING_OOM_ADJ, + DEFAULT_ENABLE_BATCHING_OOM_ADJ); + } + boolean shouldDebugUidForProcState(int uid) { SparseBooleanArray ar = mProcStateDebugUids; final var size = ar.size(); @@ -2476,6 +2498,9 @@ final class ActivityManagerConstants extends ContentObserver { pw.print(" "); pw.print(KEY_MAX_PREVIOUS_TIME); pw.print("="); pw.println(MAX_PREVIOUS_TIME); + pw.print(" "); pw.print(KEY_ENABLE_BATCHING_OOM_ADJ); + pw.print("="); pw.println(ENABLE_BATCHING_OOM_ADJ); + pw.println(); if (mOverrideMaxCachedProcesses >= 0) { pw.print(" mOverrideMaxCachedProcesses="); pw.println(mOverrideMaxCachedProcesses); diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index ab34dd4477fd..fc81d3e8c1b6 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -384,6 +384,13 @@ public class OomAdjuster { protected final ArraySet<ProcessRecord> mProcessesInCycle = new ArraySet<>(); /** + * List of processes that we want to batch for LMKD to adjust their respective + * OOM scores. + */ + @GuardedBy("mService") + protected final ArrayList<ProcessRecord> mProcsToOomAdj = new ArrayList<ProcessRecord>(); + + /** * Flag to mark if there is an ongoing oomAdjUpdate: potentially the oomAdjUpdate * could be called recursively because of the indirect calls during the update; * however the oomAdjUpdate itself doesn't support recursion - in this case we'd @@ -1246,7 +1253,7 @@ public class OomAdjuster { if (!app.isKilledByAm() && app.getThread() != null) { // We don't need to apply the update for the process which didn't get computed if (state.getCompletedAdjSeq() == mAdjSeq) { - applyOomAdjLSP(app, doingAll, now, nowElapsed, oomAdjReason); + applyOomAdjLSP(app, doingAll, now, nowElapsed, oomAdjReason, true); } if (app.isPendingFinishAttach()) { @@ -1348,6 +1355,11 @@ public class OomAdjuster { } } + if (!mProcsToOomAdj.isEmpty()) { + ProcessList.batchSetOomAdj(mProcsToOomAdj); + mProcsToOomAdj.clear(); + } + if (proactiveKillsEnabled // Proactive kills enabled? && doKillExcessiveProcesses // Should kill excessive processes? && freeSwapPercent < lowSwapThresholdPercent // Swap below threshold? @@ -3246,10 +3258,16 @@ public class OomAdjuster { mCachedAppOptimizer.onWakefulnessChanged(wakefulness); } + @GuardedBy({"mService", "mProcLock"}) + protected boolean applyOomAdjLSP(ProcessRecord app, boolean doingAll, long now, + long nowElapsed, @OomAdjReason int oomAdjReason) { + return applyOomAdjLSP(app, doingAll, now, nowElapsed, oomAdjReason, false); + } + /** Applies the computed oomadj, procstate and sched group values and freezes them in set* */ @GuardedBy({"mService", "mProcLock"}) protected boolean applyOomAdjLSP(ProcessRecord app, boolean doingAll, long now, - long nowElapsed, @OomAdjReason int oomAdjReson) { + long nowElapsed, @OomAdjReason int oomAdjReson, boolean isBatchingOomAdj) { boolean success = true; final ProcessStateRecord state = app.mState; final UidRecord uidRec = app.getUidRecord(); @@ -3266,7 +3284,12 @@ public class OomAdjuster { final int oldOomAdj = state.getSetAdj(); if (state.getCurAdj() != state.getSetAdj()) { - ProcessList.setOomAdj(app.getPid(), app.uid, state.getCurAdj()); + if (isBatchingOomAdj && mConstants.ENABLE_BATCHING_OOM_ADJ) { + mProcsToOomAdj.add(app); + } else { + ProcessList.setOomAdj(app.getPid(), app.uid, state.getCurAdj()); + } + if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.info.uid) { String msg = "Set " + app.getPid() + " " + app.processName + " adj " + state.getCurAdj() + ": " + state.getAdjType(); diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 219de709fb70..c0947247de4b 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -354,6 +354,7 @@ public final class ProcessList { // LMK_KILL_OCCURRED // LMK_START_MONITORING // LMK_BOOT_COMPLETED + // LMK_PROCS_PRIO static final byte LMK_TARGET = 0; static final byte LMK_PROCPRIO = 1; static final byte LMK_PROCREMOVE = 2; @@ -365,6 +366,7 @@ public final class ProcessList { static final byte LMK_KILL_OCCURRED = 8; // Msg to subscribed clients on kill occurred event static final byte LMK_START_MONITORING = 9; // Start monitoring if delayed earlier static final byte LMK_BOOT_COMPLETED = 10; + static final byte LMK_PROCS_PRIO = 11; // Batch option for LMK_PROCPRIO // Low Memory Killer Daemon command codes. // These must be kept in sync with async_event_type definitions in lmkd.h @@ -1561,6 +1563,50 @@ public final class ProcessList { } } + + // The max size for PROCS_PRIO cmd in LMKD + private static final int MAX_PROCS_PRIO_PACKET_SIZE = 3; + + // (4 bytes per field * 4 fields * 3 processes per batch) + 4 bytes for the LMKD cmd + private static final int MAX_OOM_ADJ_BATCH_LENGTH = ((4 * 4) * MAX_PROCS_PRIO_PACKET_SIZE) + 4; + + /** + * Set the out-of-memory badness adjustment for a list of processes. + * + * @param apps App list to adjust their respective oom score. + * + * {@hide} + */ + public static void batchSetOomAdj(ArrayList<ProcessRecord> apps) { + final int totalApps = apps.size(); + if (totalApps == 0) { + return; + } + + ByteBuffer buf = ByteBuffer.allocate(MAX_OOM_ADJ_BATCH_LENGTH); + int total_procs_in_buf = 0; + buf.putInt(LMK_PROCS_PRIO); + for (int i = 0; i < totalApps; i++) { + final int pid = apps.get(i).getPid(); + final int amt = apps.get(i).mState.getCurAdj(); + final int uid = apps.get(i).uid; + if (pid <= 0 || amt == UNKNOWN_ADJ) continue; + if (total_procs_in_buf >= MAX_PROCS_PRIO_PACKET_SIZE) { + writeLmkd(buf, null); + buf.clear(); + total_procs_in_buf = 0; + buf.allocate(MAX_OOM_ADJ_BATCH_LENGTH); + buf.putInt(LMK_PROCS_PRIO); + } + buf.putInt(pid); + buf.putInt(uid); + buf.putInt(amt); + buf.putInt(0); // Default proc type to PROC_TYPE_APP + total_procs_in_buf++; + } + writeLmkd(buf, null); + } + /* * {@hide} */ diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig index afde4f71a95f..2abfad90ee0b 100644 --- a/services/core/java/com/android/server/am/flags.aconfig +++ b/services/core/java/com/android/server/am/flags.aconfig @@ -134,3 +134,11 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "batching_oom_adj" + namespace: "backstage_power" + description: "Batch OOM adjustment calls to LMKD" + bug: "244232958" + is_fixed_read_only: true +} |