Merge branch 'internal-logger' into 'master'

Use internal log handler for crash reports and feedback

Closes #986

See merge request akwizgran/briar!802
This commit is contained in:
akwizgran
2018-05-17 08:22:48 +00:00
8 changed files with 150 additions and 18 deletions

View File

@@ -12,7 +12,6 @@
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_LOGS"/>
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/> <uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>

View File

@@ -1,10 +1,15 @@
package org.briarproject.briar.android; 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 * This exists so that the Application object will not necessarily be cast
* directly to the Briar application object. * directly to the Briar application object.
*/ */
public interface BriarApplication { public interface BriarApplication {
Collection<LogRecord> getRecentLogRecords();
AndroidComponent getApplicationComponent(); AndroidComponent getApplicationComponent();
} }

View File

@@ -12,12 +12,17 @@ import org.acra.annotation.ReportsCrashes;
import org.briarproject.bramble.BrambleCoreModule; import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.briar.BriarCoreModule; import org.briarproject.briar.BriarCoreModule;
import org.briarproject.briar.R; 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.BriarReportPrimer;
import org.briarproject.briar.android.reporting.BriarReportSenderFactory; import org.briarproject.briar.android.reporting.BriarReportSenderFactory;
import org.briarproject.briar.android.reporting.DevReportActivity; 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 java.util.logging.Logger;
import static java.util.logging.Level.INFO;
import static org.acra.ReportField.ANDROID_VERSION; import static org.acra.ReportField.ANDROID_VERSION;
import static org.acra.ReportField.APP_VERSION_CODE; import static org.acra.ReportField.APP_VERSION_CODE;
import static org.acra.ReportField.APP_VERSION_NAME; import static org.acra.ReportField.APP_VERSION_NAME;
@@ -28,7 +33,6 @@ import static org.acra.ReportField.CUSTOM_DATA;
import static org.acra.ReportField.DEVICE_FEATURES; import static org.acra.ReportField.DEVICE_FEATURES;
import static org.acra.ReportField.DISPLAY; import static org.acra.ReportField.DISPLAY;
import static org.acra.ReportField.INITIAL_CONFIGURATION; import static org.acra.ReportField.INITIAL_CONFIGURATION;
import static org.acra.ReportField.LOGCAT;
import static org.acra.ReportField.PACKAGE_NAME; import static org.acra.ReportField.PACKAGE_NAME;
import static org.acra.ReportField.PHONE_MODEL; import static org.acra.ReportField.PHONE_MODEL;
import static org.acra.ReportField.PRODUCT; import static org.acra.ReportField.PRODUCT;
@@ -36,7 +40,7 @@ import static org.acra.ReportField.REPORT_ID;
import static org.acra.ReportField.STACK_TRACE; import static org.acra.ReportField.STACK_TRACE;
import static org.acra.ReportField.USER_APP_START_DATE; import static org.acra.ReportField.USER_APP_START_DATE;
import static org.acra.ReportField.USER_CRASH_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; import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
@ReportsCrashes( @ReportsCrashes(
@@ -56,8 +60,7 @@ import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
STACK_TRACE, STACK_TRACE,
INITIAL_CONFIGURATION, CRASH_CONFIGURATION, INITIAL_CONFIGURATION, CRASH_CONFIGURATION,
DISPLAY, DEVICE_FEATURES, DISPLAY, DEVICE_FEATURES,
USER_APP_START_DATE, USER_CRASH_DATE, USER_APP_START_DATE, USER_CRASH_DATE
LOGCAT
} }
) )
public class BriarApplicationImpl extends Application public class BriarApplicationImpl extends Application
@@ -66,6 +69,8 @@ public class BriarApplicationImpl extends Application
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(BriarApplicationImpl.class.getName()); Logger.getLogger(BriarApplicationImpl.class.getName());
private final CachingLogHandler logHandler = new CachingLogHandler();
private AndroidComponent applicationComponent; private AndroidComponent applicationComponent;
@Override @Override
@@ -79,7 +84,17 @@ public class BriarApplicationImpl extends Application
super.onCreate(); super.onCreate();
if (IS_DEBUG_BUILD) enableStrictMode(); 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"); LOG.info("Created");
applicationComponent = DaggerAndroidComponent.builder() applicationComponent = DaggerAndroidComponent.builder()
@@ -104,6 +119,11 @@ public class BriarApplicationImpl extends Application
StrictMode.setVmPolicy(vmPolicy.build()); StrictMode.setVmPolicy(vmPolicy.build());
} }
@Override
public Collection<LogRecord> getRecentLogRecords() {
return logHandler.getRecentLogRecords();
}
@Override @Override
public AndroidComponent getApplicationComponent() { public AndroidComponent getApplicationComponent() {
return applicationComponent; return applicationComponent;

View File

@@ -2,11 +2,6 @@ package org.briarproject.briar.android;
import org.briarproject.briar.BuildConfig; 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 { public interface TestingConstants {
/** /**
@@ -20,12 +15,6 @@ public interface TestingConstants {
*/ */
boolean IS_BETA_BUILD = false; 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 * Whether to prevent screenshots from being taken. Setting this to true
* prevents Recent Apps from storing screenshots of private information. * prevents Recent Apps from storing screenshots of private information.

View File

@@ -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();
}
}

View File

@@ -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);
}
}
}

