/****************************************************************************** * Copyright (C) 2012, 2013, 2014, 2015, 2016 * Younghyung Cho. <yhcting77@gmail.com> * All rights reserved. * * This file is part of NetMBuddy * * This program is licensed under the FreeBSD license * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the FreeBSD Project. *****************************************************************************/ // // Not used yet // For future use. // package free.yhc.netmbuddy.core; import java.io.PrintWriter; import java.io.StringWriter; import java.lang.Thread.UncaughtExceptionHandler; import java.util.LinkedList; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import free.yhc.abaselib.AppEnv; import free.yhc.baselib.Logger; import free.yhc.netmbuddy.utils.ReportUtil; public class UnexpectedExceptionHandler implements UncaughtExceptionHandler { private static final boolean DBG = Logger.DBG_DEFAULT; private static final Logger P = Logger.create(UnexpectedExceptionHandler.class, Logger.LOGLV_DEFAULT); private static final String UNKNOWN = "unknown"; private static UnexpectedExceptionHandler sInstance = null; // This module to capturing unexpected exception. // So this SHOULD have minimum set of code in constructor, // because this module SHOULD be instantiate as early as possible // before any other module is instantiated // // Dependency on only following modules are allowed // - Util private final Thread.UncaughtExceptionHandler mOldHandler = Thread.getDefaultUncaughtExceptionHandler(); private final LinkedList<Evidence> mMods = new LinkedList<>(); private final PackageReport mPr = new PackageReport(); private final BuildReport mBr = new BuildReport(); public enum DumpLevel { FULL } public interface Evidence { String dump(DumpLevel lvl); } private class PackageReport { String packageName = UNKNOWN; String versionName = UNKNOWN; String filesDir = UNKNOWN; } // Useful Informations private class BuildReport { String androidVersion = UNKNOWN; String board = UNKNOWN; String brand = UNKNOWN; String device = UNKNOWN; String display = UNKNOWN; String fingerPrint = UNKNOWN; String host = UNKNOWN; String id = UNKNOWN; String manufacturer = UNKNOWN; String model = UNKNOWN; String product = UNKNOWN; String tags = UNKNOWN; long time = 0; String type = UNKNOWN; String user = UNKNOWN; } // ======================== // Privates // ======================== private void setEnvironmentInfo(Context context) { PackageManager pm = context.getPackageManager(); try { PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0); mPr.versionName = pi.versionName; mPr.packageName = pi.packageName; } catch (NameNotFoundException ignore) { } mPr.filesDir = context.getFilesDir().getAbsolutePath(); mBr.model = android.os.Build.MODEL; mBr.androidVersion = android.os.Build.VERSION.RELEASE; mBr.board = android.os.Build.BOARD; mBr.brand = android.os.Build.BRAND; mBr.device = android.os.Build.DEVICE; mBr.display = android.os.Build.DISPLAY; mBr.fingerPrint = android.os.Build.FINGERPRINT; mBr.host = android.os.Build.HOST; mBr.id = android.os.Build.ID; mBr.product = android.os.Build.PRODUCT; mBr.tags = android.os.Build.TAGS; mBr.time = android.os.Build.TIME; mBr.type = android.os.Build.TYPE; mBr.user = android.os.Build.USER; } private void appendCommonReport(StringBuilder report) { //noinspection StringConcatenationInsideStringBufferAppend report.append("==================== Package Information ==================\n") .append(" - name : " + mPr.packageName + "\n") .append(" - version : " + mPr.versionName + "\n") .append(" - filesDir : " + mPr.filesDir + "\n") .append("\n") .append("===================== Device Information ==================\n") .append(" - androidVer : " + mBr.androidVersion + "\n") .append(" - board : " + mBr.board + "\n") .append(" - brand : " + mBr.brand + "\n") .append(" - device : " + mBr.device + "\n") .append(" - display : " + mBr.display + "\n") .append(" - fingerprint : " + mBr.fingerPrint + "\n") .append(" - host : " + mBr.host + "\n") .append(" - id : " + mBr.id + "\n") .append(" - manufactuere: " + mBr.manufacturer + "\n") .append(" - model : " + mBr.model + "\n") .append(" - product : " + mBr.product + "\n") .append(" - tags : " + mBr.tags + "\n") .append(" - time : " + mBr.time + "\n") .append(" - type : " + mBr.type + "\n") .append(" - user : " + mBr.user + "\n") .append("\n\n"); } private UnexpectedExceptionHandler() { setEnvironmentInfo(AppEnv.getAppContext()); } // ======================== // Publics // ======================== // Get singleton instance,. public static UnexpectedExceptionHandler get() { if (null == sInstance) sInstance = new UnexpectedExceptionHandler(); return sInstance; } /** * register module that will be dumped when unexpected exception is issued. * @param m module providing evidences */ public boolean registerModule(Evidence m) { if (null == m) return false; synchronized (mMods) { if (mMods.contains(m)) return false; mMods.addLast(m); return true; } } public boolean unregisterModule(Evidence m) { synchronized (mMods) { return mMods.remove(m); } } @Override public void uncaughtException(Thread thread, Throwable ex) { StringBuilder report = new StringBuilder(); appendCommonReport(report); // collect dump informations for (Evidence tm : mMods) report.append(tm.dump(DumpLevel.FULL)).append("\n\n"); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); ex.printStackTrace(pw); report.append(sw.toString()); pw.close(); ReportUtil.storeErrReport(report.toString()); mOldHandler.uncaughtException(thread, ex); } }