1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.base;
6 
7 import android.support.annotation.UiThread;
8 
9 import org.chromium.base.annotations.CalledByNative;
10 import org.chromium.base.annotations.JNINamespace;
11 import org.chromium.base.annotations.MainDex;
12 
13 /**
14  * This UncaughtExceptionHandler will create a breakpad minidump when there is an uncaught
15  * exception.
16  *
17  * The exception's stack trace will be added to the minidump's data. This allows java-only crashes
18  * to be reported in the same way as other native crashes.
19  */
20 @JNINamespace("base::android")
21 @MainDex
22 public class JavaExceptionReporter implements Thread.UncaughtExceptionHandler {
23     private final Thread.UncaughtExceptionHandler mParent;
24     private final boolean mCrashAfterReport;
25     private boolean mHandlingException;
26 
JavaExceptionReporter( Thread.UncaughtExceptionHandler parent, boolean crashAfterReport)27     private JavaExceptionReporter(
28             Thread.UncaughtExceptionHandler parent, boolean crashAfterReport) {
29         mParent = parent;
30         mCrashAfterReport = crashAfterReport;
31     }
32 
33     @Override
uncaughtException(Thread t, Throwable e)34     public void uncaughtException(Thread t, Throwable e) {
35         if (!mHandlingException) {
36             mHandlingException = true;
37             nativeReportJavaException(mCrashAfterReport, e);
38         }
39         if (mParent != null) {
40             mParent.uncaughtException(t, e);
41         }
42     }
43 
44     /**
45      * Report and upload the stack trace as if it was a crash. This is very expensive and should
46      * be called rarely and only on the UI thread to avoid corrupting other crash uploads. Ideally
47      * only called in idle handlers.
48      *
49      * @param stackTrace The stack trace to report.
50      */
51     @UiThread
reportStackTrace(String stackTrace)52     public static void reportStackTrace(String stackTrace) {
53         assert ThreadUtils.runningOnUiThread();
54         nativeReportJavaStackTrace(stackTrace);
55     }
56 
57     @CalledByNative
installHandler(boolean crashAfterReport)58     private static void installHandler(boolean crashAfterReport) {
59         Thread.setDefaultUncaughtExceptionHandler(new JavaExceptionReporter(
60                 Thread.getDefaultUncaughtExceptionHandler(), crashAfterReport));
61     }
62 
nativeReportJavaException(boolean crashAfterReport, Throwable e)63     private static native void nativeReportJavaException(boolean crashAfterReport, Throwable e);
nativeReportJavaStackTrace(String stackTrace)64     private static native void nativeReportJavaStackTrace(String stackTrace);
65 }
66