diff --git a/bramble-android/src/main/AndroidManifest.xml b/bramble-android/src/main/AndroidManifest.xml
index 3bcd2608e..9a4bd9810 100644
--- a/bramble-android/src/main/AndroidManifest.xml
+++ b/bramble-android/src/main/AndroidManifest.xml
@@ -16,6 +16,8 @@
android:label="@string/app_name"
android:supportsRtl="true">
+
+
diff --git a/bramble-android/src/main/java/org/briarproject/bramble/BrambleAndroidModule.java b/bramble-android/src/main/java/org/briarproject/bramble/BrambleAndroidModule.java
index c8494e6fa..e0087bed5 100644
--- a/bramble-android/src/main/java/org/briarproject/bramble/BrambleAndroidModule.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/BrambleAndroidModule.java
@@ -6,7 +6,7 @@ import org.briarproject.bramble.plugin.tor.CircumventionModule;
import org.briarproject.bramble.reporting.ReportingModule;
import org.briarproject.bramble.socks.SocksModule;
import org.briarproject.bramble.system.AndroidSystemModule;
-import org.briarproject.bramble.system.DefaultTaskSchedulerModule;
+import org.briarproject.bramble.system.AndroidTaskSchedulerModule;
import dagger.Module;
@@ -14,8 +14,8 @@ import dagger.Module;
AndroidBatteryModule.class,
AndroidNetworkModule.class,
AndroidSystemModule.class,
+ AndroidTaskSchedulerModule.class,
CircumventionModule.class,
- DefaultTaskSchedulerModule.class,
ReportingModule.class,
SocksModule.class
})
diff --git a/bramble-android/src/main/java/org/briarproject/bramble/BrambleAppComponent.java b/bramble-android/src/main/java/org/briarproject/bramble/BrambleAppComponent.java
new file mode 100644
index 000000000..038f65a58
--- /dev/null
+++ b/bramble-android/src/main/java/org/briarproject/bramble/BrambleAppComponent.java
@@ -0,0 +1,8 @@
+package org.briarproject.bramble;
+
+import org.briarproject.bramble.api.system.AlarmListener;
+
+public interface BrambleAppComponent {
+
+ AlarmListener alarmListener();
+}
diff --git a/bramble-android/src/main/java/org/briarproject/bramble/BrambleApplication.java b/bramble-android/src/main/java/org/briarproject/bramble/BrambleApplication.java
new file mode 100644
index 000000000..e9c8ef991
--- /dev/null
+++ b/bramble-android/src/main/java/org/briarproject/bramble/BrambleApplication.java
@@ -0,0 +1,6 @@
+package org.briarproject.bramble;
+
+public interface BrambleApplication {
+
+ BrambleAppComponent getBrambleAppComponent();
+}
diff --git a/bramble-android/src/main/java/org/briarproject/bramble/api/system/AlarmListener.java b/bramble-android/src/main/java/org/briarproject/bramble/api/system/AlarmListener.java
new file mode 100644
index 000000000..e1dab1d57
--- /dev/null
+++ b/bramble-android/src/main/java/org/briarproject/bramble/api/system/AlarmListener.java
@@ -0,0 +1,11 @@
+package org.briarproject.bramble.api.system;
+
+import android.content.Intent;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+public interface AlarmListener {
+
+ void onAlarm(Intent intent);
+}
diff --git a/bramble-android/src/main/java/org/briarproject/bramble/system/AlarmConstants.java b/bramble-android/src/main/java/org/briarproject/bramble/system/AlarmConstants.java
new file mode 100644
index 000000000..b86be5fc6
--- /dev/null
+++ b/bramble-android/src/main/java/org/briarproject/bramble/system/AlarmConstants.java
@@ -0,0 +1,18 @@
+package org.briarproject.bramble.system;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+interface AlarmConstants {
+
+ /**
+ * Request code for the broadcast intent attached to the periodic alarm.
+ */
+ int REQUEST_ALARM = 1;
+
+ /**
+ * Key for storing the process ID in the extras of the periodic alarm's
+ * intent. This allows us to ignore alarms scheduled by dead processes.
+ */
+ String EXTRA_PID = "org.briarproject.bramble.EXTRA_PID";
+}
diff --git a/bramble-android/src/main/java/org/briarproject/bramble/system/AlarmReceiver.java b/bramble-android/src/main/java/org/briarproject/bramble/system/AlarmReceiver.java
new file mode 100644
index 000000000..c3741a816
--- /dev/null
+++ b/bramble-android/src/main/java/org/briarproject/bramble/system/AlarmReceiver.java
@@ -0,0 +1,17 @@
+package org.briarproject.bramble.system;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import org.briarproject.bramble.BrambleApplication;
+
+public class AlarmReceiver extends BroadcastReceiver {
+
+ @Override
+ public void onReceive(Context ctx, Intent intent) {
+ BrambleApplication app =
+ (BrambleApplication) ctx.getApplicationContext();
+ app.getBrambleAppComponent().alarmListener().onAlarm(intent);
+ }
+}
diff --git a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidTaskScheduler.java b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidTaskScheduler.java
new file mode 100644
index 000000000..ae430bcda
--- /dev/null
+++ b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidTaskScheduler.java
@@ -0,0 +1,204 @@
+package org.briarproject.bramble.system;
+
+import android.annotation.TargetApi;
+import android.app.AlarmManager;
+import android.app.Application;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.os.Process;
+import android.os.SystemClock;
+
+import org.briarproject.bramble.api.lifecycle.Service;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.system.AlarmListener;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.bramble.api.system.TaskScheduler;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.PriorityQueue;
+import java.util.Queue;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+
+import javax.annotation.concurrent.GuardedBy;
+import javax.annotation.concurrent.ThreadSafe;
+
+import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
+import static android.app.AlarmManager.INTERVAL_FIFTEEN_MINUTES;
+import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
+import static android.content.Context.ALARM_SERVICE;
+import static android.os.Build.VERSION.SDK_INT;
+import static java.util.Objects.requireNonNull;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.logging.Level.INFO;
+import static java.util.logging.Logger.getLogger;
+import static org.briarproject.bramble.system.AlarmConstants.EXTRA_PID;
+import static org.briarproject.bramble.system.AlarmConstants.REQUEST_ALARM;
+
+@ThreadSafe
+@NotNullByDefault
+class AndroidTaskScheduler implements TaskScheduler, Service, AlarmListener {
+
+ private static final Logger LOG =
+ getLogger(AndroidTaskScheduler.class.getName());
+
+ private static final long TICK_MS = SECONDS.toMillis(10);
+ private static final long ALARM_MS = INTERVAL_FIFTEEN_MINUTES;
+
+ private final Application app;
+ private final Clock clock;
+ private final ScheduledExecutorService scheduledExecutorService;
+ private final AlarmManager alarmManager;
+
+ private final Object lock = new Object();
+ @GuardedBy("lock")
+ private final Queue tasks = new PriorityQueue<>();
+
+ AndroidTaskScheduler(Application app, Clock clock,
+ ScheduledExecutorService scheduledExecutorService) {
+ this.app = app;
+ this.clock = clock;
+ this.scheduledExecutorService = scheduledExecutorService;
+ alarmManager = (AlarmManager)
+ requireNonNull(app.getSystemService(ALARM_SERVICE));
+ }
+
+ @Override
+ public void startService() {
+ scheduledExecutorService.scheduleAtFixedRate(this::runDueTasks,
+ TICK_MS, TICK_MS, MILLISECONDS);
+ scheduleAlarm();
+ }
+
+ @Override
+ public void stopService() {
+ cancelAlarm();
+ }
+
+ @Override
+ public Future> schedule(Runnable task, long delay, TimeUnit unit) {
+ long now = clock.currentTimeMillis();
+ long dueMillis = now + MILLISECONDS.convert(delay, unit);
+ ScheduledTask s = new ScheduledTask(task, dueMillis);
+ if (dueMillis <= now) {
+ scheduledExecutorService.execute(s);
+ } else {
+ synchronized (lock) {
+ tasks.add(s);
+ }
+ }
+ return s;
+ }
+
+ @Override
+ public Future> scheduleAtFixedRate(Runnable task, long delay,
+ long interval, TimeUnit unit) {
+ Runnable wrapped = () -> {
+ scheduleAtFixedRate(task, interval, interval, unit);
+ task.run();
+ };
+ return schedule(wrapped, delay, unit);
+ }
+
+ @Override
+ public Future> scheduleWithFixedDelay(Runnable task, long delay,
+ long interval, TimeUnit unit) {
+ Runnable wrapped = () -> {
+ task.run();
+ scheduleWithFixedDelay(task, interval, interval, unit);
+ };
+ return schedule(wrapped, delay, unit);
+ }
+
+ @Override
+ public void onAlarm(Intent intent) {
+ int extraPid = intent.getIntExtra(EXTRA_PID, -1);
+ int currentPid = Process.myPid();
+ if (extraPid == currentPid) {
+ LOG.info("Alarm");
+ rescheduleAlarm();
+ runDueTasks();
+ } else {
+ LOG.info("Ignoring alarm with PID " + extraPid
+ + ", current PID is " + currentPid);
+ }
+ }
+
+ private void runDueTasks() {
+ long now = clock.currentTimeMillis();
+ List due = new ArrayList<>();
+ synchronized (lock) {
+ while (true) {
+ ScheduledTask s = tasks.peek();
+ if (s == null || s.dueMillis > now) break;
+ due.add(tasks.remove());
+ }
+ }
+ if (LOG.isLoggable(INFO)) {
+ LOG.info("Running " + due.size() + " due tasks");
+ }
+ for (ScheduledTask s : due) {
+ if (LOG.isLoggable(INFO)) {
+ LOG.info("Task is " + (now - s.dueMillis) + " ms overdue");
+ }
+ s.run();
+ }
+ }
+
+ private void scheduleAlarm() {
+ if (SDK_INT >= 23) scheduleIdleAlarm();
+ else scheduleInexactRepeatingAlarm();
+ }
+
+ private void rescheduleAlarm() {
+ if (SDK_INT >= 23) scheduleIdleAlarm();
+ }
+
+ private void cancelAlarm() {
+ alarmManager.cancel(getAlarmPendingIntent());
+ }
+
+ private void scheduleInexactRepeatingAlarm() {
+ alarmManager.setInexactRepeating(ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() + ALARM_MS, ALARM_MS,
+ getAlarmPendingIntent());
+ }
+
+ @TargetApi(23)
+ private void scheduleIdleAlarm() {
+ alarmManager.setAndAllowWhileIdle(ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() + ALARM_MS,
+ getAlarmPendingIntent());
+ }
+
+ private PendingIntent getAlarmPendingIntent() {
+ Intent i = new Intent(app, AlarmReceiver.class);
+ i.putExtra(EXTRA_PID, android.os.Process.myPid());
+ return PendingIntent.getBroadcast(app, REQUEST_ALARM, i,
+ FLAG_CANCEL_CURRENT);
+ }
+
+ private static class ScheduledTask extends FutureTask
+ implements Comparable {
+
+ private final long dueMillis;
+
+ public ScheduledTask(Runnable runnable, long dueMillis) {
+ super(runnable, null);
+ this.dueMillis = dueMillis;
+ }
+
+ @Override
+ public int compareTo(ScheduledTask s) {
+ //noinspection UseCompareMethod
+ if (dueMillis < s.dueMillis) return -1;
+ if (dueMillis > s.dueMillis) return 1;
+ return 0;
+ }
+ }
+}
diff --git a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidTaskSchedulerModule.java b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidTaskSchedulerModule.java
new file mode 100644
index 000000000..f99ab7382
--- /dev/null
+++ b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidTaskSchedulerModule.java
@@ -0,0 +1,59 @@
+package org.briarproject.bramble.system;
+
+import android.app.Application;
+
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.system.AlarmListener;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.bramble.api.system.TaskScheduler;
+
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import dagger.Module;
+import dagger.Provides;
+
+@Module
+public class AndroidTaskSchedulerModule {
+
+ public static class EagerSingletons {
+ @Inject
+ AndroidTaskScheduler scheduler;
+ }
+
+ private final ScheduledExecutorService scheduledExecutorService;
+
+ public AndroidTaskSchedulerModule() {
+ // Discard tasks that are submitted during shutdown
+ RejectedExecutionHandler policy =
+ new ScheduledThreadPoolExecutor.DiscardPolicy();
+ scheduledExecutorService = new ScheduledThreadPoolExecutor(1, policy);
+ }
+
+ @Provides
+ @Singleton
+ AndroidTaskScheduler provideAndroidTaskScheduler(
+ LifecycleManager lifecycleManager, Application app, Clock clock) {
+ lifecycleManager.registerForShutdown(scheduledExecutorService);
+ AndroidTaskScheduler scheduler =
+ new AndroidTaskScheduler(app, clock, scheduledExecutorService);
+ lifecycleManager.registerService(scheduler);
+ return scheduler;
+ }
+
+ @Provides
+ @Singleton
+ AlarmListener provideAlarmListener(AndroidTaskScheduler scheduler) {
+ return scheduler;
+ }
+
+ @Provides
+ @Singleton
+ TaskScheduler provideTaskScheduler(AndroidTaskScheduler scheduler) {
+ return scheduler;
+ }
+}
diff --git a/bramble-android/src/main/java/org/briarproject/bramble/util/RenewableWakeLock.java b/bramble-android/src/main/java/org/briarproject/bramble/util/RenewableWakeLock.java
index 1bfa2eb1c..68ed14f72 100644
--- a/bramble-android/src/main/java/org/briarproject/bramble/util/RenewableWakeLock.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/util/RenewableWakeLock.java
@@ -5,7 +5,7 @@ import android.os.PowerManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.TaskScheduler;
-import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
@@ -39,7 +39,7 @@ public class RenewableWakeLock {
@Nullable
private PowerManager.WakeLock wakeLock; // Locking: lock
@Nullable
- private ScheduledFuture> future; // Locking: lock
+ private Future> future; // Locking: lock
public RenewableWakeLock(PowerManager powerManager,
TaskScheduler scheduler, int levelAndFlags, String tag,
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/system/TaskScheduler.java b/bramble-api/src/main/java/org/briarproject/bramble/api/system/TaskScheduler.java
index 2ecd471f1..b2e627ba2 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/system/TaskScheduler.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/system/TaskScheduler.java
@@ -2,8 +2,8 @@ package org.briarproject.bramble.api.system;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
/**
@@ -18,17 +18,17 @@ public interface TaskScheduler {
/**
* See {@link ScheduledExecutorService#schedule(Runnable, long, TimeUnit)}.
*/
- ScheduledFuture> schedule(Runnable task, long delay, TimeUnit unit);
+ Future> schedule(Runnable task, long delay, TimeUnit unit);
/**
* See {@link ScheduledExecutorService#scheduleAtFixedRate(Runnable, long, long, TimeUnit)}.
*/
- ScheduledFuture> scheduleAtFixedRate(Runnable task, long delay,
- long interval, TimeUnit unit);
+ Future> scheduleAtFixedRate(Runnable task, long delay, long interval,
+ TimeUnit unit);
/**
* See {@link ScheduledExecutorService#scheduleWithFixedDelay(Runnable, long, long, TimeUnit)}.
*/
- ScheduledFuture> scheduleWithFixedDelay(Runnable task, long delay,
+ Future> scheduleWithFixedDelay(Runnable task, long delay,
long interval, TimeUnit unit);
}
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/PollerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/PollerImpl.java
index 86f84f899..db5a878a9 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/PollerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/PollerImpl.java
@@ -189,7 +189,7 @@ class PollerImpl implements Poller, EventListener {
// it will abort safely when it finds it's been replaced
if (scheduled != null) scheduled.future.cancel(false);
PollTask task = new PollTask(p, due, randomiseNext);
- Future future = scheduler.schedule(() ->
+ Future> future = scheduler.schedule(() ->
ioExecutor.execute(task), delay, MILLISECONDS);
tasks.put(t, new ScheduledPollTask(task, future));
}
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/system/TaskSchedulerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/system/TaskSchedulerImpl.java
index 3758f2b77..3d8e7d9bd 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/system/TaskSchedulerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/system/TaskSchedulerImpl.java
@@ -3,8 +3,8 @@ package org.briarproject.bramble.system;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.TaskScheduler;
+import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import javax.annotation.concurrent.ThreadSafe;
@@ -24,19 +24,18 @@ class TaskSchedulerImpl implements TaskScheduler {
}
@Override
- public ScheduledFuture> schedule(Runnable task, long delay,
- TimeUnit unit) {
+ public Future> schedule(Runnable task, long delay, TimeUnit unit) {
return delegate.schedule(task, delay, unit);
}
@Override
- public ScheduledFuture> scheduleAtFixedRate(Runnable task, long delay,
+ public Future> scheduleAtFixedRate(Runnable task, long delay,
long interval, TimeUnit unit) {
return delegate.scheduleAtFixedRate(task, delay, interval, unit);
}
@Override
- public ScheduledFuture> scheduleWithFixedDelay(Runnable task, long delay,
+ public Future> scheduleWithFixedDelay(Runnable task, long delay,
long interval, TimeUnit unit) {
return delegate.scheduleWithFixedDelay(task, delay, interval, unit);
}
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerImpl.java
index 01f3ba070..b255e196f 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerImpl.java
@@ -198,7 +198,7 @@ class TransportKeyManagerImpl implements TransportKeyManager {
private void scheduleKeyUpdate(long now) {
long delay = timePeriodLength - now % timePeriodLength;
- scheduler.schedule((Runnable) this::updateKeys, delay, MILLISECONDS);
+ scheduler.schedule(this::updateKeys, delay, MILLISECONDS);
}
private void updateKeys() {
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/plugin/PollerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/plugin/PollerImplTest.java
index 130110486..04cd467bd 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/plugin/PollerImplTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/plugin/PollerImplTest.java
@@ -31,7 +31,7 @@ import org.junit.Test;
import java.security.SecureRandom;
import java.util.List;
import java.util.concurrent.Executor;
-import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.Future;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
@@ -55,8 +55,7 @@ public class PollerImplTest extends BrambleMockTestCase {
private final TransportPropertyManager transportPropertyManager =
context.mock(TransportPropertyManager.class);
private final Clock clock = context.mock(Clock.class);
- private final ScheduledFuture> future =
- context.mock(ScheduledFuture.class);
+ private final Future> future = context.mock(Future.class);
private final SecureRandom random;
private final Executor ioExecutor = new ImmediateExecutor();
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java b/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java
index 5a9092582..0c4de76ee 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java
@@ -2,6 +2,7 @@ package org.briarproject.briar.android;
import org.briarproject.bramble.BrambleAndroidEagerSingletons;
import org.briarproject.bramble.BrambleAndroidModule;
+import org.briarproject.bramble.BrambleAppComponent;
import org.briarproject.bramble.BrambleCoreEagerSingletons;
import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.account.BriarAccountModule;
@@ -73,7 +74,7 @@ import dagger.Component;
})
public interface AndroidComponent
extends BrambleCoreEagerSingletons, BrambleAndroidEagerSingletons,
- BriarCoreEagerSingletons, AndroidEagerSingletons {
+ BriarCoreEagerSingletons, AndroidEagerSingletons, BrambleAppComponent {
// Exposed objects
@CryptoExecutor
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 0ba14e5ec..09946b3a7 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
@@ -3,6 +3,7 @@ package org.briarproject.briar.android;
import android.app.Activity;
import android.content.SharedPreferences;
+import org.briarproject.bramble.BrambleApplication;
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
import java.util.Collection;
@@ -12,7 +13,7 @@ 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 {
+public interface BriarApplication extends BrambleApplication {
Class extends Activity> ENTRY_ACTIVITY = NavDrawerActivity.class;
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 493a542a7..0ae3159ee 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
@@ -18,6 +18,7 @@ import org.acra.ACRA;
import org.acra.ReportingInteractionMode;
import org.acra.annotation.ReportsCrashes;
import org.briarproject.bramble.BrambleAndroidEagerSingletons;
+import org.briarproject.bramble.BrambleAppComponent;
import org.briarproject.bramble.BrambleCoreEagerSingletons;
import org.briarproject.briar.BriarCoreEagerSingletons;
import org.briarproject.briar.BuildConfig;
@@ -170,6 +171,11 @@ public class BriarApplicationImpl extends Application
StrictMode.setVmPolicy(vmPolicy.build());
}
+ @Override
+ public BrambleAppComponent getBrambleAppComponent() {
+ return applicationComponent;
+ }
+
@Override
public Collection getRecentLogRecords() {
return logHandler.getRecentLogRecords();
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 862521667..7535d5cc4 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
@@ -8,6 +8,7 @@ import com.vanniktech.emoji.EmojiManager;
import com.vanniktech.emoji.google.GoogleEmojiProvider;
import org.briarproject.bramble.BrambleAndroidEagerSingletons;
+import org.briarproject.bramble.BrambleAppComponent;
import org.briarproject.bramble.BrambleCoreEagerSingletons;
import org.briarproject.briar.BriarCoreEagerSingletons;
@@ -53,6 +54,11 @@ public class TestBriarApplication extends Application
EmojiManager.install(new GoogleEmojiProvider());
}
+ @Override
+ public BrambleAppComponent getBrambleAppComponent() {
+ return applicationComponent;
+ }
+
@Override
public Collection getRecentLogRecords() {
return emptyList();