Skip to content

Commit

Permalink
Move Termux app specific logic out of CrashHandler
Browse files Browse the repository at this point in the history
Create the TermuxCrashUtils class that provides the default path and app for termux instead of hardcoding it in CrashHandler. TermuxCrashUtils can be used by termux plugins as well for their own usage or they can implement the CrashHandler.CrashHandlerClient if they want to log to different files or want custom logic.
  • Loading branch information
agnostic-apollo committed Jun 30, 2021
1 parent 93a7525 commit 23a900c
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 16 deletions.
4 changes: 2 additions & 2 deletions app/src/main/java/com/termux/app/TermuxApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import android.app.Application;

import com.termux.shared.crash.CrashHandler;
import com.termux.shared.crash.TermuxCrashUtils;
import com.termux.shared.settings.preferences.TermuxAppSharedPreferences;
import com.termux.shared.logger.Logger;

Expand All @@ -12,7 +12,7 @@ public void onCreate() {
super.onCreate();

// Set crash handler for the app
CrashHandler.setCrashHandler(this);
TermuxCrashUtils.setCrashHandler(this);

// Set log level for the app
setLogLevel();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
import com.termux.shared.markdown.MarkdownUtils;
import com.termux.shared.models.errors.Error;
import com.termux.shared.termux.AndroidUtils;
import com.termux.shared.termux.TermuxConstants;
import com.termux.shared.termux.TermuxUtils;

import java.nio.charset.Charset;

Expand All @@ -19,58 +17,85 @@
*/
public class CrashHandler implements Thread.UncaughtExceptionHandler {

private final Context context;
private final Context mContext;
private final CrashHandlerClient mCrashHandlerClient;
private final Thread.UncaughtExceptionHandler defaultUEH;

private static final String LOG_TAG = "CrashUtils";

private CrashHandler(final Context context) {
this.context = context;
private CrashHandler(@NonNull final Context context, @NonNull final CrashHandlerClient crashHandlerClient) {
this.mContext = context;
this.mCrashHandlerClient = crashHandlerClient;
this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
}

public void uncaughtException(@NonNull Thread thread, @NonNull Throwable throwable) {
logCrash(context,thread, throwable);
logCrash(mContext, mCrashHandlerClient, thread, throwable);
defaultUEH.uncaughtException(thread, throwable);
}

/**
* Set default uncaught crash handler of current thread to {@link CrashHandler}.
*/
public static void setCrashHandler(final Context context) {
public static void setCrashHandler(@NonNull final Context context, @NonNull final CrashHandlerClient crashHandlerClient) {
if (!(Thread.getDefaultUncaughtExceptionHandler() instanceof CrashHandler)) {
Thread.setDefaultUncaughtExceptionHandler(new CrashHandler(context));
Thread.setDefaultUncaughtExceptionHandler(new CrashHandler(context, crashHandlerClient));
}
}

/**
* Log a crash in the crash log file at
* {@link TermuxConstants#TERMUX_CRASH_LOG_FILE_PATH}.
* Log a crash in the crash log file at {@code crashlogFilePath}.
*
* @param context The {@link Context} for operations.
* @param crashHandlerClient The {@link CrashHandlerClient} implementation.
* @param thread The {@link Thread} in which the crash happened.
* @param throwable The {@link Throwable} thrown for the crash.
*/
public static void logCrash(final Context context, final Thread thread, final Throwable throwable) {

public static void logCrash(@NonNull final Context context, @NonNull final CrashHandlerClient crashHandlerClient, final Thread thread, final Throwable throwable) {
StringBuilder reportString = new StringBuilder();

reportString.append("## Crash Details\n");
reportString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Crash Thread", thread.toString(), "-"));
reportString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Crash Timestamp", AndroidUtils.getCurrentTimeStamp(), "-"));

reportString.append("\n\n").append(Logger.getStackTracesMarkdownString("Stacktrace", Logger.getStackTracesStringArray(throwable)));
reportString.append("\n\n").append(TermuxUtils.getAppInfoMarkdownString(context, true));

String appInfoMarkdownString = crashHandlerClient.getAppInfoMarkdownString(context);
if (appInfoMarkdownString != null && !appInfoMarkdownString.isEmpty())
reportString.append("\n\n").append(appInfoMarkdownString);

reportString.append("\n\n").append(AndroidUtils.getDeviceInfoMarkdownString(context));

// Log report string to logcat
Logger.logError(reportString.toString());

// Write report string to crash log file
Error error = FileUtils.writeStringToFile("crash log", TermuxConstants.TERMUX_CRASH_LOG_FILE_PATH, Charset.defaultCharset(), reportString.toString(), false);
Error error = FileUtils.writeStringToFile("crash log", crashHandlerClient.getCrashLogFilePath(context),
Charset.defaultCharset(), reportString.toString(), false);
if (error != null) {
Logger.logErrorExtended(LOG_TAG, error.toString());
}
}

public interface CrashHandlerClient {

/**
* Get crash log file path.
*
* @param context The {@link Context} passed to {@link CrashHandler#CrashHandler(Context, CrashHandlerClient)}.
* @return Should return the crash log file path.
*/
@NonNull
String getCrashLogFilePath(Context context);

/**
* Get app info markdown string to add to crash log.
*
* @param context The {@link Context} passed to {@link CrashHandler#CrashHandler(Context, CrashHandlerClient)}.
* @return Should return app info markdown string.
*/
String getAppInfoMarkdownString(Context context);

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.termux.shared.crash;

import android.content.Context;

import androidx.annotation.NonNull;

import com.termux.shared.termux.TermuxConstants;
import com.termux.shared.termux.TermuxUtils;

public class TermuxCrashUtils implements CrashHandler.CrashHandlerClient {

/**
* Set default uncaught crash handler of current thread to {@link CrashHandler} for Termux app
* and its plugin to log crashes at {@link TermuxConstants#TERMUX_CRASH_LOG_FILE_PATH}.
*/
public static void setCrashHandler(@NonNull final Context context) {
CrashHandler.setCrashHandler(context, new TermuxCrashUtils());
}

@NonNull
@Override
public String getCrashLogFilePath(Context context) {
return TermuxConstants.TERMUX_CRASH_LOG_FILE_PATH;
}

@Override
public String getAppInfoMarkdownString(Context context) {
return TermuxUtils.getAppInfoMarkdownString(context, true);
}

}

0 comments on commit 23a900c

Please sign in to comment.