Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 44db5155 authored by Jing Ji's avatar Jing Ji
Browse files

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
parent b39f70ce
Loading
Loading
Loading
Loading
+27 −21
Original line number Diff line number Diff line
@@ -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);
            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++;
@@ -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");
+10 −0
Original line number Diff line number Diff line
@@ -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();
    }
}
+30 −103
Original line number Diff line number Diff line
@@ -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,
@@ -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
     */
@@ -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;
                }
            }
        }
+2 −0
Original line number Diff line number Diff line
@@ -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();

+18 −0
Original line number Diff line number Diff line
@@ -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