diff --git a/bramble-android/src/main/java/org/briarproject/bramble/api/system/AndroidWakeLockFactory.java b/bramble-android/src/main/java/org/briarproject/bramble/api/system/AndroidWakeLockFactory.java deleted file mode 100644 index 7d7be15d0..000000000 --- a/bramble-android/src/main/java/org/briarproject/bramble/api/system/AndroidWakeLockFactory.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.briarproject.bramble.api.system; - -import org.briarproject.bramble.api.nullsafety.NotNullByDefault; - -@NotNullByDefault -public interface AndroidWakeLockFactory { - - AndroidWakeLock createWakeLock(); -} diff --git a/bramble-android/src/main/java/org/briarproject/bramble/api/system/AndroidWakeLockManager.java b/bramble-android/src/main/java/org/briarproject/bramble/api/system/AndroidWakeLockManager.java new file mode 100644 index 000000000..0ebf256a2 --- /dev/null +++ b/bramble-android/src/main/java/org/briarproject/bramble/api/system/AndroidWakeLockManager.java @@ -0,0 +1,27 @@ +package org.briarproject.bramble.api.system; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +import java.util.concurrent.Executor; + +@NotNullByDefault +public interface AndroidWakeLockManager { + + /** + * Creates a wake lock with the given tag. The tag is only used for + * logging; the underlying OS wake lock will use its own tag. + */ + AndroidWakeLock createWakeLock(String tag); + + /** + * Runs the given task while holding a wake lock. + */ + void runWakefully(Runnable r, String tag); + + /** + * Submits the given task to the given executor while holding a wake lock. + * The lock is released when the task completes, or if an exception is + * thrown while submitting or running the task. + */ + void executeWakefully(Runnable r, Executor executor, String tag); +} diff --git a/bramble-android/src/main/java/org/briarproject/bramble/network/AndroidNetworkManager.java b/bramble-android/src/main/java/org/briarproject/bramble/network/AndroidNetworkManager.java index c113dca2b..f6c238600 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/network/AndroidNetworkManager.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/network/AndroidNetworkManager.java @@ -9,6 +9,7 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; import org.briarproject.bramble.api.event.EventBus; +import org.briarproject.bramble.api.event.EventExecutor; import org.briarproject.bramble.api.lifecycle.Service; import org.briarproject.bramble.api.network.NetworkManager; import org.briarproject.bramble.api.network.NetworkStatus; @@ -17,6 +18,7 @@ import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.bramble.api.system.TaskScheduler; +import java.util.concurrent.Executor; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -51,6 +53,7 @@ class AndroidNetworkManager implements NetworkManager, Service { private final TaskScheduler scheduler; private final EventBus eventBus; + private final Executor eventExecutor; private final Context appContext; private final AtomicReference> connectivityCheck = new AtomicReference<>(); @@ -60,9 +63,10 @@ class AndroidNetworkManager implements NetworkManager, Service { @Inject AndroidNetworkManager(TaskScheduler scheduler, EventBus eventBus, - Application app) { + @EventExecutor Executor eventExecutor, Application app) { this.scheduler = scheduler; this.eventBus = eventBus; + this.eventExecutor = eventExecutor; this.appContext = app.getApplicationContext(); } @@ -104,7 +108,8 @@ class AndroidNetworkManager implements NetworkManager, Service { private void scheduleConnectionStatusUpdate(int delay, TimeUnit unit) { Future newConnectivityCheck = - scheduler.schedule(this::updateConnectionStatus, delay, unit); + scheduler.schedule(this::updateConnectionStatus, eventExecutor, + delay, unit); Future oldConnectivityCheck = connectivityCheck.getAndSet(newConnectivityCheck); if (oldConnectivityCheck != null) oldConnectivityCheck.cancel(false); diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothConnectionFactory.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothConnectionFactory.java index 61d543414..b14d5459b 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothConnectionFactory.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothConnectionFactory.java @@ -6,7 +6,7 @@ import org.briarproject.bramble.api.io.TimeoutMonitor; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin; import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection; -import org.briarproject.bramble.api.system.AndroidWakeLockFactory; +import org.briarproject.bramble.api.system.AndroidWakeLockManager; import java.io.IOException; @@ -15,15 +15,15 @@ class AndroidBluetoothConnectionFactory implements BluetoothConnectionFactory { private final BluetoothConnectionLimiter connectionLimiter; - private final AndroidWakeLockFactory wakeLockFactory; + private final AndroidWakeLockManager wakeLockManager; private final TimeoutMonitor timeoutMonitor; AndroidBluetoothConnectionFactory( BluetoothConnectionLimiter connectionLimiter, - AndroidWakeLockFactory wakeLockFactory, + AndroidWakeLockManager wakeLockManager, TimeoutMonitor timeoutMonitor) { this.connectionLimiter = connectionLimiter; - this.wakeLockFactory = wakeLockFactory; + this.wakeLockManager = wakeLockManager; this.timeoutMonitor = timeoutMonitor; } @@ -31,6 +31,6 @@ class AndroidBluetoothConnectionFactory public DuplexTransportConnection wrapSocket(DuplexPlugin plugin, BluetoothSocket s) throws IOException { return new AndroidBluetoothTransportConnection(plugin, - connectionLimiter, wakeLockFactory, timeoutMonitor, s); + connectionLimiter, wakeLockManager, timeoutMonitor, s); } } diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPluginFactory.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPluginFactory.java index 590117345..ecd6b95b6 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPluginFactory.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPluginFactory.java @@ -13,7 +13,7 @@ import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin; import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory; import org.briarproject.bramble.api.system.AndroidExecutor; -import org.briarproject.bramble.api.system.AndroidWakeLockFactory; +import org.briarproject.bramble.api.system.AndroidWakeLockManager; import org.briarproject.bramble.api.system.Clock; import java.security.SecureRandom; @@ -35,7 +35,7 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory { private final Executor ioExecutor; private final AndroidExecutor androidExecutor; - private final AndroidWakeLockFactory wakeLockFactory; + private final AndroidWakeLockManager wakeLockManager; private final Context appContext; private final SecureRandom secureRandom; private final EventBus eventBus; @@ -45,7 +45,7 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory { public AndroidBluetoothPluginFactory(Executor ioExecutor, AndroidExecutor androidExecutor, - AndroidWakeLockFactory wakeLockFactory, + AndroidWakeLockManager wakeLockManager, Context appContext, SecureRandom secureRandom, EventBus eventBus, @@ -54,7 +54,7 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory { BackoffFactory backoffFactory) { this.ioExecutor = ioExecutor; this.androidExecutor = androidExecutor; - this.wakeLockFactory = wakeLockFactory; + this.wakeLockManager = wakeLockManager; this.appContext = appContext; this.secureRandom = secureRandom; this.eventBus = eventBus; @@ -79,7 +79,7 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory { new BluetoothConnectionLimiterImpl(eventBus); BluetoothConnectionFactory connectionFactory = new AndroidBluetoothConnectionFactory(connectionLimiter, - wakeLockFactory, timeoutMonitor); + wakeLockManager, timeoutMonitor); Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, MAX_POLLING_INTERVAL, BACKOFF_BASE); AndroidBluetoothPlugin plugin = new AndroidBluetoothPlugin( diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothTransportConnection.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothTransportConnection.java index ad0f4f038..b6a695116 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothTransportConnection.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothTransportConnection.java @@ -7,7 +7,7 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.plugin.Plugin; import org.briarproject.bramble.api.plugin.duplex.AbstractDuplexTransportConnection; import org.briarproject.bramble.api.system.AndroidWakeLock; -import org.briarproject.bramble.api.system.AndroidWakeLockFactory; +import org.briarproject.bramble.api.system.AndroidWakeLockManager; import java.io.IOException; import java.io.InputStream; @@ -27,7 +27,7 @@ class AndroidBluetoothTransportConnection AndroidBluetoothTransportConnection(Plugin plugin, BluetoothConnectionLimiter connectionLimiter, - AndroidWakeLockFactory wakeLockFactory, + AndroidWakeLockManager wakeLockManager, TimeoutMonitor timeoutMonitor, BluetoothSocket socket) throws IOException { super(plugin); @@ -35,7 +35,7 @@ class AndroidBluetoothTransportConnection this.socket = socket; in = timeoutMonitor.createTimeoutInputStream( socket.getInputStream(), plugin.getMaxIdleTime() * 2); - wakeLock = wakeLockFactory.createWakeLock(); + wakeLock = wakeLockManager.createWakeLock("BluetoothConnection"); wakeLock.acquire(); String address = socket.getRemoteDevice().getAddress(); if (isValidBluetoothAddress(address)) remote.put(PROP_ADDRESS, address); diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidTorPlugin.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidTorPlugin.java index 391416019..79e35151c 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidTorPlugin.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidTorPlugin.java @@ -12,7 +12,7 @@ import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.bramble.api.plugin.Backoff; import org.briarproject.bramble.api.plugin.PluginCallback; import org.briarproject.bramble.api.system.AndroidWakeLock; -import org.briarproject.bramble.api.system.AndroidWakeLockFactory; +import org.briarproject.bramble.api.system.AndroidWakeLockManager; import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.ResourceProvider; @@ -40,7 +40,7 @@ class AndroidTorPlugin extends TorPlugin { ResourceProvider resourceProvider, CircumventionProvider circumventionProvider, BatteryManager batteryManager, - AndroidWakeLockFactory wakeLockFactory, + AndroidWakeLockManager wakeLockManager, Backoff backoff, TorRendezvousCrypto torRendezvousCrypto, PluginCallback callback, @@ -53,7 +53,7 @@ class AndroidTorPlugin extends TorPlugin { maxLatency, maxIdleTime, appContext.getDir("tor", MODE_PRIVATE)); this.appContext = appContext; - wakeLock = wakeLockFactory.createWakeLock(); + wakeLock = wakeLockManager.createWakeLock("TorPlugin"); } @Override diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidTorPluginFactory.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidTorPluginFactory.java index 7f477a4d5..8f2b936ee 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidTorPluginFactory.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidTorPluginFactory.java @@ -13,7 +13,7 @@ import org.briarproject.bramble.api.plugin.TorConstants; import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin; import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory; -import org.briarproject.bramble.api.system.AndroidWakeLockFactory; +import org.briarproject.bramble.api.system.AndroidWakeLockManager; import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.ResourceProvider; @@ -48,7 +48,7 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory { private final ResourceProvider resourceProvider; private final CircumventionProvider circumventionProvider; private final BatteryManager batteryManager; - private final AndroidWakeLockFactory wakeLockFactory; + private final AndroidWakeLockManager wakeLockManager; private final Clock clock; public AndroidTorPluginFactory(Executor ioExecutor, @@ -61,7 +61,7 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory { ResourceProvider resourceProvider, CircumventionProvider circumventionProvider, BatteryManager batteryManager, - AndroidWakeLockFactory wakeLockFactory, + AndroidWakeLockManager wakeLockManager, Clock clock) { this.ioExecutor = ioExecutor; this.appContext = appContext; @@ -73,7 +73,7 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory { this.resourceProvider = resourceProvider; this.circumventionProvider = circumventionProvider; this.batteryManager = batteryManager; - this.wakeLockFactory = wakeLockFactory; + this.wakeLockManager = wakeLockManager; this.clock = clock; } @@ -120,7 +120,7 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory { AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor, appContext, networkManager, locationUtils, torSocketFactory, clock, resourceProvider, circumventionProvider, batteryManager, - wakeLockFactory, backoff, torRendezvousCrypto, callback, + wakeLockManager, backoff, torRendezvousCrypto, callback, architecture, MAX_LATENCY, MAX_IDLE_TIME); eventBus.addListener(plugin); return plugin; diff --git a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSystemModule.java b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSystemModule.java index b18b99d26..714d1ab83 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSystemModule.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSystemModule.java @@ -1,13 +1,17 @@ package org.briarproject.bramble.system; import org.briarproject.bramble.api.event.EventExecutor; +import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.system.AndroidExecutor; -import org.briarproject.bramble.api.system.AndroidWakeLockFactory; +import org.briarproject.bramble.api.system.AndroidWakeLockManager; import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.ResourceProvider; import org.briarproject.bramble.api.system.SecureRandomProvider; import java.util.concurrent.Executor; +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; import javax.inject.Singleton; @@ -17,6 +21,23 @@ import dagger.Provides; @Module public class AndroidSystemModule { + private final ScheduledExecutorService scheduledExecutorService; + + public AndroidSystemModule() { + // Discard tasks that are submitted during shutdown + RejectedExecutionHandler policy = + new ScheduledThreadPoolExecutor.DiscardPolicy(); + scheduledExecutorService = new ScheduledThreadPoolExecutor(1, policy); + } + + @Provides + @Singleton + ScheduledExecutorService provideScheduledExecutorService( + LifecycleManager lifecycleManager) { + lifecycleManager.registerForShutdown(scheduledExecutorService); + return scheduledExecutorService; + } + @Provides @Singleton SecureRandomProvider provideSecureRandomProvider( @@ -51,8 +72,8 @@ public class AndroidSystemModule { @Provides @Singleton - AndroidWakeLockFactory provideWakeLockFactory( - AndroidWakeLockFactoryImpl wakeLockFactory) { - return wakeLockFactory; + AndroidWakeLockManager provideWakeLockManager( + AndroidWakeLockManagerImpl wakeLockManager) { + return wakeLockManager; } } 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 index ae9583b9f..55714cb00 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidTaskScheduler.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidTaskScheduler.java @@ -11,12 +11,14 @@ 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.AndroidWakeLockManager; 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.Executor; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; import java.util.concurrent.ScheduledExecutorService; @@ -50,6 +52,7 @@ class AndroidTaskScheduler implements TaskScheduler, Service, AlarmListener { private static final long ALARM_MS = INTERVAL_FIFTEEN_MINUTES; private final Application app; + private final AndroidWakeLockManager wakeLockManager; private final ScheduledExecutorService scheduledExecutorService; private final AlarmManager alarmManager; @@ -58,8 +61,10 @@ class AndroidTaskScheduler implements TaskScheduler, Service, AlarmListener { private final Queue tasks = new PriorityQueue<>(); AndroidTaskScheduler(Application app, + AndroidWakeLockManager wakeLockManager, ScheduledExecutorService scheduledExecutorService) { this.app = app; + this.wakeLockManager = wakeLockManager; this.scheduledExecutorService = scheduledExecutorService; alarmManager = (AlarmManager) requireNonNull(app.getSystemService(ALARM_SERVICE)); @@ -67,8 +72,9 @@ class AndroidTaskScheduler implements TaskScheduler, Service, AlarmListener { @Override public void startService() { - scheduledExecutorService.scheduleAtFixedRate(this::runDueTasks, - TICK_MS, TICK_MS, MILLISECONDS); + scheduledExecutorService.scheduleAtFixedRate( + () -> wakeLockManager.runWakefully(this::runDueTasks, + "TaskTicker"), TICK_MS, TICK_MS, MILLISECONDS); scheduleAlarm(); } @@ -78,10 +84,13 @@ class AndroidTaskScheduler implements TaskScheduler, Service, AlarmListener { } @Override - public Future schedule(Runnable task, long delay, TimeUnit unit) { + public Future schedule(Runnable task, Executor executor, long delay, + TimeUnit unit) { long now = SystemClock.elapsedRealtime(); long dueMillis = now + MILLISECONDS.convert(delay, unit); - ScheduledTask s = new ScheduledTask(task, dueMillis); + Runnable wakeful = () -> + wakeLockManager.executeWakefully(task, executor, "TaskHandoff"); + ScheduledTask s = new ScheduledTask(wakeful, dueMillis); if (dueMillis <= now) { scheduledExecutorService.execute(s); } else { @@ -93,27 +102,29 @@ class AndroidTaskScheduler implements TaskScheduler, Service, AlarmListener { } @Override - public Future scheduleWithFixedDelay(Runnable task, long delay, - long interval, TimeUnit unit) { + public Future scheduleWithFixedDelay(Runnable task, Executor executor, + long delay, long interval, TimeUnit unit) { Runnable wrapped = () -> { task.run(); - scheduleWithFixedDelay(task, interval, interval, unit); + scheduleWithFixedDelay(task, executor, interval, interval, unit); }; - return schedule(wrapped, delay, unit); + return schedule(wrapped, executor, 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 if (LOG.isLoggable(INFO)) { - LOG.info("Ignoring alarm with PID " + extraPid - + ", current PID is " + currentPid); - } + wakeLockManager.runWakefully(() -> { + int extraPid = intent.getIntExtra(EXTRA_PID, -1); + int currentPid = Process.myPid(); + if (extraPid == currentPid) { + LOG.info("Alarm"); + rescheduleAlarm(); + runDueTasks(); + } else if (LOG.isLoggable(INFO)) { + LOG.info("Ignoring alarm with PID " + extraPid + + ", current PID is " + currentPid); + } + }, "TaskAlarm"); } private void runDueTasks() { 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 index 88fc77ff9..2dcbb551c 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidTaskSchedulerModule.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidTaskSchedulerModule.java @@ -4,11 +4,10 @@ import android.app.Application; import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.system.AlarmListener; +import org.briarproject.bramble.api.system.AndroidWakeLockManager; 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; @@ -24,22 +23,14 @@ public class AndroidTaskSchedulerModule { 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) { - lifecycleManager.registerForShutdown(scheduledExecutorService); - AndroidTaskScheduler scheduler = - new AndroidTaskScheduler(app, scheduledExecutorService); + LifecycleManager lifecycleManager, Application app, + AndroidWakeLockManager wakeLockManager, + ScheduledExecutorService scheduledExecutorService) { + AndroidTaskScheduler scheduler = new AndroidTaskScheduler(app, + wakeLockManager, scheduledExecutorService); lifecycleManager.registerService(scheduler); return scheduler; } diff --git a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidWakeLockImpl.java b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidWakeLockImpl.java index d3d9a7c4b..625d43760 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidWakeLockImpl.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidWakeLockImpl.java @@ -3,9 +3,15 @@ package org.briarproject.bramble.system; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.system.AndroidWakeLock; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Logger; + import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.ThreadSafe; +import static java.util.logging.Level.FINE; +import static java.util.logging.Logger.getLogger; + /** * A wrapper around a {@link SharedWakeLock} that provides the more convenient * semantics of {@link AndroidWakeLock} (i.e. calls to acquire() and release() @@ -15,19 +21,34 @@ import javax.annotation.concurrent.ThreadSafe; @NotNullByDefault class AndroidWakeLockImpl implements AndroidWakeLock { + private static final Logger LOG = + getLogger(AndroidWakeLockImpl.class.getName()); + + private static final AtomicInteger INSTANCE_ID = new AtomicInteger(0); + private final SharedWakeLock sharedWakeLock; + private final String tag; + private final Object lock = new Object(); @GuardedBy("lock") private boolean held = false; - AndroidWakeLockImpl(SharedWakeLock sharedWakeLock) { + AndroidWakeLockImpl(SharedWakeLock sharedWakeLock, String tag) { this.sharedWakeLock = sharedWakeLock; + this.tag = tag + "_" + INSTANCE_ID.getAndIncrement(); } @Override public void acquire() { synchronized (lock) { - if (!held) { + if (held) { + if (LOG.isLoggable(FINE)) { + LOG.fine(tag + " already acquired"); + } + } else { + if (LOG.isLoggable(FINE)) { + LOG.fine(tag + " acquiring shared wake lock"); + } held = true; sharedWakeLock.acquire(); } @@ -38,8 +59,15 @@ class AndroidWakeLockImpl implements AndroidWakeLock { public void release() { synchronized (lock) { if (held) { + if (LOG.isLoggable(FINE)) { + LOG.fine(tag + " releasing shared wake lock"); + } held = false; sharedWakeLock.release(); + } else { + if (LOG.isLoggable(FINE)) { + LOG.fine(tag + " already released"); + } } } } diff --git a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidWakeLockFactoryImpl.java b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidWakeLockManagerImpl.java similarity index 54% rename from bramble-android/src/main/java/org/briarproject/bramble/system/AndroidWakeLockFactoryImpl.java rename to bramble-android/src/main/java/org/briarproject/bramble/system/AndroidWakeLockManagerImpl.java index f1e7acf8f..bf80c5fc0 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidWakeLockFactoryImpl.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidWakeLockManagerImpl.java @@ -8,8 +8,10 @@ import android.os.PowerManager; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.system.AndroidWakeLock; -import org.briarproject.bramble.api.system.AndroidWakeLockFactory; -import org.briarproject.bramble.api.system.TaskScheduler; +import org.briarproject.bramble.api.system.AndroidWakeLockManager; + +import java.util.concurrent.Executor; +import java.util.concurrent.ScheduledExecutorService; import javax.inject.Inject; @@ -20,7 +22,7 @@ import static java.util.concurrent.TimeUnit.SECONDS; import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull; @NotNullByDefault -class AndroidWakeLockFactoryImpl implements AndroidWakeLockFactory { +class AndroidWakeLockManagerImpl implements AndroidWakeLockManager { /** * How often to replace the wake lock. @@ -36,17 +38,52 @@ class AndroidWakeLockFactoryImpl implements AndroidWakeLockFactory { private final SharedWakeLock sharedWakeLock; @Inject - AndroidWakeLockFactoryImpl(TaskScheduler scheduler, Application app) { + AndroidWakeLockManagerImpl(Application app, + ScheduledExecutorService scheduledExecutorService) { PowerManager powerManager = (PowerManager) requireNonNull(app.getSystemService(POWER_SERVICE)); String tag = getWakeLockTag(app); - sharedWakeLock = new RenewableWakeLock(powerManager, scheduler, - PARTIAL_WAKE_LOCK, tag, LOCK_DURATION_MS, SAFETY_MARGIN_MS); + sharedWakeLock = new RenewableWakeLock(powerManager, + scheduledExecutorService, PARTIAL_WAKE_LOCK, tag, + LOCK_DURATION_MS, SAFETY_MARGIN_MS); } @Override - public AndroidWakeLock createWakeLock() { - return new AndroidWakeLockImpl(sharedWakeLock); + public AndroidWakeLock createWakeLock(String tag) { + return new AndroidWakeLockImpl(sharedWakeLock, tag); + } + + @Override + public void runWakefully(Runnable r, String tag) { + AndroidWakeLock wakeLock = createWakeLock(tag); + wakeLock.acquire(); + try { + r.run(); + } finally { + wakeLock.release(); + } + } + + @Override + public void executeWakefully(Runnable r, Executor executor, String tag) { + AndroidWakeLock wakeLock = createWakeLock(tag); + wakeLock.acquire(); + try { + executor.execute(() -> { + try { + r.run(); + } finally { + // Release the wake lock if the task throws an exception + wakeLock.release(); + } + }); + } catch (Exception e) { + // Release the wake lock if the executor throws an exception when + // we submit the task (in which case the release() call above won't + // happen) + wakeLock.release(); + throw e; + } } private String getWakeLockTag(Context ctx) { diff --git a/bramble-android/src/main/java/org/briarproject/bramble/system/RenewableWakeLock.java b/bramble-android/src/main/java/org/briarproject/bramble/system/RenewableWakeLock.java index c47a8dfb9..122180fd6 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/system/RenewableWakeLock.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/system/RenewableWakeLock.java @@ -4,9 +4,9 @@ import android.os.PowerManager; import android.os.PowerManager.WakeLock; 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.logging.Logger; import javax.annotation.Nullable; @@ -14,6 +14,7 @@ import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.ThreadSafe; import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.logging.Level.FINE; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import static java.util.logging.Logger.getLogger; @@ -27,7 +28,7 @@ class RenewableWakeLock implements SharedWakeLock { getLogger(RenewableWakeLock.class.getName()); private final PowerManager powerManager; - private final TaskScheduler scheduler; + private final ScheduledExecutorService scheduledExecutorService; private final int levelAndFlags; private final String tag; private final long durationMs, safetyMarginMs; @@ -44,11 +45,14 @@ class RenewableWakeLock implements SharedWakeLock { @GuardedBy("lock") private long acquired = 0; - RenewableWakeLock(PowerManager powerManager, TaskScheduler scheduler, - int levelAndFlags, String tag, long durationMs, + RenewableWakeLock(PowerManager powerManager, + ScheduledExecutorService scheduledExecutorService, + int levelAndFlags, + String tag, + long durationMs, long safetyMarginMs) { this.powerManager = powerManager; - this.scheduler = scheduler; + this.scheduledExecutorService = scheduledExecutorService; this.levelAndFlags = levelAndFlags; this.tag = tag; this.durationMs = durationMs; @@ -69,9 +73,11 @@ class RenewableWakeLock implements SharedWakeLock { // power management apps wakeLock.setReferenceCounted(false); wakeLock.acquire(durationMs + safetyMarginMs); - future = scheduler.schedule(this::renew, durationMs, - MILLISECONDS); + future = scheduledExecutorService.schedule(this::renew, + durationMs, MILLISECONDS); acquired = android.os.SystemClock.elapsedRealtime(); + } else if (LOG.isLoggable(FINE)) { + LOG.fine("Wake lock " + tag + " has " + refCount + " holders"); } } } @@ -83,6 +89,9 @@ class RenewableWakeLock implements SharedWakeLock { LOG.info("Already released"); return; } + if (LOG.isLoggable(FINE)) { + LOG.fine("Wake lock " + tag + " has " + refCount + " holders"); + } long now = android.os.SystemClock.elapsedRealtime(); long expiry = acquired + durationMs + safetyMarginMs; if (now > expiry && LOG.isLoggable(WARNING)) { @@ -93,7 +102,8 @@ class RenewableWakeLock implements SharedWakeLock { wakeLock.setReferenceCounted(false); wakeLock.acquire(durationMs + safetyMarginMs); oldWakeLock.release(); - future = scheduler.schedule(this::renew, durationMs, MILLISECONDS); + future = scheduledExecutorService.schedule(this::renew, durationMs, + MILLISECONDS); acquired = now; } } @@ -111,6 +121,8 @@ class RenewableWakeLock implements SharedWakeLock { requireNonNull(wakeLock).release(); wakeLock = null; acquired = 0; + } else if (LOG.isLoggable(FINE)) { + LOG.fine("Wake lock " + tag + " has " + refCount + " holders"); } } } 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 dad4ef86c..9d72c4cfb 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,27 +2,27 @@ package org.briarproject.bramble.api.system; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import java.util.concurrent.Executor; import java.util.concurrent.Future; -import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /** * A service that can be used to schedule the execution of tasks. - *

- * The service should only be used for running tasks on other executors - * at scheduled times. No significant work should be run by the service itself. */ @NotNullByDefault public interface TaskScheduler { /** - * See {@link ScheduledExecutorService#schedule(Runnable, long, TimeUnit)}. + * Submits the given task to the given executor after the given delay. */ - Future schedule(Runnable task, long delay, TimeUnit unit); + Future schedule(Runnable task, Executor executor, long delay, + TimeUnit unit); /** - * See {@link ScheduledExecutorService#scheduleWithFixedDelay(Runnable, long, long, TimeUnit)}. + * Submits the given task to the given executor after the given delay, + * and then repeatedly with the given interval between executions + * (measured from the end of one execution to the beginning of the next). */ - Future scheduleWithFixedDelay(Runnable task, long delay, - long interval, TimeUnit unit); + Future scheduleWithFixedDelay(Runnable task, Executor executor, + long delay, long interval, TimeUnit unit); } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/io/TimeoutMonitorImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/io/TimeoutMonitorImpl.java index ce90af8f0..e4bc71e1d 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/io/TimeoutMonitorImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/io/TimeoutMonitorImpl.java @@ -55,7 +55,8 @@ class TimeoutMonitorImpl implements TimeoutMonitor { synchronized (lock) { if (streams.isEmpty()) { task = scheduler.scheduleWithFixedDelay(this::checkTimeouts, - CHECK_INTERVAL_MS, CHECK_INTERVAL_MS, MILLISECONDS); + ioExecutor, CHECK_INTERVAL_MS, CHECK_INTERVAL_MS, + MILLISECONDS); } streams.add(stream); } @@ -73,23 +74,21 @@ class TimeoutMonitorImpl implements TimeoutMonitor { if (toCancel != null) toCancel.cancel(false); } - // Scheduler + @IoExecutor private void checkTimeouts() { - ioExecutor.execute(() -> { - List snapshot; - synchronized (lock) { - snapshot = new ArrayList<>(streams); - } - for (TimeoutInputStream stream : snapshot) { - if (stream.hasTimedOut()) { - LOG.info("Input stream has timed out"); - try { - stream.close(); - } catch (IOException e) { - logException(LOG, INFO, e); - } + List snapshot; + synchronized (lock) { + snapshot = new ArrayList<>(streams); + } + for (TimeoutInputStream stream : snapshot) { + if (stream.hasTimedOut()) { + LOG.info("Input stream has timed out"); + try { + stream.close(); + } catch (IOException e) { + logException(LOG, INFO, e); } } - }); + } } } 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 db5a878a9..361ac244b 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 @@ -118,6 +118,7 @@ class PollerImpl implements Poller, EventListener { } } + // TODO: Make this wakeful private void connectToContact(ContactId c) { for (SimplexPlugin s : pluginManager.getSimplexPlugins()) if (s.shouldPoll()) connectToContact(c, s); @@ -189,8 +190,8 @@ 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(() -> - ioExecutor.execute(task), delay, MILLISECONDS); + Future future = scheduler.schedule(task, ioExecutor, delay, + MILLISECONDS); tasks.put(t, new ScheduledPollTask(task, future)); } } finally { @@ -233,9 +234,9 @@ class PollerImpl implements Poller, EventListener { private class ScheduledPollTask { private final PollTask task; - private final Future future; + private final Future future; - private ScheduledPollTask(PollTask task, Future future) { + private ScheduledPollTask(PollTask task, Future future) { this.task = task; this.future = future; } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/rendezvous/RendezvousPollerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/rendezvous/RendezvousPollerImpl.java index 82bd71a46..22f781617 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/rendezvous/RendezvousPollerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/rendezvous/RendezvousPollerImpl.java @@ -143,8 +143,8 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener { } catch (DbException e) { throw new ServiceException(e); } - scheduler.scheduleWithFixedDelay(this::poll, POLLING_INTERVAL_MS, - POLLING_INTERVAL_MS, MILLISECONDS); + scheduler.scheduleWithFixedDelay(this::poll, worker, + POLLING_INTERVAL_MS, POLLING_INTERVAL_MS, MILLISECONDS); } @EventExecutor @@ -204,12 +204,10 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener { return plugin.createRendezvousEndpoint(k, cs.alice, h); } - // Scheduler + // Worker private void poll() { - worker.execute(() -> { - removeExpiredPendingContacts(); - for (PluginState ps : pluginStates.values()) poll(ps); - }); + removeExpiredPendingContacts(); + for (PluginState ps : pluginStates.values()) poll(ps); } // Worker 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 34af175b3..629f2ecd2 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,6 +3,7 @@ package org.briarproject.bramble.system; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.system.TaskScheduler; +import java.util.concurrent.Executor; import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -10,27 +11,30 @@ import java.util.concurrent.TimeUnit; import javax.annotation.concurrent.ThreadSafe; /** - * A {@link TaskScheduler} that delegates all calls to a - * {@link ScheduledExecutorService}. + * A {@link TaskScheduler} that uses a {@link ScheduledExecutorService}. */ @ThreadSafe @NotNullByDefault class TaskSchedulerImpl implements TaskScheduler { - private final ScheduledExecutorService delegate; + private final ScheduledExecutorService scheduledExecutorService; - TaskSchedulerImpl(ScheduledExecutorService delegate) { - this.delegate = delegate; + TaskSchedulerImpl(ScheduledExecutorService scheduledExecutorService) { + this.scheduledExecutorService = scheduledExecutorService; } @Override - public Future schedule(Runnable task, long delay, TimeUnit unit) { - return delegate.schedule(task, delay, unit); + public Future schedule(Runnable task, Executor executor, long delay, + TimeUnit unit) { + Runnable execute = () -> executor.execute(task); + return scheduledExecutorService.schedule(execute, delay, unit); } @Override - public Future scheduleWithFixedDelay(Runnable task, long delay, - long interval, TimeUnit unit) { - return delegate.scheduleWithFixedDelay(task, delay, interval, unit); + public Future scheduleWithFixedDelay(Runnable task, Executor executor, + long delay, long interval, TimeUnit unit) { + Runnable execute = () -> executor.execute(task); + return scheduledExecutorService.scheduleWithFixedDelay(execute, 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 b255e196f..f15fd82c7 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 @@ -6,6 +6,7 @@ import org.briarproject.bramble.api.contact.PendingContactId; import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.TransportCrypto; import org.briarproject.bramble.api.db.DatabaseComponent; +import org.briarproject.bramble.api.db.DatabaseExecutor; import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; @@ -198,17 +199,16 @@ class TransportKeyManagerImpl implements TransportKeyManager { private void scheduleKeyUpdate(long now) { long delay = timePeriodLength - now % timePeriodLength; - scheduler.schedule(this::updateKeys, delay, MILLISECONDS); + scheduler.schedule(this::updateKeys, dbExecutor, delay, MILLISECONDS); } + @DatabaseExecutor private void updateKeys() { - dbExecutor.execute(() -> { - try { - db.transaction(false, this::updateKeys); - } catch (DbException e) { - logException(LOG, WARNING, e); - } - }); + try { + db.transaction(false, this::updateKeys); + } catch (DbException e) { + logException(LOG, WARNING, e); + } } @Override 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 04cd467bd..99fb4b4ec 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 @@ -234,7 +234,8 @@ public class PollerImplTest extends BrambleMockTestCase { oneOf(clock).currentTimeMillis(); will(returnValue(now)); oneOf(scheduler).schedule(with(any(Runnable.class)), - with((long) pollingInterval), with(MILLISECONDS)); + with(ioExecutor), with((long) pollingInterval), + with(MILLISECONDS)); will(returnValue(future)); }}); @@ -262,7 +263,8 @@ public class PollerImplTest extends BrambleMockTestCase { oneOf(clock).currentTimeMillis(); will(returnValue(now)); oneOf(scheduler).schedule(with(any(Runnable.class)), - with((long) pollingInterval), with(MILLISECONDS)); + with(ioExecutor), with((long) pollingInterval), + with(MILLISECONDS)); will(returnValue(future)); // Second event // Get the plugin @@ -304,7 +306,8 @@ public class PollerImplTest extends BrambleMockTestCase { oneOf(clock).currentTimeMillis(); will(returnValue(now)); oneOf(scheduler).schedule(with(any(Runnable.class)), - with((long) pollingInterval), with(MILLISECONDS)); + with(ioExecutor), with((long) pollingInterval), + with(MILLISECONDS)); will(returnValue(future)); // Second event // Get the plugin @@ -320,7 +323,8 @@ public class PollerImplTest extends BrambleMockTestCase { will(returnValue(now + 1)); oneOf(future).cancel(false); oneOf(scheduler).schedule(with(any(Runnable.class)), - with((long) pollingInterval - 2), with(MILLISECONDS)); + with(ioExecutor), with((long) pollingInterval - 2), + with(MILLISECONDS)); }}); poller.eventOccurred(new ConnectionOpenedEvent(contactId, transportId, @@ -345,8 +349,8 @@ public class PollerImplTest extends BrambleMockTestCase { // Schedule a polling task immediately oneOf(clock).currentTimeMillis(); will(returnValue(now)); - oneOf(scheduler).schedule(with(any(Runnable.class)), with(0L), - with(MILLISECONDS)); + oneOf(scheduler).schedule(with(any(Runnable.class)), + with(ioExecutor), with(0L), with(MILLISECONDS)); will(returnValue(future)); will(new RunAction()); // Running the polling task schedules the next polling task @@ -357,7 +361,8 @@ public class PollerImplTest extends BrambleMockTestCase { oneOf(clock).currentTimeMillis(); will(returnValue(now)); oneOf(scheduler).schedule(with(any(Runnable.class)), - with((long) (pollingInterval * 0.5)), with(MILLISECONDS)); + with(ioExecutor), with((long) (pollingInterval * 0.5)), + with(MILLISECONDS)); will(returnValue(future)); // Get the transport properties and connected contacts oneOf(transportPropertyManager).getRemoteProperties(transportId); @@ -388,8 +393,8 @@ public class PollerImplTest extends BrambleMockTestCase { // Schedule a polling task immediately oneOf(clock).currentTimeMillis(); will(returnValue(now)); - oneOf(scheduler).schedule(with(any(Runnable.class)), with(0L), - with(MILLISECONDS)); + oneOf(scheduler).schedule(with(any(Runnable.class)), + with(ioExecutor), with(0L), with(MILLISECONDS)); will(returnValue(future)); will(new RunAction()); // Running the polling task schedules the next polling task @@ -400,7 +405,8 @@ public class PollerImplTest extends BrambleMockTestCase { oneOf(clock).currentTimeMillis(); will(returnValue(now)); oneOf(scheduler).schedule(with(any(Runnable.class)), - with((long) (pollingInterval * 0.5)), with(MILLISECONDS)); + with(ioExecutor), with((long) (pollingInterval * 0.5)), + with(MILLISECONDS)); will(returnValue(future)); // Get the transport properties and connected contacts oneOf(transportPropertyManager).getRemoteProperties(transportId); @@ -429,8 +435,8 @@ public class PollerImplTest extends BrambleMockTestCase { // Schedule a polling task immediately oneOf(clock).currentTimeMillis(); will(returnValue(now)); - oneOf(scheduler).schedule(with(any(Runnable.class)), with(0L), - with(MILLISECONDS)); + oneOf(scheduler).schedule(with(any(Runnable.class)), + with(ioExecutor), with(0L), with(MILLISECONDS)); will(returnValue(future)); // The plugin is deactivated before the task runs - cancel the task oneOf(future).cancel(false); @@ -454,7 +460,8 @@ public class PollerImplTest extends BrambleMockTestCase { oneOf(clock).currentTimeMillis(); will(returnValue(now)); oneOf(scheduler).schedule(with(any(Runnable.class)), - with((long) pollingInterval), with(MILLISECONDS)); + with(ioExecutor), with((long) pollingInterval), + with(MILLISECONDS)); will(returnValue(future)); }}); } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/rendezvous/RendezvousPollerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/rendezvous/RendezvousPollerImplTest.java index c7238cec3..2945455c5 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/rendezvous/RendezvousPollerImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/rendezvous/RendezvousPollerImplTest.java @@ -123,8 +123,8 @@ public class RendezvousPollerImplTest extends BrambleMockTestCase { e.getPendingContactState() == OFFLINE))); // Capture the poll task oneOf(scheduler).scheduleWithFixedDelay(with(any(Runnable.class)), - with(POLLING_INTERVAL_MS), with(POLLING_INTERVAL_MS), - with(MILLISECONDS)); + with(any(Executor.class)), with(POLLING_INTERVAL_MS), + with(POLLING_INTERVAL_MS), with(MILLISECONDS)); will(new CaptureArgumentAction<>(capturePollTask, Runnable.class, 0)); }}); @@ -159,8 +159,8 @@ public class RendezvousPollerImplTest extends BrambleMockTestCase { e.getPendingContactState() == FAILED))); // Schedule the poll task oneOf(scheduler).scheduleWithFixedDelay(with(any(Runnable.class)), - with(POLLING_INTERVAL_MS), with(POLLING_INTERVAL_MS), - with(MILLISECONDS)); + with(any(Executor.class)), with(POLLING_INTERVAL_MS), + with(POLLING_INTERVAL_MS), with(MILLISECONDS)); }}); rendezvousPoller.startService(); @@ -468,8 +468,8 @@ public class RendezvousPollerImplTest extends BrambleMockTestCase { will(returnValue(emptyList())); // Capture the poll task oneOf(scheduler).scheduleWithFixedDelay(with(any(Runnable.class)), - with(POLLING_INTERVAL_MS), with(POLLING_INTERVAL_MS), - with(MILLISECONDS)); + with(any(Executor.class)), with(POLLING_INTERVAL_MS), + with(POLLING_INTERVAL_MS), with(MILLISECONDS)); will(new CaptureArgumentAction<>(capturePollTask, Runnable.class, 0)); }}); @@ -545,8 +545,8 @@ public class RendezvousPollerImplTest extends BrambleMockTestCase { e.getPendingContactState() == OFFLINE))); // Capture the poll task oneOf(scheduler).scheduleWithFixedDelay(with(any(Runnable.class)), - with(POLLING_INTERVAL_MS), with(POLLING_INTERVAL_MS), - with(MILLISECONDS)); + with(any(Executor.class)), with(POLLING_INTERVAL_MS), + with(POLLING_INTERVAL_MS), with(MILLISECONDS)); will(new CaptureArgumentAction<>(capturePollTask, Runnable.class, 0)); }}); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/transport/TransportKeyManagerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/transport/TransportKeyManagerImplTest.java index 2c7140cd6..f5b93c82a 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/transport/TransportKeyManagerImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/transport/TransportKeyManagerImplTest.java @@ -117,7 +117,8 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase { new TransportKeySet(keySetId, contactId, null, updated))); // Schedule a key update at the start of the next time period oneOf(scheduler).schedule(with(any(Runnable.class)), - with(timePeriodLength - 1), with(MILLISECONDS)); + with(dbExecutor), with(timePeriodLength - 1), + with(MILLISECONDS)); }}); transportKeyManager.start(txn); @@ -420,9 +421,8 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase { } // Schedule a key update at the start of the next time period oneOf(scheduler).schedule(with(any(Runnable.class)), - with(timePeriodLength), with(MILLISECONDS)); - will(new RunAction()); - oneOf(dbExecutor).execute(with(any(Runnable.class))); + with(dbExecutor), with(timePeriodLength), + with(MILLISECONDS)); will(new RunAction()); // Start a transaction for updating keys oneOf(db).transaction(with(false), withDbRunnable(txn1)); @@ -445,7 +445,8 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase { new TransportKeySet(keySetId, contactId, null, updated))); // Schedule a key update at the start of the next time period oneOf(scheduler).schedule(with(any(Runnable.class)), - with(timePeriodLength), with(MILLISECONDS)); + with(dbExecutor), with(timePeriodLength), + with(MILLISECONDS)); }}); transportKeyManager.start(txn); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java index b8ba76a9e..4e094b782 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java @@ -28,7 +28,7 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory; import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory; import org.briarproject.bramble.api.reporting.DevConfig; import org.briarproject.bramble.api.system.AndroidExecutor; -import org.briarproject.bramble.api.system.AndroidWakeLockFactory; +import org.briarproject.bramble.api.system.AndroidWakeLockManager; import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.ResourceProvider; @@ -135,17 +135,17 @@ public class AppModule { ResourceProvider resourceProvider, CircumventionProvider circumventionProvider, BatteryManager batteryManager, - AndroidWakeLockFactory wakeLockFactory, + AndroidWakeLockManager wakeLockManager, Clock clock, TimeoutMonitor timeoutMonitor) { Context appContext = app.getApplicationContext(); DuplexPluginFactory bluetooth = new AndroidBluetoothPluginFactory( - ioExecutor, androidExecutor, wakeLockFactory, appContext, + ioExecutor, androidExecutor, wakeLockManager, appContext, random, eventBus, clock, timeoutMonitor, backoffFactory); DuplexPluginFactory tor = new AndroidTorPluginFactory(ioExecutor, appContext, networkManager, locationUtils, eventBus, torSocketFactory, backoffFactory, resourceProvider, - circumventionProvider, batteryManager, wakeLockFactory, clock); + circumventionProvider, batteryManager, wakeLockManager, clock); DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor, eventBus, backoffFactory, appContext); Collection duplex = asList(bluetooth, tor, lan); diff --git a/briar-core/src/main/java/org/briarproject/briar/feed/FeedManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/feed/FeedManagerImpl.java index 2b21060ec..713e2c090 100644 --- a/briar-core/src/main/java/org/briarproject/briar/feed/FeedManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/feed/FeedManagerImpl.java @@ -146,9 +146,8 @@ class FeedManagerImpl implements FeedManager, EventListener, OpenDatabaseHook, private void startFeedExecutor() { if (fetcherStarted.getAndSet(true)) return; LOG.info("Tor started, scheduling RSS feed fetcher"); - Runnable fetcher = () -> ioExecutor.execute(this::fetchFeeds); - scheduler.scheduleWithFixedDelay(fetcher, FETCH_DELAY_INITIAL, - FETCH_INTERVAL, FETCH_UNIT); + scheduler.scheduleWithFixedDelay(this::fetchFeeds, ioExecutor, + FETCH_DELAY_INITIAL, FETCH_INTERVAL, FETCH_UNIT); } @Override @@ -471,6 +470,7 @@ class FeedManagerImpl implements FeedManager, EventListener, OpenDatabaseHook, if (date == null) time = now; else time = Math.max(0, Math.min(date.getTime(), now)); String text = getPostText(b.toString()); + //noinspection TryWithIdenticalCatches try { // create and store post LocalAuthor localAuthor = feed.getLocalAuthor();