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;
25
26import android.app.ActivityManager;
27import android.app.ActivityOptions;
28import android.app.ActivityThread;
29import android.app.AppOpsManager;
30import android.app.ApplicationErrorReport;
31import android.app.Dialog;
32import android.content.ActivityNotFoundException;
33import android.content.Context;
34import android.content.Intent;
35import android.content.pm.ApplicationInfo;
36import android.net.Uri;
37import android.os.Binder;
38import android.os.Message;
39import android.os.Process;
40import android.os.RemoteException;
41import android.os.SystemClock;
42import android.os.SystemProperties;
43import android.os.UserHandle;
44import android.provider.Settings;
45import android.util.ArrayMap;
46import android.util.ArraySet;
47import android.util.EventLog;
48import android.util.Log;
49import android.util.Slog;
50import android.util.StatsLog;
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 != null
480                                ? task.intent.getCategories() : null;
481                        if (cats != null && cats.contains(Intent.CATEGORY_LAUNCHER)) {
482                            mService.getActivityStartController().startActivityInPackage(
483                                    task.mCallingUid, callingPid, callingUid, task.mCallingPackage,
484                                    task.intent, null, null, null, 0, 0,
485                                    new SafeActivityOptions(ActivityOptions.makeBasic()),
486                                    task.userId, null,
487                                    "AppErrors", false /*validateIncomingUser*/);
488                        }
489                    }
490                }
491            }
492            if (res == AppErrorDialog.FORCE_QUIT) {
493                long orig = Binder.clearCallingIdentity();
494                try {
495                    // Kill it with fire!
496                    mService.mStackSupervisor.handleAppCrashLocked(r);
497                    if (!r.persistent) {
498                        mService.removeProcessLocked(r, false, false, "crash");
499                        mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
500                    }
501                } finally {
502                    Binder.restoreCallingIdentity(orig);
503                }
504            }
505            if (res == AppErrorDialog.APP_INFO) {
506                appErrorIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
507                appErrorIntent.setData(Uri.parse("package:" + r.info.packageName));
508                appErrorIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
509            }
510            if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
511                appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
512            }
513            if (r != null && !r.isolated && res != AppErrorDialog.RESTART) {
514                // XXX Can't keep track of crash time for isolated processes,
515                // since they don't have a persistent identity.
516                mProcessCrashTimes.put(r.info.processName, r.uid,
517                        SystemClock.uptimeMillis());
518            }
519        }
520
521        if (appErrorIntent != null) {
522            try {
523                mContext.startActivityAsUser(appErrorIntent, new UserHandle(r.userId));
524            } catch (ActivityNotFoundException e) {
525                Slog.w(TAG, "bug report receiver dissappeared", e);
526            }
527        }
528    }
529
530    private boolean handleAppCrashInActivityController(ProcessRecord r,
531                                                       ApplicationErrorReport.CrashInfo crashInfo,
532                                                       String shortMsg, String longMsg,
533                                                       String stackTrace, long timeMillis,
534                                                       int callingPid, int callingUid) {
535        if (mService.mController == null) {
536            return false;
537        }
538
539        try {
540            String name = r != null ? r.processName : null;
541            int pid = r != null ? r.pid : callingPid;
542            int uid = r != null ? r.info.uid : callingUid;
543            if (!mService.mController.appCrashed(name, pid,
544                    shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
545                if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"))
546                        && "Native crash".equals(crashInfo.exceptionClassName)) {
547                    Slog.w(TAG, "Skip killing native crashed app " + name
548                            + "(" + pid + ") during testing");
549                } else {
550                    Slog.w(TAG, "Force-killing crashed app " + name
551                            + " at watcher's request");
552                    if (r != null) {
553                        if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null))
554                        {
555                            r.kill("crash", true);
556                        }
557                    } else {
558                        // Huh.
559                        Process.killProcess(pid);
560                        ActivityManagerService.killProcessGroup(uid, pid);
561                    }
562                }
563                return true;
564            }
565        } catch (RemoteException e) {
566            mService.mController = null;
567            Watchdog.getInstance().setActivityController(null);
568        }
569        return false;
570    }
571
572    private boolean makeAppCrashingLocked(ProcessRecord app,
573            String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
574        app.crashing = true;
575        app.crashingReport = generateProcessError(app,
576                ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
577        startAppProblemLocked(app);
578        app.stopFreezingAllLocked();
579        return handleAppCrashLocked(app, "force-crash" /*reason*/, shortMsg, longMsg, stackTrace,
580                data);
581    }
582
583    void startAppProblemLocked(ProcessRecord app) {
584        // If this app is not running under the current user, then we
585        // can't give it a report button because that would require
586        // launching the report UI under a different user.
587        app.errorReportReceiver = null;
588
589        for (int userId : mService.mUserController.getCurrentProfileIds()) {
590            if (app.userId == userId) {
591                app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
592                        mContext, app.info.packageName, app.info.flags);
593            }
594        }
595        mService.skipCurrentReceiverLocked(app);
596    }
597
598    /**
599     * Generate a process error record, suitable for attachment to a ProcessRecord.
600     *
601     * @param app The ProcessRecord in which the error occurred.
602     * @param condition Crashing, Application Not Responding, etc.  Values are defined in
603     *                      ActivityManager.ProcessErrorStateInfo
604     * @param activity The activity associated with the crash, if known.
605     * @param shortMsg Short message describing the crash.
606     * @param longMsg Long message describing the crash.
607     * @param stackTrace Full crash stack trace, may be null.
608     *
609     * @return Returns a fully-formed ProcessErrorStateInfo record.
610     */
611    private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
612            int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
613        ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
614
615        report.condition = condition;
616        report.processName = app.processName;
617        report.pid = app.pid;
618        report.uid = app.info.uid;
619        report.tag = activity;
620        report.shortMsg = shortMsg;
621        report.longMsg = longMsg;
622        report.stackTrace = stackTrace;
623
624        return report;
625    }
626
627    Intent createAppErrorIntentLocked(ProcessRecord r,
628            long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
629        ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
630        if (report == null) {
631            return null;
632        }
633        Intent result = new Intent(Intent.ACTION_APP_ERROR);
634        result.setComponent(r.errorReportReceiver);
635        result.putExtra(Intent.EXTRA_BUG_REPORT, report);
636        result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
637        return result;
638    }
639
640    private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
641            long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
642        if (r.errorReportReceiver == null) {
643            return null;
644        }
645
646        if (!r.crashing && !r.notResponding && !r.forceCrashReport) {
647            return null;
648        }
649
650        ApplicationErrorReport report = new ApplicationErrorReport();
651        report.packageName = r.info.packageName;
652        report.installerPackageName = r.errorReportReceiver.getPackageName();
653        report.processName = r.processName;
654        report.time = timeMillis;
655        report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
656
657        if (r.crashing || r.forceCrashReport) {
658            report.type = ApplicationErrorReport.TYPE_CRASH;
659            report.crashInfo = crashInfo;
660        } else if (r.notResponding) {
661            report.type = ApplicationErrorReport.TYPE_ANR;
662            report.anrInfo = new ApplicationErrorReport.AnrInfo();
663
664            report.anrInfo.activity = r.notRespondingReport.tag;
665            report.anrInfo.cause = r.notRespondingReport.shortMsg;
666            report.anrInfo.info = r.notRespondingReport.longMsg;
667        }
668
669        return report;
670    }
671
672    boolean handleAppCrashLocked(ProcessRecord app, String reason,
673            String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
674        final long now = SystemClock.uptimeMillis();
675        final boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
676                Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
677
678        final boolean procIsBoundForeground =
679            (app.curProcState == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
680
681        Long crashTime;
682        Long crashTimePersistent;
683        boolean tryAgain = false;
684
685        if (!app.isolated) {
686            crashTime = mProcessCrashTimes.get(app.info.processName, app.uid);
687            crashTimePersistent = mProcessCrashTimesPersistent.get(app.info.processName, app.uid);
688        } else {
689            crashTime = crashTimePersistent = null;
690        }
691
692        // Bump up the crash count of any services currently running in the proc.
693        for (int i = app.services.size() - 1; i >= 0; i--) {
694            // Any services running in the application need to be placed
695            // back in the pending list.
696            ServiceRecord sr = app.services.valueAt(i);
697            // If the service was restarted a while ago, then reset crash count, else increment it.
698            if (now > sr.restartTime + ProcessList.MIN_CRASH_INTERVAL) {
699                sr.crashCount = 1;
700            } else {
701                sr.crashCount++;
702            }
703            // Allow restarting for started or bound foreground services that are crashing.
704            // This includes wallpapers.
705            if (sr.crashCount < mService.mConstants.BOUND_SERVICE_MAX_CRASH_RETRY
706                    && (sr.isForeground || procIsBoundForeground)) {
707                tryAgain = true;
708            }
709        }
710
711        if (crashTime != null && now < crashTime + ProcessList.MIN_CRASH_INTERVAL) {
712            // The process crashed again very quickly. If it was a bound foreground service, let's
713            // try to restart again in a while, otherwise the process loses!
714            Slog.w(TAG, "Process " + app.info.processName
715                    + " has crashed too many times: killing!");
716            EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
717                    app.userId, app.info.processName, app.uid);
718            mService.mStackSupervisor.handleAppCrashLocked(app);
719            if (!app.persistent) {
720                // We don't want to start this process again until the user
721                // explicitly does so...  but for persistent process, we really
722                // need to keep it running.  If a persistent process is actually
723                // repeatedly crashing, then badness for everyone.
724                EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.userId, app.uid,
725                        app.info.processName);
726                if (!app.isolated) {
727                    // XXX We don't have a way to mark isolated processes
728                    // as bad, since they don't have a peristent identity.
729                    mBadProcesses.put(app.info.processName, app.uid,
730                            new BadProcessInfo(now, shortMsg, longMsg, stackTrace));
731                    mProcessCrashTimes.remove(app.info.processName, app.uid);
732                }
733                app.bad = true;
734                app.removed = true;
735                // Don't let services in this process be restarted and potentially
736                // annoy the user repeatedly.  Unless it is persistent, since those
737                // processes run critical code.
738                mService.removeProcessLocked(app, false, tryAgain, "crash");
739                mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
740                if (!showBackground) {
741                    return false;
742                }
743            }
744            mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
745        } else {
746            final TaskRecord affectedTask =
747                    mService.mStackSupervisor.finishTopCrashedActivitiesLocked(app, reason);
748            if (data != null) {
749                data.task = affectedTask;
750            }
751            if (data != null && crashTimePersistent != null
752                    && now < crashTimePersistent + ProcessList.MIN_CRASH_INTERVAL) {
753                data.repeating = true;
754            }
755        }
756
757        if (data != null && tryAgain) {
758            data.isRestartableForService = true;
759        }
760
761        // If the crashing process is what we consider to be the "home process" and it has been
762        // replaced by a third-party app, clear the package preferred activities from packages
763        // with a home activity running in the process to prevent a repeatedly crashing app
764        // from blocking the user to manually clear the list.
765        final ArrayList<ActivityRecord> activities = app.activities;
766        if (app == mService.mHomeProcess && activities.size() > 0
767                && (mService.mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
768            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
769                final ActivityRecord r = activities.get(activityNdx);
770                if (r.isActivityTypeHome()) {
771                    Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
772                    try {
773                        ActivityThread.getPackageManager()
774                                .clearPackagePreferredActivities(r.packageName);
775                    } catch (RemoteException c) {
776                        // pm is in same process, this will never happen.
777                    }
778                }
779            }
780        }
781
782        if (!app.isolated) {
783            // XXX Can't keep track of crash times for isolated processes,
784            // because they don't have a persistent identity.
785            mProcessCrashTimes.put(app.info.processName, app.uid, now);
786            mProcessCrashTimesPersistent.put(app.info.processName, app.uid, now);
787        }
788
789        if (app.crashHandler != null) mService.mHandler.post(app.crashHandler);
790        return true;
791    }
792
793    void handleShowAppErrorUi(Message msg) {
794        AppErrorDialog.Data data = (AppErrorDialog.Data) msg.obj;
795        boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
796                Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
797
798        AppErrorDialog dialogToShow = null;
799        final String packageName;
800        final int userId;
801        synchronized (mService) {
802            final ProcessRecord proc = data.proc;
803            final AppErrorResult res = data.result;
804            if (proc == null) {
805                Slog.e(TAG, "handleShowAppErrorUi: proc is null");
806                return;
807            }
808            packageName = proc.info.packageName;
809            userId = proc.userId;
810            if (proc.crashDialog != null) {
811                Slog.e(TAG, "App already has crash dialog: " + proc);
812                if (res != null) {
813                    res.set(AppErrorDialog.ALREADY_SHOWING);
814                }
815                return;
816            }
817            boolean isBackground = (UserHandle.getAppId(proc.uid)
818                    >= Process.FIRST_APPLICATION_UID
819                    && proc.pid != MY_PID);
820            for (int profileId : mService.mUserController.getCurrentProfileIds()) {
821                isBackground &= (userId != profileId);
822            }
823            if (isBackground && !showBackground) {
824                Slog.w(TAG, "Skipping crash dialog of " + proc + ": background");
825                if (res != null) {
826                    res.set(AppErrorDialog.BACKGROUND_USER);
827                }
828                return;
829            }
830            final boolean showFirstCrash = Settings.Global.getInt(
831                    mContext.getContentResolver(),
832                    Settings.Global.SHOW_FIRST_CRASH_DIALOG, 0) != 0;
833            final boolean showFirstCrashDevOption = Settings.Secure.getIntForUser(
834                    mContext.getContentResolver(),
835                    Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
836                    0,
837                    mService.mUserController.getCurrentUserId()) != 0;
838            final boolean crashSilenced = mAppsNotReportingCrashes != null &&
839                    mAppsNotReportingCrashes.contains(proc.info.packageName);
840            if ((mService.canShowErrorDialogs() || showBackground) && !crashSilenced
841                    && (showFirstCrash || showFirstCrashDevOption || data.repeating)) {
842                proc.crashDialog = dialogToShow = new AppErrorDialog(mContext, mService, data);
843            } else {
844                // The device is asleep, so just pretend that the user
845                // saw a crash dialog and hit "force quit".
846                if (res != null) {
847                    res.set(AppErrorDialog.CANT_SHOW);
848                }
849            }
850        }
851        // If we've created a crash dialog, show it without the lock held
852        if (dialogToShow != null) {
853            Slog.i(TAG, "Showing crash dialog for package " + packageName + " u" + userId);
854            dialogToShow.show();
855        }
856    }
857
858    void stopReportingCrashesLocked(ProcessRecord proc) {
859        if (mAppsNotReportingCrashes == null) {
860            mAppsNotReportingCrashes = new ArraySet<>();
861        }
862        mAppsNotReportingCrashes.add(proc.info.packageName);
863    }
864
865    static boolean isInterestingForBackgroundTraces(ProcessRecord app) {
866        // The system_server is always considered interesting.
867        if (app.pid == MY_PID) {
868            return true;
869        }
870
871        // A package is considered interesting if any of the following is true :
872        //
873        // - It's displaying an activity.
874        // - It's the SystemUI.
875        // - It has an overlay or a top UI visible.
876        //
877        // NOTE: The check whether a given ProcessRecord belongs to the systemui
878        // process is a bit of a kludge, but the same pattern seems repeated at
879        // several places in the system server.
880        return app.isInterestingToUserLocked() ||
881            (app.info != null && "com.android.systemui".equals(app.info.packageName)) ||
882            (app.hasTopUi || app.hasOverlayUi);
883    }
884
885    final void appNotResponding(ProcessRecord app, ActivityRecord activity,
886            ActivityRecord parent, boolean aboveSystem, final String annotation) {
887        ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
888        SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
889
890        if (mService.mController != null) {
891            try {
892                // 0 == continue, -1 = kill process immediately
893                int res = mService.mController.appEarlyNotResponding(
894                        app.processName, app.pid, annotation);
895                if (res < 0 && app.pid != MY_PID) {
896                    app.kill("anr", true);
897                }
898            } catch (RemoteException e) {
899                mService.mController = null;
900                Watchdog.getInstance().setActivityController(null);
901            }
902        }
903
904        long anrTime = SystemClock.uptimeMillis();
905        if (ActivityManagerService.MONITOR_CPU_USAGE) {
906            mService.updateCpuStatsNow();
907        }
908
909        // Unless configured otherwise, swallow ANRs in background processes & kill the process.
910        boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
911                Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
912
913        boolean isSilentANR;
914
915        synchronized (mService) {
916            // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
917            if (mService.mShuttingDown) {
918                Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
919                return;
920            } else if (app.notResponding) {
921                Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
922                return;
923            } else if (app.crashing) {
924                Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
925                return;
926            } else if (app.killedByAm) {
927                Slog.i(TAG, "App already killed by AM skipping ANR: " + app + " " + annotation);
928                return;
929            } else if (app.killed) {
930                Slog.i(TAG, "Skipping died app ANR: " + app + " " + annotation);
931                return;
932            }
933
934            // In case we come through here for the same app before completing
935            // this one, mark as anring now so we will bail out.
936            app.notResponding = true;
937
938            // Log the ANR to the event log.
939            EventLog.writeEvent(EventLogTags.AM_ANR, app.userId, app.pid,
940                    app.processName, app.info.flags, annotation);
941
942            // Dump thread traces as quickly as we can, starting with "interesting" processes.
943            firstPids.add(app.pid);
944
945            // Don't dump other PIDs if it's a background ANR
946            isSilentANR = !showBackground && !isInterestingForBackgroundTraces(app);
947            if (!isSilentANR) {
948                int parentPid = app.pid;
949                if (parent != null && parent.app != null && parent.app.pid > 0) {
950                    parentPid = parent.app.pid;
951                }
952                if (parentPid != app.pid) firstPids.add(parentPid);
953
954                if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
955
956                for (int i = mService.mLruProcesses.size() - 1; i >= 0; i--) {
957                    ProcessRecord r = mService.mLruProcesses.get(i);
958                    if (r != null && r.thread != null) {
959                        int pid = r.pid;
960                        if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
961                            if (r.persistent) {
962                                firstPids.add(pid);
963                                if (DEBUG_ANR) Slog.i(TAG, "Adding persistent proc: " + r);
964                            } else if (r.treatLikeActivity) {
965                                firstPids.add(pid);
966                                if (DEBUG_ANR) Slog.i(TAG, "Adding likely IME: " + r);
967                            } else {
968                                lastPids.put(pid, Boolean.TRUE);
969                                if (DEBUG_ANR) Slog.i(TAG, "Adding ANR proc: " + r);
970                            }
971                        }
972                    }
973                }
974            }
975        }
976
977        // Log the ANR to the main log.
978        StringBuilder info = new StringBuilder();
979        info.setLength(0);
980        info.append("ANR in ").append(app.processName);
981        if (activity != null && activity.shortComponentName != null) {
982            info.append(" (").append(activity.shortComponentName).append(")");
983        }
984        info.append("\n");
985        info.append("PID: ").append(app.pid).append("\n");
986        if (annotation != null) {
987            info.append("Reason: ").append(annotation).append("\n");
988        }
989        if (parent != null && parent != activity) {
990            info.append("Parent: ").append(parent.shortComponentName).append("\n");
991        }
992
993        ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);
994
995        // don't dump native PIDs for background ANRs unless it is the process of interest
996        String[] nativeProcs = null;
997        if (isSilentANR) {
998            for (int i = 0; i < NATIVE_STACKS_OF_INTEREST.length; i++) {
999                if (NATIVE_STACKS_OF_INTEREST[i].equals(app.processName)) {
1000                    nativeProcs = new String[] { app.processName };
1001                    break;
1002                }
1003            }
1004        } else {
1005            nativeProcs = NATIVE_STACKS_OF_INTEREST;
1006        }
1007
1008        int[] pids = nativeProcs == null ? null : Process.getPidsForCommands(nativeProcs);
1009        ArrayList<Integer> nativePids = null;
1010
1011        if (pids != null) {
1012            nativePids = new ArrayList<Integer>(pids.length);
1013            for (int i : pids) {
1014                nativePids.add(i);
1015            }
1016        }
1017
1018        // For background ANRs, don't pass the ProcessCpuTracker to
1019        // avoid spending 1/2 second collecting stats to rank lastPids.
1020        File tracesFile = ActivityManagerService.dumpStackTraces(
1021                true, firstPids,
1022                (isSilentANR) ? null : processCpuTracker,
1023                (isSilentANR) ? null : lastPids,
1024                nativePids);
1025
1026        String cpuInfo = null;
1027        if (ActivityManagerService.MONITOR_CPU_USAGE) {
1028            mService.updateCpuStatsNow();
1029            synchronized (mService.mProcessCpuTracker) {
1030                cpuInfo = mService.mProcessCpuTracker.printCurrentState(anrTime);
1031            }
1032            info.append(processCpuTracker.printCurrentLoad());
1033            info.append(cpuInfo);
1034        }
1035
1036        info.append(processCpuTracker.printCurrentState(anrTime));
1037
1038        Slog.e(TAG, info.toString());
1039        if (tracesFile == null) {
1040            // There is no trace file, so dump (only) the alleged culprit's threads to the log
1041            Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
1042        }
1043
1044        StatsLog.write(StatsLog.ANR_OCCURRED, app.uid, app.processName,
1045                activity == null ? "unknown": activity.shortComponentName, annotation,
1046                (app.info != null) ? (app.info.isInstantApp()
1047                        ? StatsLog.ANROCCURRED__IS_INSTANT_APP__TRUE
1048                        : StatsLog.ANROCCURRED__IS_INSTANT_APP__FALSE)
1049                        : StatsLog.ANROCCURRED__IS_INSTANT_APP__UNAVAILABLE,
1050                app != null ? (app.isInterestingToUserLocked()
1051                        ? StatsLog.ANROCCURRED__FOREGROUND_STATE__FOREGROUND
1052                        : StatsLog.ANROCCURRED__FOREGROUND_STATE__BACKGROUND)
1053                        : StatsLog.ANROCCURRED__FOREGROUND_STATE__UNKNOWN);
1054        mService.addErrorToDropBox("anr", app, app.processName, activity, parent, annotation,
1055                cpuInfo, tracesFile, null);
1056
1057        if (mService.mController != null) {
1058            try {
1059                // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
1060                int res = mService.mController.appNotResponding(
1061                        app.processName, app.pid, info.toString());
1062                if (res != 0) {
1063                    if (res < 0 && app.pid != MY_PID) {
1064                        app.kill("anr", true);
1065                    } else {
1066                        synchronized (mService) {
1067                            mService.mServices.scheduleServiceTimeoutLocked(app);
1068                        }
1069                    }
1070                    return;
1071                }
1072            } catch (RemoteException e) {
1073                mService.mController = null;
1074                Watchdog.getInstance().setActivityController(null);
1075            }
1076        }
1077
1078        synchronized (mService) {
1079            mService.mBatteryStatsService.noteProcessAnr(app.processName, app.uid);
1080
1081            if (isSilentANR) {
1082                app.kill("bg anr", true);
1083                return;
1084            }
1085
1086            // Set the app's notResponding state, and look up the errorReportReceiver
1087            makeAppNotRespondingLocked(app,
1088                    activity != null ? activity.shortComponentName : null,
1089                    annotation != null ? "ANR " + annotation : "ANR",
1090                    info.toString());
1091
1092            // Bring up the infamous App Not Responding dialog
1093            Message msg = Message.obtain();
1094            msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG;
1095            msg.obj = new AppNotRespondingDialog.Data(app, activity, aboveSystem);
1096
1097            mService.mUiHandler.sendMessage(msg);
1098        }
1099    }
1100
1101    private void makeAppNotRespondingLocked(ProcessRecord app,
1102            String activity, String shortMsg, String longMsg) {
1103        app.notResponding = true;
1104        app.notRespondingReport = generateProcessError(app,
1105                ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
1106                activity, shortMsg, longMsg, null);
1107        startAppProblemLocked(app);
1108        app.stopFreezingAllLocked();
1109    }
1110
1111    void handleShowAnrUi(Message msg) {
1112        Dialog dialogToShow = null;
1113        synchronized (mService) {
1114            AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj;
1115            final ProcessRecord proc = data.proc;
1116            if (proc == null) {
1117                Slog.e(TAG, "handleShowAnrUi: proc is null");
1118                return;
1119            }
1120            if (proc.anrDialog != null) {
1121                Slog.e(TAG, "App already has anr dialog: " + proc);
1122                MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
1123                        AppNotRespondingDialog.ALREADY_SHOWING);
1124                return;
1125            }
1126
1127            Intent intent = new Intent("android.intent.action.ANR");
1128            if (!mService.mProcessesReady) {
1129                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
1130                        | Intent.FLAG_RECEIVER_FOREGROUND);
1131            }
1132            mService.broadcastIntentLocked(null, null, intent,
1133                    null, null, 0, null, null, null, AppOpsManager.OP_NONE,
1134                    null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);
1135
1136            boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
1137                    Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
1138            if (mService.canShowErrorDialogs() || showBackground) {
1139                dialogToShow = new AppNotRespondingDialog(mService, mContext, data);
1140                proc.anrDialog = dialogToShow;
1141            } else {
1142                MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
1143                        AppNotRespondingDialog.CANT_SHOW);
1144                // Just kill the app if there is no dialog to be shown.
1145                mService.killAppAtUsersRequest(proc, null);
1146            }
1147        }
1148        // If we've created a crash dialog, show it without the lock held
1149        if (dialogToShow != null) {
1150            dialogToShow.show();
1151        }
1152    }
1153
1154    /**
1155     * Information about a process that is currently marked as bad.
1156     */
1157    static final class BadProcessInfo {
1158        BadProcessInfo(long time, String shortMsg, String longMsg, String stack) {
1159            this.time = time;
1160            this.shortMsg = shortMsg;
1161            this.longMsg = longMsg;
1162            this.stack = stack;
1163        }
1164
1165        final long time;
1166        final String shortMsg;
1167        final String longMsg;
1168        final String stack;
1169    }
1170
1171}
1172