1 /* 2 * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. 3 */ 4 5 package kotlinx.coroutines.android 6 7 import android.os.* 8 import android.support.annotation.* 9 import kotlinx.coroutines.* 10 import java.lang.reflect.* 11 import kotlin.coroutines.* 12 13 @Keep 14 internal class AndroidExceptionPreHandler : 15 AbstractCoroutineContextElement(CoroutineExceptionHandler), CoroutineExceptionHandler, Function0<Method?> { 16 17 private val preHandler by lazy(this) 18 19 // Reflectively lookup pre-handler. Implement Function0 to avoid generating second class for lambda invokenull20 override fun invoke(): Method? = try { 21 Thread::class.java.getDeclaredMethod("getUncaughtExceptionPreHandler").takeIf { 22 Modifier.isPublic(it.modifiers) && Modifier.isStatic(it.modifiers) 23 } 24 } catch (e: Throwable) { 25 null /* not found */ 26 } 27 handleExceptionnull28 override fun handleException(context: CoroutineContext, exception: Throwable) { 29 /* 30 * If we are on old SDK, then use Android's `Thread.getUncaughtExceptionPreHandler()` that ensures that 31 * an exception is logged before crashing the application. 32 * 33 * Since Android Pie default uncaught exception handler always ensures that exception is logged without interfering with 34 * pre-handler, so reflection hack is no longer needed. 35 * 36 * See https://android-review.googlesource.com/c/platform/frameworks/base/+/654578/ 37 */ 38 val thread = Thread.currentThread() 39 if (Build.VERSION.SDK_INT >= 28) { 40 thread.uncaughtExceptionHandler.uncaughtException(thread, exception) 41 } else { 42 (preHandler?.invoke(null) as? Thread.UncaughtExceptionHandler) 43 ?.uncaughtException(thread, exception) 44 } 45 } 46 } 47