Skip to content

Commit c8963f3

Browse files
committed
If debug mode is on, actually parcel the remote stacktrace so we get a full stacktrace across the process boundary.
Not super clean but just used in debug mode and I found no other way :8
1 parent 7890d9d commit c8963f3

File tree

3 files changed

+70
-9
lines changed

3 files changed

+70
-9
lines changed

app-common-io/src/main/java/eu/darken/sdmse/common/pkgs/PackageManagerExtensions.kt

-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ fun PackageManager.getInstalledPackagesAsUser(
5353
userHandle: UserHandle2,
5454
) = try {
5555
val functions = PackageManager::class.memberFunctions.filter { it.name == "getInstalledPackagesAsUser" }
56-
throw RuntimeException("lol")
5756
if (hasApiLevel(33)) {
5857
@Suppress("NewApi")
5958
functions

app-common/src/main/java/eu/darken/sdmse/common/ipc/IpcClientModule.kt

+36-5
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,52 @@
11
package eu.darken.sdmse.common.ipc
22

3+
import eu.darken.sdmse.common.debug.Bugs
4+
import eu.darken.sdmse.common.debug.logging.Logging.Priority.VERBOSE
35
import eu.darken.sdmse.common.debug.logging.Logging.Priority.WARN
46
import eu.darken.sdmse.common.debug.logging.log
7+
import java.io.ByteArrayInputStream
8+
import java.io.ObjectInputStream
9+
import kotlin.io.encoding.Base64
10+
import kotlin.io.encoding.ExperimentalEncodingApi
511

612
interface IpcClientModule {
713

14+
@OptIn(ExperimentalEncodingApi::class)
15+
fun String.decodeStacktrace(): Array<StackTraceElement>? = try {
16+
val decodedBytes = Base64.decode(this)
17+
ObjectInputStream(ByteArrayInputStream(decodedBytes)).use {
18+
it.readObject() as Array<StackTraceElement>
19+
}
20+
} catch (e: Exception) {
21+
null
22+
}
23+
824
fun Throwable.unwrapPropagation(): Throwable {
9-
val matchResult = Regex("^[a-zA-Z0-9.]+Exception").find((message ?: ""))
10-
val exceptionName = matchResult?.value ?: return this
11-
val exceptionMessage = message!!.removePrefix("$exceptionName: ").trim()
25+
val matchResult = Regex("^([a-zA-Z0-9.]+Exception): ").find((message ?: ""))
26+
val exceptionName = matchResult?.groupValues?.get(1) ?: return this
27+
val messageParts = message!!
28+
.removePrefix(matchResult.groupValues.first())
29+
.trim()
30+
.split(IpcHostModule.STACK_MARKER)
1231

1332
return try {
1433
Class.forName(exceptionName)
1534
.asSubclass(Throwable::class.java)
1635
.getConstructor(String::class.java)
17-
.newInstance(exceptionMessage)
18-
.also { it.stackTrace = this.stackTrace }
36+
.newInstance(messageParts.first())
37+
.also { newException ->
38+
// TODO: Couldn't find a way to keep the trace through parceling
39+
// it.stackTrace = this.stackTrace
40+
if (Bugs.isDebug && messageParts.size > 1) {
41+
log(VERBOSE) { "Decoding stacktrace..." }
42+
messageParts[1].decodeStacktrace()?.let { remoteTrace ->
43+
// Stacktrace on this side of the binder + the stacktrace on the other side of it
44+
newException.stackTrace = (remoteTrace + stackTrace).filter {
45+
!it.className.startsWith("android.os.Binder") && !it.className.startsWith("android.os.Parcel")
46+
}.toTypedArray()
47+
}
48+
}
49+
}
1950
} catch (e: Exception) {
2051
log(WARN) { "Failed to unwrap exception: $this" }
2152
this
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,27 @@
11
package eu.darken.sdmse.common.ipc
22

3+
import eu.darken.sdmse.common.debug.Bugs
4+
import eu.darken.sdmse.common.debug.logging.Logging.Priority.VERBOSE
5+
import eu.darken.sdmse.common.debug.logging.log
6+
import java.io.ByteArrayOutputStream
7+
import java.io.ObjectOutputStream
8+
import kotlin.io.encoding.Base64
9+
import kotlin.io.encoding.ExperimentalEncodingApi
10+
311
interface IpcHostModule {
412

13+
@OptIn(ExperimentalEncodingApi::class)
14+
fun Array<StackTraceElement>.encodeBase64(): String? = try {
15+
val baos = ByteArrayOutputStream()
16+
ObjectOutputStream(baos).use {
17+
it.writeObject(this)
18+
}
19+
Base64.encode(baos.toByteArray())
20+
} catch (e: Exception) {
21+
null
22+
}
23+
24+
525
// Not all exception can be passed through the binder
626
// See Parcel.writeException(...)
727
fun Throwable.wrapToPropagate(): Exception {
@@ -11,9 +31,20 @@ interface IpcHostModule {
1131
msgBuilder.append("\nCaused by: ")
1232
msgBuilder.append(it.toString())
1333
}
14-
return UnsupportedOperationException(msgBuilder.toString()).also {
15-
it.stackTrace = this.stackTrace
16-
// The stacktrace is still lost and not encoded for some reason...
34+
35+
if (Bugs.isDebug) {
36+
log(VERBOSE) { "Encoding stacktrace..." }
37+
// TODO Find better way to pass trace, see IpcClientModule
38+
val encodedTrace = stackTrace.encodeBase64()
39+
if (encodedTrace != null) {
40+
msgBuilder.append(STACK_MARKER).append(encodedTrace)
41+
}
1742
}
43+
44+
return UnsupportedOperationException(msgBuilder.toString())
45+
}
46+
47+
companion object {
48+
const val STACK_MARKER = "\n\n#STACK#:"
1849
}
1950
}

0 commit comments

Comments
 (0)