Loading services/core/java/com/android/server/am/ActiveServices.java +27 −21 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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) { Loading Loading @@ -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); Loading Loading @@ -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 { Loading Loading @@ -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 { Loading Loading @@ -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); 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.mOomAdjBumpedInExec = true; } } r.executeFg |= fg; r.executeNesting++; Loading Loading @@ -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) { Loading @@ -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; } Loading Loading @@ -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. Loading Loading @@ -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. Loading Loading @@ -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); Loading Loading @@ -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()) { Loading @@ -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, Loading Loading @@ -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) { Loading Loading @@ -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 { Loading Loading @@ -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) { Loading Loading @@ -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(); } Loading Loading @@ -9013,6 +9016,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; Loading Loading @@ -9075,6 +9079,7 @@ public final class ActiveServices { } } if (r != null) { r.updateOomAdjSeq(); bringDownServiceLocked(r, false); } else { Slog.e(TAG, "stopForegroundServiceDelegateLocked delegate does not exist " Loading @@ -9100,6 +9105,7 @@ public final class ActiveServices { } } if (r != null) { r.updateOomAdjSeq(); bringDownServiceLocked(r, false); } else { Slog.e(TAG, "stopForegroundServiceDelegateLocked delegate does not exist"); Loading services/core/java/com/android/server/am/ActivityManagerService.java +10 −0 Original line number Diff line number Diff line Loading @@ -20868,4 +20868,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(); } } services/core/java/com/android/server/am/OomAdjuster.java +30 −103 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -517,59 +523,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 */ Loading Loading @@ -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; Loading Loading @@ -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); Loading @@ -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) { Loading @@ -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 Loading Loading @@ -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; Loading @@ -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); Loading Loading @@ -1337,6 +1261,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; } Loading Loading @@ -1882,7 +1807,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. Loading Loading @@ -3286,13 +3211,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; } } } Loading services/core/java/com/android/server/am/OomAdjusterModernImpl.java +2 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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(); Loading services/core/java/com/android/server/am/PendingStartActivityUids.java +18 −0 Original line number Diff line number Diff line Loading @@ -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(); } } Loading
services/core/java/com/android/server/am/ActiveServices.java +27 −21 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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) { Loading Loading @@ -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); Loading Loading @@ -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 { Loading Loading @@ -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 { Loading Loading @@ -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); 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.mOomAdjBumpedInExec = true; } } r.executeFg |= fg; r.executeNesting++; Loading Loading @@ -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) { Loading @@ -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; } Loading Loading @@ -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. Loading Loading @@ -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. Loading Loading @@ -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); Loading Loading @@ -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()) { Loading @@ -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, Loading Loading @@ -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) { Loading Loading @@ -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 { Loading Loading @@ -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) { Loading Loading @@ -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(); } Loading Loading @@ -9013,6 +9016,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; Loading Loading @@ -9075,6 +9079,7 @@ public final class ActiveServices { } } if (r != null) { r.updateOomAdjSeq(); bringDownServiceLocked(r, false); } else { Slog.e(TAG, "stopForegroundServiceDelegateLocked delegate does not exist " Loading @@ -9100,6 +9105,7 @@ public final class ActiveServices { } } if (r != null) { r.updateOomAdjSeq(); bringDownServiceLocked(r, false); } else { Slog.e(TAG, "stopForegroundServiceDelegateLocked delegate does not exist"); Loading
services/core/java/com/android/server/am/ActivityManagerService.java +10 −0 Original line number Diff line number Diff line Loading @@ -20868,4 +20868,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(); } }
services/core/java/com/android/server/am/OomAdjuster.java +30 −103 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -517,59 +523,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 */ Loading Loading @@ -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; Loading Loading @@ -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); Loading @@ -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) { Loading @@ -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 Loading Loading @@ -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; Loading @@ -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); Loading Loading @@ -1337,6 +1261,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; } Loading Loading @@ -1882,7 +1807,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. Loading Loading @@ -3286,13 +3211,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; } } } Loading
services/core/java/com/android/server/am/OomAdjusterModernImpl.java +2 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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(); Loading
services/core/java/com/android/server/am/PendingStartActivityUids.java +18 −0 Original line number Diff line number Diff line Loading @@ -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(); } }