mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-12-24 06:59:27 -05:00
b78f573eb9
Signed-off-by: Tad <tad@spotco.us>
352 lines
14 KiB
Diff
352 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 | 13 ++
|
|
packages/SystemUI/res/values/strings.xml | 5 +
|
|
.../android/systemui/ErrorReportActivity.kt | 159 ++++++++++++++++++
|
|
.../java/com/android/server/am/AppErrors.java | 1 +
|
|
9 files changed, 200 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 a0b3dc0452ac..d6b9a837c46b 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();
|
|
@@ -686,7 +696,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 2ea89de7d5cb..94e33f151798 100644
|
|
--- a/core/res/res/values/strings.xml
|
|
+++ b/core/res/res/values/strings.xml
|
|
@@ -6360,4 +6360,7 @@ 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>
|
|
</resources>
|
|
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
|
|
index 888cd7a79bf6..c9733c9fa4f7 100644
|
|
--- a/core/res/res/values/symbols.xml
|
|
+++ b/core/res/res/values/symbols.xml
|
|
@@ -4852,6 +4852,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="bool" name="system_server_plays_face_haptics" />
|
|
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
|
|
index 2cc47823a109..b1ee372bd61a 100644
|
|
--- a/packages/SystemUI/AndroidManifest.xml
|
|
+++ b/packages/SystemUI/AndroidManifest.xml
|
|
@@ -969,5 +969,18 @@
|
|
<action android:name="com.android.systemui.action.DISMISS_VOLUME_PANEL_DIALOG" />
|
|
</intent-filter>
|
|
</receiver>
|
|
+
|
|
+ <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>
|
|
+
|
|
</application>
|
|
</manifest>
|
|
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
|
|
index 53f1227383b7..6abeae8f9c35 100644
|
|
--- a/packages/SystemUI/res/values/strings.xml
|
|
+++ b/packages/SystemUI/res/values/strings.xml
|
|
@@ -2607,4 +2607,9 @@
|
|
|
|
<!-- 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>
|
|
</resources>
|
|
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 08c1de61d7fb..026562a98739 100644
|
|
--- a/services/core/java/com/android/server/am/AppErrors.java
|
|
+++ b/services/core/java/com/android/server/am/AppErrors.java
|
|
@@ -827,6 +827,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;
|