From 17a71441943c6e53ba29bfac23b023d8477d615e Mon Sep 17 00:00:00 2001 From: akwizgran <michael@briarproject.org> Date: Tue, 15 May 2018 18:04:34 +0100 Subject: [PATCH] Add internal logger. --- .../briar/android/BriarApplication.java | 5 ++ .../briar/android/BriarApplicationImpl.java | 26 +++++++++- .../briar/android/TestingConstants.java | 11 ----- .../android/logging/BriefLogFormatter.java | 47 ++++++++++++++++++ .../android/logging/CachingLogHandler.java | 48 +++++++++++++++++++ .../android/reporting/BriarReportPrimer.java | 17 ++++++- .../briar/android/TestBriarApplication.java | 9 ++++ 7 files changed, 149 insertions(+), 14 deletions(-) create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/logging/BriefLogFormatter.java create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/logging/CachingLogHandler.java diff --git a/briar-android/src/main/java/org/briarproject/briar/android/BriarApplication.java b/briar-android/src/main/java/org/briarproject/briar/android/BriarApplication.java index bf78cecfa1..e537bd86d6 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/BriarApplication.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/BriarApplication.java @@ -1,10 +1,15 @@ package org.briarproject.briar.android; +import java.util.Collection; +import java.util.logging.LogRecord; + /** * This exists so that the Application object will not necessarily be cast * directly to the Briar application object. */ public interface BriarApplication { + Collection<LogRecord> getRecentLogRecords(); + AndroidComponent getApplicationComponent(); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/BriarApplicationImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/BriarApplicationImpl.java index 19ea60a892..d83a91bb4e 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/BriarApplicationImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/BriarApplicationImpl.java @@ -12,12 +12,17 @@ import org.acra.annotation.ReportsCrashes; import org.briarproject.bramble.BrambleCoreModule; import org.briarproject.briar.BriarCoreModule; import org.briarproject.briar.R; +import org.briarproject.briar.android.logging.CachingLogHandler; import org.briarproject.briar.android.reporting.BriarReportPrimer; import org.briarproject.briar.android.reporting.BriarReportSenderFactory; import org.briarproject.briar.android.reporting.DevReportActivity; +import java.util.Collection; +import java.util.logging.Handler; +import java.util.logging.LogRecord; import java.util.logging.Logger; +import static java.util.logging.Level.INFO; import static org.acra.ReportField.ANDROID_VERSION; import static org.acra.ReportField.APP_VERSION_CODE; import static org.acra.ReportField.APP_VERSION_NAME; @@ -36,7 +41,7 @@ import static org.acra.ReportField.REPORT_ID; import static org.acra.ReportField.STACK_TRACE; import static org.acra.ReportField.USER_APP_START_DATE; import static org.acra.ReportField.USER_CRASH_DATE; -import static org.briarproject.briar.android.TestingConstants.DEFAULT_LOG_LEVEL; +import static org.briarproject.briar.android.TestingConstants.IS_BETA_BUILD; import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD; @ReportsCrashes( @@ -66,6 +71,8 @@ public class BriarApplicationImpl extends Application private static final Logger LOG = Logger.getLogger(BriarApplicationImpl.class.getName()); + private final CachingLogHandler logHandler = new CachingLogHandler(); + private AndroidComponent applicationComponent; @Override @@ -79,7 +86,17 @@ public class BriarApplicationImpl extends Application super.onCreate(); if (IS_DEBUG_BUILD) enableStrictMode(); - Logger.getLogger("").setLevel(DEFAULT_LOG_LEVEL); + + Logger rootLogger = Logger.getLogger(""); + if (!IS_DEBUG_BUILD && !IS_BETA_BUILD) { + // Remove default log handlers so system log is not used + for (Handler handler : rootLogger.getHandlers()) { + rootLogger.removeHandler(handler); + } + } + rootLogger.addHandler(logHandler); + rootLogger.setLevel(INFO); + LOG.info("Created"); applicationComponent = DaggerAndroidComponent.builder() @@ -104,6 +121,11 @@ public class BriarApplicationImpl extends Application StrictMode.setVmPolicy(vmPolicy.build()); } + @Override + public Collection<LogRecord> getRecentLogRecords() { + return logHandler.getRecentLogRecords(); + } + @Override public AndroidComponent getApplicationComponent() { return applicationComponent; diff --git a/briar-android/src/main/java/org/briarproject/briar/android/TestingConstants.java b/briar-android/src/main/java/org/briarproject/briar/android/TestingConstants.java index 96f1b5cf25..e3b970dc9c 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/TestingConstants.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/TestingConstants.java @@ -2,11 +2,6 @@ package org.briarproject.briar.android; import org.briarproject.briar.BuildConfig; -import java.util.logging.Level; - -import static java.util.logging.Level.INFO; -import static java.util.logging.Level.OFF; - public interface TestingConstants { /** @@ -20,12 +15,6 @@ public interface TestingConstants { */ boolean IS_BETA_BUILD = false; - /** - * Default log level. Disable logging for final release builds. - */ - @SuppressWarnings("ConstantConditions") - Level DEFAULT_LOG_LEVEL = IS_DEBUG_BUILD || IS_BETA_BUILD ? INFO : OFF; - /** * Whether to prevent screenshots from being taken. Setting this to true * prevents Recent Apps from storing screenshots of private information. diff --git a/briar-android/src/main/java/org/briarproject/briar/android/logging/BriefLogFormatter.java b/briar-android/src/main/java/org/briarproject/briar/android/logging/BriefLogFormatter.java new file mode 100644 index 0000000000..681162aece --- /dev/null +++ b/briar-android/src/main/java/org/briarproject/briar/android/logging/BriefLogFormatter.java @@ -0,0 +1,47 @@ +package org.briarproject.briar.android.logging; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; +import java.util.logging.Formatter; +import java.util.logging.LogRecord; + +import javax.annotation.concurrent.ThreadSafe; + +import static java.util.Locale.US; + +@ThreadSafe +@NotNullByDefault +public class BriefLogFormatter extends Formatter { + + private final Object lock = new Object(); + private final DateFormat dateFormat; // Locking: lock + private final Date date; // Locking: lock + + public BriefLogFormatter() { + synchronized (lock) { + dateFormat = new SimpleDateFormat("MM-dd HH:mm:ss.SSS ", US); + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + date = new Date(); + } + } + + @Override + public String format(LogRecord record) { + String dateString; + synchronized (lock) { + date.setTime(record.getMillis()); + dateString = dateFormat.format(date); + } + StringBuilder sb = new StringBuilder(dateString); + sb.append(record.getLevel().getName().charAt(0)).append('/'); + String tag = record.getLoggerName(); + tag = tag.substring(tag.lastIndexOf('.') + 1); + sb.append(tag).append(": "); + sb.append(record.getMessage()); + return sb.toString(); + } +} diff --git a/briar-android/src/main/java/org/briarproject/briar/android/logging/CachingLogHandler.java b/briar-android/src/main/java/org/briarproject/briar/android/logging/CachingLogHandler.java new file mode 100644 index 0000000000..baa51e3f6c --- /dev/null +++ b/briar-android/src/main/java/org/briarproject/briar/android/logging/CachingLogHandler.java @@ -0,0 +1,48 @@ +package org.briarproject.briar.android.logging; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedList; +import java.util.Queue; +import java.util.logging.Handler; +import java.util.logging.LogRecord; + +import javax.annotation.concurrent.ThreadSafe; + +@ThreadSafe +@NotNullByDefault +public class CachingLogHandler extends Handler { + + private static final int MAX_RECENT_RECORDS = 100; + + private final Object lock = new Object(); + // Locking: lock + private final Queue<LogRecord> recent = new LinkedList<>(); + + @Override + public void publish(LogRecord record) { + synchronized (lock) { + recent.add(record); + if (recent.size() > MAX_RECENT_RECORDS) recent.poll(); + } + } + + @Override + public void flush() { + } + + @Override + public void close() { + synchronized (lock) { + recent.clear(); + } + } + + public Collection<LogRecord> getRecentLogRecords() { + synchronized (lock) { + return new ArrayList<>(recent); + } + } +} diff --git a/briar-android/src/main/java/org/briarproject/briar/android/reporting/BriarReportPrimer.java b/briar-android/src/main/java/org/briarproject/briar/android/reporting/BriarReportPrimer.java index f74647eba6..dbf6732422 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/reporting/BriarReportPrimer.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/reporting/BriarReportPrimer.java @@ -18,6 +18,8 @@ import org.acra.builder.ReportBuilder; import org.acra.builder.ReportPrimer; import org.briarproject.bramble.util.StringUtils; import org.briarproject.briar.BuildConfig; +import org.briarproject.briar.android.BriarApplication; +import org.briarproject.briar.android.logging.BriefLogFormatter; import java.io.File; import java.lang.reflect.InvocationTargetException; @@ -28,6 +30,8 @@ import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; +import java.util.logging.Formatter; +import java.util.logging.LogRecord; import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE; import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; @@ -69,6 +73,16 @@ public class BriarReportPrimer implements ReportPrimer { public Map<String, String> call() { Map<String, String> customData = new LinkedHashMap<>(); + // Log + BriarApplication app = + (BriarApplication) ctx.getApplicationContext(); + StringBuilder sb = new StringBuilder(); + Formatter formatter = new BriefLogFormatter(); + for (LogRecord record : app.getRecentLogRecords()) { + sb.append(formatter.format(record)).append('\n'); + } + customData.put("Log", sb.toString()); + // System memory Object o = ctx.getSystemService(ACTIVITY_SERVICE); ActivityManager am = (ActivityManager) o; @@ -223,9 +237,10 @@ public class BriarReportPrimer implements ReportPrimer { customData.put("Bluetooth LE status", btLeStatus); } - if (bt != null) + if (bt != null) { customData.put("Bluetooth address", scrubMacAddress(bt.getAddress())); + } String btSettingsAddr; try { btSettingsAddr = Settings.Secure.getString( diff --git a/briar-android/src/test/java/org/briarproject/briar/android/TestBriarApplication.java b/briar-android/src/test/java/org/briarproject/briar/android/TestBriarApplication.java index bc6016caaa..6f232bef0a 100644 --- a/briar-android/src/test/java/org/briarproject/briar/android/TestBriarApplication.java +++ b/briar-android/src/test/java/org/briarproject/briar/android/TestBriarApplication.java @@ -5,8 +5,12 @@ import android.app.Application; import org.briarproject.bramble.BrambleCoreModule; import org.briarproject.briar.BriarCoreModule; +import java.util.Collection; +import java.util.logging.LogRecord; import java.util.logging.Logger; +import static java.util.Collections.emptyList; + /** * This class only exists to avoid static initialisation of ACRA */ @@ -34,6 +38,11 @@ public class TestBriarApplication extends Application AndroidEagerSingletons.initEagerSingletons(applicationComponent); } + @Override + public Collection<LogRecord> getRecentLogRecords() { + return emptyList(); + } + @Override public AndroidComponent getApplicationComponent() { return applicationComponent; -- GitLab