diff options
| author | 2024-03-20 00:08:56 -0700 | |
|---|---|---|
| committer | 2024-03-25 14:17:38 -0700 | |
| commit | 44db5155b5639c849d9308820717717e93373897 (patch) | |
| tree | 2b700b26ead101de6de93b4fc857db564d6c70b2 | |
| parent | b39f70cee098695b9087ac45bdaa8baaa3a51bbf (diff) | |
Fix various bugs in OomAdjuster
* The UID state update for pending attach process is missing.
* The legacy partial oom adj update will skip updating the downstream
processes if target process's state isn't changing between fg/bg,
it'll cause issues with downstream processes. Now remove this,
and we'll also scan the whole chain of the downstream, along with
the target app. We're also scanning pending oom adj targets as
an opportunistic thing, given the high overhead of oom adj update.
* The new "skip oom adj update on service binding" actually had
incompatibility with the assumption of partial oom adj updates:
when we update a target process, we always assume the states of
its upstream processes are fixed and we don't need to calculate it.
But it's not true for the new "skip oom adj update on service
binding", because if we skipped the oom adj update of the service
host, if we happen to do an oom adj update for one of its downstream
processes, we may need to re-evaluate that service host, especially
with the legacy oom adj algorithm. As a mitigation to this problem,
now we're enqueueing the service host prior to executing the service,
although we're not necessarily running the oom adj updates for sure.
* The updates of the short fgs info was done after the oom adj
update, this could make the oom adj thinks it's not a short fgs until
the next oom adj update.
* The WM will run oom adj updates asynchronously, meanwhile the proc
state of the top app has been changed - in case before the async
update happens for real, if another partial update happens and the
top app is in the upstream of the target, it may confuse the
algorithm because it didn't expect the top app also needs to be
updated.
* The legacy oom adj update with cycles, will actually skip using
the partial procstate and adj to adjust the effect of the binding,
now fix it. And also check the capability changes too.
Bug: 329505886
Bug: 330410787
Test: atest FrameworksMockingServicesTests:MockingOomAdjusterTests
Test: atest FrameworksMockingServicesTests:ServiceBindingOomAdjPolicyTest
Test: Manual - b/329505886#comment1
Change-Id: I02724e123d2825b2c0eef33b741de3fdd103f290
8 files changed, 110 insertions, 135 deletions
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 133a77df3573..3b49eee368a2 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -2659,6 +2659,9 @@ public final class ActiveServices { } updateNumForegroundServicesLocked(); } + + maybeUpdateShortFgsTrackingLocked(r, + extendShortServiceTimeout); // Even if the service is already a FGS, we need to update the notification, // so we need to call it again. signalForegroundServiceObserversLocked(r); @@ -2670,8 +2673,6 @@ public final class ActiveServices { mAm.notifyPackageUse(r.serviceInfo.packageName, PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE); - maybeUpdateShortFgsTrackingLocked(r, - extendShortServiceTimeout); maybeUpdateFgsTrackingLocked(r, extendFgsTimeout); } else { if (DEBUG_FOREGROUND_SERVICE) { @@ -4158,7 +4159,7 @@ public final class ActiveServices { || (callerApp.mState.getCurProcState() <= PROCESS_STATE_TOP && c.hasFlag(Context.BIND_TREAT_LIKE_ACTIVITY)), b.client); - if (!s.mOomAdjBumpedInExec && (serviceBindingOomAdjPolicy + if (!s.wasOomAdjUpdated() && (serviceBindingOomAdjPolicy & SERVICE_BIND_OOMADJ_POLICY_SKIP_OOM_UPDATE_ON_CONNECT) == 0) { needOomAdj = true; mAm.enqueueOomAdjTargetLocked(s.app); @@ -4308,7 +4309,7 @@ public final class ActiveServices { } serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false, false, - !Flags.serviceBindingOomAdjPolicy() || r.mOomAdjBumpedInExec + !Flags.serviceBindingOomAdjPolicy() || r.wasOomAdjUpdated() ? OOM_ADJ_REASON_EXECUTING_SERVICE : OOM_ADJ_REASON_NONE); } } finally { @@ -4456,7 +4457,7 @@ public final class ActiveServices { } serviceDoneExecutingLocked(r, inDestroying, false, false, - !Flags.serviceBindingOomAdjPolicy() || r.mOomAdjBumpedInExec + !Flags.serviceBindingOomAdjPolicy() || r.wasOomAdjUpdated() ? OOM_ADJ_REASON_UNBIND_SERVICE : OOM_ADJ_REASON_NONE); } } finally { @@ -5004,13 +5005,16 @@ public final class ActiveServices { } } } - if (oomAdjReason != OOM_ADJ_REASON_NONE && r.app != null + if (r.app != null && r.app.mState.getCurProcState() > ActivityManager.PROCESS_STATE_SERVICE) { - // Force an immediate oomAdjUpdate, so the client app could be in the correct process - // state before doing any service related transactions + // Enqueue the oom adj target anyway for opportunistic oom adj updates. mAm.enqueueOomAdjTargetLocked(r.app); - mAm.updateOomAdjPendingTargetsLocked(oomAdjReason); - r.mOomAdjBumpedInExec = true; + r.updateOomAdjSeq(); + if (oomAdjReason != OOM_ADJ_REASON_NONE) { + // Force an immediate oomAdjUpdate, so the client app could be in the correct + // process state before doing any service related transactions + mAm.updateOomAdjPendingTargetsLocked(oomAdjReason); + } } r.executeFg |= fg; r.executeNesting++; @@ -5050,7 +5054,7 @@ public final class ActiveServices { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r, e); final boolean inDestroying = mDestroyingServices.contains(r); serviceDoneExecutingLocked(r, inDestroying, inDestroying, false, - !Flags.serviceBindingOomAdjPolicy() || r.mOomAdjBumpedInExec + !Flags.serviceBindingOomAdjPolicy() || r.wasOomAdjUpdated() ? OOM_ADJ_REASON_UNBIND_SERVICE : OOM_ADJ_REASON_NONE); throw e; } catch (RemoteException e) { @@ -5058,7 +5062,7 @@ public final class ActiveServices { // Keep the executeNesting count accurate. final boolean inDestroying = mDestroyingServices.contains(r); serviceDoneExecutingLocked(r, inDestroying, inDestroying, false, - !Flags.serviceBindingOomAdjPolicy() || r.mOomAdjBumpedInExec + !Flags.serviceBindingOomAdjPolicy() || r.wasOomAdjUpdated() ? OOM_ADJ_REASON_UNBIND_SERVICE : OOM_ADJ_REASON_NONE); return false; } @@ -5854,8 +5858,8 @@ public final class ActiveServices { // Force an immediate oomAdjUpdate, so the host app could be in the correct // process state before doing any service related transactions mAm.enqueueOomAdjTargetLocked(app); + r.updateOomAdjSeq(); mAm.updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_START_SERVICE); - r.mOomAdjBumpedInExec = true; } else { // Since we skipped the oom adj update, the Service#onCreate() might be running in // the cached state, if the service process drops into the cached state after the call. @@ -5896,7 +5900,7 @@ public final class ActiveServices { // Keep the executeNesting count accurate. final boolean inDestroying = mDestroyingServices.contains(r); serviceDoneExecutingLocked(r, inDestroying, inDestroying, false, - !Flags.serviceBindingOomAdjPolicy() || r.mOomAdjBumpedInExec + !Flags.serviceBindingOomAdjPolicy() || r.wasOomAdjUpdated() ? OOM_ADJ_REASON_STOP_SERVICE : OOM_ADJ_REASON_NONE); // Cleanup. @@ -5932,7 +5936,7 @@ public final class ActiveServices { null, null, 0, null, null, ActivityManager.PROCESS_STATE_UNKNOWN)); } - sendServiceArgsLocked(r, execInFg, r.mOomAdjBumpedInExec); + sendServiceArgsLocked(r, execInFg, r.wasOomAdjUpdated()); if (r.delayed) { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r); @@ -6119,7 +6123,7 @@ public final class ActiveServices { } } - boolean oomAdjusted = Flags.serviceBindingOomAdjPolicy() && r.mOomAdjBumpedInExec; + boolean oomAdjusted = Flags.serviceBindingOomAdjPolicy() && r.wasOomAdjUpdated(); // Tell the service that it has been unbound. if (r.app != null && r.app.isThreadReady()) { @@ -6132,7 +6136,7 @@ public final class ActiveServices { bumpServiceExecutingLocked(r, false, "bring down unbind", oomAdjusted ? OOM_ADJ_REASON_NONE : OOM_ADJ_REASON_UNBIND_SERVICE, oomAdjusted /* skipTimeoutIfPossible */); - oomAdjusted |= r.mOomAdjBumpedInExec; + oomAdjusted |= r.wasOomAdjUpdated(); ibr.hasBound = false; ibr.requested = false; r.app.getThread().scheduleUnbindService(r, @@ -6292,7 +6296,7 @@ public final class ActiveServices { oomAdjusted ? OOM_ADJ_REASON_NONE : OOM_ADJ_REASON_UNBIND_SERVICE, oomAdjusted /* skipTimeoutIfPossible */); mDestroyingServices.add(r); - oomAdjusted |= r.mOomAdjBumpedInExec; + oomAdjusted |= r.wasOomAdjUpdated(); r.destroying = true; r.app.getThread().scheduleStopService(r); } catch (Exception e) { @@ -6579,7 +6583,7 @@ public final class ActiveServices { } final long origId = mAm.mInjector.clearCallingIdentity(); serviceDoneExecutingLocked(r, inDestroying, inDestroying, enqueueOomAdj, - !Flags.serviceBindingOomAdjPolicy() || r.mOomAdjBumpedInExec || needOomAdj + !Flags.serviceBindingOomAdjPolicy() || r.wasOomAdjUpdated() || needOomAdj ? OOM_ADJ_REASON_EXECUTING_SERVICE : OOM_ADJ_REASON_NONE); mAm.mInjector.restoreCallingIdentity(origId); } else { @@ -6645,7 +6649,7 @@ public final class ActiveServices { } else { // Skip oom adj if it wasn't bumped during the bumpServiceExecutingLocked() } - r.mOomAdjBumpedInExec = false; + r.updateOomAdjSeq(); } r.executeFg = false; if (r.tracker != null) { @@ -7029,7 +7033,6 @@ public final class ActiveServices { sr.setProcess(null, null, 0, null); sr.isolationHostProc = null; sr.executeNesting = 0; - sr.mOomAdjBumpedInExec = false; synchronized (mAm.mProcessStats.mLock) { sr.forceClearTracker(); } @@ -9009,6 +9012,7 @@ public final class ActiveServices { r.isForeground = true; r.mFgsEnterTime = SystemClock.uptimeMillis(); r.foregroundServiceType = options.mForegroundServiceTypes; + r.updateOomAdjSeq(); setFgsRestrictionLocked(callingPackage, callingPid, callingUid, intent, r, userId, BackgroundStartPrivileges.NONE, false /* isBindService */); final ProcessServiceRecord psr = callerApp.mServices; @@ -9071,6 +9075,7 @@ public final class ActiveServices { } } if (r != null) { + r.updateOomAdjSeq(); bringDownServiceLocked(r, false); } else { Slog.e(TAG, "stopForegroundServiceDelegateLocked delegate does not exist " @@ -9096,6 +9101,7 @@ public final class ActiveServices { } } if (r != null) { + r.updateOomAdjSeq(); bringDownServiceLocked(r, false); } else { Slog.e(TAG, "stopForegroundServiceDelegateLocked delegate does not exist"); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 447dfd95e034..a626e675cd5b 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -20817,4 +20817,14 @@ public class ActivityManagerService extends IActivityManager.Stub } mOomAdjuster.mCachedAppOptimizer.binderError(debugPid, app, code, flags, err); } + + @GuardedBy("this") + void enqueuePendingTopAppIfNecessaryLocked() { + mPendingStartActivityUids.enqueuePendingTopAppIfNecessaryLocked(this); + } + + @GuardedBy("this") + void clearPendingTopAppLocked() { + mPendingStartActivityUids.clear(); + } } diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 1a7629f3182d..d13811f33658 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -409,6 +409,12 @@ public class OomAdjuster { private final OomAdjusterDebugLogger mLogger; + /** + * The process state of the current TOP app. + */ + @GuardedBy("mService") + protected int mProcessStateCurTop = PROCESS_STATE_TOP; + /** Overrideable by a test */ @VisibleForTesting protected boolean isChangeEnabled(@CachedCompatChangeId int cachedCompatChangeId, @@ -518,59 +524,6 @@ public class OomAdjuster { } /** - * Perform oom adj update on the given process. It does NOT do the re-computation - * if there is a cycle, caller should check {@link #mProcessesInCycle} and do it on its own. - */ - @GuardedBy({"mService", "mProcLock"}) - private boolean performUpdateOomAdjLSP(ProcessRecord app, int cachedAdj, - ProcessRecord topApp, long now, @OomAdjReason int oomAdjReason) { - if (app.getThread() == null) { - return false; - } - - app.mState.resetCachedInfo(); - app.mState.setCurBoundByNonBgRestrictedApp(false); - UidRecord uidRec = app.getUidRecord(); - if (uidRec != null) { - if (DEBUG_UID_OBSERVERS) { - Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec); - } - uidRec.reset(); - } - - // Check if this process is in the pending list too, remove from pending list if so. - mPendingProcessSet.remove(app); - - mProcessesInCycle.clear(); - computeOomAdjLSP(app, cachedAdj, topApp, false, now, false, true, oomAdjReason, 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--) { - // Reset the adj seq - mProcessesInCycle.valueAt(i).mState.setCompletedAdjSeq(mAdjSeq - 1); - } - return true; - } - - if (uidRec != null) { - // After uidRec.reset() above, for UidRecord with multiple processes (ProcessRecord), - // we need to apply all ProcessRecord into UidRecord. - uidRec.forEachProcess(this::updateAppUidRecIfNecessaryLSP); - if (uidRec.getCurProcState() != PROCESS_STATE_NONEXISTENT - && (uidRec.getSetProcState() != uidRec.getCurProcState() - || uidRec.getSetCapability() != uidRec.getCurCapability() - || uidRec.isSetAllowListed() != uidRec.isCurAllowListed())) { - final ActiveUids uids = mTmpUidRecords; - uids.clear(); - uids.put(uidRec.getUid(), uidRec); - updateUidsLSP(uids, SystemClock.elapsedRealtime()); - } - } - - return applyOomAdjLSP(app, false, now, SystemClock.elapsedRealtime(), oomAdjReason); - } - - /** * Update OomAdj for all processes in LRU list */ @GuardedBy("mService") @@ -599,6 +552,7 @@ public class OomAdjuster { @GuardedBy({"mService", "mProcLock"}) protected void performUpdateOomAdjLSP(@OomAdjReason int oomAdjReason) { final ProcessRecord topApp = mService.getTopApp(); + mProcessStateCurTop = mService.mAtmInternal.getTopProcessState(); // Clear any pending ones because we are doing a full update now. mPendingProcessSet.clear(); mService.mAppProfiler.mHasPreviousProcess = mService.mAppProfiler.mHasHomeProcess = false; @@ -649,54 +603,14 @@ public class OomAdjuster { mLastReason = oomAdjReason; Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason)); mService.mOomAdjProfiler.oomAdjStarted(); - mAdjSeq++; 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(); - state.setContainsCycle(false); - state.setProcStateChanged(false); - state.resetCachedInfo(); - state.setCurBoundByNonBgRestrictedApp(false); - // Check if this process is in the pending list too, remove from pending list if so. - mPendingProcessSet.remove(app); - app.mOptRecord.setLastOomAdjChangeReason(oomAdjReason); - boolean success = performUpdateOomAdjLSP(app, cachedAdj, topApp, - SystemClock.uptimeMillis(), oomAdjReason); - // The 'app' here itself might or might not be in the cycle, for example, - // the case A <=> B vs. A -> B <=> C; anyway, if we spot a cycle here, re-compute them. - if (!success || (wasCached == state.isCached() && oldAdj != INVALID_ADJ - && mProcessesInCycle.isEmpty() /* Force re-compute if there is a cycle */ - && oldCap == state.getCurCapability() - && wasBackground == ActivityManager.isProcStateBackground( - state.getSetProcState()))) { - mProcessesInCycle.clear(); - // Okay, it's unchanged, it won't impact any service it binds to, we're done here. - if (DEBUG_OOM_ADJ) { - Slog.i(TAG_OOM_ADJ, "No oomadj changes for " + app); - } - mService.mOomAdjProfiler.oomAdjEnded(); - Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); - return success; - } // Next to find out all its reachable processes ArrayList<ProcessRecord> processes = mTmpProcessList; ActiveUids uids = mTmpUidRecords; mPendingProcessSet.add(app); - - // Add all processes with cycles into the list to scan - for (int i = mProcessesInCycle.size() - 1; i >= 0; i--) { - mPendingProcessSet.add(mProcessesInCycle.valueAt(i)); - } - mProcessesInCycle.clear(); + mProcessStateCurTop = enqueuePendingTopAppIfNecessaryLSP(); boolean containsCycle = collectReachableProcessesLocked(mPendingProcessSet, processes, uids); @@ -704,14 +618,8 @@ public class OomAdjuster { // Clear the pending set as they should've been included in 'processes'. mPendingProcessSet.clear(); - if (!containsCycle) { - // Remove this app from the return list because we've done the computation on it. - processes.remove(app); - } - int size = processes.size(); if (size > 0) { - mAdjSeq--; // Update these reachable processes updateOomAdjInnerLSP(oomAdjReason, topApp, processes, uids, containsCycle, false); } else if (state.getCurRawAdj() == UNKNOWN_ADJ) { @@ -723,11 +631,25 @@ public class OomAdjuster { SystemClock.elapsedRealtime(), oomAdjReason); } mTmpProcessList.clear(); + mService.clearPendingTopAppLocked(); mService.mOomAdjProfiler.oomAdjEnded(); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); return true; } + @GuardedBy({"mService", "mProcLock"}) + protected int enqueuePendingTopAppIfNecessaryLSP() { + final int prevTopProcessState = mService.mAtmInternal.getTopProcessState(); + mService.enqueuePendingTopAppIfNecessaryLocked(); + final int topProcessState = mService.mAtmInternal.getTopProcessState(); + if (prevTopProcessState != topProcessState) { + // Unlikely but possible: WM just updated the top process state, it may have + // enqueued the new top app to the pending top UID list. Enqueue that one here too. + mService.enqueuePendingTopAppIfNecessaryLocked(); + } + return topProcessState; + } + /** * 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 @@ -930,6 +852,7 @@ public class OomAdjuster { mLastReason = oomAdjReason; Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason)); mService.mOomAdjProfiler.oomAdjStarted(); + mProcessStateCurTop = enqueuePendingTopAppIfNecessaryLSP(); final ArrayList<ProcessRecord> processes = mTmpProcessList; final ActiveUids uids = mTmpUidRecords; @@ -939,6 +862,7 @@ public class OomAdjuster { updateOomAdjInnerLSP(oomAdjReason, topApp, processes, uids, true, false); } processes.clear(); + mService.clearPendingTopAppLocked(); mService.mOomAdjProfiler.oomAdjEnded(); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); @@ -1342,6 +1266,7 @@ public class OomAdjuster { // Avoid trimming processes that are still initializing. If they aren't // hosting any components yet because they may be unfairly killed. // We however apply the oom scores set at #setAttachingProcessStatesLSP. + updateAppUidRecLSP(app); continue; } @@ -1887,7 +1812,7 @@ public class OomAdjuster { state.setSystemNoUi(false); - final int PROCESS_STATE_CUR_TOP = mService.mAtmInternal.getTopProcessState(); + final int PROCESS_STATE_CUR_TOP = mProcessStateCurTop; // Determine the importance of the process, starting with most // important to least, and assign an appropriate OOM adjustment. @@ -3291,13 +3216,15 @@ public class OomAdjuster { // If the partial values are no better, skip until the next // attempt if (client.getCurRawProcState() >= procState - && client.getCurRawAdj() >= adj) { + && client.getCurRawAdj() >= adj + && (client.getCurCapability() & app.mState.getCurCapability()) + == client.getCurCapability()) { return true; } // Else use the client's partial procstate and adj to adjust the // effect of the binding } else { - return true; + return false; } } } diff --git a/services/core/java/com/android/server/am/OomAdjusterModernImpl.java b/services/core/java/com/android/server/am/OomAdjusterModernImpl.java index 5feac1ff92cb..00e148287b67 100644 --- a/services/core/java/com/android/server/am/OomAdjusterModernImpl.java +++ b/services/core/java/com/android/server/am/OomAdjusterModernImpl.java @@ -737,6 +737,7 @@ public class OomAdjusterModernImpl extends OomAdjuster { @Override protected void performUpdateOomAdjLSP(@OomAdjReason int oomAdjReason) { final ProcessRecord topApp = mService.getTopApp(); + mProcessStateCurTop = mService.mAtmInternal.getTopProcessState(); // Clear any pending ones because we are doing a full update now. mPendingProcessSet.clear(); mService.mAppProfiler.mHasPreviousProcess = mService.mAppProfiler.mHasHomeProcess = false; @@ -763,6 +764,7 @@ public class OomAdjusterModernImpl extends OomAdjuster { @Override protected void performUpdateOomAdjPendingTargetsLocked(@OomAdjReason int oomAdjReason) { mLastReason = oomAdjReason; + mProcessStateCurTop = enqueuePendingTopAppIfNecessaryLSP(); Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason)); mService.mOomAdjProfiler.oomAdjStarted(); diff --git a/services/core/java/com/android/server/am/PendingStartActivityUids.java b/services/core/java/com/android/server/am/PendingStartActivityUids.java index da09317add90..e912d07fb42d 100644 --- a/services/core/java/com/android/server/am/PendingStartActivityUids.java +++ b/services/core/java/com/android/server/am/PendingStartActivityUids.java @@ -87,4 +87,22 @@ final class PendingStartActivityUids { synchronized boolean isPendingTopUid(int uid) { return mPendingUids.get(uid) != null; } + + // Must called with AMS locked. + synchronized void enqueuePendingTopAppIfNecessaryLocked(ActivityManagerService ams) { + for (int i = 0, size = mPendingUids.size(); i < size; i++) { + final Pair<Integer, Long> p = mPendingUids.valueAt(i); + final ProcessRecord app; + synchronized (ams.mPidsSelfLocked) { + app = ams.mPidsSelfLocked.get(p.first); + } + if (app != null) { + ams.enqueueOomAdjTargetLocked(app); + } + } + } + + synchronized void clear() { + mPendingUids.clear(); + } } diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java index e3aac0251141..5834dcd06ba9 100644 --- a/services/core/java/com/android/server/am/ServiceRecord.java +++ b/services/core/java/com/android/server/am/ServiceRecord.java @@ -267,9 +267,13 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN int mAllowStart_byBindings = REASON_DENIED; /** - * Whether or not we've bumped its oom adj scores during its execution. + * The oom adj seq number snapshot of the host process. We're taking a snapshot + * before executing the service. Since we may or may not bump the host process's + * proc state / oom adj value before that, at the end of the execution, we could + * compare this seq against the current seq of the host process to see if we could + * skip the oom adj update from there too. */ - boolean mOomAdjBumpedInExec; + int mAdjSeq; /** * Whether to use the new "while-in-use permission" logic for FGS start @@ -1884,4 +1888,17 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN } return true; } + + /** + * @return {@code true} if the host process has updated its oom adj scores. + */ + boolean wasOomAdjUpdated() { + return app != null && app.mState.getAdjSeq() > mAdjSeq; + } + + void updateOomAdjSeq() { + if (app != null) { + mAdjSeq = app.mState.getAdjSeq(); + } + } } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 060f1c8cfac0..5dbe5a946703 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -5060,6 +5060,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_MANAGER_SLEEP_STATE_CHANGED, FrameworkStatsLog.ACTIVITY_MANAGER_SLEEP_STATE_CHANGED__STATE__AWAKE); startTimeTrackingFocusedActivityLocked(); + if (mTopApp != null) { + mTopApp.addToPendingTop(); + } mTopProcessState = ActivityManager.PROCESS_STATE_TOP; Slog.d(TAG, "Top Process State changed to PROCESS_STATE_TOP"); mTaskSupervisor.comeOutOfSleepIfNeededLocked(); 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 872ac40a4d76..4c7a8fef6f0b 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java @@ -479,15 +479,7 @@ public class MockingOomAdjusterTests { sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE); updateOomAdj(app); - final int expectedAdj; - if (sService.mConstants.ENABLE_NEW_OOMADJ) { - // A cached empty process can be at best a level higher than the min cached adj. - expectedAdj = sFirstCachedAdj; - } else { - // This is wrong but legacy behavior is going to be removed and not worth fixing. - expectedAdj = CACHED_APP_MIN_ADJ; - } - + final int expectedAdj = sFirstCachedAdj; assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND); } |