View File

@@ -18,6 +18,8 @@ import org.acra.builder.ReportBuilder;
import org.acra.builder.ReportPrimer; import org.acra.builder.ReportPrimer;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.BuildConfig; import org.briarproject.briar.BuildConfig;
import org.briarproject.briar.android.BriarApplication;
import org.briarproject.briar.android.logging.BriefLogFormatter;
import java.io.File; import java.io.File;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
@@ -28,6 +30,8 @@ import java.util.Map;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask; 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;
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
@@ -69,6 +73,16 @@ public class BriarReportPrimer implements ReportPrimer {
public Map<String, String> call() { public Map<String, String> call() {
Map<String, String> customData = new LinkedHashMap<>(); 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 // System memory
Object o = ctx.getSystemService(ACTIVITY_SERVICE); Object o = ctx.getSystemService(ACTIVITY_SERVICE);
ActivityManager am = (ActivityManager) o; ActivityManager am = (ActivityManager) o;
@@ -223,9 +237,10 @@ public class BriarReportPrimer implements ReportPrimer {
customData.put("Bluetooth LE status", btLeStatus); customData.put("Bluetooth LE status", btLeStatus);
} }
if (bt != null) if (bt != null) {
customData.put("Bluetooth address", customData.put("Bluetooth address",
scrubMacAddress(bt.getAddress())); scrubMacAddress(bt.getAddress()));
}
String btSettingsAddr; String btSettingsAddr;
try { try {
btSettingsAddr = Settings.Secure.getString( btSettingsAddr = Settings.Secure.getString(

View File

@@ -5,8 +5,12 @@ import android.app.Application;
import org.briarproject.bramble.BrambleCoreModule; import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.briar.BriarCoreModule; import org.briarproject.briar.BriarCoreModule;
import java.util.Collection;
import java.util.logging.LogRecord;
import java.util.logging.Logger; import java.util.logging.Logger;
import static java.util.Collections.emptyList;
/** /**
* This class only exists to avoid static initialisation of ACRA * This class only exists to avoid static initialisation of ACRA
*/ */
@@ -34,6 +38,11 @@ public class TestBriarApplication extends Application
AndroidEagerSingletons.initEagerSingletons(applicationComponent); AndroidEagerSingletons.initEagerSingletons(applicationComponent);
} }
@Override
public Collection<LogRecord> getRecentLogRecords() {
return emptyList();
}
@Override @Override
public AndroidComponent getApplicationComponent() { public AndroidComponent getApplicationComponent() {
return applicationComponent; return applicationComponent;