• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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