Browse Source

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 year ago
parent
commit
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)
+            }
+        }
+    }
+}