summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Michael Wachenschwanz <mwachens@google.com> 2024-11-06 21:09:49 +0000
committer Michael Wachenschwanz <mwachens@google.com> 2024-11-07 11:46:00 -0800
commit26a8abbd0a3527c009ab437c7e6fd9b7932d0118 (patch)
tree44a27b51f0c20d32a9031f2a7f1118df9c5d723f
parent6349ad595039ec4cb2fefa367031d72ee7da5130 (diff)
Revert^2 "OomAdjuster Freeze Handling with CPU capability"
This reverts commit 58093e8be25c5bf023998d44d9de5fcbdc38a0dc. Reason for revert: Re-land CL with test fix Change-Id: I583cc22d890f202e644b84653bfbefb4ba4f444e
-rw-r--r--core/java/android/app/ActivityManager.java11
-rw-r--r--services/core/java/com/android/server/am/CachedAppOptimizer.java2
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java204
-rw-r--r--services/core/java/com/android/server/am/OomAdjusterModernImpl.java5
-rw-r--r--services/core/java/com/android/server/am/ProcessServiceRecord.java10
-rw-r--r--services/core/java/com/android/server/am/ProcessStateController.java25
-rw-r--r--services/core/java/com/android/server/am/flags.aconfig7
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java72
8 files changed, 271 insertions, 65 deletions
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index b447897733e1..1b707f79ab81 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1017,6 +1017,12 @@ public class ActivityManager {
public static final int PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL = 1 << 6;
/**
+ * @hide
+ * Process is guaranteed cpu time (IE. it will not be frozen).
+ */
+ public static final int PROCESS_CAPABILITY_CPU_TIME = 1 << 7;
+
+ /**
* @hide all capabilities, the ORing of all flags in {@link ProcessCapability}.
*
* Don't expose it as TestApi -- we may add new capabilities any time, which could
@@ -1028,7 +1034,8 @@ public class ActivityManager {
| PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK
| PROCESS_CAPABILITY_BFSL
| PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK
- | PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL;
+ | PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL
+ | PROCESS_CAPABILITY_CPU_TIME;
/**
* All implicit capabilities. This capability set is currently only used for processes under
@@ -1053,6 +1060,7 @@ public class ActivityManager {
pw.print((caps & PROCESS_CAPABILITY_BFSL) != 0 ? 'F' : '-');
pw.print((caps & PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK) != 0 ? 'U' : '-');
pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL) != 0 ? 'A' : '-');
+ pw.print((caps & PROCESS_CAPABILITY_CPU_TIME) != 0 ? 'T' : '-');
}
/** @hide */
@@ -1065,6 +1073,7 @@ public class ActivityManager {
sb.append((caps & PROCESS_CAPABILITY_BFSL) != 0 ? 'F' : '-');
sb.append((caps & PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK) != 0 ? 'U' : '-');
sb.append((caps & PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL) != 0 ? 'A' : '-');
+ sb.append((caps & PROCESS_CAPABILITY_CPU_TIME) != 0 ? 'T' : '-');
}
/**
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 416c11090515..da5b1fd1c079 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -101,7 +101,7 @@ import java.util.Random;
import java.util.Set;
import java.util.concurrent.Executor;
-public final class CachedAppOptimizer {
+public class CachedAppOptimizer {
// Flags stored in the DeviceConfig API.
@VisibleForTesting static final String KEY_USE_COMPACTION = "use_compaction";
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index c0676623a1e9..b84bf6b90711 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -19,6 +19,7 @@ package com.android.server.am;
import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL_IMPLICIT;
import static android.app.ActivityManager.PROCESS_CAPABILITY_BFSL;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_CPU_TIME;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
@@ -155,6 +156,7 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
+import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
@@ -469,7 +471,6 @@ public class OomAdjuster {
}
Process.setThreadPriority(tid, priority);
}
-
}
// TODO(b/346822474): hook up global state usage.
@@ -499,7 +500,8 @@ public class OomAdjuster {
}
OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids,
- ServiceThread adjusterThread, GlobalState globalState, Injector injector) {
+ ServiceThread adjusterThread, GlobalState globalState,
+ CachedAppOptimizer cachedAppOptimizer, Injector injector) {
mService = service;
mGlobalState = globalState;
mInjector = injector;
@@ -508,7 +510,7 @@ public class OomAdjuster {
mActiveUids = activeUids;
mConstants = mService.mConstants;
- mCachedAppOptimizer = new CachedAppOptimizer(mService);
+ mCachedAppOptimizer = cachedAppOptimizer;
mCacheOomRanker = new CacheOomRanker(service);
mLogger = new OomAdjusterDebugLogger(this, mService.mConstants);
@@ -2597,6 +2599,7 @@ public class OomAdjuster {
}
capability |= getDefaultCapability(app, procState);
+ capability |= getCpuCapability(app, now);
// Procstates below BFGS should never have this capability.
if (procState > PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
@@ -2739,8 +2742,12 @@ public class OomAdjuster {
if (app.mOptRecord.setShouldNotFreeze(true, dryRun,
app.mOptRecord.shouldNotFreezeReason()
| client.mOptRecord.shouldNotFreezeReason(), mAdjSeq)) {
- // Bail out early, as we only care about the return value for a dryrun.
- return true;
+ if (Flags.useCpuTimeCapability()) {
+ // Do nothing, capability updated check will handle the dryrun output.
+ } else {
+ // Bail out early, as we only care about the return value for a dryrun.
+ return true;
+ }
}
}
@@ -2751,6 +2758,8 @@ public class OomAdjuster {
// we check the final procstate, and remove it if the procsate is below BFGS.
capability |= getBfslCapabilityFromClient(client);
+ capability |= getCpuCapabilityFromClient(client);
+
if (cr.notHasFlag(Context.BIND_WAIVE_PRIORITY)) {
if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
capability |= cstate.getCurCapability();
@@ -2809,9 +2818,14 @@ public class OomAdjuster {
app.mOptRecord.shouldNotFreezeReason()
| ProcessCachedOptimizerRecord
.SHOULD_NOT_FREEZE_REASON_BINDER_ALLOW_OOM_MANAGEMENT, mAdjSeq)) {
- // Bail out early, as we only care about the return value for a dryrun.
- return true;
+ if (Flags.useCpuTimeCapability()) {
+ // Do nothing, capability updated check will handle the dryrun output.
+ } else {
+ // Bail out early, as we only care about the return value for a dryrun.
+ return true;
+ }
}
+ capability |= PROCESS_CAPABILITY_CPU_TIME;
}
// Not doing bind OOM management, so treat
// this guy more like a started service.
@@ -3053,9 +3067,14 @@ public class OomAdjuster {
app.mOptRecord.shouldNotFreezeReason()
| ProcessCachedOptimizerRecord
.SHOULD_NOT_FREEZE_REASON_BIND_WAIVE_PRIORITY, mAdjSeq)) {
- // Bail out early, as we only care about the return value for a dryrun.
- return true;
+ if (Flags.useCpuTimeCapability()) {
+ // Do nothing, capability updated check will handle the dryrun output.
+ } else {
+ // Bail out early, as we only care about the return value for a dryrun.
+ return true;
+ }
}
+ capability |= PROCESS_CAPABILITY_CPU_TIME;
}
}
if (cr.hasFlag(Context.BIND_TREAT_LIKE_ACTIVITY)) {
@@ -3108,9 +3127,24 @@ public class OomAdjuster {
capability &= ~PROCESS_CAPABILITY_BFSL;
}
if (!updated) {
- updated = adj < prevRawAdj || procState < prevProcState || schedGroup > prevSchedGroup
- || (capability != prevCapability
- && (capability & prevCapability) == prevCapability);
+ if (adj < prevRawAdj || procState < prevProcState || schedGroup > prevSchedGroup) {
+ updated = true;
+ }
+
+ if (Flags.useCpuTimeCapability()) {
+ if ((capability != prevCapability)
+ && ((capability & prevCapability) == prevCapability)) {
+ updated = true;
+ }
+ } else {
+ // Ignore PROCESS_CAPABILITY_CPU_TIME in capability comparison
+ final int curFiltered = capability & ~PROCESS_CAPABILITY_CPU_TIME;
+ final int prevFiltered = prevCapability & ~PROCESS_CAPABILITY_CPU_TIME;
+ if ((curFiltered != prevFiltered)
+ && ((curFiltered & prevFiltered) == prevFiltered)) {
+ updated = true;
+ }
+ }
}
if (dryRun) {
@@ -3186,6 +3220,8 @@ public class OomAdjuster {
// we check the final procstate, and remove it if the procsate is below BFGS.
capability |= getBfslCapabilityFromClient(client);
+ capability |= getCpuCapabilityFromClient(client);
+
if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
// If the other app is cached for any reason, for purposes here
// we are going to consider it empty.
@@ -3196,8 +3232,12 @@ public class OomAdjuster {
if (app.mOptRecord.setShouldNotFreeze(true, dryRun,
app.mOptRecord.shouldNotFreezeReason()
| client.mOptRecord.shouldNotFreezeReason(), mAdjSeq)) {
- // Bail out early, as we only care about the return value for a dryrun.
- return true;
+ if (Flags.useCpuTimeCapability()) {
+ // Do nothing, capability updated check will handle the dryrun output.
+ } else {
+ // Bail out early, as we only care about the return value for a dryrun.
+ return true;
+ }
}
}
@@ -3273,10 +3313,25 @@ public class OomAdjuster {
capability &= ~PROCESS_CAPABILITY_BFSL;
}
- if (dryRun && (adj < prevRawAdj || procState < prevProcState || schedGroup > prevSchedGroup
- || (capability != prevCapability
- && (capability & prevCapability) == prevCapability))) {
- return true;
+ if (dryRun) {
+ if (adj < prevRawAdj || procState < prevProcState || schedGroup > prevSchedGroup) {
+ return true;
+ }
+
+ if (Flags.useCpuTimeCapability()) {
+ if ((capability != prevCapability)
+ && ((capability & prevCapability) == prevCapability)) {
+ return true;
+ }
+ } else {
+ // Ignore PROCESS_CAPABILITY_CPU_TIME in capability comparison
+ final int curFiltered = capability & ~PROCESS_CAPABILITY_CPU_TIME;
+ final int prevFiltered = prevCapability & ~PROCESS_CAPABILITY_CPU_TIME;
+ if ((curFiltered != prevFiltered)
+ && ((curFiltered & prevFiltered) == prevFiltered)) {
+ return true;
+ }
+ }
}
if (adj < prevRawAdj) {
@@ -3328,6 +3383,29 @@ public class OomAdjuster {
return baseCapabilities | networkCapabilities;
}
+ private static int getCpuCapability(ProcessRecord app, long nowUptime) {
+ final UidRecord uidRec = app.getUidRecord();
+ if (uidRec != null && uidRec.isCurAllowListed()) {
+ // Process has user visible activities.
+ return PROCESS_CAPABILITY_CPU_TIME;
+ }
+ if (UserHandle.isCore(app.uid)) {
+ // Make sure all system components are not frozen.
+ return PROCESS_CAPABILITY_CPU_TIME;
+ }
+ if (app.mState.getCachedHasVisibleActivities()) {
+ // Process has user visible activities.
+ return PROCESS_CAPABILITY_CPU_TIME;
+ }
+ if (app.mServices.hasUndemotedShortForegroundService(nowUptime)) {
+ // It running a short fgs, just give it cpu time.
+ return PROCESS_CAPABILITY_CPU_TIME;
+ }
+ // TODO(b/370817323): Populate this method with all of the reasons to keep a process
+ // unfrozen.
+ return 0;
+ }
+
/**
* @return the BFSL capability from a client (of a service binding or provider).
*/
@@ -3376,6 +3454,15 @@ public class OomAdjuster {
}
/**
+ * @return the CPU capability from a client (of a service binding or provider).
+ */
+ private static int getCpuCapabilityFromClient(ProcessRecord client) {
+ // Just grant CPU capability every time
+ // TODO(b/370817323): Populate with reasons to not propagate cpu capability across bindings.
+ return client.mState.getCurCapability() & PROCESS_CAPABILITY_CPU_TIME;
+ }
+
+ /**
* Checks if for the given app and client, there's a cycle that should skip over the client
* for now or use partial values to evaluate the effect of the client binding.
* @param app
@@ -3955,6 +4042,39 @@ public class OomAdjuster {
mCacheOomRanker.dump(pw);
}
+ /**
+ * Return whether or not a process should be frozen.
+ */
+ boolean getFreezePolicy(ProcessRecord proc) {
+ // Reasons to not freeze:
+ if (Flags.useCpuTimeCapability()) {
+ if ((proc.mState.getCurCapability() & PROCESS_CAPABILITY_CPU_TIME) != 0) {
+ /// App is important enough (see {@link #getCpuCapability}) or bound by something
+ /// important enough to not be frozen.
+ return false;
+ }
+ } else {
+ // The CPU capability handling covers all setShouldNotFreeze paths. Must check
+ // shouldNotFreeze, if the CPU capability is not being used.
+ if (proc.mOptRecord.shouldNotFreeze()) {
+ return false;
+ }
+ }
+
+ if (proc.mOptRecord.isFreezeExempt()) {
+ return false;
+ }
+
+ // Reasons to freeze:
+ if (proc.mState.getCurAdj() >= FREEZER_CUTOFF_ADJ) {
+ // Oomscore is in a high enough state, it is safe to freeze.
+ return true;
+ }
+
+ // Default, do not freeze a process.
+ return false;
+ }
+
@GuardedBy({"mService", "mProcLock"})
void updateAppFreezeStateLSP(ProcessRecord app, @OomAdjReason int oomAdjReason,
boolean immediate, int oldOomAdj) {
@@ -3969,43 +4089,44 @@ public class OomAdjuster {
(state.getCurAdj() >= FREEZER_CUTOFF_ADJ ^ oldOomAdj >= FREEZER_CUTOFF_ADJ)
|| oldOomAdj == UNKNOWN_ADJ;
final boolean shouldNotFreezeChanged = opt.shouldNotFreezeAdjSeq() == mAdjSeq;
- if ((oomAdjChanged || shouldNotFreezeChanged)
+ final boolean hasCpuCapability =
+ (PROCESS_CAPABILITY_CPU_TIME & app.mState.getCurCapability())
+ == PROCESS_CAPABILITY_CPU_TIME;
+ final boolean usedToHaveCpuCapability =
+ (PROCESS_CAPABILITY_CPU_TIME & app.mState.getSetCapability())
+ == PROCESS_CAPABILITY_CPU_TIME;
+ final boolean cpuCapabilityChanged = hasCpuCapability != usedToHaveCpuCapability;
+ if ((oomAdjChanged || shouldNotFreezeChanged || cpuCapabilityChanged)
&& Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.instantForTrack(Trace.TRACE_TAG_ACTIVITY_MANAGER,
CachedAppOptimizer.ATRACE_FREEZER_TRACK,
"updateAppFreezeStateLSP " + app.processName
+ + " pid: " + app.getPid()
+ " isFreezeExempt: " + opt.isFreezeExempt()
+ " isFrozen: " + opt.isFrozen()
+ " shouldNotFreeze: " + opt.shouldNotFreeze()
+ " shouldNotFreezeReason: " + opt.shouldNotFreezeReason()
+ " curAdj: " + state.getCurAdj()
+ " oldOomAdj: " + oldOomAdj
- + " immediate: " + immediate);
+ + " immediate: " + immediate
+ + " cpuCapability: " + hasCpuCapability);
}
}
- if (app.mOptRecord.isFreezeExempt()) {
- return;
- }
-
- // if an app is already frozen and shouldNotFreeze becomes true, immediately unfreeze
- if (opt.isFrozen() && opt.shouldNotFreeze()) {
- mCachedAppOptimizer.unfreezeAppLSP(app,
- CachedAppOptimizer.getUnfreezeReasonCodeFromOomAdjReason(oomAdjReason));
- return;
- }
-
- // Use current adjustment when freezing, set adjustment when unfreezing.
- if (state.getCurAdj() >= FREEZER_CUTOFF_ADJ && !opt.isFrozen()
- && !opt.shouldNotFreeze()) {
- if (!immediate) {
- mCachedAppOptimizer.freezeAppAsyncLSP(app);
- } else {
+ if (getFreezePolicy(app)) {
+ // This process should be frozen.
+ if (immediate && !opt.isFrozen()) {
+ // And it will be frozen immediately.
mCachedAppOptimizer.freezeAppAsyncAtEarliestLSP(app);
+ } else if (!opt.isFrozen() || !opt.isPendingFreeze()) {
+ mCachedAppOptimizer.freezeAppAsyncLSP(app);
+ }
+ } else {
+ // This process should not be frozen.
+ if (opt.isFrozen() || opt.isPendingFreeze()) {
+ mCachedAppOptimizer.unfreezeAppLSP(app,
+ CachedAppOptimizer.getUnfreezeReasonCodeFromOomAdjReason(oomAdjReason));
}
- } else if (state.getSetAdj() < FREEZER_CUTOFF_ADJ) {
- mCachedAppOptimizer.unfreezeAppLSP(app,
- CachedAppOptimizer.getUnfreezeReasonCodeFromOomAdjReason(oomAdjReason));
}
}
@@ -4029,7 +4150,8 @@ public class OomAdjuster {
final int size = processes.size();
for (int i = 0; i < size; i++) {
ProcessRecord proc = processes.get(i);
- mCachedAppOptimizer.unfreezeTemporarily(proc, reason);
+ mCachedAppOptimizer.unfreezeTemporarily(proc,
+ CachedAppOptimizer.getUnfreezeReasonCodeFromOomAdjReason(reason));
}
processes.clear();
}
diff --git a/services/core/java/com/android/server/am/OomAdjusterModernImpl.java b/services/core/java/com/android/server/am/OomAdjusterModernImpl.java
index 8b660559f550..1b7e8f0bd244 100644
--- a/services/core/java/com/android/server/am/OomAdjusterModernImpl.java
+++ b/services/core/java/com/android/server/am/OomAdjusterModernImpl.java
@@ -758,8 +758,9 @@ public class OomAdjusterModernImpl extends OomAdjuster {
OomAdjusterModernImpl(ActivityManagerService service, ProcessList processList,
ActiveUids activeUids, ServiceThread adjusterThread, GlobalState globalState,
- Injector injector) {
- super(service, processList, activeUids, adjusterThread, globalState, injector);
+ CachedAppOptimizer cachedAppOptimizer, Injector injector) {
+ super(service, processList, activeUids, adjusterThread, globalState, cachedAppOptimizer,
+ injector);
}
private final ProcessRecordNodes mProcessRecordProcStateNodes = new ProcessRecordNodes(
diff --git a/services/core/java/com/android/server/am/ProcessServiceRecord.java b/services/core/java/com/android/server/am/ProcessServiceRecord.java
index 5cb8b954a2ba..364497491785 100644
--- a/services/core/java/com/android/server/am/ProcessServiceRecord.java
+++ b/services/core/java/com/android/server/am/ProcessServiceRecord.java
@@ -256,18 +256,24 @@ final class ProcessServiceRecord {
}
// Now we need to look at all short-FGS within the process and see if all of them are
// procstate-timed-out or not.
+ return !hasUndemotedShortForegroundService(nowUptime);
+ }
+
+ boolean hasUndemotedShortForegroundService(long nowUptime) {
for (int i = mServices.size() - 1; i >= 0; i--) {
final ServiceRecord sr = mServices.valueAt(i);
if (!sr.isShortFgs() || !sr.hasShortFgsInfo()) {
continue;
}
if (sr.getShortFgsInfo().getProcStateDemoteTime() >= nowUptime) {
- return false;
+ // This short fgs has not timed out yet.
+ return true;
}
}
- return true;
+ return false;
}
+
int getReportedForegroundServiceTypes() {
return mRepFgServiceTypes;
}
diff --git a/services/core/java/com/android/server/am/ProcessStateController.java b/services/core/java/com/android/server/am/ProcessStateController.java
index 01468c640f6c..57899228e6ad 100644
--- a/services/core/java/com/android/server/am/ProcessStateController.java
+++ b/services/core/java/com/android/server/am/ProcessStateController.java
@@ -29,6 +29,7 @@ import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.ServiceThread;
/**
@@ -44,13 +45,14 @@ public class ProcessStateController {
private final GlobalState mGlobalState = new GlobalState();
private ProcessStateController(ActivityManagerService ams, ProcessList processList,
- ActiveUids activeUids, ServiceThread handlerThread, OomAdjuster.Injector oomAdjInjector,
+ ActiveUids activeUids, ServiceThread handlerThread,
+ CachedAppOptimizer cachedAppOptimizer, OomAdjuster.Injector oomAdjInjector,
boolean useOomAdjusterModernImpl) {
mOomAdjuster = useOomAdjusterModernImpl
? new OomAdjusterModernImpl(ams, processList, activeUids, handlerThread,
- mGlobalState, oomAdjInjector)
+ mGlobalState, cachedAppOptimizer, oomAdjInjector)
: new OomAdjuster(ams, processList, activeUids, handlerThread, mGlobalState,
- oomAdjInjector);
+ cachedAppOptimizer, oomAdjInjector);
}
/**
@@ -594,6 +596,7 @@ public class ProcessStateController {
private final ActiveUids mActiveUids;
private ServiceThread mHandlerThread = null;
+ private CachedAppOptimizer mCachedAppOptimizer = null;
private OomAdjuster.Injector mOomAdjInjector = null;
private boolean mUseOomAdjusterModernImpl = false;
@@ -610,24 +613,38 @@ public class ProcessStateController {
if (mHandlerThread == null) {
mHandlerThread = OomAdjuster.createAdjusterThread();
}
+ if (mCachedAppOptimizer == null) {
+ mCachedAppOptimizer = new CachedAppOptimizer(mAms);
+ }
if (mOomAdjInjector == null) {
mOomAdjInjector = new OomAdjuster.Injector();
}
return new ProcessStateController(mAms, mProcessList, mActiveUids, mHandlerThread,
- mOomAdjInjector, mUseOomAdjusterModernImpl);
+ mCachedAppOptimizer, mOomAdjInjector, mUseOomAdjusterModernImpl);
}
/**
* For Testing Purposes. Set what thread OomAdjuster will offload tasks on to.
*/
+ @VisibleForTesting
public Builder setHandlerThread(ServiceThread handlerThread) {
mHandlerThread = handlerThread;
return this;
}
/**
+ * For Testing Purposes. Set the CachedAppOptimzer used by OomAdjuster.
+ */
+ @VisibleForTesting
+ public Builder setCachedAppOptimizer(CachedAppOptimizer cachedAppOptimizer) {
+ mCachedAppOptimizer = cachedAppOptimizer;
+ return this;
+ }
+
+ /**
* For Testing Purposes. Set an injector for OomAdjuster.
*/
+ @VisibleForTesting
public Builder setOomAdjusterInjector(OomAdjuster.Injector injector) {
mOomAdjInjector = injector;
return this;
diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig
index 5d5b35b8c4fb..3f0dd7f81092 100644
--- a/services/core/java/com/android/server/am/flags.aconfig
+++ b/services/core/java/com/android/server/am/flags.aconfig
@@ -261,3 +261,10 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "use_cpu_time_capability"
+ namespace: "backstage_power"
+ description: "Use PROCESS_CAPABILITY_CPU_TIME to control unfreeze state."
+ bug: "370817323"
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 4a1315583ad4..f82a86092064 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -109,6 +109,7 @@ import android.platform.test.annotations.Presubmit;
import android.platform.test.flag.junit.SetFlagsRule;
import android.util.ArrayMap;
import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import com.android.server.LocalServices;
@@ -175,6 +176,7 @@ public class MockingOomAdjusterTests {
private ActiveUids mActiveUids;
private PackageManagerInternal mPackageManagerInternal;
private ActivityManagerService mService;
+ private TestCachedAppOptimizer mTestCachedAppOptimizer;
private OomAdjusterInjector mInjector = new OomAdjusterInjector();
private int mUiTierSize;
@@ -242,9 +244,11 @@ public class MockingOomAdjusterTests {
doNothing().when(pr).enqueueProcessChangeItemLocked(anyInt(), anyInt(), anyInt(),
anyBoolean());
mActiveUids = new ActiveUids(mService, false);
+ mTestCachedAppOptimizer = new TestCachedAppOptimizer(mService);
mProcessStateController = new ProcessStateController.Builder(mService,
mService.mProcessList, mActiveUids)
.useModernOomAdjuster(mService.mConstants.ENABLE_NEW_OOMADJ)
+ .setCachedAppOptimizer(mTestCachedAppOptimizer)
.setOomAdjusterInjector(mInjector)
.build();
mService.mProcessStateController = mProcessStateController;
@@ -3110,13 +3114,13 @@ public class MockingOomAdjusterTests {
mProcessStateController.setUidTempAllowlistStateLSP(MOCKAPP_UID, true);
assertEquals(true, app.getUidRecord().isSetAllowListed());
- assertEquals(true, app.mOptRecord.shouldNotFreeze());
- assertEquals(true, app2.mOptRecord.shouldNotFreeze());
+ assertFreezeState(app, false);
+ assertFreezeState(app2, false);
mProcessStateController.setUidTempAllowlistStateLSP(MOCKAPP_UID, false);
assertEquals(false, app.getUidRecord().isSetAllowListed());
- assertEquals(false, app.mOptRecord.shouldNotFreeze());
- assertEquals(false, app2.mOptRecord.shouldNotFreeze());
+ assertFreezeState(app, true);
+ assertFreezeState(app2, true);
}
@SuppressWarnings("GuardedBy")
@@ -3138,25 +3142,25 @@ public class MockingOomAdjusterTests {
assertEquals(true, app.getUidRecord().isSetAllowListed());
assertEquals(true, app2.getUidRecord().isSetAllowListed());
- assertEquals(true, app.mOptRecord.shouldNotFreeze());
- assertEquals(true, app2.mOptRecord.shouldNotFreeze());
- assertEquals(true, app3.mOptRecord.shouldNotFreeze());
+ assertFreezeState(app, false);
+ assertFreezeState(app2, false);
+ assertFreezeState(app3, false);
// Remove app1 from allowlist.
mProcessStateController.setUidTempAllowlistStateLSP(MOCKAPP_UID, false);
assertEquals(false, app.getUidRecord().isSetAllowListed());
assertEquals(true, app2.getUidRecord().isSetAllowListed());
- assertEquals(false, app.mOptRecord.shouldNotFreeze());
- assertEquals(true, app2.mOptRecord.shouldNotFreeze());
- assertEquals(true, app3.mOptRecord.shouldNotFreeze());
+ assertFreezeState(app, true);
+ assertFreezeState(app2, false);
+ assertFreezeState(app3, false);
// Now remove app2 from allowlist.
mProcessStateController.setUidTempAllowlistStateLSP(MOCKAPP2_UID, false);
assertEquals(false, app.getUidRecord().isSetAllowListed());
assertEquals(false, app2.getUidRecord().isSetAllowListed());
- assertEquals(false, app.mOptRecord.shouldNotFreeze());
- assertEquals(false, app2.mOptRecord.shouldNotFreeze());
- assertEquals(false, app3.mOptRecord.shouldNotFreeze());
+ assertFreezeState(app, true);
+ assertFreezeState(app2, true);
+ assertFreezeState(app3, true);
}
@SuppressWarnings("GuardedBy")
@@ -3370,6 +3374,14 @@ public class MockingOomAdjusterTests {
assertEquals(expectedCached, state.isCached());
}
+ @SuppressWarnings("GuardedBy")
+ private void assertFreezeState(ProcessRecord app, boolean expectedFreezeState) {
+ boolean actualFreezeState = mTestCachedAppOptimizer.mLastSetFreezeState.get(app.getPid(),
+ false);
+ assertEquals("Unexcepted freeze state for " + app.processName, expectedFreezeState,
+ actualFreezeState);
+ }
+
private class ProcessRecordBuilder {
@SuppressWarnings("UnusedVariable")
int mPid;
@@ -3513,6 +3525,39 @@ public class MockingOomAdjusterTests {
return app;
}
}
+ private static final class TestProcessDependencies
+ implements CachedAppOptimizer.ProcessDependencies {
+ @Override
+ public long[] getRss(int pid) {
+ return new long[]{/*totalRSS*/ 0, /*fileRSS*/ 0, /*anonRSS*/ 0, /*swap*/ 0};
+ }
+
+ @Override
+ public void performCompaction(CachedAppOptimizer.CompactProfile action, int pid) {}
+ }
+
+ private static class TestCachedAppOptimizer extends CachedAppOptimizer {
+ private SparseBooleanArray mLastSetFreezeState = new SparseBooleanArray();
+
+ TestCachedAppOptimizer(ActivityManagerService ams) {
+ super(ams, null, new TestProcessDependencies());
+ }
+
+ @Override
+ public boolean useFreezer() {
+ return true;
+ }
+
+ @Override
+ public void freezeAppAsyncLSP(ProcessRecord app) {
+ mLastSetFreezeState.put(app.getPid(), true);
+ }
+
+ @Override
+ public void unfreezeAppLSP(ProcessRecord app, @UnfreezeReason int reason) {
+ mLastSetFreezeState.put(app.getPid(), false);
+ }
+ }
static class OomAdjusterInjector extends OomAdjuster.Injector {
// Jump ahead in time by this offset amount.
@@ -3524,7 +3569,6 @@ public class MockingOomAdjusterTests {
mLastSetOomAdj.clear();
}
-
void jumpUptimeAheadTo(long uptimeMillis) {
final long jumpMs = uptimeMillis - getUptimeMillis();
if (jumpMs <= 0) return;