AppErrors.java revision 41584b69fd0693c5ffc967aca07bade7e08de01a
1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.server.am;
18
19import com.android.internal.app.ProcessMap;
20import com.android.internal.logging.MetricsLogger;
21import com.android.internal.logging.nano.MetricsProto;
22import com.android.internal.os.ProcessCpuTracker;
23import com.android.server.RescueParty;
24import com.android.server.Watchdog;
25import com.android.server.am.proto.AppErrorsProto;
26
27import android.app.ActivityManager;
28import android.app.ActivityOptions;
29import android.app.ActivityThread;
30import android.app.AppOpsManager;
31import android.app.ApplicationErrorReport;
32import android.app.Dialog;
33import android.content.ActivityNotFoundException;
34import android.content.Context;
35import android.content.Intent;
36import android.content.pm.ApplicationInfo;
37import android.net.Uri;
38import android.os.Binder;
39import android.os.Message;
40import android.os.Process;
41import android.os.RemoteException;
42import android.os.SystemClock;
43import android.os.SystemProperties;
44import android.os.UserHandle;
45import android.provider.Settings;
46import android.util.ArrayMap;
47import android.util.ArraySet;
48import android.util.EventLog;
49import android.util.Log;
50import android.util.Slog;
51import android.util.SparseArray;
52import android.util.TimeUtils;
53import android.util.proto.ProtoOutputStream;
54
55import java.io.File;
56import java.io.FileDescriptor;
57import java.io.PrintWriter;
58import java.util.ArrayList;
59import java.util.Collections;
60import java.util.HashMap;
61import java.util.Set;
62
63import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
64import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
65import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
66import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
67import static com.android.server.am.ActivityManagerService.MY_PID;
68import static com.android.server.am.ActivityManagerService.SYSTEM_DEBUGGABLE;
69
70/**
71 * Controls error conditions in applications.
72 */
73class AppErrors {
74
75    private static final String TAG = TAG_WITH_CLASS_NAME ? "AppErrors" : TAG_AM;
76
77    private final ActivityManagerService mService;
78    private final Context mContext;
79
80    private ArraySet<String> mAppsNotReportingCrashes;
81
82    /**
83     * The last time that various processes have crashed since they were last explicitly started.
84     */
85    private final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<>();
86
87    /**
88     * The last time that various processes have crashed (not reset even when explicitly started).
89     */
90    private final ProcessMap<Long> mProcessCrashTimesPersistent = new ProcessMap<>();
91
92    /**
93     * Set of applications that we consider to be bad, and will reject
94     * incoming broadcasts from (which the user has no control over).
95     * Processes are added to this set when they have crashed twice within
96     * a minimum amount of time; they are removed from it when they are
97     * later restarted (hopefully due to some user action).  The value is the
98     * time it was added to the list.
99     */
100    private final ProcessMap<BadProcessInfo> mBadProcesses = new ProcessMap<>();
101
102
103    AppErrors(Context context, ActivityManagerService service) {
104        context.assertRuntimeOverlayThemable();
105        mService = service;
106        mContext = context;
107    }
108
109    void writeToProto(ProtoOutputStream proto, long fieldId, String dumpPackage) {
110        if (mProcessCrashTimes.getMap().isEmpty() && mBadProcesses.getMap().isEmpty()) {
111            return;
112        }
113
114        final long token = proto.start(fieldId);
115        final long now = SystemClock.uptimeMillis();
116        proto.write(AppErrorsProto.NOW_UPTIME_MS, now);
117
118        if (!mProcessCrashTimes.getMap().isEmpty()) {
119            final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap();
120            final int procCount = pmap.size();
121            for (int ip = 0; ip < procCount; ip++) {
122                final long ctoken = proto.start(AppErrorsProto.PROCESS_CRASH_TIMES);
123                final String pname = pmap.keyAt(ip);
124                final SparseArray<Long> uids = pmap.valueAt(ip);
125                final int uidCount = uids.size();
126
127                proto.write(AppErrorsProto.ProcessCrashTime.PROCESS_NAME, pname);
128                for (int i = 0; i < uidCount; i++) {
129                    final int puid = uids.keyAt(i);
130                    final ProcessRecord r = mService.mProcessNames.get(pname, puid);
131                    if (dumpPackage != null && (r == null || !r.pkgList.containsKey(dumpPackage))) {
132                        continue;
133                    }
134                    final long etoken = proto.start(AppErrorsProto.ProcessCrashTime.ENTRIES);
135                    proto.write(AppErrorsProto.ProcessCrashTime.Entry.UID, puid);
136                    proto.write(AppErrorsProto.ProcessCrashTime.Entry.LAST_CRASHED_AT_MS,
137                            uids.valueAt(i));
138                    proto.end(etoken);
139                }
140                proto.end(ctoken);
141            }
142
143        }
144
145        if (!mBadProcesses.getMap().isEmpty()) {
146            final ArrayMap<String, SparseArray<BadProcessInfo>> pmap = mBadProcesses.getMap();
147            final int processCount = pmap.size();
148            for (int ip = 0; ip < processCount; ip++) {
149                final long btoken = proto.start(AppErrorsProto.BAD_PROCESSES);
150                final String pname = pmap.keyAt(ip);
151                final SparseArray<BadProcessInfo> uids = pmap.valueAt(ip);
152                final int uidCount = uids.size();
153
154                proto.write(AppErrorsProto.BadProcess.PROCESS_NAME, pname);
155                for (int i = 0; i < uidCount; i++) {
156                    final int puid = uids.keyAt(i);
157                    final ProcessRecord r = mService.mProcessNames.get(pname, puid);
158                    if (dumpPackage != null && (r == null
159                            || !r.pkgList.containsKey(dumpPackage))) {
160                        continue;
161                    }
162                    final BadProcessInfo info = uids.valueAt(i);
163                    final long etoken = proto.start(AppErrorsProto.BadProcess.ENTRIES);
164                    proto.write(AppErrorsProto.BadProcess.Entry.UID, puid);
165                    proto.write(AppErrorsProto.BadProcess.Entry.CRASHED_AT_MS, info.time);
166                    proto.write(AppErrorsProto.BadProcess.Entry.SHORT_MSG, info.shortMsg);
167                    proto.write(AppErrorsProto.BadProcess.Entry.LONG_MSG, info.longMsg);
168                    proto.write(AppErrorsProto.BadProcess.Entry.STACK, info.stack);
169                    proto.end(etoken);
170                }
171                proto.end(btoken);
172            }
173        }
174
175        proto.end(token);
176    }
177
178    boolean dumpLocked(FileDescriptor fd, PrintWriter pw, boolean needSep, String dumpPackage) {
179        if (!mProcessCrashTimes.getMap().isEmpty()) {
180            boolean printed = false;
181            final long now = SystemClock.uptimeMillis();
182            final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap();
183            final int processCount = pmap.size();
184            for (int ip = 0; ip < processCount; ip++) {
185                final String pname = pmap.keyAt(ip);
186                final SparseArray<Long> uids = pmap.valueAt(ip);
187                final int uidCount = uids.size();
188                for (int i = 0; i < uidCount; i++) {
189                    final int puid = uids.keyAt(i);
190                    final ProcessRecord r = mService.mProcessNames.get(pname, puid);
191                    if (dumpPackage != null && (r == null
192                            || !r.pkgList.containsKey(dumpPackage))) {
193                        continue;
194                    }
195                    if (!printed) {
196                        if (needSep) pw.println();
197                        needSep = true;
198                        pw.println("  Time since processes crashed:");
199                        printed = true;
200                    }
201                    pw.print("    Process "); pw.print(pname);
202                    pw.print(" uid "); pw.print(puid);
203                    pw.print(": last crashed ");
204                    TimeUtils.formatDuration(now-uids.valueAt(i), pw);
205                    pw.println(" ago");
206                }
207            }
208        }
209
210        if (!mBadProcesses.getMap().isEmpty()) {
211            boolean printed = false;
212            final ArrayMap<String, SparseArray<BadProcessInfo>> pmap = mBadProcesses.getMap();
213            final int processCount = pmap.size();
214            for (int ip = 0; ip < processCount; ip++) {
215                final String pname = pmap.keyAt(ip);
216                final SparseArray<BadProcessInfo> uids = pmap.valueAt(ip);
217                final int uidCount = uids.size();
218                for (int i = 0; i < uidCount; i++) {
219                    final int puid = uids.keyAt(i);
220                    final ProcessRecord r = mService.mProcessNames.get(pname, puid);
221                    if (dumpPackage != null && (r == null
222                            || !r.pkgList.containsKey(dumpPackage))) {
223                        continue;
224                    }
225                    if (!printed) {
226                        if (needSep) pw.println();
227                        needSep = true;
228                        pw.println("  Bad processes:");
229                        printed = true;
230                    }
231                    final BadProcessInfo info = uids.valueAt(i);
232                    pw.print("    Bad process "); pw.print(pname);
233                    pw.print(" uid "); pw.print(puid);
234                    pw.print(": crashed at time "); pw.println(info.time);
235                    if (info.shortMsg != null) {
236                        pw.print("      Short msg: "); pw.println(info.shortMsg);
237                    }
238                    if (info.longMsg != null) {
239                        pw.print("      Long msg: "); pw.println(info.longMsg);
240                    }
241                    if (info.stack != null) {
242                        pw.println("      Stack:");
243                        int lastPos = 0;
244                        for (int pos = 0; pos < info.stack.length(); pos++) {
245                            if (info.stack.charAt(pos) == '\n') {
246                                pw.print("        ");
247                                pw.write(info.stack, lastPos, pos-lastPos);
248                                pw.println();
249                                lastPos = pos+1;
250                            }
251                        }
252                        if (lastPos < info.stack.length()) {
253                            pw.print("        ");
254                            pw.write(info.stack, lastPos, info.stack.length()-lastPos);
255                            pw.println();
256                        }
257                    }
258                }
259            }
260        }
261        return needSep;
262    }
263
264    boolean isBadProcessLocked(ApplicationInfo info) {
265        return mBadProcesses.get(info.processName, info.uid) != null;
266    }
267
268    void clearBadProcessLocked(ApplicationInfo info) {
269        mBadProcesses.remove(info.processName, info.uid);
270    }
271
272    void resetProcessCrashTimeLocked(ApplicationInfo info) {
273        mProcessCrashTimes.remove(info.processName, info.uid);
274    }
275
276    void resetProcessCrashTimeLocked(boolean resetEntireUser, int appId, int userId) {
277        final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap();
278        for (int ip = pmap.size() - 1; ip >= 0; ip--) {
279            SparseArray<Long> ba = pmap.valueAt(ip);
280            for (int i = ba.size() - 1; i >= 0; i--) {
281                boolean remove = false;
282                final int entUid = ba.keyAt(i);
283                if (!resetEntireUser) {
284                    if (userId == UserHandle.USER_ALL) {
285                        if (UserHandle.getAppId(entUid) == appId) {
286                            remove = true;
287                        }
288                    } else {
289                        if (entUid == UserHandle.getUid(userId, appId)) {
290                            remove = true;
291                        }
292                    }
293                } else if (UserHandle.getUserId(entUid) == userId) {
294                    remove = true;
295                }
296                if (remove) {
297                    ba.removeAt(i);
298                }
299            }
300            if (ba.size() == 0) {
301                pmap.removeAt(ip);
302            }
303        }
304    }
305
306    void loadAppsNotReportingCrashesFromConfigLocked(String appsNotReportingCrashesConfig) {
307        if (appsNotReportingCrashesConfig != null) {
308            final String[] split = appsNotReportingCrashesConfig.split(",");
309            if (split.length > 0) {
310                mAppsNotReportingCrashes = new ArraySet<>();
311                Collections.addAll(mAppsNotReportingCrashes, split);
312            }
313        }
314    }
315
316    void killAppAtUserRequestLocked(ProcessRecord app, Dialog fromDialog) {
317        app.crashing = false;
318        app.crashingReport = null;
319        app.notResponding = false;
320        app.notRespondingReport = null;
321        if (app.anrDialog == fromDialog) {
322            app.anrDialog = null;
323        }
324        if (app.waitDialog == fromDialog) {
325            app.waitDialog = null;
326        }
327        if (app.pid > 0 && app.pid != MY_PID) {
328            handleAppCrashLocked(app, "user-terminated" /*reason*/,
329                    null /*shortMsg*/, null /*longMsg*/, null /*stackTrace*/, null /*data*/);
330            app.kill("user request after error", true);
331        }
332    }
333
334    /**
335     * Induce a crash in the given app.
336     *
337     * @param uid if nonnegative, the required matching uid of the target to crash
338     * @param initialPid fast-path match for the target to crash
339     * @param packageName fallback match if the stated pid is not found or doesn't match uid
340     * @param userId If nonnegative, required to identify a match by package name
341     * @param message
342     */
343    void scheduleAppCrashLocked(int uid, int initialPid, String packageName, int userId,
344            String message) {
345        ProcessRecord proc = null;
346
347        // Figure out which process to kill.  We don't trust that initialPid
348        // still has any relation to current pids, so must scan through the
349        // list.
350
351        synchronized (mService.mPidsSelfLocked) {
352            for (int i=0; i<mService.mPidsSelfLocked.size(); i++) {
353                ProcessRecord p = mService.mPidsSelfLocked.valueAt(i);
354                if (uid >= 0 && p.uid != uid) {
355                    continue;
356                }
357                if (p.pid == initialPid) {
358                    proc = p;
359                    break;
360                }
361                if (p.pkgList.containsKey(packageName)
362                        && (userId < 0 || p.userId == userId)) {
363                    proc = p;
364                }
365            }
366        }
367
368        if (proc == null) {
369            Slog.w(TAG, "crashApplication: nothing for uid=" + uid
370                    + " initialPid=" + initialPid
371                    + " packageName=" + packageName
372                    + " userId=" + userId);
373            return;
374        }
375
376        proc.scheduleCrash(message);
377    }
378
379    /**
380     * Bring up the "unexpected error" dialog box for a crashing app.
381     * Deal with edge cases (intercepts from instrumented applications,
382     * ActivityController, error intent receivers, that sort of thing).
383     * @param r the application crashing
384     * @param crashInfo describing the failure
385     */
386    void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
387        final int callingPid = Binder.getCallingPid();
388        final int callingUid = Binder.getCallingUid();
389
390        final long origId = Binder.clearCallingIdentity();
391        try {
392            crashApplicationInner(r, crashInfo, callingPid, callingUid);
393        } finally {
394            Binder.restoreCallingIdentity(origId);
395        }
396    }
397
398    void crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo,
399            int callingPid, int callingUid) {
400        long timeMillis = System.currentTimeMillis();
401        String shortMsg = crashInfo.exceptionClassName;
402        String longMsg = crashInfo.exceptionMessage;
403        String stackTrace = crashInfo.stackTrace;
404        if (shortMsg != null && longMsg != null) {
405            longMsg = shortMsg + ": " + longMsg;
406        } else if (shortMsg != null) {
407            longMsg = shortMsg;
408        }
409
410        // If a persistent app is stuck in a crash loop, the device isn't very
411        // usable, so we want to consider sending out a rescue party.
412        if (r != null && r.persistent) {
413            RescueParty.notePersistentAppCrash(mContext, r.uid);
414        }
415
416        AppErrorResult result = new AppErrorResult();
417        TaskRecord task;
418        synchronized (mService) {
419            /**
420             * If crash is handled by instance of {@link android.app.IActivityController},
421             * finish now and don't show the app error dialog.
422             */
423            if (handleAppCrashInActivityController(r, crashInfo, shortMsg, longMsg, stackTrace,
424                    timeMillis, callingPid, callingUid)) {
425                return;
426            }
427
428            /**
429             * If this process was running instrumentation, finish now - it will be handled in
430             * {@link ActivityManagerService#handleAppDiedLocked}.
431             */
432            if (r != null && r.instr != null) {
433                return;
434            }
435
436            // Log crash in battery stats.
437            if (r != null) {
438                mService.mBatteryStatsService.noteProcessCrash(r.processName, r.uid);
439            }
440
441            AppErrorDialog.Data data = new AppErrorDialog.Data();
442            data.result = result;
443            data.proc = r;
444
445            // If we can't identify the process or it's already exceeded its crash quota,
446            // quit right away without showing a crash dialog.
447            if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) {
448                return;
449            }
450
451            final Message msg = Message.obtain();
452            msg.what = ActivityManagerService.SHOW_ERROR_UI_MSG;
453
454            task = data.task;
455            msg.obj = data;
456            mService.mUiHandler.sendMessage(msg);
457        }
458
459        int res = result.get();
460
461        Intent appErrorIntent = null;
462        MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res);
463        if (res == AppErrorDialog.TIMEOUT || res == AppErrorDialog.CANCEL) {
464            res = AppErrorDialog.FORCE_QUIT;
465        }
466        synchronized (mService) {
467            if (res == AppErrorDialog.MUTE) {
468                stopReportingCrashesLocked(r);
469            }
470            if (res == AppErrorDialog.RESTART) {
471                mService.removeProcessLocked(r, false, true, "crash");
472                if (task != null) {
473                    try {
474                        mService.startActivityFromRecents(task.taskId,
475                                ActivityOptions.makeBasic().toBundle());
476                    } catch (IllegalArgumentException e) {
477                        // Hmm, that didn't work, app might have crashed before creating a
478                        // recents entry. Let's see if we have a safe-to-restart intent.
479                        final Set<String> cats = task.intent.getCategories();
480                        if (cats != null && cats.contains(Intent.CATEGORY_LAUNCHER)) {
481                            mService.getActivityStartController().startActivityInPackage(
482                                    task.mCallingUid, callingPid, callingUid, task.mCallingPackage,
483                                    task.intent, null, null, null, 0, 0,
484                                    new SafeActivityOptions(ActivityOptions.makeBasic()),
485                                    task.userId, null,
486                                    "AppErrors");
487                        }
488                    }
489                }
490            }
491            if (res == AppErrorDialog.FORCE_QUIT) {
492                long orig = Binder.clearCallingIdentity();
493                try {
494                    // Kill it with fire!
495                    mService.mStackSupervisor.handleAppCrashLocked(r);
496                    if (!r.persistent) {
497                        mService.removeProcessLocked(r, false, false, "crash");
498                        mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
499                    }
500                } finally {
501                    Binder.restoreCallingIdentity(orig);
502                }
503            }
504            if (res == AppErrorDialog.APP_INFO) {
505                appErrorIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
506                appErrorIntent.setData(Uri.parse("package:" + r.info.packageName));
507                appErrorIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
508            }
509            if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
510                appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
511            }
512            if (r != null && !r.isolated && res != AppErrorDialog.RESTART) {
513                // XXX Can't keep track of crash time for isolated processes,
514                // since they don't have a persistent identity.
515                mProcessCrashTimes.put(r.info.processName, r.uid,
516                        SystemClock.uptimeMillis());
517            }
518        }
519
520        if (appErrorIntent != null) {
521            try {
522                mContext.startActivityAsUser(appErrorIntent, new UserHandle(r.userId));
523            } catch (ActivityNotFoundException e) {
524                Slog.w(TAG, "bug report receiver dissappeared", e);
525            }
526        }
527    }
528
529    private boolean handleAppCrashInActivityController(ProcessRecord r,
530                                                       ApplicationErrorReport.CrashInfo crashInfo,
531                                                       String shortMsg, String longMsg,
532                                                       String stackTrace, long timeMillis,
533                                                       int callingPid, int callingUid) {
534        if (mService.mController == null) {
535            return false;
536        }
537
538        try {
539            String name = r != null ? r.processName : null;
540            int pid = r != null ? r.pid : callingPid;
541            int uid = r != null ? r.info.uid : callingUid;
542            if (!mService.mController.appCrashed(name, pid,
543                    shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
544                if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"))
545                        && "Native crash".equals(crashInfo.exceptionClassName)) {
546                    Slog.w(TAG, "Skip killing native crashed app " + name
547                            + "(" + pid + ") during testing");
548                } else {
549                    Slog.w(TAG, "Force-killing crashed app " + name
550                            + " at watcher's request");
551                    if (r != null) {
552                        if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null))
553                        {
554                            r.kill("crash", true);
555                        }
556                    } else {
557                        // Huh.
558                        Process.killProcess(pid);
559                        ActivityManagerService.killProcessGroup(uid, pid);
560                    }
561                }
562                return true;
563            }
564        } catch (RemoteException e) {
565            mService.mController = null;
566            Watchdog.getInstance().setActivityController(null);
567        }
568        return false;
569    }
570
571    private boolean makeAppCrashingLocked(ProcessRecord app,
572            String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
573        app.crashing = true;
574        app.crashingReport = generateProcessError(app,
575                ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
576        startAppProblemLocked(app);
577        app.stopFreezingAllLocked();
578        return handleAppCrashLocked(app, "force-crash" /*reason*/, shortMsg, longMsg, stackTrace,
579                data);
580    }
581
582    void startAppProblemLocked(ProcessRecord app) {
583        // If this app is not running under the current user, then we
584        // can't give it a report button because that would require
585        // launching the report UI under a different user.
586        app.errorReportReceiver = null;
587
588        for (int userId : mService.mUserController.getCurrentProfileIds()) {
589            if (app.userId == userId) {
590                app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
591                        mContext, app.info.packageName, app.info.flags);
592            }
593        }
594        mService.skipCurrentReceiverLocked(app);
595    }
596
597    /**
598     * Generate a process error record, suitable for attachment to a ProcessRecord.
599     *
600     * @param app The ProcessRecord in which the error occurred.
601     * @param condition Crashing, Application Not Responding, etc.  Values are defined in
602     *                      ActivityManager.ProcessErrorStateInfo
603     * @param activity The activity associated with the crash, if known.
604     * @param shortMsg Short message describing the crash.
605     * @param longMsg Long message describing the crash.
606     * @param stackTrace Full crash stack trace, may be null.
607     *
608     * @return Returns a fully-formed ProcessErrorStateInfo record.
609     */
610    private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
611            int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
612        ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
613
614        report.condition = condition;
615        report.processName = app.processName;
616        report.pid = app.pid;
617        report.uid = app.info.uid;
618        report.tag = activity;
619        report.shortMsg = shortMsg;
620        report.longMsg = longMsg;
621        report.stackTrace = stackTrace;
622
623        return report;
624    }
625
626    Intent createAppErrorIntentLocked(ProcessRecord r,
627            long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
628        ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
629        if (report == null) {
630            return null;
631        }
632        Intent result = new Intent(Intent.ACTION_APP_ERROR);
633        result.setComponent(r.errorReportReceiver);
634        result.putExtra(Intent.EXTRA_BUG_REPORT, report);
635        result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
636        return result;
637    }
638
639    private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
640            long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
641        if (r.errorReportReceiver == null) {
642            return null;
643        }
644
645        if (!r.crashing && !r.notResponding && !r.forceCrashReport) {
646            return null;
647        }
648
649        ApplicationErrorReport report = new ApplicationErrorReport();
650        report.packageName = r.info.packageName;
651        report.installerPackageName = r.errorReportReceiver.getPackageName();
652        report.processName = r.processName;
653        report.time = timeMillis;
654        report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
655
656        if (r.crashing || r.forceCrashReport) {
657            report.type = ApplicationErrorReport.TYPE_CRASH;
658            report.crashInfo = crashInfo;
659        } else if (r.notResponding) {
660            report.type = ApplicationErrorReport.TYPE_ANR;
661            report.anrInfo = new ApplicationErrorReport.AnrInfo();
662
663            report.anrInfo.activity = r.notRespondingReport.tag;
664            report.anrInfo.cause = r.notRespondingReport.shortMsg;
665            report.anrInfo.info = r.notRespondingReport.longMsg;
666        }
667
668        return report;
669    }
670
671    boolean handleAppCrashLocked(ProcessRecord app, String reason,
672            String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
673        final long now = SystemClock.uptimeMillis();
674        final boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
675                Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
676
677        final boolean procIsBoundForeground =
678            (app.curProcState == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
679
680        Long crashTime;
681        Long crashTimePersistent;
682        boolean tryAgain = false;
683
684        if (!app.isolated) {
685            crashTime = mProcessCrashTimes.get(app.info.processName, app.uid);
686            crashTimePersistent = mProcessCrashTimesPersistent.get(app.info.processName, app.uid);
687        } else {
688            crashTime = crashTimePersistent = null;
689        }
690
691        // Bump up the crash count of any services currently running in the proc.
692        for (int i = app.services.size() - 1; i >= 0; i--) {
693            // Any services running in the application need to be placed
694            // back in the pending list.
695            ServiceRecord sr = app.services.valueAt(i);
696            // If the service was restarted a while ago, then reset crash count, else increment it.
697            if (now > sr.restartTime + ProcessList.MIN_CRASH_INTERVAL) {
698                sr.crashCount = 1;
699            } else {
700                sr.crashCount++;
701            }
702            // Allow restarting for started or bound foreground services that are crashing.
703            // This includes wallpapers.
704            if (sr.crashCount < mService.mConstants.BOUND_SERVICE_MAX_CRASH_RETRY
705                    && (sr.isForeground || procIsBoundForeground)) {
706                tryAgain = true;
707            }
708        }
709
710        if (crashTime != null && now < crashTime + ProcessList.MIN_CRASH_INTERVAL) {
711            // The process crashed again very quickly. If it was a bound foreground service, let's
712            // try to restart again in a while, otherwise the process loses!
713            Slog.w(TAG, "Process " + app.info.processName
714                    + " has crashed too many times: killing!");
715            EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
716                    app.userId, app.info.processName, app.uid);
717            mService.mStackSupervisor.handleAppCrashLocked(app);
718            if (!app.persistent) {
719                // We don't want to start this process again until the user
720                // explicitly does so...  but for persistent process, we really
721                // need to keep it running.  If a persistent process is actually
722                // repeatedly crashing, then badness for everyone.
723                EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.userId, app.uid,
724                        app.info.processName);
725                if (!app.isolated) {
726                    // XXX We don't have a way to mark isolated processes
727                    // as bad, since they don't have a peristent identity.
728                    mBadProcesses.put(app.info.processName, app.uid,
729                            new BadProcessInfo(now, shortMsg, longMsg, stackTrace));
730                    mProcessCrashTimes.remove(app.info.processName, app.uid);
731                }
732                app.bad = true;
733                app.removed = true;
734                // Don't let services in this process be restarted and potentially
735                // annoy the user repeatedly.  Unless it is persistent, since those
736                // processes run critical code.
737                mService.removeProcessLocked(app, false, tryAgain, "crash");
738                mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
739                if (!showBackground) {
740                    return false;
741                }
742            }
743            mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
744        } else {
745            TaskRecord affectedTask =
746                    mService.mStackSupervisor.finishTopRunningActivityLocked(app, reason);
747            if (data != null) {
748                data.task = affectedTask;
749            }
750            if (data != null && crashTimePersistent != null
751                    && now < crashTimePersistent + ProcessList.MIN_CRASH_INTERVAL) {
752                data.repeating = true;
753            }
754        }
755
756        if (data != null && tryAgain) {
757            data.isRestartableForService = true;
758        }
759
760        // If the crashing process is what we consider to be the "home process" and it has been
761        // replaced by a third-party app, clear the package preferred activities from packages
762        // with a home activity running in the process to prevent a repeatedly crashing app
763        // from blocking the user to manually clear the list.
764        final ArrayList<ActivityRecord> activities = app.activities;
765        if (app == mService.mHomeProcess && activities.size() > 0
766                && (mService.mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
767            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
768                final ActivityRecord r = activities.get(activityNdx);
769                if (r.isActivityTypeHome()) {
770                    Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
771                    try {
772                        ActivityThread.getPackageManager()
773                                .clearPackagePreferredActivities(r.packageName);
774                    } catch (RemoteException c) {
775                        // pm is in same process, this will never happen.
776                    }
777                }
778            }
779        }
780
781        if (!app.isolated) {
782            // XXX Can't keep track of crash times for isolated processes,
783            // because they don't have a persistent identity.
784            mProcessCrashTimes.put(app.info.processName, app.uid, now);
785            mProcessCrashTimesPersistent.put(app.info.processName, app.uid, now);
786        }
787
788        if (app.crashHandler != null) mService.mHandler.post(app.crashHandler);
789        return true;
790    }
791
792    void handleShowAppErrorUi(Message msg) {
793        AppErrorDialog.Data data = (AppErrorDialog.Data) msg.obj;
794        boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
795                Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
796        synchronized (mService) {
797            ProcessRecord proc = data.proc;
798            AppErrorResult res = data.result;
799            if (proc != null && proc.crashDialog != null) {
800                Slog.e(TAG, "App already has crash dialog: " + proc);
801                if (res != null) {
802                    res.set(AppErrorDialog.ALREADY_SHOWING);
803                }
804                return;
805            }
806            boolean isBackground = (UserHandle.getAppId(proc.uid)
807                    >= Process.FIRST_APPLICATION_UID
808                    && proc.pid != MY_PID);
809            for (int userId : mService.mUserController.getCurrentProfileIds()) {
810                isBackground &= (proc.userId != userId);
811            }
812            if (isBackground && !showBackground) {
813                Slog.w(TAG, "Skipping crash dialog of " + proc + ": background");
814                if (res != null) {
815                    res.set(AppErrorDialog.BACKGROUND_USER);
816                }
817                return;
818            }
819            final boolean showFirstCrash = Settings.Global.getInt(
820                    mContext.getContentResolver(),
821                    Settings.Global.SHOW_FIRST_CRASH_DIALOG, 0) != 0;
822            final boolean showFirstCrashDevOption = Settings.Secure.getIntForUser(
823                    mContext.getContentResolver(),
824                    Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
825                    0,
826                    mService.mUserController.getCurrentUserId()) != 0;
827            final boolean crashSilenced = mAppsNotReportingCrashes != null &&
828                    mAppsNotReportingCrashes.contains(proc.info.packageName);
829            if ((mService.canShowErrorDialogs() || showBackground) && !crashSilenced
830                    && (showFirstCrash || showFirstCrashDevOption || data.repeating)) {
831                proc.crashDialog = new AppErrorDialog(mContext, mService, data);
832            } else {
833                // The device is asleep, so just pretend that the user
834                // saw a crash dialog and hit "force quit".
835                if (res != null) {
836                    res.set(AppErrorDialog.CANT_SHOW);
837                }
838            }
839        }
840        // If we've created a crash dialog, show it without the lock held
841        if(data.proc.crashDialog != null) {
842            Slog.i(TAG, "Showing crash dialog for package " + data.proc.info.packageName
843                    + " u" + data.proc.userId);
844            data.proc.crashDialog.show();
845        }
846    }
847
848    void stopReportingCrashesLocked(ProcessRecord proc) {
849        if (mAppsNotReportingCrashes == null) {
850            mAppsNotReportingCrashes = new ArraySet<>();
851        }
852        mAppsNotReportingCrashes.add(proc.info.packageName);
853    }
854
855    static boolean isInterestingForBackgroundTraces(ProcessRecord app) {
856        // The system_server is always considered interesting.
857        if (app.pid == MY_PID) {
858            return true;
859        }
860
861        // A package is considered interesting if any of the following is true :
862        //
863        // - It's displaying an activity.
864        // - It's the SystemUI.
865        // - It has an overlay or a top UI visible.
866        //
867        // NOTE: The check whether a given ProcessRecord belongs to the systemui
868        // process is a bit of a kludge, but the same pattern seems repeated at
869        // several places in the system server.
870        return app.isInterestingToUserLocked() ||
871            (app.info != null && "com.android.systemui".equals(app.info.packageName)) ||
872            (app.hasTopUi || app.hasOverlayUi);
873    }
874
875    final void appNotResponding(ProcessRecord app, ActivityRecord activity,
876            ActivityRecord parent, boolean aboveSystem, final String annotation) {
877        ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
878        SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
879
880        if (mService.mController != null) {
881            try {
882                // 0 == continue, -1 = kill process immediately
883                int res = mService.mController.appEarlyNotResponding(
884                        app.processName, app.pid, annotation);
885                if (res < 0 && app.pid != MY_PID) {
886                    app.kill("anr", true);
887                }
888            } catch (RemoteException e) {
889                mService.mController = null;
890                Watchdog.getInstance().setActivityController(null);
891            }
892        }
893
894        long anrTime = SystemClock.uptimeMillis();
895        if (ActivityManagerService.MONITOR_CPU_USAGE) {
896            mService.updateCpuStatsNow();
897        }
898
899        // Unless configured otherwise, swallow ANRs in background processes & kill the process.
900        boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
901                Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
902
903        boolean isSilentANR;
904
905        synchronized (mService) {
906            // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
907            if (mService.mShuttingDown) {
908                Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
909                return;
910            } else if (app.notResponding) {
911                Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
912                return;
913            } else if (app.crashing) {
914                Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
915                return;
916            } else if (app.killedByAm) {
917                Slog.i(TAG, "App already killed by AM skipping ANR: " + app + " " + annotation);
918                return;
919            } else if (app.killed) {
920                Slog.i(TAG, "Skipping died app ANR: " + app + " " + annotation);
921                return;
922            }
923
924            // In case we come through here for the same app before completing
925            // this one, mark as anring now so we will bail out.
926            app.notResponding = true;
927
928            // Log the ANR to the event log.
929            EventLog.writeEvent(EventLogTags.AM_ANR, app.userId, app.pid,
930                    app.processName, app.info.flags, annotation);
931
932            // Dump thread traces as quickly as we can, starting with "interesting" processes.
933            firstPids.add(app.pid);
934
935            // Don't dump other PIDs if it's a background ANR
936            isSilentANR = !showBackground && !isInterestingForBackgroundTraces(app);
937            if (!isSilentANR) {
938                int parentPid = app.pid;
939                if (parent != null && parent.app != null && parent.app.pid > 0) {
940                    parentPid = parent.app.pid;
941                }
942                if (parentPid != app.pid) firstPids.add(parentPid);
943
944                if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
945
946                for (int i = mService.mLruProcesses.size() - 1; i >= 0; i--) {
947                    ProcessRecord r = mService.mLruProcesses.get(i);
948                    if (r != null && r.thread != null) {
949                        int pid = r.pid;
950                        if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
951                            if (r.persistent) {
952                                firstPids.add(pid);
953                                if (DEBUG_ANR) Slog.i(TAG, "Adding persistent proc: " + r);
954                            } else if (r.treatLikeActivity) {
955                                firstPids.add(pid);
956                                if (DEBUG_ANR) Slog.i(TAG, "Adding likely IME: " + r);
957                            } else {
958                                lastPids.put(pid, Boolean.TRUE);
959                                if (DEBUG_ANR) Slog.i(TAG, "Adding ANR proc: " + r);
960                            }
961                        }
962                    }
963                }
964            }
965        }
966
967        // Log the ANR to the main log.
968        StringBuilder info = new StringBuilder();
969        info.setLength(0);
970        info.append("ANR in ").append(app.processName);
971        if (activity != null && activity.shortComponentName != null) {
972            info.append(" (").append(activity.shortComponentName).append(")");
973        }
974        info.append("\n");
975        info.append("PID: ").append(app.pid).append("\n");
976        if (annotation != null) {
977            info.append("Reason: ").append(annotation).append("\n");
978        }
979        if (parent != null && parent != activity) {
980            info.append("Parent: ").append(parent.shortComponentName).append("\n");
981        }
982
983        ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);
984
985        // don't dump native PIDs for background ANRs unless it is the process of interest
986        String[] nativeProcs = null;
987        if (isSilentANR) {
988            for (int i = 0; i < NATIVE_STACKS_OF_INTEREST.length; i++) {
989                if (NATIVE_STACKS_OF_INTEREST[i].equals(app.processName)) {
990                    nativeProcs = new String[] { app.processName };
991                    break;
992                }
993            }
994        } else {
995            nativeProcs = NATIVE_STACKS_OF_INTEREST;
996        }
997
998        int[] pids = nativeProcs == null ? null : Process.getPidsForCommands(nativeProcs);
999        ArrayList<Integer> nativePids = null;
1000
1001        if (pids != null) {
1002            nativePids = new ArrayList<Integer>(pids.length);
1003            for (int i : pids) {
1004                nativePids.add(i);
1005            }
1006        }
1007
1008        // For background ANRs, don't pass the ProcessCpuTracker to
1009        // avoid spending 1/2 second collecting stats to rank lastPids.
1010        File tracesFile = ActivityManagerService.dumpStackTraces(
1011                true, firstPids,
1012                (isSilentANR) ? null : processCpuTracker,
1013                (isSilentANR) ? null : lastPids,
1014                nativePids);
1015
1016        String cpuInfo = null;
1017        if (ActivityManagerService.MONITOR_CPU_USAGE) {
1018            mService.updateCpuStatsNow();
1019            synchronized (mService.mProcessCpuTracker) {
1020                cpuInfo = mService.mProcessCpuTracker.printCurrentState(anrTime);
1021            }
1022            info.append(processCpuTracker.printCurrentLoad());
1023            info.append(cpuInfo);
1024        }
1025
1026        info.append(processCpuTracker.printCurrentState(anrTime));
1027
1028        Slog.e(TAG, info.toString());
1029        if (tracesFile == null) {
1030            // There is no trace file, so dump (only) the alleged culprit's threads to the log
1031            Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
1032        }
1033
1034        mService.addErrorToDropBox("anr", app, app.processName, activity, parent, annotation,
1035                cpuInfo, tracesFile, null);
1036
1037        if (mService.mController != null) {
1038            try {
1039                // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
1040                int res = mService.mController.appNotResponding(
1041                        app.processName, app.pid, info.toString());
1042                if (res != 0) {
1043                    if (res < 0 && app.pid != MY_PID) {
1044                        app.kill("anr", true);
1045                    } else {
1046                        synchronized (mService) {
1047                            mService.mServices.scheduleServiceTimeoutLocked(app);
1048                        }
1049                    }
1050                    return;
1051                }
1052            } catch (RemoteException e) {
1053                mService.mController = null;
1054                Watchdog.getInstance().setActivityController(null);
1055            }
1056        }
1057
1058        synchronized (mService) {
1059            mService.mBatteryStatsService.noteProcessAnr(app.processName, app.uid);
1060
1061            if (isSilentANR) {
1062                app.kill("bg anr", true);
1063                return;
1064            }
1065
1066            // Set the app's notResponding state, and look up the errorReportReceiver
1067            makeAppNotRespondingLocked(app,
1068                    activity != null ? activity.shortComponentName : null,
1069                    annotation != null ? "ANR " + annotation : "ANR",
1070                    info.toString());
1071
1072            // Bring up the infamous App Not Responding dialog
1073            Message msg = Message.obtain();
1074            HashMap<String, Object> map = new HashMap<String, Object>();
1075            msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG;
1076            msg.obj = map;
1077            msg.arg1 = aboveSystem ? 1 : 0;
1078            map.put("app", app);
1079            if (activity != null) {
1080                map.put("activity", activity);
1081            }
1082
1083            mService.mUiHandler.sendMessage(msg);
1084        }
1085    }
1086
1087    private void makeAppNotRespondingLocked(ProcessRecord app,
1088            String activity, String shortMsg, String longMsg) {
1089        app.notResponding = true;
1090        app.notRespondingReport = generateProcessError(app,
1091                ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
1092                activity, shortMsg, longMsg, null);
1093        startAppProblemLocked(app);
1094        app.stopFreezingAllLocked();
1095    }
1096
1097    void handleShowAnrUi(Message msg) {
1098        Dialog d = null;
1099        synchronized (mService) {
1100            HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1101            ProcessRecord proc = (ProcessRecord)data.get("app");
1102            if (proc != null && proc.anrDialog != null) {
1103                Slog.e(TAG, "App already has anr dialog: " + proc);
1104                MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
1105                        AppNotRespondingDialog.ALREADY_SHOWING);
1106                return;
1107            }
1108
1109            Intent intent = new Intent("android.intent.action.ANR");
1110            if (!mService.mProcessesReady) {
1111                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
1112                        | Intent.FLAG_RECEIVER_FOREGROUND);
1113            }
1114            mService.broadcastIntentLocked(null, null, intent,
1115                    null, null, 0, null, null, null, AppOpsManager.OP_NONE,
1116                    null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);
1117
1118            boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
1119                    Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
1120            if (mService.canShowErrorDialogs() || showBackground) {
1121                d = new AppNotRespondingDialog(mService,
1122                        mContext, proc, (ActivityRecord)data.get("activity"),
1123                        msg.arg1 != 0);
1124                proc.anrDialog = d;
1125            } else {
1126                MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
1127                        AppNotRespondingDialog.CANT_SHOW);
1128                // Just kill the app if there is no dialog to be shown.
1129                mService.killAppAtUsersRequest(proc, null);
1130            }
1131        }
1132        // If we've created a crash dialog, show it without the lock held
1133        if (d != null) {
1134            d.show();
1135        }
1136    }
1137
1138    /**
1139     * Information about a process that is currently marked as bad.
1140     */
1141    static final class BadProcessInfo {
1142        BadProcessInfo(long time, String shortMsg, String longMsg, String stack) {
1143            this.time = time;
1144            this.shortMsg = shortMsg;
1145            this.longMsg = longMsg;
1146            this.stack = stack;
1147        }
1148
1149        final long time;
1150        final String shortMsg;
1151        final String longMsg;
1152        final String stack;
1153    }
1154
1155}
1156