void handleShowAnrUi(Message msg) { Dialog d = null; synchronized (mService) { HashMap<String, Object> data = (HashMap<String, Object>) msg.obj; ProcessRecord proc = (ProcessRecord) data.get("app"); if (proc != null && proc.anrDialog != null) { Slog.e(TAG, "App already has anr dialog: " + proc); MetricsLogger.action( mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR, AppNotRespondingDialog.ALREADY_SHOWING); return; } Intent intent = new Intent("android.intent.action.ANR"); if (!mService.mProcessesReady) { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); } mService.broadcastIntentLocked( null, null, intent, null, null, 0, null, null, null, AppOpsManager.OP_NONE, null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */); if (mService.canShowErrorDialogs()) { d = new AppNotRespondingDialog( mService, mContext, proc, (ActivityRecord) data.get("activity"), msg.arg1 != 0); proc.anrDialog = d; } else { MetricsLogger.action( mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR, AppNotRespondingDialog.CANT_SHOW); // Just kill the app if there is no dialog to be shown. mService.killAppAtUsersRequest(proc, null); } } // If we've created a crash dialog, show it without the lock held if (d != null) { d.show(); } }
void killAppAtUserRequestLocked(ProcessRecord app, Dialog fromDialog) { app.crashing = false; app.crashingReport = null; app.notResponding = false; app.notRespondingReport = null; if (app.anrDialog == fromDialog) { app.anrDialog = null; } if (app.waitDialog == fromDialog) { app.waitDialog = null; } if (app.pid > 0 && app.pid != MY_PID) { handleAppCrashLocked( app, "user-terminated" /*reason*/, null /*shortMsg*/, null /*longMsg*/, null /*stackTrace*/, null /*data*/); app.kill("user request after error", true); } }