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

Commit 3a18f339 authored by Jing Ji's avatar Jing Ji Committed by Automerger Merge Worker
Browse files

Merge "Add a few fine-grained locks in the ActivityManagerService" into sc-dev am: 5fe6130c

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13425780

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I5e297af355dc4a9796c8608b97d5e6611b837f5e
parents 350911f5 5fe6130c
Loading
Loading
Loading
Loading
+149 −82

File changed.

Preview size limit exceeded, changes collapsed.

+560 −1733

File changed.

Preview size limit exceeded, changes collapsed.

+2 −2
Original line number Diff line number Diff line
@@ -71,8 +71,8 @@ final class AppErrorDialog extends BaseErrorDialog implements View.OnClickListen
        BidiFormatter bidi = BidiFormatter.getInstance();

        CharSequence name;
        if ((mProc.pkgList.size() == 1) &&
                (name = context.getPackageManager().getApplicationLabel(mProc.info)) != null) {
        if ((mProc.getPkgList().size() == 1)
                && (name = context.getPackageManager().getApplicationLabel(mProc.info)) != null) {
            setTitle(res.getString(
                    data.repeating ? com.android.internal.R.string.aerr_application_repeated
                            : com.android.internal.R.string.aerr_application,
+330 −285
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import android.util.SparseArray;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.ProcessMap;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
@@ -74,27 +75,32 @@ class AppErrors {
    private final Context mContext;
    private final PackageWatchdog mPackageWatchdog;

    @GuardedBy("mBadProcessLock")
    private ArraySet<String> mAppsNotReportingCrashes;

    /**
     * The last time that various processes have crashed since they were last explicitly started.
     */
    @GuardedBy("mBadProcessLock")
    private final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<>();

    /**
     * The last time that various processes have crashed (not reset even when explicitly started).
     */
    @GuardedBy("mBadProcessLock")
    private final ProcessMap<Long> mProcessCrashTimesPersistent = new ProcessMap<>();

    /**
     * The last time that various processes have crashed and shown an error dialog.
     */
    @GuardedBy("mBadProcessLock")
    private final ProcessMap<Long> mProcessCrashShowDialogTimes = new ProcessMap<>();

    /**
     * A pairing between how many times various processes have crashed since a given time.
     * Entry and exit conditions for this map are similar to mProcessCrashTimes.
     */
    @GuardedBy("mBadProcessLock")
    private final ProcessMap<Pair<Long, Integer>> mProcessCrashCounts = new ProcessMap<>();

    /**
@@ -116,6 +122,16 @@ class AppErrors {
     * lock operations from the simple lookup cases.
     */
    private volatile ProcessMap<BadProcessInfo> mBadProcesses = new ProcessMap<>();

    /**
     * Dedicated lock for {@link #mAppsNotReportingCrashes}, {@link #mProcessCrashTimes},
     * {@link #mProcessCrashTimesPersistent}, {@link #mProcessCrashShowDialogTimes},
     * {@link #mProcessCrashCounts} and {@link #mBadProcesses}.
     *
     * <p>The naming convention of the function with this lock should be "-LBp"</b>
     *
     * @See mBadProcesses
     */
    private final Object mBadProcessLock = new Object();

    AppErrors(Context context, ActivityManagerService service, PackageWatchdog watchdog) {
@@ -126,19 +142,20 @@ class AppErrors {
    }

    /** Resets the current state but leaves the constructor-provided fields unchanged. */
    public void resetStateLocked() {
    public void resetState() {
        Slog.i(TAG, "Resetting AppErrors");
        synchronized (mBadProcessLock) {
            mAppsNotReportingCrashes.clear();
            mProcessCrashTimes.clear();
            mProcessCrashTimesPersistent.clear();
            mProcessCrashShowDialogTimes.clear();
            mProcessCrashCounts.clear();
        synchronized (mBadProcessLock) {
            mBadProcesses = new ProcessMap<>();
        }
    }

    void dumpDebug(ProtoOutputStream proto, long fieldId, String dumpPackage) {
        synchronized (mBadProcessLock) {
            final ProcessMap<BadProcessInfo> badProcesses = mBadProcesses;
            if (mProcessCrashTimes.getMap().isEmpty() && badProcesses.getMap().isEmpty()) {
                return;
@@ -162,7 +179,7 @@ class AppErrors {
                        final int puid = uids.keyAt(i);
                        final ProcessRecord r = mService.getProcessNames().get(pname, puid);
                        if (dumpPackage != null
                            && (r == null || !r.pkgList.containsKey(dumpPackage))) {
                                && (r == null || !r.getPkgList().containsKey(dumpPackage))) {
                            continue;
                        }
                        final long etoken = proto.start(AppErrorsProto.ProcessCrashTime.ENTRIES);
@@ -190,7 +207,7 @@ class AppErrors {
                        final int puid = uids.keyAt(i);
                        final ProcessRecord r = mService.getProcessNames().get(pname, puid);
                        if (dumpPackage != null && (r == null
                            || !r.pkgList.containsKey(dumpPackage))) {
                                    || !r.getPkgList().containsKey(dumpPackage))) {
                            continue;
                        }
                        final BadProcessInfo info = uids.valueAt(i);
@@ -208,9 +225,11 @@ class AppErrors {

            proto.end(token);
        }
    }

    boolean dumpLocked(FileDescriptor fd, PrintWriter pw, boolean needSep, String dumpPackage) {
        final long now = SystemClock.uptimeMillis();
        synchronized (mBadProcessLock) {
            if (!mProcessCrashTimes.getMap().isEmpty()) {
                boolean printed = false;
                final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap();
@@ -223,7 +242,7 @@ class AppErrors {
                        final int puid = uids.keyAt(i);
                        final ProcessRecord r = mService.getProcessNames().get(pname, puid);
                        if (dumpPackage != null && (r == null
                            || !r.pkgList.containsKey(dumpPackage))) {
                                    || !r.getPkgList().containsKey(dumpPackage))) {
                            continue;
                        }
                        if (!printed) {
@@ -253,7 +272,8 @@ class AppErrors {
                    for (int i = 0; i < uidCount; i++) {
                        final int puid = uids.keyAt(i);
                        final ProcessRecord r = mService.getProcessNames().get(pname, puid);
                    if (dumpPackage != null && (r == null || !r.pkgList.containsKey(dumpPackage))) {
                        if (dumpPackage != null
                                && (r == null || !r.getPkgList().containsKey(dumpPackage))) {
                            continue;
                        }
                        if (!printed) {
@@ -270,6 +290,7 @@ class AppErrors {
                    }
                }
            }
        }

        final ProcessMap<BadProcessInfo> badProcesses = mBadProcesses;
        if (!badProcesses.getMap().isEmpty()) {
@@ -284,7 +305,7 @@ class AppErrors {
                    final int puid = uids.keyAt(i);
                    final ProcessRecord r = mService.getProcessNames().get(pname, puid);
                    if (dumpPackage != null && (r == null
                            || !r.pkgList.containsKey(dumpPackage))) {
                            || !r.getPkgList().containsKey(dumpPackage))) {
                        continue;
                    }
                    if (!printed) {
@@ -349,16 +370,19 @@ class AppErrors {
        }
    }

    void resetProcessCrashTimeLocked(final String processName, final int uid) {
    void resetProcessCrashTime(final String processName, final int uid) {
        synchronized (mBadProcessLock) {
            mProcessCrashTimes.remove(processName, uid);
            mProcessCrashCounts.remove(processName, uid);
        }
    }

    void resetProcessCrashTimeLocked(boolean resetEntireUser, int appId, int userId) {
    void resetProcessCrashTime(boolean resetEntireUser, int appId, int userId) {
        synchronized (mBadProcessLock) {
            final ArrayMap<String, SparseArray<Long>> pTimeMap = mProcessCrashTimes.getMap();
            for (int ip = pTimeMap.size() - 1; ip >= 0; ip--) {
                SparseArray<Long> ba = pTimeMap.valueAt(ip);
            resetProcessCrashMapLocked(ba, resetEntireUser, appId, userId);
                resetProcessCrashMapLBp(ba, resetEntireUser, appId, userId);
                if (ba.size() == 0) {
                    pTimeMap.removeAt(ip);
                }
@@ -368,14 +392,16 @@ class AppErrors {
                    mProcessCrashCounts.getMap();
            for (int ip = pCountMap.size() - 1; ip >= 0; ip--) {
                SparseArray<Pair<Long, Integer>> ba = pCountMap.valueAt(ip);
            resetProcessCrashMapLocked(ba, resetEntireUser, appId, userId);
                resetProcessCrashMapLBp(ba, resetEntireUser, appId, userId);
                if (ba.size() == 0) {
                    pCountMap.removeAt(ip);
                }
            }
        }
    }

    private void resetProcessCrashMapLocked(SparseArray<?> ba, boolean resetEntireUser,
    @GuardedBy("mBadProcessLock")
    private void resetProcessCrashMapLBp(SparseArray<?> ba, boolean resetEntireUser,
            int appId, int userId) {
        for (int i = ba.size() - 1; i >= 0; i--) {
            boolean remove = false;
@@ -399,15 +425,17 @@ class AppErrors {
        }
    }

    void loadAppsNotReportingCrashesFromConfigLocked(String appsNotReportingCrashesConfig) {
    void loadAppsNotReportingCrashesFromConfig(String appsNotReportingCrashesConfig) {
        if (appsNotReportingCrashesConfig != null) {
            final String[] split = appsNotReportingCrashesConfig.split(",");
            if (split.length > 0) {
                synchronized (mBadProcessLock) {
                    mAppsNotReportingCrashes = new ArraySet<>();
                    Collections.addAll(mAppsNotReportingCrashes, split);
                }
            }
        }
    }

    void killAppAtUserRequestLocked(ProcessRecord app) {
        ProcessRecord.ErrorDialogController controller =
@@ -465,7 +493,7 @@ class AppErrors {
                    proc = p;
                    break;
                }
                if (p.pkgList.containsKey(packageName)
                if (p.getPkgList().containsKey(packageName)
                        && (userId < 0 || p.userId == userId)) {
                    proc = p;
                }
@@ -516,7 +544,7 @@ class AppErrors {
        }
    }

    void crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo,
    private void crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo,
            int callingPid, int callingUid) {
        long timeMillis = System.currentTimeMillis();
        String shortMsg = crashInfo.exceptionClassName;
@@ -599,13 +627,16 @@ class AppErrors {
        if (res == AppErrorDialog.TIMEOUT || res == AppErrorDialog.CANCEL) {
            res = AppErrorDialog.FORCE_QUIT;
        }
        synchronized (mService) {
        if (res == AppErrorDialog.MUTE) {
                stopReportingCrashesLocked(r);
            synchronized (mBadProcessLock) {
                stopReportingCrashesLBp(r);
            }
        }
        if (res == AppErrorDialog.RESTART) {
            synchronized (mService) {
                mService.mProcessList.removeProcessLocked(r, false, true,
                        ApplicationExitInfo.REASON_CRASH, "crash");
            }
            if (taskId != INVALID_TASK_ID) {
                try {
                    mService.startActivityFromRecents(taskId,
@@ -623,8 +654,10 @@ class AppErrors {
                // Kill it with fire!
                mService.mAtmInternal.onHandleAppCrash(r.getWindowProcessController());
                if (!r.isPersistent()) {
                    synchronized (mService) {
                        mService.mProcessList.removeProcessLocked(r, false, false,
                                ApplicationExitInfo.REASON_CRASH, "crash");
                    }
                    mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
                }
            } finally {
@@ -637,6 +670,7 @@ class AppErrors {
            appErrorIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        }
        if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
            synchronized (mService) {
                appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
            }
        }
@@ -769,7 +803,7 @@ class AppErrors {
        return report;
    }

    boolean handleAppCrashLocked(ProcessRecord app, String reason,
    private boolean handleAppCrashLocked(ProcessRecord app, String reason,
            String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
        final long now = SystemClock.uptimeMillis();
        final boolean showBackground = Settings.Secure.getIntForUser(mContext.getContentResolver(),
@@ -783,6 +817,7 @@ class AppErrors {
        Long crashTimePersistent;
        boolean tryAgain = false;

        synchronized (mBadProcessLock) {
            if (!app.isolated) {
                crashTime = mProcessCrashTimes.get(app.processName, app.uid);
                crashTimePersistent = mProcessCrashTimesPersistent.get(app.processName, app.uid);
@@ -795,7 +830,8 @@ class AppErrors {
                // Any services running in the application need to be placed
                // back in the pending list.
                ServiceRecord sr = app.getRunningServiceAt(i);
            // If the service was restarted a while ago, then reset crash count, else increment it.
                // If the service was restarted a while ago, then reset crash count,
                // else increment it.
                if (now > sr.restartTime + ActivityManagerConstants.MIN_CRASH_INTERVAL) {
                    sr.crashCount = 1;
                } else {
@@ -811,12 +847,13 @@ class AppErrors {

            final boolean quickCrash = crashTime != null
                    && now < crashTime + ActivityManagerConstants.MIN_CRASH_INTERVAL;
        if (quickCrash || isProcOverCrashLimit(app, now)) {
            // The process either crashed again very quickly or has been crashing periodically in
            // the last few hours. If it was a bound foreground service, let's try to restart again
            // in a while, otherwise the process loses!
            if (quickCrash || isProcOverCrashLimitLBp(app, now)) {
                // The process either crashed again very quickly or has been crashing periodically
                // in the last few hours. If it was a bound foreground service, let's try to
                // restart again in a while, otherwise the process loses!
                Slog.w(TAG, "Process " + app.processName + " has crashed too many times, killing!"
                    + " Reason: " + (quickCrash ? "crashed quickly" : "over process crash limit"));
                        + " Reason: "
                        + (quickCrash ? "crashed quickly" : "over process crash limit"));
                EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
                        app.userId, app.processName, app.uid);
                mService.mAtmInternal.onHandleAppCrash(app.getWindowProcessController());
@@ -855,7 +892,8 @@ class AppErrors {
                    data.taskId = affectedTaskId;
                }
                if (data != null && crashTimePersistent != null
                    && now < crashTimePersistent + ActivityManagerConstants.MIN_CRASH_INTERVAL) {
                        && now < crashTimePersistent
                        + ActivityManagerConstants.MIN_CRASH_INTERVAL) {
                    data.repeating = true;
                }
            }
@@ -869,7 +907,8 @@ class AppErrors {
            // with a home activity running in the process to prevent a repeatedly crashing app
            // from blocking the user to manually clear the list.
            final WindowProcessController proc = app.getWindowProcessController();
        if (proc.isHomeProcess() && proc.hasActivities() && (app.info.flags & FLAG_SYSTEM) == 0) {
            if (proc.isHomeProcess() && proc.hasActivities()
                    && (app.info.flags & FLAG_SYSTEM) == 0) {
                proc.clearPackagePreferredForHomeActivities();
            }

@@ -878,14 +917,16 @@ class AppErrors {
                // because they don't have a persistent identity.
                mProcessCrashTimes.put(app.processName, app.uid, now);
                mProcessCrashTimesPersistent.put(app.processName, app.uid, now);
            updateProcessCrashCount(app.processName, app.uid, now);
                updateProcessCrashCountLBp(app.processName, app.uid, now);
            }
        }

        if (app.crashHandler != null) mService.mHandler.post(app.crashHandler);
        return true;
    }

    private void updateProcessCrashCount(String processName, int uid, long now) {
    @GuardedBy("mBadProcessLock")
    private void updateProcessCrashCountLBp(String processName, int uid, long now) {
        Pair<Long, Integer> count = mProcessCrashCounts.get(processName, uid);
        if (count == null || (count.first + PROCESS_CRASH_COUNT_RESET_INTERVAL) < now) {
            count = new Pair<>(now, 1);
@@ -895,7 +936,8 @@ class AppErrors {
        mProcessCrashCounts.put(processName, uid, count);
    }

    private boolean isProcOverCrashLimit(ProcessRecord app, long now) {
    @GuardedBy("mBadProcessLock")
    private boolean isProcOverCrashLimitLBp(ProcessRecord app, long now) {
        final Pair<Long, Integer> crashCount = mProcessCrashCounts.get(app.processName, app.uid);
        return !app.isolated && crashCount != null
                && now < (crashCount.first + PROCESS_CRASH_COUNT_RESET_INTERVAL)
@@ -938,6 +980,7 @@ class AppErrors {
                return;
            }
            Long crashShowErrorTime = null;
            synchronized (mBadProcessLock) {
                if (!proc.isolated) {
                    crashShowErrorTime = mProcessCrashShowDialogTimes.get(proc.processName,
                            proc.uid);
@@ -950,8 +993,8 @@ class AppErrors {
                        Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
                        0,
                        mService.mUserController.getCurrentUserId()) != 0;
            final boolean crashSilenced = mAppsNotReportingCrashes != null &&
                    mAppsNotReportingCrashes.contains(proc.info.packageName);
                final boolean crashSilenced = mAppsNotReportingCrashes != null
                        && mAppsNotReportingCrashes.contains(proc.info.packageName);
                final long now = SystemClock.uptimeMillis();
                final boolean shouldThottle = crashShowErrorTime != null
                        && now < crashShowErrorTime + ActivityManagerConstants.MIN_CRASH_INTERVAL;
@@ -971,8 +1014,10 @@ class AppErrors {
                }
            }
        }
    }

    private void stopReportingCrashesLocked(ProcessRecord proc) {
    @GuardedBy("mBadProcessLock")
    private void stopReportingCrashesLBp(ProcessRecord proc) {
        if (mAppsNotReportingCrashes == null) {
            mAppsNotReportingCrashes = new ArraySet<>();
        }
+58 −65
Original line number Diff line number Diff line
@@ -79,6 +79,7 @@ import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
@@ -159,8 +160,7 @@ public final class AppExitInfoTracker {
     * persistent storage.
     */
    @VisibleForTesting
    @GuardedBy("mLock")
    boolean mAppExitInfoLoaded = false;
    AtomicBoolean mAppExitInfoLoaded = new AtomicBoolean();

    /**
     * Temporary list being used to filter/sort intermediate results in {@link #getExitInfo}.
@@ -273,37 +273,32 @@ public final class AppExitInfoTracker {
            return;
        }

        synchronized (mLock) {
            if (!mAppExitInfoLoaded) {
        if (!mAppExitInfoLoaded.get()) {
            return;
        }
            mKillHandler.obtainMessage(KillHandler.MSG_PROC_DIED, obtainRawRecordLocked(app))
        mKillHandler.obtainMessage(KillHandler.MSG_PROC_DIED, obtainRawRecord(app))
                .sendToTarget();
    }
    }

    void scheduleNoteAppKill(final ProcessRecord app, final @Reason int reason,
            final @SubReason int subReason, final String msg) {
        synchronized (mLock) {
            if (!mAppExitInfoLoaded) {
        if (!mAppExitInfoLoaded.get()) {
            return;
        }
        if (app == null || app.info == null) {
            return;
        }

            ApplicationExitInfo raw = obtainRawRecordLocked(app);
        ApplicationExitInfo raw = obtainRawRecord(app);
        raw.setReason(reason);
        raw.setSubReason(subReason);
        raw.setDescription(msg);
        mKillHandler.obtainMessage(KillHandler.MSG_APP_KILL, raw).sendToTarget();
    }
    }

    void scheduleNoteAppKill(final int pid, final int uid, final @Reason int reason,
            final @SubReason int subReason, final String msg) {
        synchronized (mLock) {
            if (!mAppExitInfoLoaded) {
        if (!mAppExitInfoLoaded.get()) {
            return;
        }
        ProcessRecord app;
@@ -319,7 +314,6 @@ public final class AppExitInfoTracker {
            scheduleNoteAppKill(app, reason, subReason, msg);
        }
    }
    }

    interface LmkdKillListener {
        /**
@@ -414,7 +408,7 @@ public final class AppExitInfoTracker {

    @GuardedBy("mLock")
    private ApplicationExitInfo addExitInfoLocked(ApplicationExitInfo raw) {
        if (!mAppExitInfoLoaded) {
        if (!mAppExitInfoLoaded.get()) {
            Slog.w(TAG, "Skipping saving the exit info due to ongoing loading from storage");
            return null;
        }
@@ -627,9 +621,7 @@ public final class AppExitInfoTracker {
    @VisibleForTesting
    void loadExistingProcessExitInfo() {
        if (!mProcExitInfoFile.canRead()) {
            synchronized (mLock) {
                mAppExitInfoLoaded = true;
            }
            mAppExitInfoLoaded.set(true);
            return;
        }

@@ -665,7 +657,7 @@ public final class AppExitInfoTracker {
        }
        synchronized (mLock) {
            pruneAnrTracesIfNecessaryLocked();
            mAppExitInfoLoaded = true;
            mAppExitInfoLoaded.set(true);
        }
    }

@@ -834,7 +826,7 @@ public final class AppExitInfoTracker {
        container.addExitInfoLocked(info);
    }

    @GuardedBy("mLocked")
    @GuardedBy("mLock")
    private void forEachPackageLocked(
            BiFunction<String, SparseArray<AppExitInfoContainer>, Integer> callback) {
        if (callback != null) {
@@ -859,7 +851,7 @@ public final class AppExitInfoTracker {
        }
    }

    @GuardedBy("mLocked")
    @GuardedBy("mLock")
    private void removePackageLocked(String packageName, int uid, boolean removeUid, int userId) {
        if (removeUid) {
            mActiveAppStateSummary.remove(uid);
@@ -896,7 +888,7 @@ public final class AppExitInfoTracker {
        }
    }

    @GuardedBy("mLocked")
    @GuardedBy("mLock")
    private void removeByUserIdLocked(final int userId) {
        if (userId == UserHandle.USER_ALL) {
            mData.getMap().clear();
@@ -922,14 +914,15 @@ public final class AppExitInfoTracker {
    }

    @VisibleForTesting
    @GuardedBy("mLock")
    ApplicationExitInfo obtainRawRecordLocked(ProcessRecord app) {
    ApplicationExitInfo obtainRawRecord(ProcessRecord app) {
        ApplicationExitInfo info = mRawRecordsPool.acquire();
        if (info == null) {
            info = new ApplicationExitInfo();
        }

        final int definingUid = app.hostingRecord != null ? app.hostingRecord.getDefiningUid() : 0;
        synchronized (mService) {
            final int definingUid = app.hostingRecord != null
                    ? app.hostingRecord.getDefiningUid() : 0;
            info.setPid(app.pid);
            info.setRealUid(app.uid);
            info.setPackageUid(app.info.uid);
@@ -941,16 +934,16 @@ public final class AppExitInfoTracker {
            info.setReason(ApplicationExitInfo.REASON_UNKNOWN);
            info.setStatus(0);
            info.setImportance(procStateToImportance(app.setProcState));
        info.setPss(app.lastPss);
        info.setRss(app.mLastRss);
            info.setPss(app.mProfile.getLastPss());
            info.setRss(app.mProfile.getLastRss());
            info.setTimestamp(System.currentTimeMillis());
        }

        return info;
    }

    @VisibleForTesting
    @GuardedBy("mLock")
    void recycleRawRecordLocked(ApplicationExitInfo info) {
    void recycleRawRecord(ApplicationExitInfo info) {
        info.setProcessName(null);
        info.setDescription(null);
        info.setPackageList(null);
@@ -1549,16 +1542,16 @@ public final class AppExitInfoTracker {
                    ApplicationExitInfo raw = (ApplicationExitInfo) msg.obj;
                    synchronized (mLock) {
                        handleNoteProcessDiedLocked(raw);
                        recycleRawRecordLocked(raw);
                    }
                    recycleRawRecord(raw);
                }
                break;
                case MSG_APP_KILL: {
                    ApplicationExitInfo raw = (ApplicationExitInfo) msg.obj;
                    synchronized (mLock) {
                        handleNoteAppKillLocked(raw);
                        recycleRawRecordLocked(raw);
                    }
                    recycleRawRecord(raw);
                }
                break;
                default:
Loading