Merge "Revert "[1/n] OomAdjuster implementation correctness and efficiency overhaul"" into main
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index da2588b..73e8272 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -6434,7 +6434,6 @@
}
updateServiceConnectionActivitiesLocked(psr);
psr.removeAllConnections();
- psr.removeAllSdkSandboxConnections();
psr.mAllowlistManager = false;
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index c20f0aa..89d8c77 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -22,7 +22,6 @@
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_POWER_QUICK;
import static com.android.server.am.BroadcastConstants.DEFER_BOOT_COMPLETED_BROADCAST_BACKGROUND_RESTRICTED_ONLY;
import static com.android.server.am.BroadcastConstants.DEFER_BOOT_COMPLETED_BROADCAST_TARGET_T_ONLY;
-import static com.android.server.am.BroadcastConstants.getDeviceConfigBoolean;
import android.annotation.NonNull;
import android.app.ActivityThread;
@@ -155,11 +154,6 @@
static final String KEY_TIERED_CACHED_ADJ_DECAY_TIME = "tiered_cached_adj_decay_time";
static final String KEY_USE_MODERN_TRIM = "use_modern_trim";
- /**
- * Whether or not to enable the new oom adjuster implementation.
- */
- static final String KEY_ENABLE_NEW_OOMADJ = "enable_new_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;
@@ -223,11 +217,6 @@
private static final boolean DEFAULT_USE_MODERN_TRIM = true;
/**
- * The default value to {@link #KEY_ENABLE_NEW_OOMADJ}.
- */
- private static final boolean DEFAULT_ENABLE_NEW_OOM_ADJ = false;
-
- /**
* Same as {@link TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED}
*/
private static final int
@@ -1063,9 +1052,6 @@
/** @see #KEY_USE_MODERN_TRIM */
public boolean USE_MODERN_TRIM = DEFAULT_USE_MODERN_TRIM;
- /** @see #KEY_ENABLE_NEW_OOMADJ */
- public boolean ENABLE_NEW_OOMADJ = DEFAULT_ENABLE_NEW_OOM_ADJ;
-
/**
* Indicates whether PSS profiling in AppProfiler is disabled or not.
*/
@@ -1335,7 +1321,6 @@
CUR_TRIM_EMPTY_PROCESSES = rawMaxEmptyProcesses / 2;
CUR_TRIM_CACHED_PROCESSES = (Integer.min(CUR_MAX_CACHED_PROCESSES, MAX_CACHED_PROCESSES)
- rawMaxEmptyProcesses) / 3;
- loadNativeBootDeviceConfigConstants();
mDefaultDisableAppProfilerPssProfiling = context.getResources().getBoolean(
R.bool.config_am_disablePssProfiling);
APP_PROFILER_PSS_PROFILING_DISABLED = mDefaultDisableAppProfilerPssProfiling;
@@ -1378,11 +1363,6 @@
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_COMPONENT_ALIAS));
}
- private void loadNativeBootDeviceConfigConstants() {
- ENABLE_NEW_OOMADJ = getDeviceConfigBoolean(KEY_ENABLE_NEW_OOMADJ,
- DEFAULT_ENABLE_NEW_OOM_ADJ);
- }
-
public void setOverrideMaxCachedProcesses(int value) {
mOverrideMaxCachedProcesses = value;
updateMaxCachedProcesses();
@@ -2033,13 +2013,6 @@
DEFAULT_USE_MODERN_TRIM);
}
- private void updateEnableNewOomAdj() {
- ENABLE_NEW_OOMADJ = DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
- KEY_ENABLE_NEW_OOMADJ,
- DEFAULT_ENABLE_NEW_OOM_ADJ);
- }
-
private void updateFGSPermissionEnforcementFlagsIfNecessary(@NonNull String name) {
ForegroundServiceTypePolicy.getDefaultPolicy()
.updatePermissionEnforcementFlagIfNecessary(name);
@@ -2236,9 +2209,6 @@
pw.print(" "); pw.print(KEY_TIERED_CACHED_ADJ_DECAY_TIME);
pw.print("="); pw.println(TIERED_CACHED_ADJ_DECAY_TIME);
- pw.print(" "); pw.print(KEY_ENABLE_NEW_OOMADJ);
- pw.print("="); pw.println(ENABLE_NEW_OOMADJ);
-
pw.print(" "); pw.print(KEY_DISABLE_APP_PROFILER_PSS_PROFILING);
pw.print("="); pw.println(APP_PROFILER_PSS_PROFILING_DISABLED);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c1f2f67..a0fae26 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2029,7 +2029,6 @@
app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
app.mProfile.addHostingComponentType(HOSTING_COMPONENT_TYPE_SYSTEM);
addPidLocked(app);
- mOomAdjuster.onProcessBeginLocked(app);
updateLruProcessLocked(app, false, null);
updateOomAdjLocked(OOM_ADJ_REASON_SYSTEM_INIT);
}
@@ -2423,9 +2422,7 @@
mProcessList.init(this, activeUids, mPlatformCompat);
mAppProfiler = new AppProfiler(this, BackgroundThread.getHandler().getLooper(), null);
mPhantomProcessList = new PhantomProcessList(this);
- mOomAdjuster = mConstants.ENABLE_NEW_OOMADJ
- ? new OomAdjusterModernImpl(this, mProcessList, activeUids, handlerThread)
- : new OomAdjuster(this, mProcessList, activeUids, handlerThread);
+ mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids, handlerThread);
mIntentFirewall = null;
mProcessStats = new ProcessStatsService(this, mContext.getCacheDir());
@@ -2486,9 +2483,7 @@
mAppProfiler = new AppProfiler(this, BackgroundThread.getHandler().getLooper(),
new LowMemDetector(this));
mPhantomProcessList = new PhantomProcessList(this);
- mOomAdjuster = mConstants.ENABLE_NEW_OOMADJ
- ? new OomAdjusterModernImpl(this, mProcessList, activeUids)
- : new OomAdjuster(this, mProcessList, activeUids);
+ mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids);
// Broadcast policy parameters
final BroadcastConstants foreConstants = new BroadcastConstants(
@@ -4600,7 +4595,6 @@
EventLogTags.writeAmProcBound(app.userId, pid, app.processName);
synchronized (mProcLock) {
- mOomAdjuster.onProcessBeginLocked(app);
mOomAdjuster.setAttachingProcessStatesLSP(app);
clearProcessForegroundLocked(app);
app.setDebugging(false);
@@ -6986,7 +6980,6 @@
sdkSandboxClientAppPackage,
new HostingRecord(HostingRecord.HOSTING_TYPE_ADDED_APPLICATION,
customProcess != null ? customProcess : info.processName));
- mOomAdjuster.onProcessBeginLocked(app);
updateLruProcessLocked(app, false, null);
updateOomAdjLocked(app, OOM_ADJ_REASON_PROCESS_BEGIN);
}
diff --git a/services/core/java/com/android/server/am/BroadcastConstants.java b/services/core/java/com/android/server/am/BroadcastConstants.java
index 2fff79b..8c1fd51 100644
--- a/services/core/java/com/android/server/am/BroadcastConstants.java
+++ b/services/core/java/com/android/server/am/BroadcastConstants.java
@@ -373,7 +373,7 @@
* Return the {@link SystemProperty} name for the given key in our
* {@link DeviceConfig} namespace.
*/
- private static @NonNull String propertyFor(@NonNull String key) {
+ private @NonNull String propertyFor(@NonNull String key) {
return "persist.device_config." + NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT + "." + key;
}
@@ -382,11 +382,11 @@
* {@link DeviceConfig} namespace, but with a different prefix that can be
* used to locally override the {@link DeviceConfig} value.
*/
- private static @NonNull String propertyOverrideFor(@NonNull String key) {
+ private @NonNull String propertyOverrideFor(@NonNull String key) {
return "persist.sys." + NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT + "." + key;
}
- static boolean getDeviceConfigBoolean(@NonNull String key, boolean def) {
+ private boolean getDeviceConfigBoolean(@NonNull String key, boolean def) {
return SystemProperties.getBoolean(propertyOverrideFor(key),
SystemProperties.getBoolean(propertyFor(key), def));
}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 1f9e89e..459c6ff 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -41,7 +41,6 @@
import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_TOP;
import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
-import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_ACTIVITY;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_ALLOWLIST;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_BACKUP;
@@ -125,7 +124,6 @@
import static com.android.server.am.ProcessList.VISIBLE_APP_ADJ;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal.OomAdjReason;
@@ -371,21 +369,20 @@
*/
private final Handler mProcessGroupHandler;
- protected final int[] mTmpSchedGroup = new int[1];
+ private final int[] mTmpSchedGroup = new int[1];
- final ActivityManagerService mService;
- final ProcessList mProcessList;
- final ActivityManagerGlobalLock mProcLock;
+ private final ActivityManagerService mService;
+ private final ProcessList mProcessList;
+ private final ActivityManagerGlobalLock mProcLock;
private final int mNumSlots;
- protected final ArrayList<ProcessRecord> mTmpProcessList = new ArrayList<ProcessRecord>();
- protected final ArrayList<ProcessRecord> mTmpProcessList2 = new ArrayList<ProcessRecord>();
- protected final ArrayList<UidRecord> mTmpBecameIdle = new ArrayList<UidRecord>();
- protected final ActiveUids mTmpUidRecords;
- protected final ArrayDeque<ProcessRecord> mTmpQueue;
- protected final ArraySet<ProcessRecord> mTmpProcessSet = new ArraySet<>();
- protected final ArraySet<ProcessRecord> mPendingProcessSet = new ArraySet<>();
- protected final ArraySet<ProcessRecord> mProcessesInCycle = new ArraySet<>();
+ private final ArrayList<ProcessRecord> mTmpProcessList = new ArrayList<ProcessRecord>();
+ private final ArrayList<UidRecord> mTmpBecameIdle = new ArrayList<UidRecord>();
+ private final ActiveUids mTmpUidRecords;
+ private final ArrayDeque<ProcessRecord> mTmpQueue;
+ private final ArraySet<ProcessRecord> mTmpProcessSet = new ArraySet<>();
+ private final ArraySet<ProcessRecord> mPendingProcessSet = new ArraySet<>();
+ private final ArraySet<ProcessRecord> mProcessesInCycle = new ArraySet<>();
/**
* Flag to mark if there is an ongoing oomAdjUpdate: potentially the oomAdjUpdate
@@ -415,7 +412,7 @@
this(service, processList, activeUids, createAdjusterThread());
}
- static ServiceThread createAdjusterThread() {
+ private static ServiceThread createAdjusterThread() {
// The process group is usually critical to the response time of foreground app, so the
// setter should apply it as soon as possible.
final ServiceThread adjusterThread =
@@ -535,7 +532,7 @@
mPendingProcessSet.remove(app);
mProcessesInCycle.clear();
- computeOomAdjLSP(app, cachedAdj, topApp, false, now, false, true, oomAdjReason, true);
+ computeOomAdjLSP(app, cachedAdj, topApp, false, now, false, true);
if (!mProcessesInCycle.isEmpty()) {
// We can't use the score here if there is a cycle, abort.
for (int i = mProcessesInCycle.size() - 1; i >= 0; i--) {
@@ -553,7 +550,7 @@
&& (uidRec.getSetProcState() != uidRec.getCurProcState()
|| uidRec.getSetCapability() != uidRec.getCurCapability()
|| uidRec.isSetAllowListed() != uidRec.isCurAllowListed())) {
- final ActiveUids uids = mTmpUidRecords;
+ ActiveUids uids = mTmpUidRecords;
uids.clear();
uids.put(uidRec.getUid(), uidRec);
updateUidsLSP(uids, SystemClock.elapsedRealtime());
@@ -636,20 +633,19 @@
}
@GuardedBy({"mService", "mProcLock"})
- protected boolean performUpdateOomAdjLSP(ProcessRecord app, @OomAdjReason int oomAdjReason) {
+ private boolean performUpdateOomAdjLSP(ProcessRecord app, @OomAdjReason int oomAdjReason) {
final ProcessRecord topApp = mService.getTopApp();
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason));
mService.mOomAdjProfiler.oomAdjStarted();
mAdjSeq++;
+ // Firstly, try to see if the importance of itself gets changed
final ProcessStateRecord state = app.mState;
final boolean wasCached = state.isCached();
final int oldAdj = state.getCurRawAdj();
final int cachedAdj = oldAdj >= CACHED_APP_MIN_ADJ
? oldAdj : UNKNOWN_ADJ;
-
- // Firstly, try to see if the importance of itself gets changed
final boolean wasBackground = ActivityManager.isProcStateBackground(
state.getSetProcState());
final int oldCap = state.getSetCapability();
@@ -697,6 +693,8 @@
mPendingProcessSet.clear();
if (!containsCycle) {
+ // Reset the flag
+ state.setReachable(false);
// Remove this app from the return list because we've done the computation on it.
processes.remove(app);
}
@@ -720,13 +718,8 @@
return true;
}
- /**
- * Collect the reachable processes from the given {@code apps}, the result will be
- * returned in the given {@code processes}, which will include the processes from
- * the given {@code apps}.
- */
@GuardedBy("mService")
- protected boolean collectReachableProcessesLocked(ArraySet<ProcessRecord> apps,
+ private boolean collectReachableProcessesLocked(ArraySet<ProcessRecord> apps,
ArrayList<ProcessRecord> processes, ActiveUids uids) {
final ArrayDeque<ProcessRecord> queue = mTmpQueue;
queue.clear();
@@ -831,15 +824,11 @@
if (size > 0) {
// Reverse the process list, since the updateOomAdjInnerLSP scans from the end of it.
for (int l = 0, r = size - 1; l < r; l++, r--) {
- final ProcessRecord t = processes.get(l);
- final ProcessRecord u = processes.get(r);
- t.mState.setReachable(false);
- u.mState.setReachable(false);
- processes.set(l, u);
+ ProcessRecord t = processes.get(l);
+ processes.set(l, processes.get(r));
processes.set(r, t);
}
}
-
return containsCycle;
}
@@ -939,18 +928,24 @@
* Update OomAdj for all processes within the given list (could be partial), or the whole LRU
* list if the given list is null; when it's partial update, each process's client proc won't
* get evaluated recursively here.
- *
- * <p>Note: If the given {@code processes} is not null, the expectation to it is, the caller
- * must have called {@link collectReachableProcessesLocked} on it.
*/
@GuardedBy({"mService", "mProcLock"})
- protected void updateOomAdjInnerLSP(@OomAdjReason int oomAdjReason, final ProcessRecord topApp,
+ private void updateOomAdjInnerLSP(@OomAdjReason int oomAdjReason, final ProcessRecord topApp,
ArrayList<ProcessRecord> processes, ActiveUids uids, boolean potentialCycles,
boolean startProfiling) {
+ if (startProfiling) {
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason));
+ mService.mOomAdjProfiler.oomAdjStarted();
+ }
+ final long now = SystemClock.uptimeMillis();
+ final long nowElapsed = SystemClock.elapsedRealtime();
+ final long oldTime = now - mConstants.mMaxEmptyTimeMillis;
final boolean fullUpdate = processes == null;
- final ArrayList<ProcessRecord> activeProcesses = fullUpdate
- ? mProcessList.getLruProcessesLOSP() : processes;
ActiveUids activeUids = uids;
+ ArrayList<ProcessRecord> activeProcesses = fullUpdate ? mProcessList.getLruProcessesLOSP()
+ : processes;
+ final int numProc = activeProcesses.size();
+
if (activeUids == null) {
final int numUids = mActiveUids.size();
activeUids = mTmpUidRecords;
@@ -961,14 +956,14 @@
}
}
- if (startProfiling) {
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason));
- mService.mOomAdjProfiler.oomAdjStarted();
+ // Reset state in all uid records.
+ for (int i = activeUids.size() - 1; i >= 0; i--) {
+ final UidRecord uidRec = activeUids.valueAt(i);
+ if (DEBUG_UID_OBSERVERS) {
+ Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec);
+ }
+ uidRec.reset();
}
- final long now = SystemClock.uptimeMillis();
- final long nowElapsed = SystemClock.elapsedRealtime();
- final long oldTime = now - mConstants.mMaxEmptyTimeMillis;
- final int numProc = activeProcesses.size();
mAdjSeq++;
if (fullUpdate) {
@@ -976,9 +971,6 @@
mNewNumAServiceProcs = 0;
}
- // Reset state in all uid records.
- resetUidRecordsLsp(activeUids);
-
boolean retryCycles = false;
boolean computeClients = fullUpdate || potentialCycles;
@@ -1004,9 +996,8 @@
if (!app.isKilledByAm() && app.getThread() != null) {
state.setProcStateChanged(false);
app.mOptRecord.setLastOomAdjChangeReason(oomAdjReason);
- // It won't enter cycle if not computing clients.
computeOomAdjLSP(app, UNKNOWN_ADJ, topApp, fullUpdate, now, false,
- computeClients, oomAdjReason, true);
+ computeClients); // It won't enter cycle if not computing clients.
// if any app encountered a cycle, we need to perform an additional loop later
retryCycles |= state.containsCycle();
// Keep the completedAdjSeq to up to date.
@@ -1043,7 +1034,7 @@
final ProcessStateRecord state = app.mState;
if (!app.isKilledByAm() && app.getThread() != null && state.containsCycle()) {
if (computeOomAdjLSP(app, UNKNOWN_ADJ, topApp, true, now,
- true, true, oomAdjReason, true)) {
+ true, true)) {
retryCycles = true;
}
}
@@ -1054,33 +1045,10 @@
assignCachedAdjIfNecessary(mProcessList.getLruProcessesLOSP());
- postUpdateOomAdjInnerLSP(oomAdjReason, activeUids, now, nowElapsed, oldTime);
-
- if (startProfiling) {
- mService.mOomAdjProfiler.oomAdjEnded();
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- }
- }
-
- @GuardedBy({"mService", "mProcLock"})
- private void resetUidRecordsLsp(@NonNull ActiveUids activeUids) {
- // Reset state in all uid records.
- for (int i = activeUids.size() - 1; i >= 0; i--) {
- final UidRecord uidRec = activeUids.valueAt(i);
- if (DEBUG_UID_OBSERVERS) {
- Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec);
- }
- uidRec.reset();
- }
- }
-
- @GuardedBy({"mService", "mProcLock"})
- protected void postUpdateOomAdjInnerLSP(@OomAdjReason int oomAdjReason, ActiveUids activeUids,
- long now, long nowElapsed, long oldTime) {
mNumNonCachedProcs = 0;
mNumCachedHiddenProcs = 0;
- final boolean allChanged = updateAndTrimProcessLSP(now, nowElapsed, oldTime, activeUids,
+ boolean allChanged = updateAndTrimProcessLSP(now, nowElapsed, oldTime, activeUids,
oomAdjReason);
mNumServiceProcs = mNewNumServiceProcs;
@@ -1117,10 +1085,14 @@
Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms");
}
}
+ if (startProfiling) {
+ mService.mOomAdjProfiler.oomAdjEnded();
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
}
@GuardedBy({"mService", "mProcLock"})
- protected void assignCachedAdjIfNecessary(ArrayList<ProcessRecord> lruList) {
+ private void assignCachedAdjIfNecessary(ArrayList<ProcessRecord> lruList) {
final int numLru = lruList.size();
if (mConstants.USE_TIERED_CACHED_ADJ) {
final long now = SystemClock.uptimeMillis();
@@ -1441,7 +1413,7 @@
}
@GuardedBy({"mService", "mProcLock"})
- protected void updateAppUidRecIfNecessaryLSP(final ProcessRecord app) {
+ private void updateAppUidRecIfNecessaryLSP(final ProcessRecord app) {
if (!app.isKilledByAm() && app.getThread() != null) {
if (app.isolated && app.mServices.numberOfRunningServices() <= 0
&& app.getIsolatedEntryPoint() == null) {
@@ -1470,7 +1442,7 @@
}
@GuardedBy({"mService", "mProcLock"})
- protected void updateUidsLSP(ActiveUids activeUids, final long nowElapsed) {
+ private void updateUidsLSP(ActiveUids activeUids, final long nowElapsed) {
// This compares previously set procstate to the current procstate in regards to whether
// or not the app's network access will be blocked. So, this needs to be called before
// we update the UidRecord's procstate by calling {@link UidRecord#setSetProcState}.
@@ -1608,7 +1580,7 @@
return true;
}
- protected final ComputeOomAdjWindowCallback mTmpComputeOomAdjWindowCallback =
+ private final ComputeOomAdjWindowCallback mTmpComputeOomAdjWindowCallback =
new ComputeOomAdjWindowCallback();
/** These methods are called inline during computeOomAdjLSP(), on the same thread */
@@ -1747,30 +1719,24 @@
}
@GuardedBy({"mService", "mProcLock"})
- protected boolean computeOomAdjLSP(ProcessRecord app, int cachedAdj,
+ private boolean computeOomAdjLSP(ProcessRecord app, int cachedAdj,
ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval,
- boolean computeClients, int oomAdjReason, boolean couldRecurse) {
+ boolean computeClients) {
final ProcessStateRecord state = app.mState;
- if (couldRecurse) {
- if (mAdjSeq == state.getAdjSeq()) {
- if (state.getAdjSeq() == state.getCompletedAdjSeq()) {
- // This adjustment has already been computed successfully.
- return false;
- } else {
- // The process is being computed, so there is a cycle. We cannot
- // rely on this process's state.
- state.setContainsCycle(true);
- mProcessesInCycle.add(app);
+ if (mAdjSeq == state.getAdjSeq()) {
+ if (state.getAdjSeq() == state.getCompletedAdjSeq()) {
+ // This adjustment has already been computed successfully.
+ return false;
+ } else {
+ // The process is being computed, so there is a cycle. We cannot
+ // rely on this process's state.
+ state.setContainsCycle(true);
+ mProcessesInCycle.add(app);
- return false;
- }
+ return false;
}
}
- int prevAppAdj = getInitialAdj(app);
- int prevProcState = getInitialProcState(app);
- int prevCapability = getInitialCapability(app);
-
if (app.getThread() == null) {
state.setAdjSeq(mAdjSeq);
state.setCurrentSchedulingGroup(SCHED_GROUP_BACKGROUND);
@@ -1779,8 +1745,6 @@
state.setCurRawAdj(CACHED_APP_MAX_ADJ);
state.setCompletedAdjSeq(state.getAdjSeq());
state.setCurCapability(PROCESS_CAPABILITY_NONE);
- onProcessStateChanged(app, prevProcState);
- onProcessOomAdjChanged(app, prevAppAdj);
return false;
}
@@ -1789,7 +1753,7 @@
state.setAdjTarget(null);
state.setEmpty(false);
state.setCached(false);
- if (!couldRecurse || !cycleReEval) {
+ if (!cycleReEval) {
// Don't reset this flag when doing cycles re-evaluation.
state.setNoKillOnBgRestrictedAndIdle(false);
// If this UID is currently allowlisted, it should not be frozen.
@@ -1800,6 +1764,9 @@
final int appUid = app.info.uid;
final int logUid = mService.mCurOomAdjUid;
+ int prevAppAdj = state.getCurAdj();
+ int prevProcState = state.getCurProcState();
+ int prevCapability = state.getCurCapability();
final ProcessServiceRecord psr = app.mServices;
if (state.getMaxAdj() <= FOREGROUND_APP_ADJ) {
@@ -1845,8 +1812,6 @@
state.setCurRawProcState(state.getCurProcState());
state.setCurAdj(state.getMaxAdj());
state.setCompletedAdjSeq(state.getAdjSeq());
- onProcessStateChanged(app, prevProcState);
- onProcessOomAdjChanged(app, prevAppAdj);
// if curAdj is less than prevAppAdj, then this process was promoted
return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState;
}
@@ -1860,7 +1825,7 @@
int adj;
int schedGroup;
int procState;
- int capability = cycleReEval ? getInitialCapability(app) : 0;
+ int capability = cycleReEval ? app.mState.getCurCapability() : 0;
boolean foregroundActivities = false;
boolean hasVisibleActivities = false;
@@ -1939,7 +1904,7 @@
// value that the caller wants us to.
adj = cachedAdj;
procState = PROCESS_STATE_CACHED_EMPTY;
- if (!couldRecurse || !state.containsCycle()) {
+ if (!state.containsCycle()) {
state.setCached(true);
state.setEmpty(true);
state.setAdjType("cch-empty");
@@ -2204,10 +2169,8 @@
}
}
- state.setCurBoundByNonBgRestrictedApp(getInitialIsCurBoundByNonBgRestrictedApp(app));
-
- state.setScheduleLikeTopApp(false);
-
+ boolean boundByNonBgRestricted = state.isCurBoundByNonBgRestrictedApp();
+ boolean scheduleLikeTopApp = false;
for (int is = psr.numberOfRunningServices() - 1;
is >= 0 && (adj > FOREGROUND_APP_ADJ
|| schedGroup == SCHED_GROUP_BACKGROUND
@@ -2280,18 +2243,6 @@
}
}
- if (!couldRecurse) {
- // We're entering recursive functions below, if we're told it's not a recursive
- // loop, abort here.
- continue;
- }
-
-
- state.setCurRawAdj(adj);
- state.setCurRawProcState(procState);
- state.setCurrentSchedulingGroup(schedGroup);
- state.setCurCapability(capability);
-
ArrayMap<IBinder, ArrayList<ConnectionRecord>> serviceConnections = s.getConnections();
for (int conni = serviceConnections.size() - 1;
conni >= 0 && (adj > FOREGROUND_APP_ADJ
@@ -2312,13 +2263,335 @@
continue;
}
- computeServiceHostOomAdjLSP(cr, app, cr.binding.client, now, topApp, doingAll,
- cycleReEval, computeClients, oomAdjReason, cachedAdj, true);
+ boolean trackedProcState = false;
- adj = state.getCurRawAdj();
- procState = state.getCurRawProcState();
- schedGroup = state.getCurrentSchedulingGroup();
- capability = state.getCurCapability();
+ ProcessRecord client = cr.binding.client;
+ if (app.isSdkSandbox && cr.binding.attributedClient != null) {
+ // For SDK sandboxes, use the attributed client (eg the app that
+ // requested the sandbox)
+ client = cr.binding.attributedClient;
+ }
+ final ProcessStateRecord cstate = client.mState;
+ if (computeClients) {
+ computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now,
+ cycleReEval, true);
+ } else {
+ cstate.setCurRawAdj(cstate.getCurAdj());
+ cstate.setCurRawProcState(cstate.getCurProcState());
+ }
+
+ int clientAdj = cstate.getCurRawAdj();
+ int clientProcState = cstate.getCurRawProcState();
+
+ final boolean clientIsSystem = clientProcState < PROCESS_STATE_TOP;
+
+ boundByNonBgRestricted |= cstate.isCurBoundByNonBgRestrictedApp()
+ || clientProcState <= PROCESS_STATE_BOUND_TOP
+ || (clientProcState == PROCESS_STATE_FOREGROUND_SERVICE
+ && !cstate.isBackgroundRestricted());
+
+ if (client.mOptRecord.shouldNotFreeze()) {
+ // Propagate the shouldNotFreeze flag down the bindings.
+ app.mOptRecord.setShouldNotFreeze(true);
+ }
+
+ // We always propagate PROCESS_CAPABILITY_BFSL over bindings here,
+ // but, right before actually setting it to the process,
+ // we check the final procstate, and remove it if the procsate is below BFGS.
+ capability |= getBfslCapabilityFromClient(client);
+
+ if (cr.notHasFlag(Context.BIND_WAIVE_PRIORITY)) {
+ if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
+ capability |= cstate.getCurCapability();
+ }
+
+ // If an app has network capability by default
+ // (by having procstate <= BFGS), then the apps it binds to will get
+ // elevated to a high enough procstate anyway to get network unless they
+ // request otherwise, so don't propagate the network capability by default
+ // in this case unless they explicitly request it.
+ if ((cstate.getCurCapability()
+ & PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0) {
+ if (clientProcState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
+ // This is used to grant network access to Expedited Jobs.
+ if (cr.hasFlag(Context.BIND_BYPASS_POWER_NETWORK_RESTRICTIONS)) {
+ capability |= PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
+ }
+ } else {
+ capability |= PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
+ }
+ }
+ if ((cstate.getCurCapability()
+ & PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK) != 0) {
+ if (clientProcState <= PROCESS_STATE_IMPORTANT_FOREGROUND) {
+ // This is used to grant network access to User Initiated Jobs.
+ if (cr.hasFlag(Context.BIND_BYPASS_USER_NETWORK_RESTRICTIONS)) {
+ capability |= PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK;
+ }
+ }
+ }
+
+ if (shouldSkipDueToCycle(app, cstate, procState, adj, cycleReEval)) {
+ continue;
+ }
+
+ 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. The specific cached state
+ // doesn't propagate except under certain conditions.
+ clientProcState = PROCESS_STATE_CACHED_EMPTY;
+ }
+ String adjType = null;
+ if (cr.hasFlag(Context.BIND_ALLOW_OOM_MANAGEMENT)) {
+ // Similar to BIND_WAIVE_PRIORITY, keep it unfrozen.
+ if (clientAdj < CACHED_APP_MIN_ADJ) {
+ app.mOptRecord.setShouldNotFreeze(true);
+ }
+ // Not doing bind OOM management, so treat
+ // this guy more like a started service.
+ if (state.hasShownUi() && !state.getCachedIsHomeProcess()) {
+ // If this process has shown some UI, let it immediately
+ // go to the LRU list because it may be pretty heavy with
+ // UI stuff. We'll tag it with a label just to help
+ // debug and understand what is going on.
+ if (adj > clientAdj) {
+ adjType = "cch-bound-ui-services";
+ }
+ state.setCached(false);
+ clientAdj = adj;
+ clientProcState = procState;
+ } else {
+ if (now >= (s.lastActivity
+ + mConstants.MAX_SERVICE_INACTIVITY)) {
+ // This service has not seen activity within
+ // recent memory, so allow it to drop to the
+ // LRU list if there is no other reason to keep
+ // it around. We'll also tag it with a label just
+ // to help debug and undertand what is going on.
+ if (adj > clientAdj) {
+ adjType = "cch-bound-services";
+ }
+ clientAdj = adj;
+ }
+ }
+ }
+ if (adj > clientAdj) {
+ // If this process has recently shown UI, and
+ // the process that is binding to it is less
+ // important than being visible, then we don't
+ // care about the binding as much as we care
+ // about letting this process get into the LRU
+ // list to be killed and restarted if needed for
+ // memory.
+ if (state.hasShownUi() && !state.getCachedIsHomeProcess()
+ && clientAdj > PERCEPTIBLE_APP_ADJ) {
+ if (adj >= CACHED_APP_MIN_ADJ) {
+ adjType = "cch-bound-ui-services";
+ }
+ } else {
+ int newAdj;
+ int lbAdj = VISIBLE_APP_ADJ; // lower bound of adj.
+ if (cr.hasFlag(Context.BIND_ABOVE_CLIENT
+ | Context.BIND_IMPORTANT)) {
+ if (clientAdj >= PERSISTENT_SERVICE_ADJ) {
+ newAdj = clientAdj;
+ } else {
+ // make this service persistent
+ newAdj = PERSISTENT_SERVICE_ADJ;
+ schedGroup = SCHED_GROUP_DEFAULT;
+ procState = ActivityManager.PROCESS_STATE_PERSISTENT;
+ cr.trackProcState(procState, mAdjSeq);
+ trackedProcState = true;
+ }
+ } else if (cr.hasFlag(Context.BIND_NOT_PERCEPTIBLE)
+ && clientAdj <= PERCEPTIBLE_APP_ADJ
+ && adj >= (lbAdj = PERCEPTIBLE_LOW_APP_ADJ)) {
+ newAdj = PERCEPTIBLE_LOW_APP_ADJ;
+ } else if (cr.hasFlag(Context.BIND_ALMOST_PERCEPTIBLE)
+ && cr.notHasFlag(Context.BIND_NOT_FOREGROUND)
+ && clientAdj < PERCEPTIBLE_APP_ADJ
+ && adj >= (lbAdj = PERCEPTIBLE_APP_ADJ)) {
+ // This is for user-initiated jobs.
+ // We use APP_ADJ + 1 here, so we can tell them apart from FGS.
+ newAdj = PERCEPTIBLE_APP_ADJ + 1;
+ } else if (cr.hasFlag(Context.BIND_ALMOST_PERCEPTIBLE)
+ && cr.hasFlag(Context.BIND_NOT_FOREGROUND)
+ && clientAdj < PERCEPTIBLE_APP_ADJ
+ && adj >= (lbAdj = (PERCEPTIBLE_MEDIUM_APP_ADJ + 2))) {
+ // This is for expedited jobs.
+ // We use MEDIUM_APP_ADJ + 2 here, so we can tell apart
+ // EJ and short-FGS.
+ newAdj = PERCEPTIBLE_MEDIUM_APP_ADJ + 2;
+ } else if (cr.hasFlag(Context.BIND_NOT_VISIBLE)
+ && clientAdj < PERCEPTIBLE_APP_ADJ
+ && adj >= (lbAdj = PERCEPTIBLE_APP_ADJ)) {
+ newAdj = PERCEPTIBLE_APP_ADJ;
+ } else if (clientAdj >= PERCEPTIBLE_APP_ADJ) {
+ newAdj = clientAdj;
+ } else if (cr.hasFlag(BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE)
+ && clientAdj <= VISIBLE_APP_ADJ
+ && adj > VISIBLE_APP_ADJ) {
+ newAdj = VISIBLE_APP_ADJ;
+ } else {
+ if (adj > VISIBLE_APP_ADJ) {
+ // TODO: Is this too limiting for apps bound from TOP?
+ newAdj = Math.max(clientAdj, lbAdj);
+ } else {
+ newAdj = adj;
+ }
+ }
+ if (!cstate.isCached()) {
+ state.setCached(false);
+ }
+ if (adj > newAdj) {
+ adj = newAdj;
+ state.setCurRawAdj(adj);
+ adjType = "service";
+ }
+ }
+ }
+ if (cr.notHasFlag(Context.BIND_NOT_FOREGROUND
+ | Context.BIND_IMPORTANT_BACKGROUND)) {
+ // This will treat important bound services identically to
+ // the top app, which may behave differently than generic
+ // foreground work.
+ final int curSchedGroup = cstate.getCurrentSchedulingGroup();
+ if (curSchedGroup > schedGroup) {
+ if (cr.hasFlag(Context.BIND_IMPORTANT)) {
+ schedGroup = curSchedGroup;
+ } else {
+ schedGroup = SCHED_GROUP_DEFAULT;
+ }
+ }
+ if (clientProcState < PROCESS_STATE_TOP) {
+ // Special handling for above-top states (persistent
+ // processes). These should not bring the current process
+ // into the top state, since they are not on top. Instead
+ // give them the best bound state after that.
+ if (cr.hasFlag(BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE)) {
+ clientProcState = PROCESS_STATE_FOREGROUND_SERVICE;
+ } else if (cr.hasFlag(Context.BIND_FOREGROUND_SERVICE)) {
+ clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+ } else if (mService.mWakefulness.get()
+ == PowerManagerInternal.WAKEFULNESS_AWAKE
+ && cr.hasFlag(Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE))
+ {
+ clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+ } else {
+ clientProcState =
+ PROCESS_STATE_IMPORTANT_FOREGROUND;
+ }
+ } else if (clientProcState == PROCESS_STATE_TOP) {
+ // Go at most to BOUND_TOP, unless requested to elevate
+ // to client's state.
+ clientProcState = PROCESS_STATE_BOUND_TOP;
+ final boolean enabled = cstate.getCachedCompatChange(
+ CACHED_COMPAT_CHANGE_PROCESS_CAPABILITY);
+ if (enabled) {
+ if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
+ // TOP process passes all capabilities to the service.
+ capability |= cstate.getCurCapability();
+ } else {
+ // TOP process passes no capability to the service.
+ }
+ } else {
+ // TOP process passes all capabilities to the service.
+ capability |= cstate.getCurCapability();
+ }
+ }
+ } else if (cr.notHasFlag(Context.BIND_IMPORTANT_BACKGROUND)) {
+ if (clientProcState <
+ PROCESS_STATE_TRANSIENT_BACKGROUND) {
+ clientProcState =
+ PROCESS_STATE_TRANSIENT_BACKGROUND;
+ }
+ } else {
+ if (clientProcState <
+ PROCESS_STATE_IMPORTANT_BACKGROUND) {
+ clientProcState =
+ PROCESS_STATE_IMPORTANT_BACKGROUND;
+ }
+ }
+
+ if (schedGroup < SCHED_GROUP_TOP_APP
+ && cr.hasFlag(Context.BIND_SCHEDULE_LIKE_TOP_APP)
+ && clientIsSystem) {
+ schedGroup = SCHED_GROUP_TOP_APP;
+ scheduleLikeTopApp = true;
+ }
+
+ if (!trackedProcState) {
+ cr.trackProcState(clientProcState, mAdjSeq);
+ }
+
+ if (procState > clientProcState) {
+ procState = clientProcState;
+ state.setCurRawProcState(procState);
+ if (adjType == null) {
+ adjType = "service";
+ }
+ }
+ if (procState < PROCESS_STATE_IMPORTANT_BACKGROUND
+ && cr.hasFlag(Context.BIND_SHOWING_UI)) {
+ app.setPendingUiClean(true);
+ }
+ if (adjType != null) {
+ state.setAdjType(adjType);
+ state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
+ .REASON_SERVICE_IN_USE);
+ state.setAdjSource(client);
+ state.setAdjSourceProcState(clientProcState);
+ state.setAdjTarget(s.instanceName);
+ if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+ reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
+ + ": " + app + ", due to " + client
+ + " adj=" + adj + " procState="
+ + ProcessList.makeProcStateString(procState));
+ }
+ }
+ } else { // BIND_WAIVE_PRIORITY == true
+ // BIND_WAIVE_PRIORITY bindings are special when it comes to the
+ // freezer. Processes bound via WPRI are expected to be running,
+ // but they are not promoted in the LRU list to keep them out of
+ // cached. As a result, they can freeze based on oom_adj alone.
+ // Normally, bindToDeath would fire when a cached app would die
+ // in the background, but nothing will fire when a running process
+ // pings a frozen process. Accordingly, any cached app that is
+ // bound by an unfrozen app via a WPRI binding has to remain
+ // unfrozen.
+ if (clientAdj < CACHED_APP_MIN_ADJ) {
+ app.mOptRecord.setShouldNotFreeze(true);
+ }
+ }
+ if (cr.hasFlag(Context.BIND_TREAT_LIKE_ACTIVITY)) {
+ psr.setTreatLikeActivity(true);
+ }
+ final ActivityServiceConnectionsHolder a = cr.activity;
+ if (cr.hasFlag(Context.BIND_ADJUST_WITH_ACTIVITY)) {
+ if (a != null && adj > FOREGROUND_APP_ADJ
+ && a.isActivityVisible()) {
+ adj = FOREGROUND_APP_ADJ;
+ state.setCurRawAdj(adj);
+ if (cr.notHasFlag(Context.BIND_NOT_FOREGROUND)) {
+ if (cr.hasFlag(Context.BIND_IMPORTANT)) {
+ schedGroup = SCHED_GROUP_TOP_APP_BOUND;
+ } else {
+ schedGroup = SCHED_GROUP_DEFAULT;
+ }
+ }
+ state.setCached(false);
+ state.setAdjType("service");
+ state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
+ .REASON_SERVICE_IN_USE);
+ state.setAdjSource(a);
+ state.setAdjSourceProcState(procState);
+ state.setAdjTarget(s.instanceName);
+ if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+ reportOomAdjMessageLocked(TAG_OOM_ADJ,
+ "Raise to service w/activity: " + app);
+ }
+ }
+ }
}
}
}
@@ -2330,27 +2603,97 @@
|| procState > PROCESS_STATE_TOP);
provi--) {
ContentProviderRecord cpr = ppr.getProviderAt(provi);
- if (couldRecurse) {
- // We're entering recursive functions below.
- state.setCurRawAdj(adj);
- state.setCurRawProcState(procState);
- state.setCurrentSchedulingGroup(schedGroup);
- state.setCurCapability(capability);
+ for (int i = cpr.connections.size() - 1;
+ i >= 0 && (adj > FOREGROUND_APP_ADJ
+ || schedGroup == SCHED_GROUP_BACKGROUND
+ || procState > PROCESS_STATE_TOP);
+ i--) {
+ ContentProviderConnection conn = cpr.connections.get(i);
+ ProcessRecord client = conn.client;
+ final ProcessStateRecord cstate = client.mState;
+ if (client == app) {
+ // Being our own client is not interesting.
+ continue;
+ }
+ if (computeClients) {
+ computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now, cycleReEval, true);
+ } else {
+ cstate.setCurRawAdj(cstate.getCurAdj());
+ cstate.setCurRawProcState(cstate.getCurProcState());
+ }
- for (int i = cpr.connections.size() - 1;
- i >= 0 && (adj > FOREGROUND_APP_ADJ
- || schedGroup == SCHED_GROUP_BACKGROUND
- || procState > PROCESS_STATE_TOP);
- i--) {
- ContentProviderConnection conn = cpr.connections.get(i);
- ProcessRecord client = conn.client;
- computeProviderHostOomAdjLSP(conn, app, client, now, topApp, doingAll,
- cycleReEval, computeClients, oomAdjReason, cachedAdj, true);
+ if (shouldSkipDueToCycle(app, cstate, procState, adj, cycleReEval)) {
+ continue;
+ }
- adj = state.getCurRawAdj();
- procState = state.getCurRawProcState();
- schedGroup = state.getCurrentSchedulingGroup();
- capability = state.getCurCapability();
+ int clientAdj = cstate.getCurRawAdj();
+ int clientProcState = cstate.getCurRawProcState();
+
+ // We always propagate PROCESS_CAPABILITY_BFSL to providers here,
+ // but, right before actually setting it to the process,
+ // we check the final procstate, and remove it if the procsate is below BFGS.
+ capability |= getBfslCapabilityFromClient(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.
+ clientProcState = PROCESS_STATE_CACHED_EMPTY;
+ }
+ if (client.mOptRecord.shouldNotFreeze()) {
+ // Propagate the shouldNotFreeze flag down the bindings.
+ app.mOptRecord.setShouldNotFreeze(true);
+ }
+
+ boundByNonBgRestricted |= cstate.isCurBoundByNonBgRestrictedApp()
+ || clientProcState <= PROCESS_STATE_BOUND_TOP
+ || (clientProcState == PROCESS_STATE_FOREGROUND_SERVICE
+ && !cstate.isBackgroundRestricted());
+
+ String adjType = null;
+ if (adj > clientAdj) {
+ if (state.hasShownUi() && !state.getCachedIsHomeProcess()
+ && clientAdj > PERCEPTIBLE_APP_ADJ) {
+ adjType = "cch-ui-provider";
+ } else {
+ adj = Math.max(clientAdj, FOREGROUND_APP_ADJ);
+ state.setCurRawAdj(adj);
+ adjType = "provider";
+ }
+ state.setCached(state.isCached() & cstate.isCached());
+ }
+
+ if (clientProcState <= PROCESS_STATE_FOREGROUND_SERVICE) {
+ if (adjType == null) {
+ adjType = "provider";
+ }
+ if (clientProcState == PROCESS_STATE_TOP) {
+ clientProcState = PROCESS_STATE_BOUND_TOP;
+ } else {
+ clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+ }
+ }
+
+ conn.trackProcState(clientProcState, mAdjSeq);
+ if (procState > clientProcState) {
+ procState = clientProcState;
+ state.setCurRawProcState(procState);
+ }
+ if (cstate.getCurrentSchedulingGroup() > schedGroup) {
+ schedGroup = SCHED_GROUP_DEFAULT;
+ }
+ if (adjType != null) {
+ state.setAdjType(adjType);
+ state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
+ .REASON_PROVIDER_IN_USE);
+ state.setAdjSource(client);
+ state.setAdjSourceProcState(clientProcState);
+ state.setAdjTarget(cpr.name);
+ if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+ reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
+ + ": " + app + ", due to " + client
+ + " adj=" + adj + " procState="
+ + ProcessList.makeProcStateString(procState));
+ }
}
}
// If the provider has external (non-framework) process
@@ -2456,7 +2799,7 @@
// restrictions on screen off
if (procState >= PROCESS_STATE_BOUND_FOREGROUND_SERVICE
&& mService.mWakefulness.get() != PowerManagerInternal.WAKEFULNESS_AWAKE
- && !state.shouldScheduleLikeTopApp()) {
+ && !scheduleLikeTopApp) {
if (schedGroup > SCHED_GROUP_RESTRICTED) {
schedGroup = SCHED_GROUP_RESTRICTED;
}
@@ -2474,7 +2817,6 @@
capability &= ~PROCESS_CAPABILITY_BFSL;
}
- state.setHasForegroundActivities(foregroundActivities);
if (app.isPendingFinishAttach()) {
// If the app is still starting up. We reset the computations to the
@@ -2492,580 +2834,22 @@
// it when computing the final cached adj later. Note that we don't need to
// worry about this for max adj above, since max adj will always be used to
// keep it out of the cached vaues.
+ state.setCurAdj(adj);
state.setCurCapability(capability);
+ state.setCurrentSchedulingGroup(schedGroup);
+ state.setCurProcState(procState);
+ state.setCurRawProcState(procState);
state.updateLastInvisibleTime(hasVisibleActivities);
+ state.setHasForegroundActivities(foregroundActivities);
state.setCompletedAdjSeq(mAdjSeq);
-
- schedGroup = setIntermediateAdjLSP(app, adj, prevAppAdj, schedGroup);
- setIntermediateProcStateLSP(app, procState, prevProcState);
- setIntermediateSchedGroupLSP(state, schedGroup);
+ state.setCurBoundByNonBgRestrictedApp(boundByNonBgRestricted);
// if curAdj or curProcState improved, then this process was promoted
return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState
|| state.getCurCapability() != prevCapability;
}
- /**
- * @return The proposed change to the schedGroup.
- */
- @GuardedBy({"mService", "mProcLock"})
- protected int setIntermediateAdjLSP(ProcessRecord app, int adj, int prevRawAppAdj,
- int schedGroup) {
- final ProcessStateRecord state = app.mState;
- state.setCurRawAdj(adj);
-
- adj = app.mServices.modifyRawOomAdj(adj);
- if (adj > state.getMaxAdj()) {
- adj = state.getMaxAdj();
- if (adj <= PERCEPTIBLE_LOW_APP_ADJ) {
- schedGroup = SCHED_GROUP_DEFAULT;
- }
- }
-
- state.setCurAdj(adj);
-
- return schedGroup;
- }
-
- @GuardedBy({"mService", "mProcLock"})
- protected void setIntermediateProcStateLSP(ProcessRecord app, int procState,
- int prevProcState) {
- final ProcessStateRecord state = app.mState;
- state.setCurProcState(procState);
- state.setCurRawProcState(procState);
- }
-
- @GuardedBy({"mService", "mProcLock"})
- protected void setIntermediateSchedGroupLSP(ProcessStateRecord state, int schedGroup) {
- // Put bound foreground services in a special sched group for additional
- // restrictions on screen off
- if (state.getCurProcState() >= PROCESS_STATE_BOUND_FOREGROUND_SERVICE
- && mService.mWakefulness.get() != PowerManagerInternal.WAKEFULNESS_AWAKE
- && !state.shouldScheduleLikeTopApp()) {
- if (schedGroup > SCHED_GROUP_RESTRICTED) {
- schedGroup = SCHED_GROUP_RESTRICTED;
- }
- }
-
- state.setCurrentSchedulingGroup(schedGroup);
- }
-
- @GuardedBy({"mService", "mProcLock"})
- protected void computeServiceHostOomAdjLSP(ConnectionRecord cr, ProcessRecord app,
- ProcessRecord client, long now, ProcessRecord topApp, boolean doingAll,
- boolean cycleReEval, boolean computeClients, int oomAdjReason, int cachedAdj,
- boolean couldRecurse) {
- if (app.isPendingFinishAttach()) {
- // We've set the attaching process state in the computeInitialOomAdjLSP. Skip it here.
- return;
- }
-
- final ProcessStateRecord state = app.mState;
- ProcessStateRecord cstate = client.mState;
-
- if (couldRecurse) {
- if (app.isSdkSandbox && cr.binding.attributedClient != null) {
- // For SDK sandboxes, use the attributed client (eg the app that
- // requested the sandbox)
- client = cr.binding.attributedClient;
- cstate = client.mState;
- }
- if (computeClients) {
- computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now, cycleReEval, true,
- oomAdjReason, true);
- } else {
- cstate.setCurRawAdj(cstate.getCurAdj());
- cstate.setCurRawProcState(cstate.getCurProcState());
- }
- }
-
- int clientAdj = cstate.getCurRawAdj();
- int clientProcState = cstate.getCurRawProcState();
-
- final boolean clientIsSystem = clientProcState < PROCESS_STATE_TOP;
-
- int adj = state.getCurRawAdj();
- int procState = state.getCurRawProcState();
- int schedGroup = state.getCurrentSchedulingGroup();
- int capability = state.getCurCapability();
-
- final int prevRawAdj = adj;
- final int prevProcState = procState;
- final int prevSchedGroup = schedGroup;
-
- final int appUid = app.info.uid;
- final int logUid = mService.mCurOomAdjUid;
-
- state.setCurBoundByNonBgRestrictedApp(state.isCurBoundByNonBgRestrictedApp()
- || cstate.isCurBoundByNonBgRestrictedApp()
- || clientProcState <= PROCESS_STATE_BOUND_TOP
- || (clientProcState == PROCESS_STATE_FOREGROUND_SERVICE
- && !cstate.isBackgroundRestricted()));
-
- if (client.mOptRecord.shouldNotFreeze()) {
- // Propagate the shouldNotFreeze flag down the bindings.
- app.mOptRecord.setShouldNotFreeze(true);
- }
-
- boolean trackedProcState = false;
-
- // We always propagate PROCESS_CAPABILITY_BFSL over bindings here,
- // but, right before actually setting it to the process,
- // we check the final procstate, and remove it if the procsate is below BFGS.
- capability |= getBfslCapabilityFromClient(client);
-
- if (cr.notHasFlag(Context.BIND_WAIVE_PRIORITY)) {
- if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
- capability |= cstate.getCurCapability();
- }
-
- // If an app has network capability by default
- // (by having procstate <= BFGS), then the apps it binds to will get
- // elevated to a high enough procstate anyway to get network unless they
- // request otherwise, so don't propagate the network capability by default
- // in this case unless they explicitly request it.
- if ((cstate.getCurCapability()
- & PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0) {
- if (clientProcState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
- // This is used to grant network access to Expedited Jobs.
- if (cr.hasFlag(Context.BIND_BYPASS_POWER_NETWORK_RESTRICTIONS)) {
- capability |= PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
- }
- } else {
- capability |= PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
- }
- }
- if ((cstate.getCurCapability()
- & PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK) != 0) {
- if (clientProcState <= PROCESS_STATE_IMPORTANT_FOREGROUND) {
- // This is used to grant network access to User Initiated Jobs.
- if (cr.hasFlag(Context.BIND_BYPASS_USER_NETWORK_RESTRICTIONS)) {
- capability |= PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK;
- }
- }
- }
-
- if (couldRecurse && shouldSkipDueToCycle(app, cstate, procState, adj, cycleReEval)) {
- return;
- }
-
- 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. The specific cached state
- // doesn't propagate except under certain conditions.
- clientProcState = PROCESS_STATE_CACHED_EMPTY;
- }
- String adjType = null;
- if (cr.hasFlag(Context.BIND_ALLOW_OOM_MANAGEMENT)) {
- // Similar to BIND_WAIVE_PRIORITY, keep it unfrozen.
- if (clientAdj < CACHED_APP_MIN_ADJ) {
- app.mOptRecord.setShouldNotFreeze(true);
- }
- // Not doing bind OOM management, so treat
- // this guy more like a started service.
- if (state.hasShownUi() && !state.getCachedIsHomeProcess()) {
- // If this process has shown some UI, let it immediately
- // go to the LRU list because it may be pretty heavy with
- // UI stuff. We'll tag it with a label just to help
- // debug and understand what is going on.
- if (adj > clientAdj) {
- adjType = "cch-bound-ui-services";
- }
- state.setCached(false);
- clientAdj = adj;
- clientProcState = procState;
- } else {
- if (now >= (cr.binding.service.lastActivity
- + mConstants.MAX_SERVICE_INACTIVITY)) {
- // This service has not seen activity within
- // recent memory, so allow it to drop to the
- // LRU list if there is no other reason to keep
- // it around. We'll also tag it with a label just
- // to help debug and undertand what is going on.
- if (adj > clientAdj) {
- adjType = "cch-bound-services";
- }
- clientAdj = adj;
- }
- }
- }
- if (adj > clientAdj) {
- // If this process has recently shown UI, and
- // the process that is binding to it is less
- // important than being visible, then we don't
- // care about the binding as much as we care
- // about letting this process get into the LRU
- // list to be killed and restarted if needed for
- // memory.
- if (state.hasShownUi() && !state.getCachedIsHomeProcess()
- && clientAdj > PERCEPTIBLE_APP_ADJ) {
- if (adj >= CACHED_APP_MIN_ADJ) {
- adjType = "cch-bound-ui-services";
- }
- } else {
- int newAdj;
- int lbAdj = VISIBLE_APP_ADJ; // lower bound of adj.
- if (cr.hasFlag(Context.BIND_ABOVE_CLIENT
- | Context.BIND_IMPORTANT)) {
- if (clientAdj >= PERSISTENT_SERVICE_ADJ) {
- newAdj = clientAdj;
- } else {
- // make this service persistent
- newAdj = PERSISTENT_SERVICE_ADJ;
- schedGroup = SCHED_GROUP_DEFAULT;
- procState = ActivityManager.PROCESS_STATE_PERSISTENT;
- cr.trackProcState(procState, mAdjSeq);
- trackedProcState = true;
- }
- } else if (cr.hasFlag(Context.BIND_NOT_PERCEPTIBLE)
- && clientAdj <= PERCEPTIBLE_APP_ADJ
- && adj >= (lbAdj = PERCEPTIBLE_LOW_APP_ADJ)) {
- newAdj = PERCEPTIBLE_LOW_APP_ADJ;
- } else if (cr.hasFlag(Context.BIND_ALMOST_PERCEPTIBLE)
- && cr.notHasFlag(Context.BIND_NOT_FOREGROUND)
- && clientAdj < PERCEPTIBLE_APP_ADJ
- && adj >= (lbAdj = PERCEPTIBLE_APP_ADJ)) {
- // This is for user-initiated jobs.
- // We use APP_ADJ + 1 here, so we can tell them apart from FGS.
- newAdj = PERCEPTIBLE_APP_ADJ + 1;
- } else if (cr.hasFlag(Context.BIND_ALMOST_PERCEPTIBLE)
- && cr.hasFlag(Context.BIND_NOT_FOREGROUND)
- && clientAdj < PERCEPTIBLE_APP_ADJ
- && adj >= (lbAdj = (PERCEPTIBLE_MEDIUM_APP_ADJ + 2))) {
- // This is for expedited jobs.
- // We use MEDIUM_APP_ADJ + 2 here, so we can tell apart
- // EJ and short-FGS.
- newAdj = PERCEPTIBLE_MEDIUM_APP_ADJ + 2;
- } else if (cr.hasFlag(Context.BIND_NOT_VISIBLE)
- && clientAdj < PERCEPTIBLE_APP_ADJ
- && adj >= (lbAdj = PERCEPTIBLE_APP_ADJ)) {
- newAdj = PERCEPTIBLE_APP_ADJ;
- } else if (clientAdj >= PERCEPTIBLE_APP_ADJ) {
- newAdj = clientAdj;
- } else if (cr.hasFlag(BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE)
- && clientAdj <= VISIBLE_APP_ADJ
- && adj > VISIBLE_APP_ADJ) {
- newAdj = VISIBLE_APP_ADJ;
- } else {
- if (adj > VISIBLE_APP_ADJ) {
- // TODO: Is this too limiting for apps bound from TOP?
- newAdj = Math.max(clientAdj, lbAdj);
- } else {
- newAdj = adj;
- }
- }
- if (!cstate.isCached()) {
- state.setCached(false);
- }
- if (adj > newAdj) {
- adj = newAdj;
- state.setCurRawAdj(adj);
- adjType = "service";
- }
- }
- }
- if (cr.notHasFlag(Context.BIND_NOT_FOREGROUND
- | Context.BIND_IMPORTANT_BACKGROUND)) {
- // This will treat important bound services identically to
- // the top app, which may behave differently than generic
- // foreground work.
- final int curSchedGroup = cstate.getCurrentSchedulingGroup();
- if (curSchedGroup > schedGroup) {
- if (cr.hasFlag(Context.BIND_IMPORTANT)) {
- schedGroup = curSchedGroup;
- } else {
- schedGroup = SCHED_GROUP_DEFAULT;
- }
- }
- if (clientProcState < PROCESS_STATE_TOP) {
- // Special handling for above-top states (persistent
- // processes). These should not bring the current process
- // into the top state, since they are not on top. Instead
- // give them the best bound state after that.
- if (cr.hasFlag(BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE)) {
- clientProcState = PROCESS_STATE_FOREGROUND_SERVICE;
- } else if (cr.hasFlag(Context.BIND_FOREGROUND_SERVICE)) {
- clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
- } else if (mService.mWakefulness.get()
- == PowerManagerInternal.WAKEFULNESS_AWAKE
- && cr.hasFlag(Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE)) {
- clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
- } else {
- clientProcState =
- PROCESS_STATE_IMPORTANT_FOREGROUND;
- }
- } else if (clientProcState == PROCESS_STATE_TOP) {
- // Go at most to BOUND_TOP, unless requested to elevate
- // to client's state.
- clientProcState = PROCESS_STATE_BOUND_TOP;
- final boolean enabled = cstate.getCachedCompatChange(
- CACHED_COMPAT_CHANGE_PROCESS_CAPABILITY);
- if (enabled) {
- if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
- // TOP process passes all capabilities to the service.
- capability |= cstate.getCurCapability();
- } else {
- // TOP process passes no capability to the service.
- }
- } else {
- // TOP process passes all capabilities to the service.
- capability |= cstate.getCurCapability();
- }
- }
- } else if (cr.notHasFlag(Context.BIND_IMPORTANT_BACKGROUND)) {
- if (clientProcState < PROCESS_STATE_TRANSIENT_BACKGROUND) {
- clientProcState =
- PROCESS_STATE_TRANSIENT_BACKGROUND;
- }
- } else {
- if (clientProcState < PROCESS_STATE_IMPORTANT_BACKGROUND) {
- clientProcState =
- PROCESS_STATE_IMPORTANT_BACKGROUND;
- }
- }
-
- if (schedGroup < SCHED_GROUP_TOP_APP
- && cr.hasFlag(Context.BIND_SCHEDULE_LIKE_TOP_APP)
- && clientIsSystem) {
- schedGroup = SCHED_GROUP_TOP_APP;
- state.setScheduleLikeTopApp(true);
- }
-
- if (!trackedProcState) {
- cr.trackProcState(clientProcState, mAdjSeq);
- }
-
- if (procState > clientProcState) {
- procState = clientProcState;
- state.setCurRawProcState(procState);
- if (adjType == null) {
- adjType = "service";
- }
- }
- if (procState < PROCESS_STATE_IMPORTANT_BACKGROUND
- && cr.hasFlag(Context.BIND_SHOWING_UI)) {
- app.setPendingUiClean(true);
- }
- if (adjType != null) {
- state.setAdjType(adjType);
- state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
- .REASON_SERVICE_IN_USE);
- state.setAdjSource(client);
- state.setAdjSourceProcState(clientProcState);
- state.setAdjTarget(cr.binding.service.instanceName);
- if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
- reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
- + ": " + app + ", due to " + client
- + " adj=" + adj + " procState="
- + ProcessList.makeProcStateString(procState));
- }
- }
- } else { // BIND_WAIVE_PRIORITY == true
- // BIND_WAIVE_PRIORITY bindings are special when it comes to the
- // freezer. Processes bound via WPRI are expected to be running,
- // but they are not promoted in the LRU list to keep them out of
- // cached. As a result, they can freeze based on oom_adj alone.
- // Normally, bindToDeath would fire when a cached app would die
- // in the background, but nothing will fire when a running process
- // pings a frozen process. Accordingly, any cached app that is
- // bound by an unfrozen app via a WPRI binding has to remain
- // unfrozen.
- if (clientAdj < CACHED_APP_MIN_ADJ) {
- app.mOptRecord.setShouldNotFreeze(true);
- }
- }
- if (cr.hasFlag(Context.BIND_TREAT_LIKE_ACTIVITY)) {
- app.mServices.setTreatLikeActivity(true);
- if (clientProcState <= PROCESS_STATE_CACHED_ACTIVITY
- && procState > PROCESS_STATE_CACHED_ACTIVITY) {
- // This is a cached process, but somebody wants us to treat it like it has
- // an activity, okay!
- procState = PROCESS_STATE_CACHED_ACTIVITY;
- state.setAdjType("cch-as-act");
- }
- }
- final ActivityServiceConnectionsHolder a = cr.activity;
- if (cr.hasFlag(Context.BIND_ADJUST_WITH_ACTIVITY)) {
- if (a != null && adj > FOREGROUND_APP_ADJ
- && a.isActivityVisible()) {
- adj = FOREGROUND_APP_ADJ;
- state.setCurRawAdj(adj);
- if (cr.notHasFlag(Context.BIND_NOT_FOREGROUND)) {
- if (cr.hasFlag(Context.BIND_IMPORTANT)) {
- schedGroup = SCHED_GROUP_TOP_APP_BOUND;
- } else {
- schedGroup = SCHED_GROUP_DEFAULT;
- }
- }
- state.setCached(false);
- state.setAdjType("service");
- state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
- .REASON_SERVICE_IN_USE);
- state.setAdjSource(a);
- state.setAdjSourceProcState(procState);
- state.setAdjTarget(cr.binding.service.instanceName);
- if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
- reportOomAdjMessageLocked(TAG_OOM_ADJ,
- "Raise to service w/activity: " + app);
- }
- }
- }
-
- capability |= getDefaultCapability(app, procState);
-
- // Procstates below BFGS should never have this capability.
- if (procState > PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
- capability &= ~PROCESS_CAPABILITY_BFSL;
- }
-
- if (adj < prevRawAdj) {
- schedGroup = setIntermediateAdjLSP(app, adj, prevRawAdj, schedGroup);
- }
- if (procState < prevProcState) {
- setIntermediateProcStateLSP(app, procState, prevProcState);
- }
- if (schedGroup > prevSchedGroup) {
- setIntermediateSchedGroupLSP(state, schedGroup);
- }
- state.setCurCapability(capability);
-
- state.setEmpty(false);
- }
-
- protected void computeProviderHostOomAdjLSP(ContentProviderConnection conn, ProcessRecord app,
- ProcessRecord client, long now, ProcessRecord topApp, boolean doingAll,
- boolean cycleReEval, boolean computeClients, int oomAdjReason, int cachedAdj,
- boolean couldRecurse) {
- if (app.isPendingFinishAttach()) {
- // We've set the attaching process state in the computeInitialOomAdjLSP. Skip it here.
- return;
- }
-
- final ProcessStateRecord state = app.mState;
- final ProcessStateRecord cstate = client.mState;
-
- if (client == app) {
- // Being our own client is not interesting.
- return;
- }
- if (couldRecurse) {
- if (computeClients) {
- computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now, cycleReEval, true,
- oomAdjReason, true);
- } else if (couldRecurse) {
- cstate.setCurRawAdj(cstate.getCurAdj());
- cstate.setCurRawProcState(cstate.getCurProcState());
- }
-
- if (shouldSkipDueToCycle(app, cstate, state.getCurRawProcState(), state.getCurRawAdj(),
- cycleReEval)) {
- return;
- }
- }
-
- int clientAdj = cstate.getCurRawAdj();
- int clientProcState = cstate.getCurRawProcState();
-
- int adj = state.getCurRawAdj();
- int procState = state.getCurRawProcState();
- int schedGroup = state.getCurrentSchedulingGroup();
- int capability = state.getCurCapability();
-
- final int prevRawAdj = adj;
- final int prevProcState = procState;
- final int prevSchedGroup = schedGroup;
-
- final int appUid = app.info.uid;
- final int logUid = mService.mCurOomAdjUid;
-
- // We always propagate PROCESS_CAPABILITY_BFSL to providers here,
- // but, right before actually setting it to the process,
- // we check the final procstate, and remove it if the procsate is below BFGS.
- capability |= getBfslCapabilityFromClient(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.
- clientProcState = PROCESS_STATE_CACHED_EMPTY;
- }
- if (client.mOptRecord.shouldNotFreeze()) {
- // Propagate the shouldNotFreeze flag down the bindings.
- app.mOptRecord.setShouldNotFreeze(true);
- }
-
- state.setCurBoundByNonBgRestrictedApp(state.isCurBoundByNonBgRestrictedApp()
- || cstate.isCurBoundByNonBgRestrictedApp()
- || clientProcState <= PROCESS_STATE_BOUND_TOP
- || (clientProcState == PROCESS_STATE_FOREGROUND_SERVICE
- && !cstate.isBackgroundRestricted()));
-
- String adjType = null;
- if (adj > clientAdj) {
- if (state.hasShownUi() && !state.getCachedIsHomeProcess()
- && clientAdj > PERCEPTIBLE_APP_ADJ) {
- adjType = "cch-ui-provider";
- } else {
- adj = Math.max(clientAdj, FOREGROUND_APP_ADJ);
- state.setCurRawAdj(adj);
- adjType = "provider";
- }
- state.setCached(state.isCached() & cstate.isCached());
- }
-
- if (clientProcState <= PROCESS_STATE_FOREGROUND_SERVICE) {
- if (adjType == null) {
- adjType = "provider";
- }
- if (clientProcState == PROCESS_STATE_TOP) {
- clientProcState = PROCESS_STATE_BOUND_TOP;
- } else {
- clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
- }
- }
-
- conn.trackProcState(clientProcState, mAdjSeq);
- if (procState > clientProcState) {
- procState = clientProcState;
- state.setCurRawProcState(procState);
- }
- if (cstate.getCurrentSchedulingGroup() > schedGroup) {
- schedGroup = SCHED_GROUP_DEFAULT;
- }
- if (adjType != null) {
- state.setAdjType(adjType);
- state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
- .REASON_PROVIDER_IN_USE);
- state.setAdjSource(client);
- state.setAdjSourceProcState(clientProcState);
- state.setAdjTarget(conn.provider.name);
- if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
- reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
- + ": " + app + ", due to " + client
- + " adj=" + adj + " procState="
- + ProcessList.makeProcStateString(procState));
- }
- }
-
- // Procstates below BFGS should never have this capability.
- if (procState > PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
- capability &= ~PROCESS_CAPABILITY_BFSL;
- }
-
- if (adj < prevRawAdj) {
- schedGroup = setIntermediateAdjLSP(app, adj, prevRawAdj, schedGroup);
- }
- if (procState < prevProcState) {
- setIntermediateProcStateLSP(app, procState, prevProcState);
- }
- if (schedGroup > prevSchedGroup) {
- setIntermediateSchedGroupLSP(state, schedGroup);
- }
- state.setCurCapability(capability);
-
- state.setEmpty(false);
- }
-
- protected int getDefaultCapability(ProcessRecord app, int procState) {
+ private int getDefaultCapability(ProcessRecord app, int procState) {
final int networkCapabilities =
NetworkPolicyManager.getDefaultProcessNetworkCapabilities(procState);
final int baseCapabilities;
@@ -3098,7 +2882,7 @@
/**
* @return the BFSL capability from a client (of a service binding or provider).
*/
- protected int getBfslCapabilityFromClient(ProcessRecord client) {
+ int getBfslCapabilityFromClient(ProcessRecord client) {
// Procstates above FGS should always have this flag. We shouldn't need this logic,
// but let's do it just in case.
if (client.mState.getCurProcState() < PROCESS_STATE_FOREGROUND_SERVICE) {
@@ -3183,7 +2967,7 @@
/** Inform the oomadj observer of changes to oomadj. Used by tests. */
@GuardedBy("mService")
- protected void reportOomAdjMessageLocked(String tag, String msg) {
+ private void reportOomAdjMessageLocked(String tag, String msg) {
Slog.d(tag, msg);
synchronized (mService.mOomAdjObserverLock) {
if (mService.mCurOomAdjObserver != null) {
@@ -3199,7 +2983,7 @@
/** 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,
+ private boolean applyOomAdjLSP(ProcessRecord app, boolean doingAll, long now,
long nowElapsed, @OomAdjReason int oomAdjReson) {
boolean success = true;
final ProcessStateRecord state = app.mState;
@@ -3488,8 +3272,6 @@
int initialCapability = PROCESS_CAPABILITY_NONE;
boolean initialCached = true;
final ProcessStateRecord state = app.mState;
- final int prevProcState = PROCESS_STATE_UNKNOWN;
- final int prevAdj = UNKNOWN_ADJ;
// If the process has been marked as foreground, it is starting as the top app (with
// Zygote#START_AS_TOP_APP_ARG), so boost the thread priority of its default UI thread.
if (state.hasForegroundActivities()) {
@@ -3524,9 +3306,6 @@
state.setCurRawAdj(ProcessList.FOREGROUND_APP_ADJ);
state.setForcingToImportant(null);
state.setHasShownUi(false);
-
- onProcessStateChanged(app, prevProcState);
- onProcessOomAdjChanged(app, prevAdj);
}
// ONLY used for unit testing in OomAdjusterTests.java
@@ -3774,56 +3553,4 @@
}
processes.clear();
}
-
- @GuardedBy("mService")
- void onProcessBeginLocked(@NonNull ProcessRecord app) {
- // Empty, the OomAdjusterModernImpl will have an implementation.
- }
-
- @GuardedBy("mService")
- void onProcessEndLocked(@NonNull ProcessRecord app) {
- // Empty, the OomAdjusterModernImpl will have an implementation.
- }
-
- /**
- * Called when the process state is changed outside of the OomAdjuster.
- */
- @GuardedBy("mService")
- void onProcessStateChanged(@NonNull ProcessRecord app, int prevProcState) {
- // Empty, the OomAdjusterModernImpl will have an implementation.
- }
-
- /**
- * Called when the oom adj is changed outside of the OomAdjuster.
- */
- @GuardedBy("mService")
- void onProcessOomAdjChanged(@NonNull ProcessRecord app, int prevAdj) {
- // Empty, the OomAdjusterModernImpl will have an implementation.
- }
-
- @VisibleForTesting
- void resetInternal() {
- // Empty, the OomAdjusterModernImpl will have an implementation.
- }
-
- @GuardedBy("mService")
- protected int getInitialAdj(@NonNull ProcessRecord app) {
- return app.mState.getCurAdj();
- }
-
- @GuardedBy("mService")
- protected int getInitialProcState(@NonNull ProcessRecord app) {
- return app.mState.getCurProcState();
- }
-
- @GuardedBy("mService")
- protected int getInitialCapability(@NonNull ProcessRecord app) {
- return app.mState.getCurCapability();
- }
-
- @GuardedBy("mService")
- protected boolean getInitialIsCurBoundByNonBgRestrictedApp(@NonNull ProcessRecord app) {
- // The caller will set the initial value in this implementation.
- return app.mState.isCurBoundByNonBgRestrictedApp();
- }
}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.md b/services/core/java/com/android/server/am/OomAdjuster.md
index da5e12e..16091d1 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.md
+++ b/services/core/java/com/android/server/am/OomAdjuster.md
@@ -130,28 +130,3 @@
* Iterate the processes from least important to most important ones.
* A maximum retries of 10 is enforced, while in practice, the maximum retries could reach only 2 to 3.
-## The Modern Implementation
-
-As aforementioned, the OomAdjuster makes the computation in a recursive way, while this is inefficient in dealing with the cycles. The overall code complexity should be around **O((1 + num(retries)) * num(procs) * num(binding connections))**. In addition, depending on the ordering of the input, the algorithm may produce different results and sometimes it's wrong.
-
-The new "Modern Implementation" is based on the rationale that, apps can't promote the service/provider it connects to, to a higher bucket than itself. We are introducing a bucket based, breadth first search algorithm, as illustrated below:
-
-```
-for all processes in the process list
- compute the state of each process, but, excluding its clients
- put each process to the corresponding bucket according to the state value
-done
-
-for each bucket, starting from the top most to the bottom most
- for each process in the bucket
- for each process it binds to
- if the state of the bindee process could be elevated because of the binding; then
- move the bindee process to the higher bucket
- fi
- done
- done
-done
-```
-
-The overall code complexity should be around **O(num(procs) * num(binding connections))**, which saves the retry time from the existing algorithm.
-
diff --git a/services/core/java/com/android/server/am/OomAdjusterModernImpl.java b/services/core/java/com/android/server/am/OomAdjusterModernImpl.java
deleted file mode 100644
index b852ef5..0000000
--- a/services/core/java/com/android/server/am/OomAdjusterModernImpl.java
+++ /dev/null
@@ -1,1125 +0,0 @@
-/*
- * Copyright (C) 2023 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.
- */
-
-package com.android.server.am;
-
-import static android.app.ActivityManager.PROCESS_STATE_BACKUP;
-import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
-import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
-import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
-import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
-import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY;
-import static android.app.ActivityManager.PROCESS_STATE_CACHED_RECENT;
-import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
-import static android.app.ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
-import static android.app.ActivityManager.PROCESS_STATE_HOME;
-import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
-import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
-import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
-import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT;
-import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT_UI;
-import static android.app.ActivityManager.PROCESS_STATE_RECEIVER;
-import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
-import static android.app.ActivityManager.PROCESS_STATE_TOP;
-import static android.app.ActivityManager.PROCESS_STATE_TOP_SLEEPING;
-import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
-import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
-
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_UID_OBSERVERS;
-import static com.android.server.am.ActivityManagerService.TAG_UID_OBSERVERS;
-import static com.android.server.am.ProcessList.BACKUP_APP_ADJ;
-import static com.android.server.am.ProcessList.CACHED_APP_MIN_ADJ;
-import static com.android.server.am.ProcessList.FOREGROUND_APP_ADJ;
-import static com.android.server.am.ProcessList.HEAVY_WEIGHT_APP_ADJ;
-import static com.android.server.am.ProcessList.HOME_APP_ADJ;
-import static com.android.server.am.ProcessList.NATIVE_ADJ;
-import static com.android.server.am.ProcessList.PERCEPTIBLE_APP_ADJ;
-import static com.android.server.am.ProcessList.PERCEPTIBLE_LOW_APP_ADJ;
-import static com.android.server.am.ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ;
-import static com.android.server.am.ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ;
-import static com.android.server.am.ProcessList.PERSISTENT_PROC_ADJ;
-import static com.android.server.am.ProcessList.PERSISTENT_SERVICE_ADJ;
-import static com.android.server.am.ProcessList.PREVIOUS_APP_ADJ;
-import static com.android.server.am.ProcessList.SCHED_GROUP_BACKGROUND;
-import static com.android.server.am.ProcessList.SERVICE_ADJ;
-import static com.android.server.am.ProcessList.SERVICE_B_ADJ;
-import static com.android.server.am.ProcessList.SYSTEM_ADJ;
-import static com.android.server.am.ProcessList.UNKNOWN_ADJ;
-import static com.android.server.am.ProcessList.VISIBLE_APP_ADJ;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.ActivityManager;
-import android.app.ActivityManagerInternal.OomAdjReason;
-import android.content.pm.ServiceInfo;
-import android.os.IBinder;
-import android.os.SystemClock;
-import android.os.Trace;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.Slog;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.ServiceThread;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.function.Consumer;
-
-/**
- * A modern implementation of the oom adjuster.
- */
-public class OomAdjusterModernImpl extends OomAdjuster {
- static final String TAG = "OomAdjusterModernImpl";
-
- // The ADJ_SLOT_INVALID is NOT an actual slot.
- static final int ADJ_SLOT_INVALID = -1;
- static final int ADJ_SLOT_NATIVE = 0;
- static final int ADJ_SLOT_SYSTEM = 1;
- static final int ADJ_SLOT_PERSISTENT_PROC = 2;
- static final int ADJ_SLOT_PERSISTENT_SERVICE = 3;
- static final int ADJ_SLOT_FOREGROUND_APP = 4;
- static final int ADJ_SLOT_PERCEPTIBLE_RECENT_FOREGROUND_APP = 5;
- static final int ADJ_SLOT_VISIBLE_APP = 6;
- static final int ADJ_SLOT_PERCEPTIBLE_APP = 7;
- static final int ADJ_SLOT_PERCEPTIBLE_MEDIUM_APP = 8;
- static final int ADJ_SLOT_PERCEPTIBLE_LOW_APP = 9;
- static final int ADJ_SLOT_BACKUP_APP = 10;
- static final int ADJ_SLOT_HEAVY_WEIGHT_APP = 11;
- static final int ADJ_SLOT_SERVICE = 12;
- static final int ADJ_SLOT_HOME_APP = 13;
- static final int ADJ_SLOT_PREVIOUS_APP = 14;
- static final int ADJ_SLOT_SERVICE_B = 15;
- static final int ADJ_SLOT_CACHED_APP = 16;
- static final int ADJ_SLOT_UNKNOWN = 17;
-
- @IntDef(prefix = { "ADJ_SLOT_" }, value = {
- ADJ_SLOT_INVALID,
- ADJ_SLOT_NATIVE,
- ADJ_SLOT_SYSTEM,
- ADJ_SLOT_PERSISTENT_PROC,
- ADJ_SLOT_PERSISTENT_SERVICE,
- ADJ_SLOT_FOREGROUND_APP,
- ADJ_SLOT_PERCEPTIBLE_RECENT_FOREGROUND_APP,
- ADJ_SLOT_VISIBLE_APP,
- ADJ_SLOT_PERCEPTIBLE_APP,
- ADJ_SLOT_PERCEPTIBLE_MEDIUM_APP,
- ADJ_SLOT_PERCEPTIBLE_LOW_APP,
- ADJ_SLOT_BACKUP_APP,
- ADJ_SLOT_HEAVY_WEIGHT_APP,
- ADJ_SLOT_SERVICE,
- ADJ_SLOT_HOME_APP,
- ADJ_SLOT_PREVIOUS_APP,
- ADJ_SLOT_SERVICE_B,
- ADJ_SLOT_CACHED_APP,
- ADJ_SLOT_UNKNOWN,
- })
- @Retention(RetentionPolicy.SOURCE)
- @interface AdjSlot{}
-
- static final int[] ADJ_SLOT_VALUES = new int[] {
- NATIVE_ADJ,
- SYSTEM_ADJ,
- PERSISTENT_PROC_ADJ,
- PERSISTENT_SERVICE_ADJ,
- FOREGROUND_APP_ADJ,
- PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ,
- VISIBLE_APP_ADJ,
- PERCEPTIBLE_APP_ADJ,
- PERCEPTIBLE_MEDIUM_APP_ADJ,
- PERCEPTIBLE_LOW_APP_ADJ,
- BACKUP_APP_ADJ,
- HEAVY_WEIGHT_APP_ADJ,
- SERVICE_ADJ,
- HOME_APP_ADJ,
- PREVIOUS_APP_ADJ,
- SERVICE_B_ADJ,
- CACHED_APP_MIN_ADJ,
- UNKNOWN_ADJ,
- };
-
- /**
- * Note: Always use the raw adj to call this API.
- */
- static @AdjSlot int adjToSlot(int adj) {
- if (adj >= ADJ_SLOT_VALUES[0] && adj <= ADJ_SLOT_VALUES[ADJ_SLOT_VALUES.length - 1]) {
- // Conduct a binary search, in most of the cases it'll get a hit.
- final int index = Arrays.binarySearch(ADJ_SLOT_VALUES, adj);
- if (index >= 0) {
- return index;
- }
- // If not found, the returned index above should be (-(insertion point) - 1),
- // let's return the first slot that's less than the adj value.
- return -(index + 1) - 1;
- }
- return ADJ_SLOT_VALUES.length - 1;
- }
-
- static final int[] PROC_STATE_SLOTS = new int[] {
- PROCESS_STATE_PERSISTENT, // 0
- PROCESS_STATE_PERSISTENT_UI,
- PROCESS_STATE_TOP,
- PROCESS_STATE_BOUND_TOP,
- PROCESS_STATE_FOREGROUND_SERVICE,
- PROCESS_STATE_BOUND_FOREGROUND_SERVICE,
- PROCESS_STATE_IMPORTANT_FOREGROUND,
- PROCESS_STATE_IMPORTANT_BACKGROUND,
- PROCESS_STATE_TRANSIENT_BACKGROUND,
- PROCESS_STATE_BACKUP,
- PROCESS_STATE_SERVICE,
- PROCESS_STATE_RECEIVER,
- PROCESS_STATE_TOP_SLEEPING,
- PROCESS_STATE_HEAVY_WEIGHT,
- PROCESS_STATE_HOME,
- PROCESS_STATE_LAST_ACTIVITY,
- PROCESS_STATE_CACHED_ACTIVITY,
- PROCESS_STATE_CACHED_ACTIVITY_CLIENT,
- PROCESS_STATE_CACHED_RECENT,
- PROCESS_STATE_CACHED_EMPTY,
- PROCESS_STATE_UNKNOWN, // -1
- };
-
- static int processStateToSlot(@ActivityManager.ProcessState int state) {
- if (state >= PROCESS_STATE_PERSISTENT && state <= PROCESS_STATE_CACHED_EMPTY) {
- return state;
- }
- return PROC_STATE_SLOTS.length - 1;
- }
-
- /**
- * A container node in the {@link LinkedProcessRecordList},
- * holding the references to {@link ProcessRecord}.
- */
- static class ProcessRecordNode {
- static final int NODE_TYPE_PROC_STATE = 0;
- static final int NODE_TYPE_ADJ = 1;
-
- @IntDef(prefix = { "NODE_TYPE_" }, value = {
- NODE_TYPE_PROC_STATE,
- NODE_TYPE_ADJ,
- })
- @Retention(RetentionPolicy.SOURCE)
- @interface NodeType {}
-
- static final int NUM_NODE_TYPE = NODE_TYPE_ADJ + 1;
-
- @Nullable ProcessRecordNode mPrev;
- @Nullable ProcessRecordNode mNext;
- final @Nullable ProcessRecord mApp;
-
- ProcessRecordNode(@Nullable ProcessRecord app) {
- mApp = app;
- }
-
- void unlink() {
- if (mPrev != null) {
- mPrev.mNext = mNext;
- }
- if (mNext != null) {
- mNext.mPrev = mPrev;
- }
- mPrev = mNext = null;
- }
-
- boolean isLinked() {
- return mPrev != null && mNext != null;
- }
-
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder();
- sb.append("ProcessRecordNode{");
- sb.append(Integer.toHexString(System.identityHashCode(this)));
- sb.append(' ');
- sb.append(mApp);
- sb.append(' ');
- sb.append(mApp != null ? mApp.mState.getCurProcState() : PROCESS_STATE_UNKNOWN);
- sb.append(' ');
- sb.append(mApp != null ? mApp.mState.getCurAdj() : UNKNOWN_ADJ);
- sb.append(' ');
- sb.append(Integer.toHexString(System.identityHashCode(mPrev)));
- sb.append(' ');
- sb.append(Integer.toHexString(System.identityHashCode(mNext)));
- sb.append('}');
- return sb.toString();
- }
- }
-
- private class ProcessRecordNodes {
- private final @ProcessRecordNode.NodeType int mType;
-
- private final LinkedProcessRecordList[] mProcessRecordNodes;
- // The last node besides the tail.
- private final ProcessRecordNode[] mLastNode;
-
- ProcessRecordNodes(@ProcessRecordNode.NodeType int type, int size) {
- mType = type;
- mProcessRecordNodes = new LinkedProcessRecordList[size];
- for (int i = 0; i < size; i++) {
- mProcessRecordNodes[i] = new LinkedProcessRecordList(type);
- }
- mLastNode = new ProcessRecordNode[size];
- }
-
- int size() {
- return mProcessRecordNodes.length;
- }
-
- @VisibleForTesting
- void reset() {
- for (int i = 0; i < mProcessRecordNodes.length; i++) {
- mProcessRecordNodes[i].reset();
- mLastNode[i] = null;
- }
- }
-
- void resetLastNodes() {
- for (int i = 0; i < mProcessRecordNodes.length; i++) {
- mLastNode[i] = mProcessRecordNodes[i].getLastNodeBeforeTail();
- }
- }
-
- void setLastNodeToHead(int slot) {
- mLastNode[slot] = mProcessRecordNodes[slot].HEAD;
- }
-
- void forEachNewNode(int slot, @NonNull Consumer<OomAdjusterArgs> callback) {
- ProcessRecordNode node = mLastNode[slot].mNext;
- final ProcessRecordNode tail = mProcessRecordNodes[slot].TAIL;
- while (node != tail) {
- mTmpOomAdjusterArgs.mApp = node.mApp;
- // Save the next before calling callback, since that may change the node.mNext.
- final ProcessRecordNode next = node.mNext;
- callback.accept(mTmpOomAdjusterArgs);
- // There are couple of cases:
- // a) The current node is moved to another slot
- // - for this case, we'd need to keep using the "next" node.
- // b) There are one or more new nodes being appended to this slot
- // - for this case, we'd need to make sure we scan the new node too.
- // Based on the assumption that case a) is only possible with
- // the computeInitialOomAdjLSP(), where the movings are for single node only,
- // we may safely assume that, if the "next" used to be the "tail" here, and it's
- // now a new tail somewhere else, that's case a); otherwise, it's case b);
- node = next == tail && node.mNext != null && node.mNext.mNext != null
- ? node.mNext : next;
- }
- }
-
- int getNumberOfSlots() {
- return mProcessRecordNodes.length;
- }
-
- void moveAppTo(@NonNull ProcessRecord app, int prevSlot, int newSlot) {
- final ProcessRecordNode node = app.mLinkedNodes[mType];
- if (prevSlot != ADJ_SLOT_INVALID) {
- if (mLastNode[prevSlot] == node) {
- mLastNode[prevSlot] = node.mPrev;
- }
- node.unlink();
- }
- mProcessRecordNodes[newSlot].append(node);
- }
-
- void moveAllNodesTo(int fromSlot, int toSlot) {
- final LinkedProcessRecordList fromList = mProcessRecordNodes[fromSlot];
- final LinkedProcessRecordList toList = mProcessRecordNodes[toSlot];
- if (fromSlot != toSlot && fromList.HEAD.mNext != fromList.TAIL) {
- fromList.moveTo(toList);
- mLastNode[fromSlot] = fromList.getLastNodeBeforeTail();
- }
- }
-
- void moveAppToTail(ProcessRecord app) {
- final ProcessRecordNode node = app.mLinkedNodes[mType];
- int slot;
- switch (mType) {
- case ProcessRecordNode.NODE_TYPE_PROC_STATE:
- slot = processStateToSlot(app.mState.getCurProcState());
- if (mLastNode[slot] == node) {
- mLastNode[slot] = node.mPrev;
- }
- mProcessRecordNodes[slot].moveNodeToTail(node);
- break;
- case ProcessRecordNode.NODE_TYPE_ADJ:
- slot = adjToSlot(app.mState.getCurRawAdj());
- if (mLastNode[slot] == node) {
- mLastNode[slot] = node.mPrev;
- }
- mProcessRecordNodes[slot].moveNodeToTail(node);
- break;
- default:
- return;
- }
-
- }
-
- void reset(int slot) {
- mProcessRecordNodes[slot].reset();
- }
-
- void unlink(@NonNull ProcessRecord app) {
- final ProcessRecordNode node = app.mLinkedNodes[mType];
- final int slot = getCurrentSlot(app);
- if (slot != ADJ_SLOT_INVALID) {
- if (mLastNode[slot] == node) {
- mLastNode[slot] = node.mPrev;
- }
- }
- node.unlink();
- }
-
- void append(@NonNull ProcessRecord app) {
- append(app, getCurrentSlot(app));
- }
-
- void append(@NonNull ProcessRecord app, int targetSlot) {
- final ProcessRecordNode node = app.mLinkedNodes[mType];
- mProcessRecordNodes[targetSlot].append(node);
- }
-
- private int getCurrentSlot(@NonNull ProcessRecord app) {
- switch (mType) {
- case ProcessRecordNode.NODE_TYPE_PROC_STATE:
- return processStateToSlot(app.mState.getCurProcState());
- case ProcessRecordNode.NODE_TYPE_ADJ:
- return adjToSlot(app.mState.getCurRawAdj());
- }
- return ADJ_SLOT_INVALID;
- }
-
- String toString(int slot, int logUid) {
- return "lastNode=" + mLastNode[slot] + " " + mProcessRecordNodes[slot].toString(logUid);
- }
-
- /**
- * A simple version of {@link java.util.LinkedList}, as here we don't allocate new node
- * while adding an object to it.
- */
- private static class LinkedProcessRecordList {
- // Sentinel head/tail, to make bookkeeping work easier.
- final ProcessRecordNode HEAD = new ProcessRecordNode(null);
- final ProcessRecordNode TAIL = new ProcessRecordNode(null);
- final @ProcessRecordNode.NodeType int mNodeType;
-
- LinkedProcessRecordList(@ProcessRecordNode.NodeType int nodeType) {
- HEAD.mNext = TAIL;
- TAIL.mPrev = HEAD;
- mNodeType = nodeType;
- }
-
- void append(@NonNull ProcessRecordNode node) {
- node.mNext = TAIL;
- node.mPrev = TAIL.mPrev;
- TAIL.mPrev.mNext = node;
- TAIL.mPrev = node;
- }
-
- void moveTo(@NonNull LinkedProcessRecordList toList) {
- if (HEAD.mNext != TAIL) {
- toList.TAIL.mPrev.mNext = HEAD.mNext;
- HEAD.mNext.mPrev = toList.TAIL.mPrev;
- toList.TAIL.mPrev = TAIL.mPrev;
- TAIL.mPrev.mNext = toList.TAIL;
- HEAD.mNext = TAIL;
- TAIL.mPrev = HEAD;
- }
- }
-
- void moveNodeToTail(@NonNull ProcessRecordNode node) {
- node.unlink();
- append(node);
- }
-
- @NonNull ProcessRecordNode getLastNodeBeforeTail() {
- return TAIL.mPrev;
- }
-
- @VisibleForTesting
- void reset() {
- HEAD.mNext = TAIL;
- TAIL.mPrev = HEAD;
- }
-
- String toString(int logUid) {
- final StringBuilder sb = new StringBuilder();
- sb.append("LinkedProcessRecordList{");
- sb.append(HEAD);
- sb.append(' ');
- sb.append(TAIL);
- sb.append('[');
- ProcessRecordNode node = HEAD.mNext;
- while (node != TAIL) {
- if (node.mApp != null && node.mApp.uid == logUid) {
- sb.append(node);
- sb.append(',');
- }
- node = node.mNext;
- }
- sb.append(']');
- sb.append('}');
- return sb.toString();
- }
- }
- }
-
- /**
- * A data class for holding the parameters in computing oom adj.
- */
- private class OomAdjusterArgs {
- ProcessRecord mApp;
- ProcessRecord mTopApp;
- long mNow;
- int mCachedAdj;
- @OomAdjReason int mOomAdjReason;
- @NonNull ActiveUids mUids;
- boolean mFullUpdate;
-
- void update(ProcessRecord topApp, long now, int cachedAdj,
- @OomAdjReason int oomAdjReason, @NonNull ActiveUids uids, boolean fullUpdate) {
- mTopApp = topApp;
- mNow = now;
- mCachedAdj = cachedAdj;
- mOomAdjReason = oomAdjReason;
- mUids = uids;
- mFullUpdate = fullUpdate;
- }
- }
-
- OomAdjusterModernImpl(ActivityManagerService service, ProcessList processList,
- ActiveUids activeUids) {
- this(service, processList, activeUids, createAdjusterThread());
- }
-
- OomAdjusterModernImpl(ActivityManagerService service, ProcessList processList,
- ActiveUids activeUids, ServiceThread adjusterThread) {
- super(service, processList, activeUids, adjusterThread);
- }
-
- private final ProcessRecordNodes mProcessRecordProcStateNodes = new ProcessRecordNodes(
- ProcessRecordNode.NODE_TYPE_PROC_STATE, PROC_STATE_SLOTS.length);
- private final ProcessRecordNodes mProcessRecordAdjNodes = new ProcessRecordNodes(
- ProcessRecordNode.NODE_TYPE_ADJ, ADJ_SLOT_VALUES.length);
- private final OomAdjusterArgs mTmpOomAdjusterArgs = new OomAdjusterArgs();
-
- void linkProcessRecordToList(@NonNull ProcessRecord app) {
- mProcessRecordProcStateNodes.append(app);
- mProcessRecordAdjNodes.append(app);
- }
-
- void unlinkProcessRecordFromList(@NonNull ProcessRecord app) {
- mProcessRecordProcStateNodes.unlink(app);
- mProcessRecordAdjNodes.unlink(app);
- }
-
- @Override
- @VisibleForTesting
- void resetInternal() {
- mProcessRecordProcStateNodes.reset();
- mProcessRecordAdjNodes.reset();
- }
-
- @GuardedBy("mService")
- @Override
- void onProcessBeginLocked(@NonNull ProcessRecord app) {
- // Check one type should be good enough.
- if (app.mLinkedNodes[ProcessRecordNode.NODE_TYPE_PROC_STATE] == null) {
- for (int i = 0; i < app.mLinkedNodes.length; i++) {
- app.mLinkedNodes[i] = new ProcessRecordNode(app);
- }
- }
- if (!app.mLinkedNodes[ProcessRecordNode.NODE_TYPE_PROC_STATE].isLinked()) {
- linkProcessRecordToList(app);
- }
- }
-
- @GuardedBy("mService")
- @Override
- void onProcessEndLocked(@NonNull ProcessRecord app) {
- if (app.mLinkedNodes[ProcessRecordNode.NODE_TYPE_PROC_STATE] != null
- && app.mLinkedNodes[ProcessRecordNode.NODE_TYPE_PROC_STATE].isLinked()) {
- unlinkProcessRecordFromList(app);
- }
- }
-
- @GuardedBy("mService")
- @Override
- void onProcessStateChanged(@NonNull ProcessRecord app, int prevProcState) {
- updateProcStateSlotIfNecessary(app, prevProcState);
- }
-
- @GuardedBy("mService")
- void onProcessOomAdjChanged(@NonNull ProcessRecord app, int prevAdj) {
- updateAdjSlotIfNecessary(app, prevAdj);
- }
-
- @GuardedBy("mService")
- @Override
- protected int getInitialAdj(@NonNull ProcessRecord app) {
- return UNKNOWN_ADJ;
- }
-
- @GuardedBy("mService")
- @Override
- protected int getInitialProcState(@NonNull ProcessRecord app) {
- return PROCESS_STATE_UNKNOWN;
- }
-
- @GuardedBy("mService")
- @Override
- protected int getInitialCapability(@NonNull ProcessRecord app) {
- return 0;
- }
-
- @GuardedBy("mService")
- @Override
- protected boolean getInitialIsCurBoundByNonBgRestrictedApp(@NonNull ProcessRecord app) {
- return false;
- }
-
- private void updateAdjSlotIfNecessary(ProcessRecord app, int prevRawAdj) {
- if (app.mState.getCurRawAdj() != prevRawAdj) {
- final int slot = adjToSlot(app.mState.getCurRawAdj());
- final int prevSlot = adjToSlot(prevRawAdj);
- if (slot != prevSlot && slot != ADJ_SLOT_INVALID) {
- mProcessRecordAdjNodes.moveAppTo(app, prevSlot, slot);
- }
- }
- }
-
- private void updateProcStateSlotIfNecessary(ProcessRecord app, int prevProcState) {
- if (app.mState.getCurProcState() != prevProcState) {
- final int slot = processStateToSlot(app.mState.getCurProcState());
- final int prevSlot = processStateToSlot(prevProcState);
- if (slot != prevSlot) {
- mProcessRecordProcStateNodes.moveAppTo(app, prevSlot, slot);
- }
- }
- }
-
- @Override
- protected boolean performUpdateOomAdjLSP(ProcessRecord app, @OomAdjReason int oomAdjReason) {
- final ProcessRecord topApp = mService.getTopApp();
-
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason));
- mService.mOomAdjProfiler.oomAdjStarted();
- mAdjSeq++;
-
- final ProcessStateRecord state = app.mState;
- final int oldAdj = state.getCurRawAdj();
- final int cachedAdj = oldAdj >= CACHED_APP_MIN_ADJ
- ? oldAdj : UNKNOWN_ADJ;
-
- final ActiveUids uids = mTmpUidRecords;
- final ArraySet<ProcessRecord> targetProcesses = mTmpProcessSet;
- final ArrayList<ProcessRecord> reachableProcesses = mTmpProcessList;
- final long now = SystemClock.uptimeMillis();
- final long nowElapsed = SystemClock.elapsedRealtime();
-
- uids.clear();
- targetProcesses.clear();
- targetProcesses.add(app);
- reachableProcesses.clear();
-
- // Find out all reachable processes from this app.
- collectReachableProcessesLocked(targetProcesses, reachableProcesses, uids);
-
- // Copy all of the reachable processes into the target process set.
- targetProcesses.addAll(reachableProcesses);
- reachableProcesses.clear();
-
- final boolean result = performNewUpdateOomAdjLSP(oomAdjReason,
- topApp, targetProcesses, uids, false, now, cachedAdj);
-
- reachableProcesses.addAll(targetProcesses);
- assignCachedAdjIfNecessary(reachableProcesses);
- for (int i = uids.size() - 1; i >= 0; i--) {
- final UidRecord uidRec = uids.valueAt(i);
- uidRec.forEachProcess(this::updateAppUidRecIfNecessaryLSP);
- }
- updateUidsLSP(uids, nowElapsed);
- for (int i = 0, size = targetProcesses.size(); i < size; i++) {
- applyOomAdjLSP(targetProcesses.valueAt(i), false, now, nowElapsed, oomAdjReason);
- }
- targetProcesses.clear();
- reachableProcesses.clear();
-
- mService.mOomAdjProfiler.oomAdjEnded();
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- return result;
- }
-
- @GuardedBy({"mService", "mProcLock"})
- @Override
- protected void updateOomAdjInnerLSP(@OomAdjReason int oomAdjReason, final ProcessRecord topApp,
- ArrayList<ProcessRecord> processes, ActiveUids uids, boolean potentialCycles,
- boolean startProfiling) {
- final boolean fullUpdate = processes == null;
- final ArrayList<ProcessRecord> activeProcesses = fullUpdate
- ? mProcessList.getLruProcessesLOSP() : processes;
- ActiveUids activeUids = uids;
- if (activeUids == null) {
- final int numUids = mActiveUids.size();
- activeUids = mTmpUidRecords;
- activeUids.clear();
- for (int i = 0; i < numUids; i++) {
- UidRecord uidRec = mActiveUids.valueAt(i);
- activeUids.put(uidRec.getUid(), uidRec);
- }
- }
-
- if (startProfiling) {
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason));
- mService.mOomAdjProfiler.oomAdjStarted();
- }
- final long now = SystemClock.uptimeMillis();
- final long nowElapsed = SystemClock.elapsedRealtime();
- final long oldTime = now - mConstants.mMaxEmptyTimeMillis;
- final int numProc = activeProcesses.size();
-
- mAdjSeq++;
- if (fullUpdate) {
- mNewNumServiceProcs = 0;
- mNewNumAServiceProcs = 0;
- }
-
- final ArraySet<ProcessRecord> targetProcesses = mTmpProcessSet;
- targetProcesses.clear();
- if (!fullUpdate) {
- targetProcesses.addAll(activeProcesses);
- }
-
- performNewUpdateOomAdjLSP(oomAdjReason, topApp, targetProcesses, activeUids,
- fullUpdate, now, UNKNOWN_ADJ);
-
- if (fullUpdate) {
- assignCachedAdjIfNecessary(mProcessList.getLruProcessesLOSP());
- postUpdateOomAdjInnerLSP(oomAdjReason, activeUids, now, nowElapsed, oldTime);
- } else {
- activeProcesses.clear();
- activeProcesses.addAll(targetProcesses);
- assignCachedAdjIfNecessary(activeProcesses);
-
- for (int i = activeUids.size() - 1; i >= 0; i--) {
- final UidRecord uidRec = activeUids.valueAt(i);
- uidRec.forEachProcess(this::updateAppUidRecIfNecessaryLSP);
- }
- updateUidsLSP(activeUids, nowElapsed);
-
- for (int i = 0, size = targetProcesses.size(); i < size; i++) {
- applyOomAdjLSP(targetProcesses.valueAt(i), false, now, nowElapsed, oomAdjReason);
- }
-
- activeProcesses.clear();
- }
- targetProcesses.clear();
-
- if (startProfiling) {
- mService.mOomAdjProfiler.oomAdjEnded();
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- }
- return;
- }
-
- /**
- * Perform the oom adj update on the given {@code targetProcesses}.
- *
- * <p>Note: The expectation to the given {@code targetProcesses} is, the caller
- * must have called {@link collectReachableProcessesLocked} on it.
- */
- private boolean performNewUpdateOomAdjLSP(@OomAdjReason int oomAdjReason,
- ProcessRecord topApp, ArraySet<ProcessRecord> targetProcesses, ActiveUids uids,
- boolean fullUpdate, long now, int cachedAdj) {
-
- final ArrayList<ProcessRecord> clientProcesses = mTmpProcessList2;
- clientProcesses.clear();
-
- // We'll need to collect the upstream processes of the target apps here, because those
- // processes would potentially impact the procstate/adj via bindings.
- if (!fullUpdate) {
- final boolean containsCycle = collectReversedReachableProcessesLocked(targetProcesses,
- clientProcesses);
-
- // If any of its upstream processes are in a cycle,
- // move them into the candidate targets.
- if (containsCycle) {
- // Add all client apps to the target process list.
- for (int i = 0, size = clientProcesses.size(); i < size; i++) {
- final ProcessRecord client = clientProcesses.get(i);
- final UidRecord uidRec = client.getUidRecord();
- targetProcesses.add(client);
- if (uidRec != null) {
- uids.put(uidRec.getUid(), uidRec);
- }
- }
- clientProcesses.clear();
- }
- for (int i = 0, size = targetProcesses.size(); i < size; i++) {
- final ProcessRecord app = targetProcesses.valueAt(i);
- app.mState.resetCachedInfo();
- final UidRecord uidRec = app.getUidRecord();
- if (uidRec != null) {
- if (DEBUG_UID_OBSERVERS) {
- Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec);
- }
- uidRec.reset();
- }
- }
- } else {
- final ArrayList<ProcessRecord> lru = mProcessList.getLruProcessesLOSP();
- for (int i = 0, size = lru.size(); i < size; i++) {
- final ProcessRecord app = lru.get(i);
- app.mState.resetCachedInfo();
- final UidRecord uidRec = app.getUidRecord();
- if (uidRec != null) {
- if (DEBUG_UID_OBSERVERS) {
- Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec);
- }
- uidRec.reset();
- }
- }
- }
-
- updateNewOomAdjInnerLSP(oomAdjReason, topApp, targetProcesses, clientProcesses, uids,
- cachedAdj, now, fullUpdate);
-
- clientProcesses.clear();
-
- return true;
- }
-
- /**
- * Collect the reversed reachable processes from the given {@code apps}, the result will be
- * returned in the given {@code processes}, which will <em>NOT</em> include the processes from
- * the given {@code apps}.
- */
- @GuardedBy("mService")
- private boolean collectReversedReachableProcessesLocked(ArraySet<ProcessRecord> apps,
- ArrayList<ProcessRecord> clientProcesses) {
- final ArrayDeque<ProcessRecord> queue = mTmpQueue;
- queue.clear();
- clientProcesses.clear();
- for (int i = 0, size = apps.size(); i < size; i++) {
- final ProcessRecord app = apps.valueAt(i);
- app.mState.setReachable(true);
- app.mState.setReversedReachable(true);
- queue.offer(app);
- }
-
- // Track if any of them reachables could include a cycle
- boolean containsCycle = false;
-
- // Scan upstreams of the process record
- for (ProcessRecord pr = queue.poll(); pr != null; pr = queue.poll()) {
- if (!pr.mState.isReachable()) {
- // If not in the given initial set of apps, add it.
- clientProcesses.add(pr);
- }
- final ProcessServiceRecord psr = pr.mServices;
- for (int i = psr.numberOfRunningServices() - 1; i >= 0; i--) {
- final ServiceRecord s = psr.getRunningServiceAt(i);
- final ArrayMap<IBinder, ArrayList<ConnectionRecord>> serviceConnections =
- s.getConnections();
- for (int j = serviceConnections.size() - 1; j >= 0; j--) {
- final ArrayList<ConnectionRecord> clist = serviceConnections.valueAt(j);
- for (int k = clist.size() - 1; k >= 0; k--) {
- final ConnectionRecord cr = clist.get(k);
- final ProcessRecord client = cr.binding.client;
- containsCycle |= client.mState.isReversedReachable();
- if (client.mState.isReversedReachable()) {
- continue;
- }
- queue.offer(client);
- client.mState.setReversedReachable(true);
- }
- }
- }
- final ProcessProviderRecord ppr = pr.mProviders;
- for (int i = ppr.numberOfProviders() - 1; i >= 0; i--) {
- final ContentProviderRecord cpr = ppr.getProviderAt(i);
- for (int j = cpr.connections.size() - 1; j >= 0; j--) {
- final ContentProviderConnection conn = cpr.connections.get(j);
- final ProcessRecord client = conn.client;
- containsCycle |= client.mState.isReversedReachable();
- if (client.mState.isReversedReachable()) {
- continue;
- }
- queue.offer(client);
- client.mState.setReversedReachable(true);
- }
- }
- // If this process is a sandbox itself, also add the app on whose behalf
- // its running
- if (pr.isSdkSandbox) {
- for (int is = psr.numberOfRunningServices() - 1; is >= 0; is--) {
- ServiceRecord s = psr.getRunningServiceAt(is);
- ArrayMap<IBinder, ArrayList<ConnectionRecord>> serviceConnections =
- s.getConnections();
- for (int conni = serviceConnections.size() - 1; conni >= 0; conni--) {
- ArrayList<ConnectionRecord> clist = serviceConnections.valueAt(conni);
- for (int i = clist.size() - 1; i >= 0; i--) {
- ConnectionRecord cr = clist.get(i);
- ProcessRecord attributedApp = cr.binding.attributedClient;
- if (attributedApp == null || attributedApp == pr) {
- continue;
- }
- containsCycle |= attributedApp.mState.isReversedReachable();
- if (attributedApp.mState.isReversedReachable()) {
- continue;
- }
- queue.offer(attributedApp);
- attributedApp.mState.setReversedReachable(true);
- }
- }
- }
- }
- }
-
- // Reset the temporary bits.
- for (int i = clientProcesses.size() - 1; i >= 0; i--) {
- clientProcesses.get(i).mState.setReversedReachable(false);
- }
- for (int i = 0, size = apps.size(); i < size; i++) {
- final ProcessRecord app = apps.valueAt(i);
- app.mState.setReachable(false);
- app.mState.setReversedReachable(false);
- }
- return containsCycle;
- }
-
- @GuardedBy({"mService", "mProcLock"})
- private void updateNewOomAdjInnerLSP(@OomAdjReason int oomAdjReason, final ProcessRecord topApp,
- ArraySet<ProcessRecord> targetProcesses, ArrayList<ProcessRecord> clientProcesses,
- ActiveUids uids, int cachedAdj, long now, boolean fullUpdate) {
- mTmpOomAdjusterArgs.update(topApp, now, cachedAdj, oomAdjReason, uids, fullUpdate);
-
- mProcessRecordProcStateNodes.resetLastNodes();
- mProcessRecordAdjNodes.resetLastNodes();
-
- final int procStateTarget = mProcessRecordProcStateNodes.size() - 1;
- final int adjTarget = mProcessRecordAdjNodes.size() - 1;
-
- final int appUid = !fullUpdate && targetProcesses.size() > 0
- ? targetProcesses.valueAt(0).uid : -1;
- final int logUid = mService.mCurOomAdjUid;
-
- mAdjSeq++;
- // All apps to be updated will be moved to the lowest slot.
- if (fullUpdate) {
- // Move all the process record node to the lowest slot, we'll do recomputation on all of
- // them. Use the processes from the lru list, because the scanning order matters here.
- final ArrayList<ProcessRecord> lruList = mProcessList.getLruProcessesLOSP();
- for (int i = procStateTarget; i >= 0; i--) {
- mProcessRecordProcStateNodes.reset(i);
- // Force the last node to the head since we'll recompute all of them.
- mProcessRecordProcStateNodes.setLastNodeToHead(i);
- }
- // enqueue the targets in the reverse order of the lru list.
- for (int i = lruList.size() - 1; i >= 0; i--) {
- mProcessRecordProcStateNodes.append(lruList.get(i), procStateTarget);
- }
- // Do the same to the adj nodes.
- for (int i = adjTarget; i >= 0; i--) {
- mProcessRecordAdjNodes.reset(i);
- // Force the last node to the head since we'll recompute all of them.
- mProcessRecordAdjNodes.setLastNodeToHead(i);
- }
- for (int i = lruList.size() - 1; i >= 0; i--) {
- mProcessRecordAdjNodes.append(lruList.get(i), adjTarget);
- }
- } else {
- // Move the target processes to the lowest slot.
- for (int i = 0, size = targetProcesses.size(); i < size; i++) {
- final ProcessRecord app = targetProcesses.valueAt(i);
- final int procStateSlot = processStateToSlot(app.mState.getCurProcState());
- final int adjSlot = adjToSlot(app.mState.getCurRawAdj());
- mProcessRecordProcStateNodes.moveAppTo(app, procStateSlot, procStateTarget);
- mProcessRecordAdjNodes.moveAppTo(app, adjSlot, adjTarget);
- }
- // Move the "lastNode" to head to make sure we scan all nodes in this slot.
- mProcessRecordProcStateNodes.setLastNodeToHead(procStateTarget);
- mProcessRecordAdjNodes.setLastNodeToHead(adjTarget);
- }
-
- // All apps to be updated have been moved to the lowest slot.
- // Do an initial pass of the computation.
- mProcessRecordProcStateNodes.forEachNewNode(mProcessRecordProcStateNodes.size() - 1,
- this::computeInitialOomAdjLSP);
-
- if (!fullUpdate) {
- // We didn't update the client processes with the computeInitialOomAdjLSP
- // because they don't need to do so. But they'll be playing vital roles in
- // computing the bindings. So include them into the scan list below.
- for (int i = 0, size = clientProcesses.size(); i < size; i++) {
- mProcessRecordProcStateNodes.moveAppToTail(clientProcesses.get(i));
- }
- // We don't update the adj list since we're resetting it below.
- }
-
- // Now nodes are set into their slots, without facting in the bindings.
- // The nodes between the `lastNode` pointer and the TAIL should be the new nodes.
- //
- // The whole rationale here is that, the bindings from client to host app, won't elevate
- // the host app's procstate/adj higher than the client app's state (BIND_ABOVE_CLIENT
- // is a special case here, but client app's raw adj is still no less than the host app's).
- // Therefore, starting from the top to the bottom, for each slot, scan all of the new nodes,
- // check its bindings, elevate its host app's slot if necessary.
- //
- // We'd have to do this in two passes: 1) scan procstate node list; 2) scan adj node list.
- // Because the procstate and adj are not always in sync - there are cases where
- // the processes with lower proc state could be getting a higher oom adj score.
- // And because of this, the procstate and adj node lists are basically two priority heaps.
- //
- // As the 2nd pass with the adj node lists potentially includes a significant amount of
- // duplicated scans as the 1st pass has done, we'll reset the last node pointers for
- // the adj node list before the 1st pass; so during the 1st pass, if any app's adj slot
- // gets bumped, we'll only scan those in 2nd pass.
-
- mProcessRecordAdjNodes.resetLastNodes();
-
- // 1st pass, scan each slot in the procstate node list.
- for (int i = 0, end = mProcessRecordProcStateNodes.size() - 1; i < end; i++) {
- mProcessRecordProcStateNodes.forEachNewNode(i, this::computeHostOomAdjLSP);
- }
-
- // 2nd pass, scan each slot in the adj node list.
- for (int i = 0, end = mProcessRecordAdjNodes.size() - 1; i < end; i++) {
- mProcessRecordAdjNodes.forEachNewNode(i, this::computeHostOomAdjLSP);
- }
- }
-
- @GuardedBy({"mService", "mProcLock"})
- private void computeInitialOomAdjLSP(OomAdjusterArgs args) {
- final ProcessRecord app = args.mApp;
- final int cachedAdj = args.mCachedAdj;
- final ProcessRecord topApp = args.mTopApp;
- final long now = args.mNow;
- final int oomAdjReason = args.mOomAdjReason;
- final ActiveUids uids = args.mUids;
- final boolean fullUpdate = args.mFullUpdate;
-
- if (DEBUG_OOM_ADJ) {
- Slog.i(TAG, "OOM ADJ initial args app=" + app
- + " cachedAdj=" + cachedAdj
- + " topApp=" + topApp
- + " now=" + now
- + " oomAdjReason=" + oomAdjReasonToString(oomAdjReason)
- + " fullUpdate=" + fullUpdate);
- }
-
- if (uids != null) {
- final UidRecord uidRec = app.getUidRecord();
-
- if (uidRec != null) {
- uids.put(uidRec.getUid(), uidRec);
- }
- }
-
- computeOomAdjLSP(app, cachedAdj, topApp, fullUpdate, now, false, false, oomAdjReason,
- false);
- }
-
- /**
- * @return The proposed change to the schedGroup.
- */
- @GuardedBy({"mService", "mProcLock"})
- @Override
- protected int setIntermediateAdjLSP(ProcessRecord app, int adj, int prevRawAppAdj,
- int schedGroup) {
- schedGroup = super.setIntermediateAdjLSP(app, adj, prevRawAppAdj, schedGroup);
-
- updateAdjSlotIfNecessary(app, prevRawAppAdj);
-
- return schedGroup;
- }
-
- @GuardedBy({"mService", "mProcLock"})
- @Override
- protected void setIntermediateProcStateLSP(ProcessRecord app, int procState,
- int prevProcState) {
- super.setIntermediateProcStateLSP(app, procState, prevProcState);
-
- updateProcStateSlotIfNecessary(app, prevProcState);
- }
-
- @GuardedBy({"mService", "mProcLock"})
- private void computeHostOomAdjLSP(OomAdjusterArgs args) {
- final ProcessRecord app = args.mApp;
- final int cachedAdj = args.mCachedAdj;
- final ProcessRecord topApp = args.mTopApp;
- final long now = args.mNow;
- final @OomAdjReason int oomAdjReason = args.mOomAdjReason;
- final boolean fullUpdate = args.mFullUpdate;
- final ActiveUids uids = args.mUids;
-
- final ProcessServiceRecord psr = app.mServices;
- for (int i = psr.numberOfConnections() - 1; i >= 0; i--) {
- ConnectionRecord cr = psr.getConnectionAt(i);
- ProcessRecord service = cr.hasFlag(ServiceInfo.FLAG_ISOLATED_PROCESS)
- ? cr.binding.service.isolationHostProc : cr.binding.service.app;
- if (service == null || service == app
- || (service.mState.getMaxAdj() >= SYSTEM_ADJ
- && service.mState.getMaxAdj() < FOREGROUND_APP_ADJ)
- || (service.mState.getCurAdj() <= FOREGROUND_APP_ADJ
- && service.mState.getCurrentSchedulingGroup() > SCHED_GROUP_BACKGROUND
- && service.mState.getCurProcState() <= PROCESS_STATE_TOP)) {
- continue;
- }
-
-
- computeServiceHostOomAdjLSP(cr, service, app, now, topApp, fullUpdate, false, false,
- oomAdjReason, cachedAdj, false);
- }
-
- for (int i = psr.numberOfSdkSandboxConnections() - 1; i >= 0; i--) {
- final ConnectionRecord cr = psr.getSdkSandboxConnectionAt(i);
- final ProcessRecord service = cr.binding.service.app;
- if (service == null || service == app
- || (service.mState.getMaxAdj() >= SYSTEM_ADJ
- && service.mState.getMaxAdj() < FOREGROUND_APP_ADJ)
- || (service.mState.getCurAdj() <= FOREGROUND_APP_ADJ
- && service.mState.getCurrentSchedulingGroup() > SCHED_GROUP_BACKGROUND
- && service.mState.getCurProcState() <= PROCESS_STATE_TOP)) {
- continue;
- }
-
- computeServiceHostOomAdjLSP(cr, service, app, now, topApp, fullUpdate, false, false,
- oomAdjReason, cachedAdj, false);
- }
-
- final ProcessProviderRecord ppr = app.mProviders;
- for (int i = ppr.numberOfProviderConnections() - 1; i >= 0; i--) {
- ContentProviderConnection cpc = ppr.getProviderConnectionAt(i);
- ProcessRecord provider = cpc.provider.proc;
- if (provider == null || provider == app
- || (provider.mState.getMaxAdj() >= ProcessList.SYSTEM_ADJ
- && provider.mState.getMaxAdj() < FOREGROUND_APP_ADJ)
- || (provider.mState.getCurAdj() <= FOREGROUND_APP_ADJ
- && provider.mState.getCurrentSchedulingGroup() > SCHED_GROUP_BACKGROUND
- && provider.mState.getCurProcState() <= PROCESS_STATE_TOP)) {
- continue;
- }
-
- computeProviderHostOomAdjLSP(cpc, provider, app, now, topApp, fullUpdate, false, false,
- oomAdjReason, cachedAdj, false);
- }
- }
-}
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 7037fec..f532122c1 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -22,7 +22,6 @@
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.ActivityManagerService.MY_PID;
-import static com.android.server.am.OomAdjusterModernImpl.ProcessRecordNode.NUM_NODE_TYPE;
import static java.util.Objects.requireNonNull;
@@ -64,7 +63,6 @@
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.os.Zygote;
import com.android.server.FgThread;
-import com.android.server.am.OomAdjusterModernImpl.ProcessRecordNode;
import com.android.server.wm.WindowProcessController;
import com.android.server.wm.WindowProcessListener;
@@ -436,8 +434,6 @@
*/
volatile boolean mSkipProcessGroupCreation;
- final ProcessRecordNode[] mLinkedNodes = new ProcessRecordNode[NUM_NODE_TYPE];
-
void setStartParams(int startUid, HostingRecord hostingRecord, String seInfo,
long startUptime, long startElapsedTime) {
this.mStartUid = startUid;
@@ -1118,7 +1114,6 @@
mState.onCleanupApplicationRecordLSP();
mServices.onCleanupApplicationRecordLocked();
mReceivers.onCleanupApplicationRecordLocked();
- mService.mOomAdjuster.onProcessEndLocked(this);
return mProviders.onCleanupApplicationRecordLocked(allowRestart);
}
diff --git a/services/core/java/com/android/server/am/ProcessServiceRecord.java b/services/core/java/com/android/server/am/ProcessServiceRecord.java
index a165e88..7ff6d11 100644
--- a/services/core/java/com/android/server/am/ProcessServiceRecord.java
+++ b/services/core/java/com/android/server/am/ProcessServiceRecord.java
@@ -19,7 +19,6 @@
import static android.app.ProcessMemoryState.HOSTING_COMPONENT_TYPE_BOUND_SERVICE;
import static android.app.ProcessMemoryState.HOSTING_COMPONENT_TYPE_FOREGROUND_SERVICE;
-import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ServiceInfo;
@@ -135,11 +134,6 @@
private final ArraySet<ConnectionRecord> mConnections = new ArraySet<>();
/**
- * All ConnectionRecord this process holds indirectly to SDK sandbox processes.
- */
- private @Nullable ArraySet<ConnectionRecord> mSdkSandboxConnections;
-
- /**
* A set of UIDs of all bound clients.
*/
private ArraySet<Integer> mBoundClientUids = new ArraySet<>();
@@ -496,18 +490,13 @@
void addConnection(ConnectionRecord connection) {
mConnections.add(connection);
- addSdkSandboxConnectionIfNecessary(connection);
}
void removeConnection(ConnectionRecord connection) {
mConnections.remove(connection);
- removeSdkSandboxConnectionIfNecessary(connection);
}
void removeAllConnections() {
- for (int i = 0, size = mConnections.size(); i < size; i++) {
- removeSdkSandboxConnectionIfNecessary(mConnections.valueAt(i));
- }
mConnections.clear();
}
@@ -519,39 +508,6 @@
return mConnections.size();
}
- private void addSdkSandboxConnectionIfNecessary(ConnectionRecord connection) {
- final ProcessRecord attributedClient = connection.binding.attributedClient;
- if (attributedClient != null && connection.binding.service.isSdkSandbox) {
- if (attributedClient.mServices.mSdkSandboxConnections == null) {
- attributedClient.mServices.mSdkSandboxConnections = new ArraySet<>();
- }
- attributedClient.mServices.mSdkSandboxConnections.add(connection);
- }
- }
-
- private void removeSdkSandboxConnectionIfNecessary(ConnectionRecord connection) {
- final ProcessRecord attributedClient = connection.binding.attributedClient;
- if (attributedClient != null && connection.binding.service.isSdkSandbox) {
- if (attributedClient.mServices.mSdkSandboxConnections == null) {
- attributedClient.mServices.mSdkSandboxConnections.remove(connection);
- }
- }
- }
-
- void removeAllSdkSandboxConnections() {
- if (mSdkSandboxConnections != null) {
- mSdkSandboxConnections.clear();
- }
- }
-
- ConnectionRecord getSdkSandboxConnectionAt(int index) {
- return mSdkSandboxConnections != null ? mSdkSandboxConnections.valueAt(index) : null;
- }
-
- int numberOfSdkSandboxConnections() {
- return mSdkSandboxConnections != null ? mSdkSandboxConnections.size() : 0;
- }
-
void addBoundClientUid(int clientUid, String clientPackageName, long bindFlags) {
mBoundClientUids.add(clientUid);
mApp.getWindowProcessController()
diff --git a/services/core/java/com/android/server/am/ProcessStateRecord.java b/services/core/java/com/android/server/am/ProcessStateRecord.java
index a9c388c..db341d2 100644
--- a/services/core/java/com/android/server/am/ProcessStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessStateRecord.java
@@ -378,12 +378,6 @@
private boolean mReachable;
/**
- * Whether or not this process is reversed reachable from given process.
- */
- @GuardedBy("mService")
- private boolean mReversedReachable;
-
- /**
* The most recent time when the last visible activity within this process became invisible.
*
* <p> It'll be set to 0 if there is never a visible activity, or Long.MAX_VALUE if there is
@@ -460,9 +454,6 @@
@GuardedBy("mService")
private int mCachedSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
- @GuardedBy("mService")
- private boolean mScheduleLikeTopApp = false;
-
ProcessStateRecord(ProcessRecord app) {
mApp = app;
mService = app.mService;
@@ -623,11 +614,9 @@
void forceProcessStateUpTo(int newState) {
if (mRepProcState > newState) {
synchronized (mProcLock) {
- final int prevProcState = mRepProcState;
setReportedProcState(newState);
setCurProcState(newState);
setCurRawProcState(newState);
- mService.mOomAdjuster.onProcessStateChanged(mApp, prevProcState);
}
}
}
@@ -996,16 +985,6 @@
}
@GuardedBy("mService")
- boolean isReversedReachable() {
- return mReversedReachable;
- }
-
- @GuardedBy("mService")
- void setReversedReachable(boolean reversedReachable) {
- mReversedReachable = reversedReachable;
- }
-
- @GuardedBy("mService")
void resetCachedInfo() {
mCachedHasActivities = VALUE_INVALID;
mCachedIsHeavyWeight = VALUE_INVALID;
@@ -1155,16 +1134,6 @@
return mCachedSchedGroup;
}
- @GuardedBy("mService")
- boolean shouldScheduleLikeTopApp() {
- return mScheduleLikeTopApp;
- }
-
- @GuardedBy("mService")
- void setScheduleLikeTopApp(boolean scheduleLikeTopApp) {
- mScheduleLikeTopApp = scheduleLikeTopApp;
- }
-
@GuardedBy(anyOf = {"mService", "mProcLock"})
public String makeAdjReason() {
if (mAdjSource != null || mAdjTarget != null) {
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 976e740..1f4563f 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -105,7 +105,6 @@
import com.android.server.wm.ActivityTaskManagerService;
import com.android.server.wm.WindowProcessController;
-import org.junit.After;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -207,10 +206,8 @@
setFieldValue(AppProfiler.class, profiler, "mProfilerLock", new Object());
doReturn(new ActivityManagerService.ProcessChangeItem()).when(pr)
.enqueueProcessChangeItemLocked(anyInt(), anyInt());
- sService.mOomAdjuster = sService.mConstants.ENABLE_NEW_OOMADJ
- ? new OomAdjusterModernImpl(sService, sService.mProcessList,
- new ActiveUids(sService, false))
- : new OomAdjuster(sService, sService.mProcessList, new ActiveUids(sService, false));
+ sService.mOomAdjuster = new OomAdjuster(sService, sService.mProcessList,
+ new ActiveUids(sService, false));
sService.mOomAdjuster.mAdjSeq = 10000;
sService.mWakefulness = new AtomicInteger(PowerManagerInternal.WAKEFULNESS_AWAKE);
if (sService.mConstants.USE_TIERED_CACHED_ADJ) {
@@ -223,11 +220,6 @@
LocalServices.removeServiceForTest(PackageManagerInternal.class);
}
- @After
- public void tearDown() {
- sService.mOomAdjuster.resetInternal();
- }
-
private static <T> void setFieldValue(Class clazz, Object obj, String fieldName, T val) {
try {
Field field = clazz.getDeclaredField(fieldName);
@@ -257,9 +249,6 @@
ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
lru.clear();
Collections.addAll(lru, apps);
- for (ProcessRecord app : apps) {
- sService.mOomAdjuster.onProcessBeginLocked(app);
- }
}
/**
@@ -270,7 +259,6 @@
@SuppressWarnings("GuardedBy")
private void updateOomAdj(ProcessRecord... apps) {
if (apps.length == 1) {
- sService.mOomAdjuster.onProcessBeginLocked(apps[0]);
sService.mOomAdjuster.updateOomAdjLocked(apps[0], OOM_ADJ_REASON_NONE);
} else {
setProcessesToLru(apps);
@@ -612,13 +600,10 @@
s.lastTopAlmostPerceptibleBindRequestUptimeMs = nowUptime;
s.getConnections().clear();
app.mServices.updateHasTopStartedAlmostPerceptibleServices();
- sService.mOomAdjuster.onProcessBeginLocked(system);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
updateOomAdj(app);
assertEquals(PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ + 2, app.mState.getSetAdj());
-
- sService.mOomAdjuster.resetInternal();
}
// Out of grace period but valid binding allows the adjustment.
@@ -635,13 +620,10 @@
s.lastTopAlmostPerceptibleBindRequestUptimeMs =
nowUptime - 2 * sService.mConstants.mServiceBindAlmostPerceptibleTimeoutMs;
app.mServices.updateHasTopStartedAlmostPerceptibleServices();
- sService.mOomAdjuster.onProcessBeginLocked(system);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
updateOomAdj(app);
assertEquals(PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ + 2, app.mState.getSetAdj());
-
- sService.mOomAdjuster.resetInternal();
}
// Out of grace period and no valid binding so no adjustment.
@@ -659,13 +641,10 @@
nowUptime - 2 * sService.mConstants.mServiceBindAlmostPerceptibleTimeoutMs;
s.getConnections().clear();
app.mServices.updateHasTopStartedAlmostPerceptibleServices();
- sService.mOomAdjuster.onProcessBeginLocked(system);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
updateOomAdj(app);
assertNotEquals(PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ + 2, app.mState.getSetAdj());
-
- sService.mOomAdjuster.resetInternal();
}
}
@@ -678,12 +657,11 @@
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, true));
system.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
system.mState.setHasTopUi(true);
- sService.mOomAdjuster.onProcessBeginLocked(system);
// Simulate the system starting and binding to a service in the app.
ServiceRecord s = bindService(app, system,
null, Context.BIND_ALMOST_PERCEPTIBLE, mock(IBinder.class));
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
- updateOomAdj(system, app);
+ sService.mOomAdjuster.updateOomAdjLocked(app, OOM_ADJ_REASON_NONE);
assertProcStates(app, PROCESS_STATE_IMPORTANT_FOREGROUND,
PERCEPTIBLE_APP_ADJ + 1, SCHED_GROUP_DEFAULT);
@@ -872,7 +850,6 @@
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
- client.mServices.setTreatLikeActivity(true);
bindService(app, client, null, Context.BIND_WAIVE_PRIORITY
| Context.BIND_TREAT_LIKE_ACTIVITY, mock(IBinder.class));
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
@@ -1029,7 +1006,7 @@
bindService(app, client, null, Context.BIND_NOT_FOREGROUND, mock(IBinder.class));
client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
- updateOomAdj(client, app);
+ updateOomAdj(app);
assertEquals(PROCESS_STATE_TRANSIENT_BACKGROUND, app.mState.getSetProcState());
assertNoBfsl(app);
@@ -1155,7 +1132,7 @@
assertNoBfsl(app);
client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
- updateOomAdj(client, app);
+ updateOomAdj(app);
assertEquals(PERSISTENT_SERVICE_ADJ, app.mState.getSetAdj());
assertBfsl(app);
@@ -1171,7 +1148,7 @@
bindService(app, client, null, Context.BIND_NOT_PERCEPTIBLE, mock(IBinder.class));
client.mState.setRunningRemoteAnimation(true);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
- updateOomAdj(client, app);
+ updateOomAdj(app);
assertEquals(PERCEPTIBLE_LOW_APP_ADJ, app.mState.getSetAdj());
}
@@ -1222,8 +1199,6 @@
updateOomAdj(client, app);
assertEquals(PERCEPTIBLE_MEDIUM_APP_ADJ + 2, app.mState.getSetAdj());
-
- sService.mOomAdjuster.resetInternal();
}
{
@@ -1242,8 +1217,6 @@
doReturn(false).when(wpc).isHeavyWeightProcess();
assertEquals(PERCEPTIBLE_MEDIUM_APP_ADJ + 2, app.mState.getSetAdj());
-
- sService.mOomAdjuster.resetInternal();
}
{
@@ -1256,11 +1229,9 @@
mock(IBinder.class));
client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
- updateOomAdj(client, app);
+ sService.mOomAdjuster.updateOomAdjLocked(app, OOM_ADJ_REASON_NONE);
assertEquals(PERCEPTIBLE_APP_ADJ + 1, app.mState.getSetAdj());
-
- sService.mOomAdjuster.resetInternal();
}
{
@@ -1275,12 +1246,10 @@
mock(IBinder.class));
client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
- updateOomAdj(client, app);
+ sService.mOomAdjuster.updateOomAdjLocked(app, OOM_ADJ_REASON_NONE);
doReturn(false).when(wpc).isHeavyWeightProcess();
assertEquals(PERCEPTIBLE_APP_ADJ + 1, app.mState.getSetAdj());
-
- sService.mOomAdjuster.resetInternal();
}
}
@@ -1880,7 +1849,7 @@
bindService(app1, client1, null, Context.BIND_SCHEDULE_LIKE_TOP_APP, mock(IBinder.class));
bindService(app2, client2, null, Context.BIND_SCHEDULE_LIKE_TOP_APP, mock(IBinder.class));
- updateOomAdj(client1, client2, app1, app2);
+ updateOomAdj(app1, app2);
assertProcStates(app1, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, VISIBLE_APP_ADJ,
SCHED_GROUP_TOP_APP);
@@ -1930,8 +1899,6 @@
s1.getConnections().clear();
s2.getConnections().clear();
- client1.mServices.removeAllConnections();
- client2.mServices.removeAllConnections();
client1.mState.setMaxAdj(UNKNOWN_ADJ);
client2.mState.setMaxAdj(UNKNOWN_ADJ);
client1.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
@@ -1942,7 +1909,7 @@
bindService(app2, client2, s2, Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE,
mock(IBinder.class));
- updateOomAdj(client1, client2, app1, app2);
+ updateOomAdj(app1, app2);
// VISIBLE_APP_ADJ is the max oom-adj for BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE.
assertProcStates(app1, PROCESS_STATE_FOREGROUND_SERVICE, VISIBLE_APP_ADJ,
@@ -1955,7 +1922,7 @@
doReturn(client2).when(sService).getTopApp();
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
- updateOomAdj(client2, app2);
+ sService.mOomAdjuster.updateOomAdjLocked(app2, OOM_ADJ_REASON_NONE);
assertProcStates(app2, PROCESS_STATE_BOUND_TOP, VISIBLE_APP_ADJ,
SCHED_GROUP_DEFAULT);
}
@@ -2010,7 +1977,6 @@
app.setPendingFinishAttach(true);
app.mState.setHasForegroundActivities(false);
- sService.mOomAdjuster.onProcessBeginLocked(app);
sService.mOomAdjuster.setAttachingProcessStatesLSP(app);
updateOomAdj(app);
@@ -2025,9 +1991,7 @@
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
app.setPendingFinishAttach(true);
app.mState.setHasForegroundActivities(true);
- doReturn(app).when(sService).getTopApp();
- sService.mOomAdjuster.onProcessBeginLocked(app);
sService.mOomAdjuster.setAttachingProcessStatesLSP(app);
updateOomAdj(app);
@@ -2124,7 +2088,7 @@
anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
doNothing().when(sService.mServices)
.scheduleServiceTimeoutLocked(any(ProcessRecord.class));
- updateOomAdj(client1, client2, app1, app2, app3);
+ sService.mOomAdjuster.updateOomAdjLocked(client1, OOM_ADJ_REASON_NONE);
assertEquals(PROCESS_STATE_CACHED_EMPTY, client1.mState.getSetProcState());
assertEquals(PROCESS_STATE_SERVICE, app1.mState.getSetProcState());
@@ -2462,8 +2426,6 @@
lru.clear();
lru.add(app2);
lru.add(app);
- sService.mOomAdjuster.onProcessBeginLocked(app2);
- sService.mOomAdjuster.onProcessBeginLocked(app);
final ComponentName cn = ComponentName.unflattenFromString(
MOCKAPP_PACKAGENAME + "/.TestService");
@@ -2566,7 +2528,7 @@
doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
doReturn(app).when(sService).getTopApp();
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
- updateOomAdj(app);
+ sService.mOomAdjuster.updateOomAdjLocked(app, OOM_ADJ_REASON_NONE);
assertEquals(FOREGROUND_APP_ADJ, app.mState.getSetAdj());