浏览代码

feat: Show error logs on crash when unprivileged

...however, don't do this in privileged mode because OpenEuiccService is
supposed to be background, and we don't want to just randomly show up
when things go wrong.
Peter Cai 1 年之前
父节点
当前提交
c0d1c29b7f

+ 2 - 10
app-common/src/main/java/im/angry/openeuicc/ui/LogsActivity.kt

@@ -8,6 +8,7 @@ import androidx.appcompat.app.AppCompatActivity
 import androidx.lifecycle.lifecycleScope
 import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
 import im.angry.openeuicc.common.R
+import im.angry.openeuicc.util.*
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
@@ -44,16 +45,7 @@ class LogsActivity : AppCompatActivity() {
     private suspend fun reload() = withContext(Dispatchers.Main) {
         swipeRefresh.isRefreshing = true
 
-        val logStr = withContext(Dispatchers.IO) {
-            try {
-                Runtime.getRuntime().exec("logcat -t 1024").inputStream.readBytes()
-                    .decodeToString()
-            } catch (_: Exception) {
-                ""
-            }
-        }
-
-        logText.text = logStr
+        logText.text = intent.extras?.getString("log") ?: readSelfLog()
 
         swipeRefresh.isRefreshing = false
 

+ 11 - 0
app-common/src/main/java/im/angry/openeuicc/util/Utils.kt

@@ -8,9 +8,11 @@ import androidx.fragment.app.Fragment
 import im.angry.openeuicc.OpenEuiccApplication
 import im.angry.openeuicc.core.EuiccChannel
 import im.angry.openeuicc.core.EuiccChannelManager
+import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.sync.Mutex
 import kotlinx.coroutines.sync.withLock
+import kotlinx.coroutines.withContext
 import net.typeblog.lpac_jni.LocalProfileInfo
 import java.lang.RuntimeException
 import kotlin.coroutines.resume
@@ -26,6 +28,15 @@ val Context.selfAppVersion: String
             throw RuntimeException(e)
         }
 
+suspend fun readSelfLog(lines: Int = 2048): String = withContext(Dispatchers.IO) {
+    try {
+        Runtime.getRuntime().exec("logcat -t $lines").inputStream.readBytes()
+            .decodeToString()
+    } catch (_: Exception) {
+        ""
+    }
+}
+
 interface OpenEuiccContextMarker {
     val openEuiccMarkerContext: Context
         get() = when (this) {

+ 1 - 1
app-unpriv/src/main/AndroidManifest.xml

@@ -2,7 +2,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android">
 
     <application
-        android:name="im.angry.openeuicc.OpenEuiccApplication"
+        android:name="im.angry.openeuicc.UnprivilegedOpenEuiccApplication"
         android:allowBackup="true"
         android:icon="@mipmap/ic_launcher"
         android:label="@string/app_name"

+ 23 - 0
app-unpriv/src/main/java/im/angry/openeuicc/UnprivilegedOpenEuiccApplication.kt

@@ -0,0 +1,23 @@
+package im.angry.openeuicc
+
+import android.content.Intent
+import im.angry.openeuicc.ui.LogsActivity
+import im.angry.openeuicc.util.*
+import kotlinx.coroutines.runBlocking
+import kotlin.system.exitProcess
+
+class UnprivilegedOpenEuiccApplication : OpenEuiccApplication() {
+    override fun onCreate() {
+        super.onCreate()
+
+        Thread.setDefaultUncaughtExceptionHandler { _, _ ->
+            Intent(this, LogsActivity::class.java).apply {
+                addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+                addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+                putExtra("log", runBlocking { readSelfLog() })
+                startActivity(this)
+                exitProcess(-1)
+            }
+        }
+    }
+}