Skip to content

Commit 34bc72b

Browse files
committed
Do not use reflective exception pre-handler on newer Androids, since Pie runtime ensures that uncaught exception is always logged
Fixes #822
1 parent 34eaa5c commit 34bc72b

File tree

1 file changed

+26
-14
lines changed

1 file changed

+26
-14
lines changed

ui/kotlinx-coroutines-android/src/AndroidExceptionPreHandler.kt

+26-14
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,42 @@
44

55
package kotlinx.coroutines.android
66

7+
import android.os.*
78
import android.support.annotation.*
89
import kotlinx.coroutines.*
910
import java.lang.reflect.*
1011
import kotlin.coroutines.*
1112

12-
private val getter =
13-
try {
14-
Thread::class.java.getDeclaredMethod("getUncaughtExceptionPreHandler").takeIf {
15-
Modifier.isPublic(it.modifiers) && Modifier.isStatic(it.modifiers)
16-
}
17-
}
18-
catch (e: Throwable) { null /* not found */ }
13+
private val getter by lazy {
14+
try {
15+
Thread::class.java.getDeclaredMethod("getUncaughtExceptionPreHandler").takeIf {
16+
Modifier.isPublic(it.modifiers) && Modifier.isStatic(it.modifiers)
17+
}
18+
} catch (e: Throwable) {
19+
null /* not found */
20+
}
21+
}
1922

20-
/**
21-
* Uses Android's `Thread.getUncaughtExceptionPreHandler()` whose default behavior is to log exception.
22-
* See
23-
* [here](https://github.com/aosp-mirror/platform_frameworks_base/blob/2efbc7239f419c931784acf98960ed6abc38c3f2/core/java/com/android/internal/os/RuntimeInit.java#L142)
24-
*/
2523
@Keep
2624
internal class AndroidExceptionPreHandler :
2725
AbstractCoroutineContextElement(CoroutineExceptionHandler), CoroutineExceptionHandler
2826
{
2927
override fun handleException(context: CoroutineContext, exception: Throwable) {
30-
(getter?.invoke(null) as? Thread.UncaughtExceptionHandler)
31-
?.uncaughtException(Thread.currentThread(), exception)
28+
/*
29+
* Is we are on old SDK, then use Android's `Thread.getUncaughtExceptionPreHandler()` that ensures that
30+
* exception is logged before crashing the application.
31+
*
32+
* Since Android Pie default uncaught exception handler always ensures that exception is logged without interfering with
33+
* pre-handler, so reflection hack is no longer needed.
34+
*
35+
* See https://android-review.googlesource.com/c/platform/frameworks/base/+/654578/
36+
*/
37+
val thread = Thread.currentThread()
38+
if (Build.VERSION.SDK_INT >= 28) {
39+
thread.uncaughtExceptionHandler.uncaughtException(thread, exception)
40+
} else {
41+
(getter?.invoke(null) as? Thread.UncaughtExceptionHandler)
42+
?.uncaughtException(thread, exception)
43+
}
3244
}
3345
}

0 commit comments

Comments
 (0)