blob: 190e9e1141b02179454d62a5c6af5bc25d11790a [file] [log] [blame]
Adrian Roos20d7df32016-01-12 18:59:43 +01001/*
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.os.ProcessCpuTracker;
21import com.android.server.Watchdog;
22
23import android.app.Activity;
24import android.app.ActivityManager;
25import android.app.ActivityOptions;
26import android.app.ActivityThread;
27import android.app.AppOpsManager;
28import android.app.ApplicationErrorReport;
29import android.app.Dialog;
30import android.content.ActivityNotFoundException;
31import android.content.Context;
32import android.content.Intent;
33import android.content.pm.ApplicationInfo;
34import android.content.pm.IPackageDataObserver;
35import android.content.pm.PackageManager;
36import android.os.Binder;
37import android.os.Bundle;
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.SparseArray;
51import android.util.TimeUtils;
52
53import java.io.File;
54import java.io.FileDescriptor;
55import java.io.PrintWriter;
56import java.util.ArrayList;
57import java.util.Collections;
58import java.util.HashMap;
59import java.util.concurrent.Semaphore;
60
61import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
62import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
63import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
64import static com.android.server.am.ActivityManagerService.MY_PID;
65import static com.android.server.am.ActivityManagerService.SYSTEM_DEBUGGABLE;
66
67/**
68 * Controls error conditions in applications.
69 */
70class AppErrors {
71
72 private static final String TAG = TAG_WITH_CLASS_NAME ? "AppErrors" : TAG_AM;
73
74 private final ActivityManagerService mService;
75 private final Context mContext;
76
77 private ArraySet<String> mAppsNotReportingCrashes;
78
79 /**
80 * The last time that various processes have crashed since they were last explicitly started.
81 */
82 private final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<>();
83
84 /**
85 * The last time that various processes have crashed (not reset even when explicitly started).
86 */
87 private final ProcessMap<Long> mProcessCrashTimesPersistent = new ProcessMap<>();
88
89 /**
90 * Set of applications that we consider to be bad, and will reject
91 * incoming broadcasts from (which the user has no control over).
92 * Processes are added to this set when they have crashed twice within
93 * a minimum amount of time; they are removed from it when they are
94 * later restarted (hopefully due to some user action). The value is the
95 * time it was added to the list.
96 */
97 private final ProcessMap<BadProcessInfo> mBadProcesses = new ProcessMap<>();
98
99
100 AppErrors(Context context, ActivityManagerService service) {
101 mService = service;
102 mContext = context;
103 }
104
105 boolean dumpLocked(FileDescriptor fd, PrintWriter pw, boolean needSep,
106 String dumpPackage) {
107 if (!mProcessCrashTimes.getMap().isEmpty()) {
108 boolean printed = false;
109 final long now = SystemClock.uptimeMillis();
110 final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap();
111 final int processCount = pmap.size();
112 for (int ip = 0; ip < processCount; ip++) {
113 final String pname = pmap.keyAt(ip);
114 final SparseArray<Long> uids = pmap.valueAt(ip);
115 final int uidCount = uids.size();
116 for (int i = 0; i < uidCount; i++) {
117 final int puid = uids.keyAt(i);
118 final ProcessRecord r = mService.mProcessNames.get(pname, puid);
119 if (dumpPackage != null && (r == null
120 || !r.pkgList.containsKey(dumpPackage))) {
121 continue;
122 }
123 if (!printed) {
124 if (needSep) pw.println();
125 needSep = true;
126 pw.println(" Time since processes crashed:");
127 printed = true;
128 }
129 pw.print(" Process "); pw.print(pname);
130 pw.print(" uid "); pw.print(puid);
131 pw.print(": last crashed ");
132 TimeUtils.formatDuration(now-uids.valueAt(i), pw);
133 pw.println(" ago");
134 }
135 }
136 }
137
138 if (!mBadProcesses.getMap().isEmpty()) {
139 boolean printed = false;
140 final ArrayMap<String, SparseArray<BadProcessInfo>> pmap = mBadProcesses.getMap();
141 final int processCount = pmap.size();
142 for (int ip = 0; ip < processCount; ip++) {
143 final String pname = pmap.keyAt(ip);
144 final SparseArray<BadProcessInfo> uids = pmap.valueAt(ip);
145 final int uidCount = uids.size();
146 for (int i = 0; i < uidCount; i++) {
147 final int puid = uids.keyAt(i);
148 final ProcessRecord r = mService.mProcessNames.get(pname, puid);
149 if (dumpPackage != null && (r == null
150 || !r.pkgList.containsKey(dumpPackage))) {
151 continue;
152 }
153 if (!printed) {
154 if (needSep) pw.println();
155 needSep = true;
156 pw.println(" Bad processes:");
157 printed = true;
158 }
159 final BadProcessInfo info = uids.valueAt(i);
160 pw.print(" Bad process "); pw.print(pname);
161 pw.print(" uid "); pw.print(puid);
162 pw.print(": crashed at time "); pw.println(info.time);
163 if (info.shortMsg != null) {
164 pw.print(" Short msg: "); pw.println(info.shortMsg);
165 }
166 if (info.longMsg != null) {
167 pw.print(" Long msg: "); pw.println(info.longMsg);
168 }
169 if (info.stack != null) {
170 pw.println(" Stack:");
171 int lastPos = 0;
172 for (int pos = 0; pos < info.stack.length(); pos++) {
173 if (info.stack.charAt(pos) == '\n') {
174 pw.print(" ");
175 pw.write(info.stack, lastPos, pos-lastPos);
176 pw.println();
177 lastPos = pos+1;
178 }
179 }
180 if (lastPos < info.stack.length()) {
181 pw.print(" ");
182 pw.write(info.stack, lastPos, info.stack.length()-lastPos);
183 pw.println();
184 }
185 }
186 }
187 }
188 }
189 return needSep;
190 }
191
192 boolean isBadProcessLocked(ApplicationInfo info) {
193 return mBadProcesses.get(info.processName, info.uid) != null;
194 }
195
196 void clearBadProcessLocked(ApplicationInfo info) {
197 mBadProcesses.remove(info.processName, info.uid);
198 }
199
200 void resetProcessCrashTimeLocked(ApplicationInfo info) {
201 mProcessCrashTimes.remove(info.processName, info.uid);
202 }
203
204 void resetProcessCrashTimeLocked(boolean resetEntireUser, int appId, int userId) {
205 final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap();
206 for (int ip = pmap.size() - 1; ip >= 0; ip--) {
207 SparseArray<Long> ba = pmap.valueAt(ip);
208 for (int i = ba.size() - 1; i >= 0; i--) {
209 boolean remove = false;
210 final int entUid = ba.keyAt(i);
211 if (!resetEntireUser) {
212 if (userId == UserHandle.USER_ALL) {
213 if (UserHandle.getAppId(entUid) == appId) {
214 remove = true;
215 }
216 } else {
217 if (entUid == UserHandle.getUid(userId, appId)) {
218 remove = true;
219 }
220 }
221 } else if (UserHandle.getUserId(entUid) == userId) {
222 remove = true;
223 }
224 if (remove) {
225 ba.removeAt(i);
226 }
227 }
228 if (ba.size() == 0) {
229 pmap.removeAt(ip);
230 }
231 }
232 }
233
234 void loadAppsNotReportingCrashesFromConfigLocked(String appsNotReportingCrashesConfig) {
235 if (appsNotReportingCrashesConfig != null) {
236 final String[] split = appsNotReportingCrashesConfig.split(",");
237 if (split.length > 0) {
238 mAppsNotReportingCrashes = new ArraySet<>();
239 Collections.addAll(mAppsNotReportingCrashes, split);
240 }
241 }
242 }
243
244 void killAppAtUserRequestLocked(ProcessRecord app, Dialog fromDialog) {
245 app.crashing = false;
246 app.crashingReport = null;
247 app.notResponding = false;
248 app.notRespondingReport = null;
249 if (app.anrDialog == fromDialog) {
250 app.anrDialog = null;
251 }
252 if (app.waitDialog == fromDialog) {
253 app.waitDialog = null;
254 }
255 if (app.pid > 0 && app.pid != MY_PID) {
256 handleAppCrashLocked(app, "user-terminated" /*reason*/,
257 null /*shortMsg*/, null /*longMsg*/, null /*stackTrace*/, null /*data*/);
258 app.kill("user request after error", true);
259 }
260 }
261
262 void scheduleAppCrashLocked(int uid, int initialPid, String packageName,
263 String message) {
264 ProcessRecord proc = null;
265
266 // Figure out which process to kill. We don't trust that initialPid
267 // still has any relation to current pids, so must scan through the
268 // list.
269
270 synchronized (mService.mPidsSelfLocked) {
271 for (int i=0; i<mService.mPidsSelfLocked.size(); i++) {
272 ProcessRecord p = mService.mPidsSelfLocked.valueAt(i);
273 if (p.uid != uid) {
274 continue;
275 }
276 if (p.pid == initialPid) {
277 proc = p;
278 break;
279 }
280 if (p.pkgList.containsKey(packageName)) {
281 proc = p;
282 }
283 }
284 }
285
286 if (proc == null) {
287 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
288 + " initialPid=" + initialPid
289 + " packageName=" + packageName);
290 return;
291 }
292
293 if (proc.thread != null) {
294 if (proc.pid == Process.myPid()) {
295 Log.w(TAG, "crashApplication: trying to crash self!");
296 return;
297 }
298 long ident = Binder.clearCallingIdentity();
299 try {
300 proc.thread.scheduleCrash(message);
301 } catch (RemoteException e) {
302 } finally {
303 Binder.restoreCallingIdentity(ident);
304 }
305 }
306 }
307
308 /**
309 * Bring up the "unexpected error" dialog box for a crashing app.
310 * Deal with edge cases (intercepts from instrumented applications,
311 * ActivityController, error intent receivers, that sort of thing).
312 * @param r the application crashing
313 * @param crashInfo describing the failure
314 */
315 void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
316 long timeMillis = System.currentTimeMillis();
317 String shortMsg = crashInfo.exceptionClassName;
318 String longMsg = crashInfo.exceptionMessage;
319 String stackTrace = crashInfo.stackTrace;
320 if (shortMsg != null && longMsg != null) {
321 longMsg = shortMsg + ": " + longMsg;
322 } else if (shortMsg != null) {
323 longMsg = shortMsg;
324 }
325
326 AppErrorResult result = new AppErrorResult();
327 TaskRecord task;
328 synchronized (mService) {
329 if (mService.mController != null) {
330 try {
331 String name = r != null ? r.processName : null;
332 int pid = r != null ? r.pid : Binder.getCallingPid();
333 int uid = r != null ? r.info.uid : Binder.getCallingUid();
334 if (!mService.mController.appCrashed(name, pid,
335 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
336 if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"))
337 && "Native crash".equals(crashInfo.exceptionClassName)) {
338 Slog.w(TAG, "Skip killing native crashed app " + name
339 + "(" + pid + ") during testing");
340 } else {
341 Slog.w(TAG, "Force-killing crashed app " + name
342 + " at watcher's request");
343 if (r != null) {
344 r.kill("crash", true);
345 } else {
346 // Huh.
347 Process.killProcess(pid);
348 ActivityManagerService.killProcessGroup(uid, pid);
349 }
350 }
351 return;
352 }
353 } catch (RemoteException e) {
354 mService.mController = null;
355 Watchdog.getInstance().setActivityController(null);
356 }
357 }
358
359 final long origId = Binder.clearCallingIdentity();
360
361 // If this process is running instrumentation, finish it.
362 if (r != null && r.instrumentationClass != null) {
363 Slog.w(TAG, "Error in app " + r.processName
364 + " running instrumentation " + r.instrumentationClass + ":");
365 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
366 if (longMsg != null) Slog.w(TAG, " " + longMsg);
367 Bundle info = new Bundle();
368 info.putString("shortMsg", shortMsg);
369 info.putString("longMsg", longMsg);
370 mService.finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
371 Binder.restoreCallingIdentity(origId);
372 return;
373 }
374
375 // Log crash in battery stats.
376 if (r != null) {
377 mService.mBatteryStatsService.noteProcessCrash(r.processName, r.uid);
378 }
379
380 AppErrorDialog.Data data = new AppErrorDialog.Data();
381 data.result = result;
382 data.proc = r;
383
384 // If we can't identify the process or it's already exceeded its crash quota,
385 // quit right away without showing a crash dialog.
386 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) {
387 Binder.restoreCallingIdentity(origId);
388 return;
389 }
390
391 Message msg = Message.obtain();
392 msg.what = ActivityManagerService.SHOW_ERROR_UI_MSG;
393
394 task = data.task;
395 msg.obj = data;
396 mService.mUiHandler.sendMessage(msg);
397
398 Binder.restoreCallingIdentity(origId);
399 }
400
401 int res = result.get();
402
403 Intent appErrorIntent = null;
404 final long ident = Binder.clearCallingIdentity();
405 try {
406 if (res == AppErrorDialog.RESET) {
407 String[] packageList = r.getPackageList();
408 if (packageList != null) {
409 PackageManager pm = mContext.getPackageManager();
410 final Semaphore s = new Semaphore(0);
411 for (int i = 0; i < packageList.length; i++) {
412 if (i < packageList.length - 1) {
413 pm.deleteApplicationCacheFiles(packageList[i], null);
414 } else {
415 pm.deleteApplicationCacheFiles(packageList[i],
416 new IPackageDataObserver.Stub() {
417 @Override
418 public void onRemoveCompleted(String packageName,
419 boolean succeeded) {
420 s.release();
421 }
422 });
423
424 // Wait until cache has been cleared before we restart.
425 try {
426 s.acquire();
427 } catch (InterruptedException e) {
428 }
429 }
430 }
431 }
432 // If there was nothing to reset, just restart;
433 res = AppErrorDialog.RESTART;
434 }
435 synchronized (mService) {
436 if (res == AppErrorDialog.MUTE) {
437 stopReportingCrashesLocked(r);
438 }
439 if (res == AppErrorDialog.RESTART) {
440 mService.removeProcessLocked(r, false, true, "crash");
441 if (task != null) {
442 try {
443 mService.startActivityFromRecents(task.taskId,
444 ActivityOptions.makeBasic().toBundle());
445 } catch (IllegalArgumentException e) {
446 // Hmm, that didn't work, app might have crashed before creating a
447 // recents entry. Let's see if we have a safe-to-restart intent.
448 if (task.intent.getCategories().contains(
449 Intent.CATEGORY_LAUNCHER)) {
450 mService.startActivityInPackage(task.mCallingUid,
451 task.mCallingPackage, task.intent,
452 null, null, null, 0, 0,
453 ActivityOptions.makeBasic().toBundle(),
454 task.userId, null, null);
455 }
456 }
457 }
458 }
459 if (res == AppErrorDialog.FORCE_QUIT) {
460 long orig = Binder.clearCallingIdentity();
461 try {
462 // Kill it with fire!
463 mService.mStackSupervisor.handleAppCrashLocked(r);
464 if (!r.persistent) {
465 mService.removeProcessLocked(r, false, false, "crash");
466 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
467 }
468 } finally {
469 Binder.restoreCallingIdentity(orig);
470 }
471 }
472 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
473 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
474 }
475 if (r != null && !r.isolated && res != AppErrorDialog.RESTART) {
476 // XXX Can't keep track of crash time for isolated processes,
477 // since they don't have a persistent identity.
478 mProcessCrashTimes.put(r.info.processName, r.uid,
479 SystemClock.uptimeMillis());
480 }
481 }
482 } finally {
483 Binder.restoreCallingIdentity(ident);
484 }
485
486 if (appErrorIntent != null) {
487 try {
488 mContext.startActivityAsUser(appErrorIntent, new UserHandle(r.userId));
489 } catch (ActivityNotFoundException e) {
490 Slog.w(TAG, "bug report receiver dissappeared", e);
491 }
492 }
493 }
494
495 private boolean makeAppCrashingLocked(ProcessRecord app,
496 String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
497 app.crashing = true;
498 app.crashingReport = generateProcessError(app,
499 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
500 startAppProblemLocked(app);
501 app.stopFreezingAllLocked();
502 return handleAppCrashLocked(app, "force-crash" /*reason*/, shortMsg, longMsg, stackTrace,
503 data);
504 }
505
506 void startAppProblemLocked(ProcessRecord app) {
507 // If this app is not running under the current user, then we
508 // can't give it a report button because that would require
509 // launching the report UI under a different user.
510 app.errorReportReceiver = null;
511
512 for (int userId : mService.mUserController.getCurrentProfileIdsLocked()) {
513 if (app.userId == userId) {
514 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
515 mContext, app.info.packageName, app.info.flags);
516 }
517 }
518 mService.skipCurrentReceiverLocked(app);
519 }
520
521 /**
522 * Generate a process error record, suitable for attachment to a ProcessRecord.
523 *
524 * @param app The ProcessRecord in which the error occurred.
525 * @param condition Crashing, Application Not Responding, etc. Values are defined in
526 * ActivityManager.AppErrorStateInfo
527 * @param activity The activity associated with the crash, if known.
528 * @param shortMsg Short message describing the crash.
529 * @param longMsg Long message describing the crash.
530 * @param stackTrace Full crash stack trace, may be null.
531 *
532 * @return Returns a fully-formed AppErrorStateInfo record.
533 */
534 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
535 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
536 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
537
538 report.condition = condition;
539 report.processName = app.processName;
540 report.pid = app.pid;
541 report.uid = app.info.uid;
542 report.tag = activity;
543 report.shortMsg = shortMsg;
544 report.longMsg = longMsg;
545 report.stackTrace = stackTrace;
546
547 return report;
548 }
549
550 Intent createAppErrorIntentLocked(ProcessRecord r,
551 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
552 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
553 if (report == null) {
554 return null;
555 }
556 Intent result = new Intent(Intent.ACTION_APP_ERROR);
557 result.setComponent(r.errorReportReceiver);
558 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
559 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
560 return result;
561 }
562
563 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
564 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
565 if (r.errorReportReceiver == null) {
566 return null;
567 }
568
569 if (!r.crashing && !r.notResponding && !r.forceCrashReport) {
570 return null;
571 }
572
573 ApplicationErrorReport report = new ApplicationErrorReport();
574 report.packageName = r.info.packageName;
575 report.installerPackageName = r.errorReportReceiver.getPackageName();
576 report.processName = r.processName;
577 report.time = timeMillis;
578 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
579
580 if (r.crashing || r.forceCrashReport) {
581 report.type = ApplicationErrorReport.TYPE_CRASH;
582 report.crashInfo = crashInfo;
583 } else if (r.notResponding) {
584 report.type = ApplicationErrorReport.TYPE_ANR;
585 report.anrInfo = new ApplicationErrorReport.AnrInfo();
586
587 report.anrInfo.activity = r.notRespondingReport.tag;
588 report.anrInfo.cause = r.notRespondingReport.shortMsg;
589 report.anrInfo.info = r.notRespondingReport.longMsg;
590 }
591
592 return report;
593 }
594
595 boolean handleAppCrashLocked(ProcessRecord app, String reason,
596 String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
597 long now = SystemClock.uptimeMillis();
598
599 Long crashTime;
600 Long crashTimePersistent;
601 if (!app.isolated) {
602 crashTime = mProcessCrashTimes.get(app.info.processName, app.uid);
603 crashTimePersistent = mProcessCrashTimesPersistent.get(app.info.processName, app.uid);
604 } else {
605 crashTime = crashTimePersistent = null;
606 }
607 if (crashTime != null && now < crashTime+ProcessList.MIN_CRASH_INTERVAL) {
608 // This process loses!
609 Slog.w(TAG, "Process " + app.info.processName
610 + " has crashed too many times: killing!");
611 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
612 app.userId, app.info.processName, app.uid);
613 mService.mStackSupervisor.handleAppCrashLocked(app);
614 if (!app.persistent) {
615 // We don't want to start this process again until the user
616 // explicitly does so... but for persistent process, we really
617 // need to keep it running. If a persistent process is actually
618 // repeatedly crashing, then badness for everyone.
619 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.userId, app.uid,
620 app.info.processName);
621 if (!app.isolated) {
622 // XXX We don't have a way to mark isolated processes
623 // as bad, since they don't have a peristent identity.
624 mBadProcesses.put(app.info.processName, app.uid,
625 new BadProcessInfo(now, shortMsg, longMsg, stackTrace));
626 mProcessCrashTimes.remove(app.info.processName, app.uid);
627 }
628 app.bad = true;
629 app.removed = true;
630 // Don't let services in this process be restarted and potentially
631 // annoy the user repeatedly. Unless it is persistent, since those
632 // processes run critical code.
633 mService.removeProcessLocked(app, false, false, "crash");
634 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
635 return false;
636 }
637 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
638 } else {
639 TaskRecord affectedTask =
640 mService.mStackSupervisor.finishTopRunningActivityLocked(app, reason);
641 if (data != null) {
642 data.task = affectedTask;
643 }
644 if (data != null && crashTimePersistent != null
645 && now < crashTimePersistent + ProcessList.MIN_CRASH_INTERVAL) {
646 data.repeating = true;
647 }
648 }
649
650 // Bump up the crash count of any services currently running in the proc.
651 for (int i=app.services.size()-1; i>=0; i--) {
652 // Any services running in the application need to be placed
653 // back in the pending list.
654 ServiceRecord sr = app.services.valueAt(i);
655 sr.crashCount++;
656 }
657
658 // If the crashing process is what we consider to be the "home process" and it has been
659 // replaced by a third-party app, clear the package preferred activities from packages
660 // with a home activity running in the process to prevent a repeatedly crashing app
661 // from blocking the user to manually clear the list.
662 final ArrayList<ActivityRecord> activities = app.activities;
663 if (app == mService.mHomeProcess && activities.size() > 0
664 && (mService.mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
665 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
666 final ActivityRecord r = activities.get(activityNdx);
667 if (r.isHomeActivity()) {
668 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
669 try {
670 ActivityThread.getPackageManager()
671 .clearPackagePreferredActivities(r.packageName);
672 } catch (RemoteException c) {
673 // pm is in same process, this will never happen.
674 }
675 }
676 }
677 }
678
679 if (!app.isolated) {
680 // XXX Can't keep track of crash times for isolated processes,
681 // because they don't have a perisistent identity.
682 mProcessCrashTimes.put(app.info.processName, app.uid, now);
683 mProcessCrashTimesPersistent.put(app.info.processName, app.uid, now);
684 }
685
686 if (app.crashHandler != null) mService.mHandler.post(app.crashHandler);
687 return true;
688 }
689
690 void handleShowAppErrorUi(Message msg) {
691 AppErrorDialog.Data data = (AppErrorDialog.Data) msg.obj;
692 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
693 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
694 synchronized (mService) {
695 ProcessRecord proc = data.proc;
696 AppErrorResult res = data.result;
697 if (proc != null && proc.crashDialog != null) {
698 Slog.e(TAG, "App already has crash dialog: " + proc);
699 if (res != null) {
700 res.set(0);
701 }
702 return;
703 }
704 boolean isBackground = (UserHandle.getAppId(proc.uid)
705 >= Process.FIRST_APPLICATION_UID
706 && proc.pid != MY_PID);
707 for (int userId : mService.mUserController.getCurrentProfileIdsLocked()) {
708 isBackground &= (proc.userId != userId);
709 }
710 if (isBackground && !showBackground) {
711 Slog.w(TAG, "Skipping crash dialog of " + proc + ": background");
712 if (res != null) {
713 res.set(0);
714 }
715 return;
716 }
717 final boolean crashSilenced = mAppsNotReportingCrashes != null &&
718 mAppsNotReportingCrashes.contains(proc.info.packageName);
719 if (mService.canShowErrorDialogs() && !crashSilenced) {
720 Dialog d = new AppErrorDialog(mContext, mService, data);
721 d.show();
722 proc.crashDialog = d;
723 } else {
724 // The device is asleep, so just pretend that the user
725 // saw a crash dialog and hit "force quit".
726 if (res != null) {
727 res.set(0);
728 }
729 }
730 }
731 }
732
733 void stopReportingCrashesLocked(ProcessRecord proc) {
734 if (mAppsNotReportingCrashes == null) {
735 mAppsNotReportingCrashes = new ArraySet<>();
736 }
737 mAppsNotReportingCrashes.add(proc.info.packageName);
738 }
739
740 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
741 ActivityRecord parent, boolean aboveSystem, final String annotation) {
742 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
743 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
744
745 if (mService.mController != null) {
746 try {
747 // 0 == continue, -1 = kill process immediately
Adrian Roosa85a2c62016-01-26 09:14:22 -0800748 int res = mService.mController.appEarlyNotResponding(
749 app.processName, app.pid, annotation);
Adrian Roos20d7df32016-01-12 18:59:43 +0100750 if (res < 0 && app.pid != MY_PID) {
751 app.kill("anr", true);
752 }
753 } catch (RemoteException e) {
754 mService.mController = null;
755 Watchdog.getInstance().setActivityController(null);
756 }
757 }
758
759 long anrTime = SystemClock.uptimeMillis();
760 if (ActivityManagerService.MONITOR_CPU_USAGE) {
761 mService.updateCpuStatsNow();
762 }
763
764 synchronized (mService) {
765 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
766 if (mService.mShuttingDown) {
767 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
768 return;
769 } else if (app.notResponding) {
770 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
771 return;
772 } else if (app.crashing) {
773 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
774 return;
775 }
776
777 // In case we come through here for the same app before completing
778 // this one, mark as anring now so we will bail out.
779 app.notResponding = true;
780
781 // Log the ANR to the event log.
782 EventLog.writeEvent(EventLogTags.AM_ANR, app.userId, app.pid,
783 app.processName, app.info.flags, annotation);
784
785 // Dump thread traces as quickly as we can, starting with "interesting" processes.
786 firstPids.add(app.pid);
787
788 int parentPid = app.pid;
789 if (parent != null && parent.app != null && parent.app.pid > 0) {
790 parentPid = parent.app.pid;
791 }
792 if (parentPid != app.pid) firstPids.add(parentPid);
793
794 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
795
796 for (int i = mService.mLruProcesses.size() - 1; i >= 0; i--) {
797 ProcessRecord r = mService.mLruProcesses.get(i);
798 if (r != null && r.thread != null) {
799 int pid = r.pid;
800 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
801 if (r.persistent) {
802 firstPids.add(pid);
803 } else {
804 lastPids.put(pid, Boolean.TRUE);
805 }
806 }
807 }
808 }
809 }
810
811 // Log the ANR to the main log.
812 StringBuilder info = new StringBuilder();
813 info.setLength(0);
814 info.append("ANR in ").append(app.processName);
815 if (activity != null && activity.shortComponentName != null) {
816 info.append(" (").append(activity.shortComponentName).append(")");
817 }
818 info.append("\n");
819 info.append("PID: ").append(app.pid).append("\n");
820 if (annotation != null) {
821 info.append("Reason: ").append(annotation).append("\n");
822 }
823 if (parent != null && parent != activity) {
824 info.append("Parent: ").append(parent.shortComponentName).append("\n");
825 }
826
827 final ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);
828
829 File tracesFile = mService.dumpStackTraces(true, firstPids, processCpuTracker, lastPids,
830 NATIVE_STACKS_OF_INTEREST);
831
832 String cpuInfo = null;
833 if (ActivityManagerService.MONITOR_CPU_USAGE) {
834 mService.updateCpuStatsNow();
835 synchronized (mService.mProcessCpuTracker) {
836 cpuInfo = mService.mProcessCpuTracker.printCurrentState(anrTime);
837 }
838 info.append(processCpuTracker.printCurrentLoad());
839 info.append(cpuInfo);
840 }
841
842 info.append(processCpuTracker.printCurrentState(anrTime));
843
844 Slog.e(TAG, info.toString());
845 if (tracesFile == null) {
846 // There is no trace file, so dump (only) the alleged culprit's threads to the log
847 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
848 }
849
850 mService.addErrorToDropBox("anr", app, app.processName, activity, parent, annotation,
851 cpuInfo, tracesFile, null);
852
853 if (mService.mController != null) {
854 try {
855 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
856 int res = mService.mController.appNotResponding(
857 app.processName, app.pid, info.toString());
858 if (res != 0) {
859 if (res < 0 && app.pid != MY_PID) {
860 app.kill("anr", true);
861 } else {
862 synchronized (mService) {
863 mService.mServices.scheduleServiceTimeoutLocked(app);
864 }
865 }
866 return;
867 }
868 } catch (RemoteException e) {
869 mService.mController = null;
870 Watchdog.getInstance().setActivityController(null);
871 }
872 }
873
874 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
875 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
876 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
877
878 synchronized (mService) {
879 mService.mBatteryStatsService.noteProcessAnr(app.processName, app.uid);
880
881 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
882 app.kill("bg anr", true);
883 return;
884 }
885
886 // Set the app's notResponding state, and look up the errorReportReceiver
887 makeAppNotRespondingLocked(app,
888 activity != null ? activity.shortComponentName : null,
889 annotation != null ? "ANR " + annotation : "ANR",
890 info.toString());
891
892 // Bring up the infamous App Not Responding dialog
893 Message msg = Message.obtain();
894 HashMap<String, Object> map = new HashMap<String, Object>();
895 msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG;
896 msg.obj = map;
897 msg.arg1 = aboveSystem ? 1 : 0;
898 map.put("app", app);
899 if (activity != null) {
900 map.put("activity", activity);
901 }
902
903 mService.mUiHandler.sendMessage(msg);
904 }
905 }
906
907 private void makeAppNotRespondingLocked(ProcessRecord app,
908 String activity, String shortMsg, String longMsg) {
909 app.notResponding = true;
910 app.notRespondingReport = generateProcessError(app,
911 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
912 activity, shortMsg, longMsg, null);
913 startAppProblemLocked(app);
914 app.stopFreezingAllLocked();
915 }
916
917 void handleShowAnrUi(Message msg) {
918 synchronized (mService) {
919 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
920 ProcessRecord proc = (ProcessRecord)data.get("app");
921 if (proc != null && proc.anrDialog != null) {
922 Slog.e(TAG, "App already has anr dialog: " + proc);
923 return;
924 }
925
926 Intent intent = new Intent("android.intent.action.ANR");
927 if (!mService.mProcessesReady) {
928 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
929 | Intent.FLAG_RECEIVER_FOREGROUND);
930 }
931 mService.broadcastIntentLocked(null, null, intent,
932 null, null, 0, null, null, null, AppOpsManager.OP_NONE,
933 null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);
934
935 if (mService.canShowErrorDialogs()) {
936 Dialog d = new AppNotRespondingDialog(mService,
937 mContext, proc, (ActivityRecord)data.get("activity"),
938 msg.arg1 != 0);
939 d.show();
940 proc.anrDialog = d;
941 } else {
942 // Just kill the app if there is no dialog to be shown.
943 mService.killAppAtUsersRequest(proc, null);
944 }
945 }
946 }
947
948 /**
949 * Information about a process that is currently marked as bad.
950 */
951 static final class BadProcessInfo {
952 BadProcessInfo(long time, String shortMsg, String longMsg, String stack) {
953 this.time = time;
954 this.shortMsg = shortMsg;
955 this.longMsg = longMsg;
956 this.stack = stack;
957 }
958
959 final long time;
960 final String shortMsg;
961 final String longMsg;
962 final String stack;
963 }
964
965}