Android12 支持发送ANR和ACTION_APP_ERROR广播
一、需求说明
-
在系统发生ANR事件时发送:android.intent.action.ANR通知上层日志服务。对应的广播内容:
Key Value Type action android.intent.action.ANR packageName 发生ANR的应用包名 String -
在有应用奔溃时发送Intent.ACTION_APP_ERROR广播通知上层日志服务。对应的广播内容:
Key Value Type action Intent.ACTION_APP_ERROR Intent.EXTRA_BUG_REPORT 应用的Crash信息 ApplicationErrorReport.CrashInfo
二、实现代码
diff --git a/frameworks/base/services/core/java/com/android/server/am/AppErrors.java b/frameworks/base/services/core/java/com/android/server/am/AppErrors.java
index 8debf9d7a18..2c7fa682203 100644
--- a/frameworks/base/services/core/java/com/android/server/am/AppErrors.java
+++ b/frameworks/base/services/core/java/com/android/server/am/AppErrors.java
@@ -70,6 +70,10 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -70,6 +70,10 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.List;
+import android.content.Intent;
+import android.app.AppOpsManager;
+import android.os.UserHandle;
+import static android.app.AppOpsManager.OP_NONE;
/**
* Controls error conditions in applications.
@@ -564,6 +568,9 @@ class AppErrors {
private void crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo,
int callingPid, int callingUid) {
long timeMillis = System.currentTimeMillis();
String shortMsg = crashInfo.exceptionClassName;
String longMsg = crashInfo.exceptionMessage;
@@ -629,7 +636,9 @@ class AppErrors {
if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) {
return;
}
-
+
+ CrashMonitor.sendCrashBroadcast(mContext,r,timeMillis,crashInfo);
final Message msg = Message.obtain();
msg.what = ActivityManagerService.SHOW_ERROR_UI_MSG;
@@ -1083,6 +1092,18 @@ class AppErrors {
if (!proc.isPersistent()) {
packageList = proc.getPackageListWithVersionCode();
}
+
+ Intent intent = new Intent("android.intent.action.ANR");
+ intent.putExtra("packageName", proc.info.packageName);
+ if (!mService.mProcessesReady) {
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND);
+ }
+ mService.broadcastIntentLocked(null, null, null,intent, null, null, 0, null, null, null,null, AppOpsManager.OP_NONE,
+ null, false, false, MY_PID, Process.SYSTEM_UID, Binder.getCallingUid(),
+ Binder.getCallingPid(), UserHandle.USER_ALL);
+
if (errState.getDialogController().hasAnrDialogs()) {
Slog.e(TAG, "App already has anr dialog: " + proc);
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
diff --git a/frameworks/base/services/core/java/com/android/server/am/CrashMonitor.java b/frameworks/base/services/core/java/com/android/server/am/CrashMonitor.java
new file mode 100644
index 00000000000..38d76eb273a
--- /dev/null
+++ b/frameworks/base/services/core/java/com/android/server/am/CrashMonitor.java
@@ -0,0 +1,47 @@
+package com.android.server.am;
+
+import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
+
+import android.os.UserHandle;
+import android.app.ApplicationErrorReport;
+import android.content.Context;
+import android.content.Intent;
+
+class CrashMonitor {
+ private static final String TAG = "CrashMonitor";
+ private static Intent getCrashIntent(ProcessRecord r,
+ long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
+ ApplicationErrorReport report = new ApplicationErrorReport();
+ report.packageName = r.info.packageName;
+ if (r.mErrorState.getErrorReportReceiver() != null) {
+ report.installerPackageName = r.mErrorState.getErrorReportReceiver().getPackageName();
+ }
+ report.processName = r.processName;
+ report.time = timeMillis;
+ report.systemApp = (r.info.flags & FLAG_SYSTEM) != 0;
+ if (r.mErrorState.isCrashing() || r.mErrorState.isForceCrashReport()) {
+ report.type = ApplicationErrorReport.TYPE_CRASH;
+ report.crashInfo = crashInfo;
+ } else if(r.mErrorState.isNotResponding()) {
+ report.type = ApplicationErrorReport.TYPE_ANR;
+ report.anrInfo = new ApplicationErrorReport.AnrInfo();
+ report.anrInfo.activity = r.mErrorState.getNotRespondingReport().tag;
+ report.anrInfo.cause = r.mErrorState.getNotRespondingReport().shortMsg;
+ report.anrInfo.info = r.mErrorState.getNotRespondingReport().longMsg;
+ }
+
+ Intent result = new Intent(Intent.ACTION_APP_ERROR);
+ result.putExtra(Intent.EXTRA_BUG_REPORT, report);
+ return result;
+ }
+
+
+ public static void sendCrashBroadcast(Context context, ProcessRecord r,
+ long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
+ Intent intent = getCrashIntent(r, timeMillis, crashInfo);
+ context.sendBroadcastAsUser(intent, UserHandle.ALL);
+ }
+}