瀏覽代碼

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 2 年之前
父節點
當前提交
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.lifecycle.lifecycleScope
 import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
 import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
 import im.angry.openeuicc.common.R
 import im.angry.openeuicc.common.R
+import im.angry.openeuicc.util.*
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
 import kotlinx.coroutines.withContext
@@ -44,16 +45,7 @@ class LogsActivity : AppCompatActivity() {
     private suspend fun reload() = withContext(Dispatchers.Main) {
     private suspend fun reload() = withContext(Dispatchers.Main) {
         swipeRefresh.isRefreshing = true
         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
         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.OpenEuiccApplication
 import im.angry.openeuicc.core.EuiccChannel
 import im.angry.openeuicc.core.EuiccChannel
 import im.angry.openeuicc.core.EuiccChannelManager
 import im.angry.openeuicc.core.EuiccChannelManager
+import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.sync.Mutex
 import kotlinx.coroutines.sync.Mutex
 import kotlinx.coroutines.sync.withLock
 import kotlinx.coroutines.sync.withLock
+import kotlinx.coroutines.withContext
 import net.typeblog.lpac_jni.LocalProfileInfo
 import net.typeblog.lpac_jni.LocalProfileInfo
 import java.lang.RuntimeException
 import java.lang.RuntimeException
 import kotlin.coroutines.resume
 import kotlin.coroutines.resume
@@ -26,6 +28,15 @@ val Context.selfAppVersion: String
             throw RuntimeException(e)
             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 {
 interface OpenEuiccContextMarker {
     val openEuiccMarkerContext: Context
     val openEuiccMarkerContext: Context
         get() = when (this) {
         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">
 <manifest xmlns:android="http://schemas.android.com/apk/res/android">
 
 
     <application
     <application
-        android:name="im.angry.openeuicc.OpenEuiccApplication"
+        android:name="im.angry.openeuicc.UnprivilegedOpenEuiccApplication"
         android:allowBackup="true"
         android:allowBackup="true"
         android:icon="@mipmap/ic_launcher"
         android:icon="@mipmap/ic_launcher"
         android:label="@string/app_name"
         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)
+            }
+        }
+    }
+}