DivestOS/Patches/LineageOS-21.0/android_frameworks_base/0026-Crash_Details.patch
Tavi 58923f2ef9
21.0: More work
Signed-off-by: Tavi <tavi@divested.dev>
2024-12-05 14:46:14 -05:00

356 lines
14 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Mon, 8 Aug 2022 19:03:37 +0300
Subject: [PATCH] add an option to show the details of an application error to
the user
Adds a "Show details" item to crash and ANR (app not responding) dialogs that takes the user to a
SystemUI activity which shows the error details and allows to copy them to the clipboard or to
export them via the standard sharing UI.
---
.../android/app/ApplicationErrorReport.java | 14 +-
core/res/res/layout/app_anr_dialog.xml | 4 +-
core/res/res/layout/app_error_dialog.xml | 4 +-
core/res/res/values/strings.xml | 3 +
core/res/res/values/symbols.xml | 3 +
packages/SystemUI/AndroidManifest.xml | 12 ++
packages/SystemUI/res/values/strings.xml | 5 +
.../android/systemui/ErrorReportActivity.kt | 159 ++++++++++++++++++
.../java/com/android/server/am/AppErrors.java | 1 +
9 files changed, 199 insertions(+), 6 deletions(-)
create mode 100644 packages/SystemUI/src/com/android/systemui/ErrorReportActivity.kt
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index 9cea5e8ef4cf..e9f28d80b6ed 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -98,6 +98,9 @@ public class ApplicationErrorReport implements Parcelable {
*/
public String packageName;
+ /** @hide */
+ public long packageVersion;
+
/**
* Package name of the application which installed the application this
* report pertains to.
@@ -162,13 +165,18 @@ public class ApplicationErrorReport implements Parcelable {
String packageName, int appFlags) {
// check if error reporting is enabled in secure settings
int enabled = Settings.Global.getInt(context.getContentResolver(),
- Settings.Global.SEND_ACTION_APP_ERROR, 0);
+ Settings.Global.SEND_ACTION_APP_ERROR, 1);
if (enabled == 0) {
return null;
}
PackageManager pm = context.getPackageManager();
+ ComponentName systemUiReceiver = getErrorReportReceiver(pm, packageName, "com.android.systemui");
+ if (systemUiReceiver != null) {
+ return systemUiReceiver;
+ }
+
// look for receiver in the installer package
String candidate = null;
ComponentName result = null;
@@ -233,6 +241,7 @@ public class ApplicationErrorReport implements Parcelable {
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(type);
dest.writeString(packageName);
+ dest.writeLong(packageVersion);
dest.writeString(installerPackageName);
dest.writeString(processName);
dest.writeLong(time);
@@ -260,6 +269,7 @@ public class ApplicationErrorReport implements Parcelable {
public void readFromParcel(Parcel in) {
type = in.readInt();
packageName = in.readString();
+ packageVersion = in.readLong();
installerPackageName = in.readString();
processName = in.readString();
time = in.readLong();
@@ -704,7 +714,7 @@ public class ApplicationErrorReport implements Parcelable {
*/
public void dump(Printer pw, String prefix) {
pw.println(prefix + "type: " + type);
- pw.println(prefix + "packageName: " + packageName);
+ pw.println(prefix + "packageName: " + packageName + ":" + packageVersion);
pw.println(prefix + "installerPackageName: " + installerPackageName);
pw.println(prefix + "processName: " + processName);
pw.println(prefix + "time: " + time);
diff --git a/core/res/res/layout/app_anr_dialog.xml b/core/res/res/layout/app_anr_dialog.xml
index 5ad0f4c0f6cc..ad3a2d2991de 100644
--- a/core/res/res/layout/app_anr_dialog.xml
+++ b/core/res/res/layout/app_anr_dialog.xml
@@ -41,8 +41,8 @@
android:id="@+id/aerr_report"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/aerr_report"
- android:drawableStart="@drawable/ic_feedback"
+ android:text="@string/aerr_show_details"
+ android:drawableStart="@drawable/ic_info_outline_24"
style="@style/aerr_list_item" />
</LinearLayout>
diff --git a/core/res/res/layout/app_error_dialog.xml b/core/res/res/layout/app_error_dialog.xml
index c3b149a1e295..a47b82018377 100644
--- a/core/res/res/layout/app_error_dialog.xml
+++ b/core/res/res/layout/app_error_dialog.xml
@@ -52,8 +52,8 @@
android:id="@+id/aerr_report"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/aerr_report"
- android:drawableStart="@drawable/ic_feedback"
+ android:text="@string/aerr_show_details"
+ android:drawableStart="@drawable/ic_info_outline_24"
style="@style/aerr_list_item" />
<Button
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 59066eb83f1c..d422e6f2aca6 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -6337,6 +6337,9 @@ ul.</string>
<!-- Title for preference of the system default locale. [CHAR LIMIT=50]-->
<string name="system_locale_title">System default</string>
+ <!-- Button that opens the screen with details of an application error -->
+ <string name="aerr_show_details">Show details</string>
+
<!-- Display content to tell the user the sim card name and number-->
<string name="default_card_name">CARD <xliff:g id="cardNumber" example="1">%d</xliff:g></string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a1804672da73..07d3924d8d39 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -5174,6 +5174,9 @@
<java-symbol type="id" name="language_picker_item" />
<java-symbol type="id" name="language_picker_header" />
+ <!-- Button that opens the screen with details of an application error -->
+ <java-symbol type="string" name="aerr_show_details" />
+
<java-symbol type="dimen" name="status_bar_height_default" />
<java-symbol type="string" name="default_card_name"/>
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 00604a316019..6f003b4ec257 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -1069,6 +1069,18 @@
android:exported="false">
</activity>
+ <activity
+ android:name=".ErrorReportActivity"
+ android:exported="true"
+ android:theme="@android:style/Theme.DeviceDefault.DayNight"
+ android:documentLaunchMode="always"
+ android:process=":ui"
+ >
+ <intent-filter>
+ <action android:name="android.intent.action.APP_ERROR" />
+ </intent-filter>
+ </activity>
+
<provider
android:authorities="com.android.systemui.customization"
android:name="com.android.systemui.keyguard.CustomizationProvider"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d2b186d9af2c..48a08ff2b7e9 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -3159,6 +3159,11 @@
<!-- Time format for the Dream Time Complication for 24-hour time format [CHAR LIMIT=NONE] -->
<string name="dream_time_complication_24_hr_time_format">kk:mm</string>
+ <string name="error_report_title">Error in %1$s</string>
+ <string name="copy_to_clipboard">Copy to clipboard</string>
+ <string name="copied_to_clipboard">Copied to clipboard</string>
+ <string name="error_share">Share</string>
+
<!-- Title for the log access confirmation dialog. [CHAR LIMIT=NONE] -->
<string name="log_access_confirmation_title">Allow <xliff:g id="log_access_app_name" example="Example App">%s</xliff:g> to access all device logs?</string>
<!-- Label for the allow button on the log access confirmation dialog. [CHAR LIMIT=40] -->
diff --git a/packages/SystemUI/src/com/android/systemui/ErrorReportActivity.kt b/packages/SystemUI/src/com/android/systemui/ErrorReportActivity.kt
new file mode 100644
index 000000000000..94630b044fbe
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ErrorReportActivity.kt
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2022 GrapheneOS
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui
+
+import android.app.Activity
+import android.app.ApplicationErrorReport
+import android.content.ClipData
+import android.content.ClipDescription
+import android.content.ClipboardManager
+import android.content.Intent
+import android.graphics.Typeface
+import android.os.Build
+import android.os.Bundle
+import android.util.StringBuilderPrinter
+import android.util.TypedValue
+import android.view.Gravity
+import android.view.View
+import android.widget.Button
+import android.widget.LinearLayout
+import android.widget.LinearLayout.LayoutParams
+import android.widget.ScrollView
+import android.widget.TextView
+import android.widget.Toast
+
+class ErrorReportActivity : Activity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ val title: String
+ val reportText: String
+ try {
+ val report = intent.getParcelableExtra<ApplicationErrorReport>(Intent.EXTRA_BUG_REPORT)!!
+ val pm = packageManager
+ val ai = pm.getApplicationInfo(report.packageName, 0)
+ title = getString(R.string.error_report_title, ai.loadLabel(pm))
+
+ reportText = errorReportToText(report)
+ } catch (e: Exception) {
+ e.printStackTrace()
+ finishAndRemoveTask()
+ return
+ }
+
+ setTitle(title)
+
+ val textView = TextView(this).apply {
+ typeface = Typeface.MONOSPACE
+ text = reportText
+ textSize = 12f
+ setTextIsSelectable(true)
+ // default color is too light
+ val color = if (resources.configuration.isNightModeActive) 0xff_d0_d0_d0 else 0xff_00_00_00
+ setTextColor(color.toInt())
+ }
+
+ val scroller = ScrollView(this).apply {
+ isScrollbarFadingEnabled = false
+ scrollBarStyle = View.SCROLLBARS_INSIDE_INSET
+ addView(textView)
+ }
+
+ val formattedReportText = "```\n" + reportText + "\n```"
+ val clipData = ClipData.newPlainText(title, formattedReportText)
+
+ val btnCopy = Button(this).apply {
+ setText(R.string.copy_to_clipboard)
+ setOnClickListener { _ ->
+ val cm = getSystemService(ClipboardManager::class.java)
+ cm.setPrimaryClip(clipData)
+ Toast.makeText(this@ErrorReportActivity, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show()
+ }
+ }
+
+ val btnShare = Button(this).apply {
+ setText(R.string.error_share)
+ setOnClickListener { _ ->
+ val i = Intent(Intent.ACTION_SEND)
+ i.clipData = clipData
+ i.type = ClipDescription.MIMETYPE_TEXT_PLAIN
+ i.putExtra(Intent.EXTRA_SUBJECT, title)
+ i.putExtra(Intent.EXTRA_TEXT, formattedReportText)
+ startActivity(Intent.createChooser(i, title))
+ }
+ }
+
+ val buttonLayout = LinearLayout(this).apply {
+ orientation = LinearLayout.HORIZONTAL
+ gravity = Gravity.CENTER
+ addView(btnCopy)
+ addView(btnShare)
+ }
+
+ val pad = px(16)
+
+ val layout = LinearLayout(this).apply {
+ orientation = LinearLayout.VERTICAL
+ addView(scroller, LayoutParams(LayoutParams.MATCH_PARENT, 0, 1f))
+ addView(buttonLayout)
+ setPadding(pad, pad, pad, pad)
+ }
+
+ setContentView(layout)
+ }
+
+ fun px(dp: Int) = TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_PX, dp.toFloat(), resources.displayMetrics).toInt()
+
+ fun errorReportToText(r: ApplicationErrorReport) =
+
+"""type: ${reportTypeToString(r.type)}
+osVersion: ${Build.FINGERPRINT}
+package: ${r.packageName}:${r.packageVersion}
+process: ${r.processName}
+
+${reportInfoToString(r)}"""
+
+ fun reportInfoToString(r: ApplicationErrorReport): String {
+ if (r.type == ApplicationErrorReport.TYPE_CRASH) {
+ return r.crashInfo.stackTrace
+ }
+
+ val sb = StringBuilder()
+ val printer = StringBuilderPrinter(sb)
+
+ when (r.type) {
+ ApplicationErrorReport.TYPE_ANR ->
+ r.anrInfo.dump(printer, "")
+ ApplicationErrorReport.TYPE_BATTERY ->
+ r.batteryInfo.dump(printer, "")
+ ApplicationErrorReport.TYPE_RUNNING_SERVICE ->
+ r.runningServiceInfo.dump(printer, "")
+ }
+
+ return sb.toString()
+ }
+
+ fun reportTypeToString(type: Int) = when (type) {
+ ApplicationErrorReport.TYPE_CRASH -> "crash"
+ ApplicationErrorReport.TYPE_ANR -> "ANR"
+ ApplicationErrorReport.TYPE_BATTERY -> "battery"
+ ApplicationErrorReport.TYPE_RUNNING_SERVICE -> "running_service"
+ else -> "unknown ($type)"
+ }
+}
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 061bcd740f6b..937b0eacff66 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -838,6 +838,7 @@ class AppErrors {
ApplicationErrorReport report = new ApplicationErrorReport();
report.packageName = r.info.packageName;
+ report.packageVersion = r.info.longVersionCode;
report.installerPackageName = errState.getErrorReportReceiver().getPackageName();
report.processName = r.processName;
report.time = timeMillis;