diff --git a/bramble-android/src/main/java/org/briarproject/bramble/api/system/AndroidWakeLock.java b/bramble-android/src/main/java/org/briarproject/bramble/api/system/AndroidWakeLock.java new file mode 100644 index 000000000..307a86086 --- /dev/null +++ b/bramble-android/src/main/java/org/briarproject/bramble/api/system/AndroidWakeLock.java @@ -0,0 +1,19 @@ +package org.briarproject.bramble.api.system; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +@NotNullByDefault +public interface AndroidWakeLock { + + /** + * Acquires the wake lock. This has no effect if the wake lock has already + * been acquired. + */ + void acquire(); + + /** + * Releases the wake lock. This has no effect if the wake lock has already + * been released. + */ + void release(); +} 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 new file mode 100644 index 000000000..7d7be15d0 --- /dev/null +++ b/bramble-android/src/main/java/org/briarproject/bramble/api/system/AndroidWakeLockFactory.java @@ -0,0 +1,9 @@ +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/plugin/bluetooth/AndroidBluetoothConnectionFactory.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothConnectionFactory.java new file mode 100644 index 000000000..61d543414 --- /dev/null +++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothConnectionFactory.java @@ -0,0 +1,36 @@ +package org.briarproject.bramble.plugin.bluetooth; + +import android.bluetooth.BluetoothSocket; + +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 java.io.IOException; + +@NotNullByDefault +class AndroidBluetoothConnectionFactory + implements BluetoothConnectionFactory { + + private final BluetoothConnectionLimiter connectionLimiter; + private final AndroidWakeLockFactory wakeLockFactory; + private final TimeoutMonitor timeoutMonitor; + + AndroidBluetoothConnectionFactory( + BluetoothConnectionLimiter connectionLimiter, + AndroidWakeLockFactory wakeLockFactory, + TimeoutMonitor timeoutMonitor) { + this.connectionLimiter = connectionLimiter; + this.wakeLockFactory = wakeLockFactory; + this.timeoutMonitor = timeoutMonitor; + } + + @Override + public DuplexTransportConnection wrapSocket(DuplexPlugin plugin, + BluetoothSocket s) throws IOException { + return new AndroidBluetoothTransportConnection(plugin, + connectionLimiter, wakeLockFactory, timeoutMonitor, s); + } +} diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPlugin.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPlugin.java index 5c51b4c61..68df9233a 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPlugin.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPlugin.java @@ -9,7 +9,6 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import org.briarproject.bramble.api.io.TimeoutMonitor; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.bramble.api.plugin.Backoff; @@ -18,7 +17,6 @@ import org.briarproject.bramble.api.plugin.PluginException; import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection; import org.briarproject.bramble.api.system.AndroidExecutor; import org.briarproject.bramble.api.system.Clock; -import org.briarproject.bramble.api.system.TaskScheduler; import org.briarproject.bramble.util.AndroidUtils; import org.briarproject.bramble.util.IoUtils; @@ -60,14 +58,14 @@ import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress; @MethodsNotNullByDefault @ParametersNotNullByDefault -class AndroidBluetoothPlugin extends BluetoothPlugin { +class AndroidBluetoothPlugin + extends BluetoothPlugin { private static final Logger LOG = getLogger(AndroidBluetoothPlugin.class.getName()); private static final int MAX_DISCOVERY_MS = 10_000; - private final TaskScheduler scheduler; private final AndroidExecutor androidExecutor; private final Context appContext; private final Clock clock; @@ -79,10 +77,9 @@ class AndroidBluetoothPlugin extends BluetoothPlugin { private volatile BluetoothAdapter adapter = null; AndroidBluetoothPlugin(BluetoothConnectionLimiter connectionLimiter, - TimeoutMonitor timeoutMonitor, + BluetoothConnectionFactory connectionFactory, Executor ioExecutor, SecureRandom secureRandom, - TaskScheduler scheduler, AndroidExecutor androidExecutor, Context appContext, Clock clock, @@ -90,9 +87,8 @@ class AndroidBluetoothPlugin extends BluetoothPlugin { PluginCallback callback, int maxLatency, int maxIdleTime) { - super(connectionLimiter, timeoutMonitor, ioExecutor, secureRandom, + super(connectionLimiter, connectionFactory, ioExecutor, secureRandom, backoff, callback, maxLatency, maxIdleTime); - this.scheduler = scheduler; this.androidExecutor = androidExecutor; this.appContext = appContext; this.clock = clock; @@ -187,13 +183,7 @@ class AndroidBluetoothPlugin extends BluetoothPlugin { @Override DuplexTransportConnection acceptConnection(BluetoothServerSocket ss) throws IOException { - return wrapSocket(ss.accept()); - } - - private DuplexTransportConnection wrapSocket(BluetoothSocket s) - throws IOException { - return new AndroidBluetoothTransportConnection(this, connectionLimiter, - timeoutMonitor, appContext, scheduler, s); + return connectionFactory.wrapSocket(this, ss.accept()); } @Override @@ -210,7 +200,7 @@ class AndroidBluetoothPlugin extends BluetoothPlugin { try { s = d.createInsecureRfcommSocketToServiceRecord(u); s.connect(); - return wrapSocket(s); + return connectionFactory.wrapSocket(this, s); } catch (IOException e) { IoUtils.tryToClose(s, LOG, WARNING); throw e; 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 265a98339..590117345 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 @@ -1,5 +1,6 @@ package org.briarproject.bramble.plugin.bluetooth; +import android.bluetooth.BluetoothSocket; import android.content.Context; import org.briarproject.bramble.api.event.EventBus; @@ -12,8 +13,8 @@ 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.Clock; -import org.briarproject.bramble.api.system.TaskScheduler; import java.security.SecureRandom; import java.util.concurrent.Executor; @@ -33,8 +34,8 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory { private static final double BACKOFF_BASE = 1.2; private final Executor ioExecutor; - private final TaskScheduler scheduler; private final AndroidExecutor androidExecutor; + private final AndroidWakeLockFactory wakeLockFactory; private final Context appContext; private final SecureRandom secureRandom; private final EventBus eventBus; @@ -43,8 +44,8 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory { private final BackoffFactory backoffFactory; public AndroidBluetoothPluginFactory(Executor ioExecutor, - TaskScheduler scheduler, AndroidExecutor androidExecutor, + AndroidWakeLockFactory wakeLockFactory, Context appContext, SecureRandom secureRandom, EventBus eventBus, @@ -52,8 +53,8 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory { TimeoutMonitor timeoutMonitor, BackoffFactory backoffFactory) { this.ioExecutor = ioExecutor; - this.scheduler = scheduler; this.androidExecutor = androidExecutor; + this.wakeLockFactory = wakeLockFactory; this.appContext = appContext; this.secureRandom = secureRandom; this.eventBus = eventBus; @@ -76,12 +77,15 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory { public DuplexPlugin createPlugin(PluginCallback callback) { BluetoothConnectionLimiter connectionLimiter = new BluetoothConnectionLimiterImpl(eventBus); + BluetoothConnectionFactory connectionFactory = + new AndroidBluetoothConnectionFactory(connectionLimiter, + wakeLockFactory, timeoutMonitor); Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, MAX_POLLING_INTERVAL, BACKOFF_BASE); AndroidBluetoothPlugin plugin = new AndroidBluetoothPlugin( - connectionLimiter, timeoutMonitor, ioExecutor, secureRandom, - scheduler, androidExecutor, appContext, clock, backoff, - callback, MAX_LATENCY, MAX_IDLE_TIME); + connectionLimiter, connectionFactory, ioExecutor, secureRandom, + androidExecutor, appContext, clock, backoff, callback, + MAX_LATENCY, MAX_IDLE_TIME); eventBus.addListener(plugin); return plugin; } 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 7a82ff8a3..ad0f4f038 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 @@ -1,26 +1,19 @@ package org.briarproject.bramble.plugin.bluetooth; import android.bluetooth.BluetoothSocket; -import android.content.Context; -import android.os.PowerManager; import org.briarproject.bramble.api.io.TimeoutMonitor; 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.TaskScheduler; -import org.briarproject.bramble.util.RenewableWakeLock; +import org.briarproject.bramble.api.system.AndroidWakeLock; +import org.briarproject.bramble.api.system.AndroidWakeLockFactory; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import static android.content.Context.POWER_SERVICE; -import static android.os.PowerManager.PARTIAL_WAKE_LOCK; -import static java.util.concurrent.TimeUnit.MINUTES; -import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull; import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_ADDRESS; -import static org.briarproject.bramble.util.AndroidUtils.getWakeLockTag; import static org.briarproject.bramble.util.AndroidUtils.isValidBluetoothAddress; @NotNullByDefault @@ -28,26 +21,21 @@ class AndroidBluetoothTransportConnection extends AbstractDuplexTransportConnection { private final BluetoothConnectionLimiter connectionLimiter; - private final RenewableWakeLock wakeLock; private final BluetoothSocket socket; private final InputStream in; + private final AndroidWakeLock wakeLock; AndroidBluetoothTransportConnection(Plugin plugin, BluetoothConnectionLimiter connectionLimiter, + AndroidWakeLockFactory wakeLockFactory, TimeoutMonitor timeoutMonitor, - Context appContext, - TaskScheduler scheduler, BluetoothSocket socket) throws IOException { super(plugin); this.connectionLimiter = connectionLimiter; this.socket = socket; in = timeoutMonitor.createTimeoutInputStream( socket.getInputStream(), plugin.getMaxIdleTime() * 2); - PowerManager powerManager = (PowerManager) - requireNonNull(appContext.getSystemService(POWER_SERVICE)); - String tag = getWakeLockTag(appContext); - wakeLock = new RenewableWakeLock(powerManager, scheduler, - PARTIAL_WAKE_LOCK, tag, 1, MINUTES); + wakeLock = wakeLockFactory.createWakeLock(); 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 4f8b01b09..391416019 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 @@ -4,7 +4,6 @@ import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; -import android.os.PowerManager; import org.briarproject.bramble.api.battery.BatteryManager; import org.briarproject.bramble.api.network.NetworkManager; @@ -12,11 +11,11 @@ import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; 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.Clock; import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.ResourceProvider; -import org.briarproject.bramble.api.system.TaskScheduler; -import org.briarproject.bramble.util.RenewableWakeLock; import java.io.IOException; import java.util.concurrent.Executor; @@ -24,20 +23,15 @@ import java.util.concurrent.Executor; import javax.net.SocketFactory; import static android.content.Context.MODE_PRIVATE; -import static android.content.Context.POWER_SERVICE; -import static android.os.PowerManager.PARTIAL_WAKE_LOCK; -import static java.util.concurrent.TimeUnit.MINUTES; -import static org.briarproject.bramble.util.AndroidUtils.getWakeLockTag; @MethodsNotNullByDefault @ParametersNotNullByDefault class AndroidTorPlugin extends TorPlugin { private final Context appContext; - private final RenewableWakeLock wakeLock; + private final AndroidWakeLock wakeLock; AndroidTorPlugin(Executor ioExecutor, - TaskScheduler scheduler, Context appContext, NetworkManager networkManager, LocationUtils locationUtils, @@ -46,6 +40,7 @@ class AndroidTorPlugin extends TorPlugin { ResourceProvider resourceProvider, CircumventionProvider circumventionProvider, BatteryManager batteryManager, + AndroidWakeLockFactory wakeLockFactory, Backoff backoff, TorRendezvousCrypto torRendezvousCrypto, PluginCallback callback, @@ -58,11 +53,7 @@ class AndroidTorPlugin extends TorPlugin { maxLatency, maxIdleTime, appContext.getDir("tor", MODE_PRIVATE)); this.appContext = appContext; - PowerManager pm = (PowerManager) - appContext.getSystemService(POWER_SERVICE); - if (pm == null) throw new AssertionError(); - wakeLock = new RenewableWakeLock(pm, scheduler, PARTIAL_WAKE_LOCK, - getWakeLockTag(appContext), 1, MINUTES); + wakeLock = wakeLockFactory.createWakeLock(); } @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 71482e1f2..7f477a4d5 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,10 +13,10 @@ 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.Clock; import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.ResourceProvider; -import org.briarproject.bramble.api.system.TaskScheduler; import org.briarproject.bramble.util.AndroidUtils; import java.util.concurrent.Executor; @@ -39,7 +39,6 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory { private static final double BACKOFF_BASE = 1.2; private final Executor ioExecutor; - private final TaskScheduler scheduler; private final Context appContext; private final NetworkManager networkManager; private final LocationUtils locationUtils; @@ -49,10 +48,10 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory { private final ResourceProvider resourceProvider; private final CircumventionProvider circumventionProvider; private final BatteryManager batteryManager; + private final AndroidWakeLockFactory wakeLockFactory; private final Clock clock; public AndroidTorPluginFactory(Executor ioExecutor, - TaskScheduler scheduler, Context appContext, NetworkManager networkManager, LocationUtils locationUtils, @@ -62,9 +61,9 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory { ResourceProvider resourceProvider, CircumventionProvider circumventionProvider, BatteryManager batteryManager, + AndroidWakeLockFactory wakeLockFactory, Clock clock) { this.ioExecutor = ioExecutor; - this.scheduler = scheduler; this.appContext = appContext; this.networkManager = networkManager; this.locationUtils = locationUtils; @@ -74,6 +73,7 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory { this.resourceProvider = resourceProvider; this.circumventionProvider = circumventionProvider; this.batteryManager = batteryManager; + this.wakeLockFactory = wakeLockFactory; this.clock = clock; } @@ -117,11 +117,11 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory { Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, MAX_POLLING_INTERVAL, BACKOFF_BASE); TorRendezvousCrypto torRendezvousCrypto = new TorRendezvousCryptoImpl(); - AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor, scheduler, + AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor, appContext, networkManager, locationUtils, torSocketFactory, clock, resourceProvider, circumventionProvider, batteryManager, - backoff, torRendezvousCrypto, callback, architecture, - MAX_LATENCY, MAX_IDLE_TIME); + wakeLockFactory, 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 89bf2a321..b18b99d26 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 @@ -2,6 +2,7 @@ package org.briarproject.bramble.system; import org.briarproject.bramble.api.event.EventExecutor; import org.briarproject.bramble.api.system.AndroidExecutor; +import org.briarproject.bramble.api.system.AndroidWakeLockFactory; import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.ResourceProvider; import org.briarproject.bramble.api.system.SecureRandomProvider; @@ -47,4 +48,11 @@ public class AndroidSystemModule { ResourceProvider provideResourceProvider(AndroidResourceProvider provider) { return provider; } + + @Provides + @Singleton + AndroidWakeLockFactory provideWakeLockFactory( + AndroidWakeLockFactoryImpl wakeLockFactory) { + return wakeLockFactory; + } } diff --git a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidWakeLockFactoryImpl.java b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidWakeLockFactoryImpl.java new file mode 100644 index 000000000..f1e7acf8f --- /dev/null +++ b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidWakeLockFactoryImpl.java @@ -0,0 +1,64 @@ +package org.briarproject.bramble.system; + +import android.app.Application; +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +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 javax.inject.Inject; + +import static android.content.Context.POWER_SERVICE; +import static android.os.PowerManager.PARTIAL_WAKE_LOCK; +import static java.util.concurrent.TimeUnit.MINUTES; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull; + +@NotNullByDefault +class AndroidWakeLockFactoryImpl implements AndroidWakeLockFactory { + + /** + * How often to replace the wake lock. + */ + private static final long LOCK_DURATION_MS = MINUTES.toMillis(1); + + /** + * Automatically release the lock this many milliseconds after it's due + * to have been replaced and released. + */ + private static final long SAFETY_MARGIN_MS = SECONDS.toMillis(30); + + private final SharedWakeLock sharedWakeLock; + + @Inject + AndroidWakeLockFactoryImpl(TaskScheduler scheduler, Application app) { + 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); + } + + @Override + public AndroidWakeLock createWakeLock() { + return new AndroidWakeLockImpl(sharedWakeLock); + } + + private String getWakeLockTag(Context ctx) { + PackageManager pm = ctx.getPackageManager(); + for (PackageInfo info : pm.getInstalledPackages(0)) { + String name = info.packageName.toLowerCase(); + if (name.startsWith("com.huawei.powergenie")) { + return "LocationManagerService"; + } else if (name.startsWith("com.evenwell.powermonitor")) { + return "AudioIn"; + } + } + return ctx.getPackageName(); + } +} 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 new file mode 100644 index 000000000..d3d9a7c4b --- /dev/null +++ b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidWakeLockImpl.java @@ -0,0 +1,46 @@ +package org.briarproject.bramble.system; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.bramble.api.system.AndroidWakeLock; + +import javax.annotation.concurrent.GuardedBy; +import javax.annotation.concurrent.ThreadSafe; + +/** + * A wrapper around a {@link SharedWakeLock} that provides the more convenient + * semantics of {@link AndroidWakeLock} (i.e. calls to acquire() and release() + * don't need to be balanced). + */ +@ThreadSafe +@NotNullByDefault +class AndroidWakeLockImpl implements AndroidWakeLock { + + private final SharedWakeLock sharedWakeLock; + private final Object lock = new Object(); + @GuardedBy("lock") + private boolean held = false; + + AndroidWakeLockImpl(SharedWakeLock sharedWakeLock) { + this.sharedWakeLock = sharedWakeLock; + } + + @Override + public void acquire() { + synchronized (lock) { + if (!held) { + held = true; + sharedWakeLock.acquire(); + } + } + } + + @Override + public void release() { + synchronized (lock) { + if (held) { + held = false; + sharedWakeLock.release(); + } + } + } +} 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 new file mode 100644 index 000000000..c47a8dfb9 --- /dev/null +++ b/bramble-android/src/main/java/org/briarproject/bramble/system/RenewableWakeLock.java @@ -0,0 +1,118 @@ +package org.briarproject.bramble.system; + +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.logging.Logger; + +import javax.annotation.Nullable; +import javax.annotation.concurrent.GuardedBy; +import javax.annotation.concurrent.ThreadSafe; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.logging.Level.INFO; +import static java.util.logging.Level.WARNING; +import static java.util.logging.Logger.getLogger; +import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull; + +@ThreadSafe +@NotNullByDefault +class RenewableWakeLock implements SharedWakeLock { + + private static final Logger LOG = + getLogger(RenewableWakeLock.class.getName()); + + private final PowerManager powerManager; + private final TaskScheduler scheduler; + private final int levelAndFlags; + private final String tag; + private final long durationMs, safetyMarginMs; + + private final Object lock = new Object(); + @GuardedBy("lock") + @Nullable + private WakeLock wakeLock; + @GuardedBy("lock") + @Nullable + private Future future; + @GuardedBy("lock") + private int refCount = 0; + @GuardedBy("lock") + private long acquired = 0; + + RenewableWakeLock(PowerManager powerManager, TaskScheduler scheduler, + int levelAndFlags, String tag, long durationMs, + long safetyMarginMs) { + this.powerManager = powerManager; + this.scheduler = scheduler; + this.levelAndFlags = levelAndFlags; + this.tag = tag; + this.durationMs = durationMs; + this.safetyMarginMs = safetyMarginMs; + } + + @Override + public void acquire() { + synchronized (lock) { + refCount++; + if (refCount == 1) { + if (LOG.isLoggable(INFO)) { + LOG.info("Acquiring wake lock " + tag); + } + wakeLock = powerManager.newWakeLock(levelAndFlags, tag); + // We do our own reference counting so we can replace the lock + // TODO: Check whether using a ref-counted wake lock affects + // power management apps + wakeLock.setReferenceCounted(false); + wakeLock.acquire(durationMs + safetyMarginMs); + future = scheduler.schedule(this::renew, durationMs, + MILLISECONDS); + acquired = android.os.SystemClock.elapsedRealtime(); + } + } + } + + private void renew() { + if (LOG.isLoggable(INFO)) LOG.info("Renewing wake lock " + tag); + synchronized (lock) { + if (wakeLock == null) { + LOG.info("Already released"); + return; + } + long now = android.os.SystemClock.elapsedRealtime(); + long expiry = acquired + durationMs + safetyMarginMs; + if (now > expiry && LOG.isLoggable(WARNING)) { + LOG.warning("Wake lock expired " + (now - expiry) + " ms ago"); + } + WakeLock oldWakeLock = wakeLock; + wakeLock = powerManager.newWakeLock(levelAndFlags, tag); + wakeLock.setReferenceCounted(false); + wakeLock.acquire(durationMs + safetyMarginMs); + oldWakeLock.release(); + future = scheduler.schedule(this::renew, durationMs, MILLISECONDS); + acquired = now; + } + } + + @Override + public void release() { + synchronized (lock) { + refCount--; + if (refCount == 0) { + if (LOG.isLoggable(INFO)) { + LOG.info("Releasing wake lock " + tag); + } + requireNonNull(future).cancel(false); + future = null; + requireNonNull(wakeLock).release(); + wakeLock = null; + acquired = 0; + } + } + } +} + diff --git a/bramble-android/src/main/java/org/briarproject/bramble/system/SharedWakeLock.java b/bramble-android/src/main/java/org/briarproject/bramble/system/SharedWakeLock.java new file mode 100644 index 000000000..db0a07043 --- /dev/null +++ b/bramble-android/src/main/java/org/briarproject/bramble/system/SharedWakeLock.java @@ -0,0 +1,22 @@ +package org.briarproject.bramble.system; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.bramble.api.system.AndroidWakeLock; + +@NotNullByDefault +interface SharedWakeLock { + + /** + * Acquires the wake lock. This increments the wake lock's reference count, + * so unlike {@link AndroidWakeLock#acquire()} every call to this method + * must be followed by a balancing call to {@link #release()}. + */ + void acquire(); + + /** + * Releases the wake lock. This decrements the wake lock's reference count, + * so unlike {@link AndroidWakeLock#release()} every call to this method + * must follow a balancing call to {@link #acquire()}. + */ + void release(); +} diff --git a/bramble-android/src/main/java/org/briarproject/bramble/util/AndroidUtils.java b/bramble-android/src/main/java/org/briarproject/bramble/util/AndroidUtils.java index 00ee3ea19..4d5c8ea13 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/util/AndroidUtils.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/util/AndroidUtils.java @@ -3,8 +3,6 @@ package org.briarproject.bramble.util; import android.annotation.SuppressLint; import android.bluetooth.BluetoothAdapter; import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; import android.os.Build; import android.provider.Settings; @@ -119,17 +117,4 @@ public class AndroidUtils { if (SDK_INT < 24) return new String[] {"image/jpeg", "image/png"}; else return new String[] {"image/jpeg", "image/png", "image/gif"}; } - - public static String getWakeLockTag(Context ctx) { - PackageManager pm = ctx.getPackageManager(); - for (PackageInfo info : pm.getInstalledPackages(0)) { - String name = info.packageName.toLowerCase(); - if (name.startsWith("com.huawei.powergenie")) { - return "LocationManagerService"; - } else if (name.startsWith("com.evenwell.powermonitor")) { - return "AudioIn"; - } - } - return ctx.getPackageName(); - } } 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 deleted file mode 100644 index 68ed14f72..000000000 --- a/bramble-android/src/main/java/org/briarproject/bramble/util/RenewableWakeLock.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.briarproject.bramble.util; - -import android.os.PowerManager; - -import org.briarproject.bramble.api.nullsafety.NotNullByDefault; -import org.briarproject.bramble.api.system.TaskScheduler; - -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.logging.Logger; - -import javax.annotation.Nullable; -import javax.annotation.concurrent.ThreadSafe; - -import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static java.util.logging.Level.INFO; - -@ThreadSafe -@NotNullByDefault -public class RenewableWakeLock { - - private static final Logger LOG = - Logger.getLogger(RenewableWakeLock.class.getName()); - - /** - * Automatically release the lock this many milliseconds after it's due - * to have been replaced and released. - */ - private static final int SAFETY_MARGIN_MS = 10_000; - - private final PowerManager powerManager; - private final TaskScheduler scheduler; - private final int levelAndFlags; - private final String tag; - private final long durationMs; - private final Runnable renewTask; - - private final Object lock = new Object(); - @Nullable - private PowerManager.WakeLock wakeLock; // Locking: lock - @Nullable - private Future future; // Locking: lock - - public RenewableWakeLock(PowerManager powerManager, - TaskScheduler scheduler, int levelAndFlags, String tag, - long duration, TimeUnit timeUnit) { - this.powerManager = powerManager; - this.scheduler = scheduler; - this.levelAndFlags = levelAndFlags; - this.tag = tag; - durationMs = MILLISECONDS.convert(duration, timeUnit); - renewTask = this::renew; - } - - public void acquire() { - if (LOG.isLoggable(INFO)) LOG.info("Acquiring wake lock " + tag); - synchronized (lock) { - if (wakeLock != null) { - LOG.info("Already acquired"); - return; - } - wakeLock = powerManager.newWakeLock(levelAndFlags, tag); - wakeLock.setReferenceCounted(false); - wakeLock.acquire(durationMs + SAFETY_MARGIN_MS); - future = scheduler.schedule(renewTask, durationMs, MILLISECONDS); - } - } - - private void renew() { - if (LOG.isLoggable(INFO)) LOG.info("Renewing wake lock " + tag); - synchronized (lock) { - if (wakeLock == null) { - LOG.info("Already released"); - return; - } - PowerManager.WakeLock oldWakeLock = wakeLock; - wakeLock = powerManager.newWakeLock(levelAndFlags, tag); - wakeLock.setReferenceCounted(false); - wakeLock.acquire(durationMs + SAFETY_MARGIN_MS); - oldWakeLock.release(); - future = scheduler.schedule(renewTask, durationMs, MILLISECONDS); - } - } - - public void release() { - if (LOG.isLoggable(INFO)) LOG.info("Releasing wake lock " + tag); - synchronized (lock) { - if (wakeLock == null) { - LOG.info("Already released"); - return; - } - if (future == null) throw new AssertionError(); - future.cancel(false); - future = null; - wakeLock.release(); - wakeLock = null; - } - } -} - diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothConnectionFactory.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothConnectionFactory.java new file mode 100644 index 000000000..27689f979 --- /dev/null +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothConnectionFactory.java @@ -0,0 +1,14 @@ +package org.briarproject.bramble.plugin.bluetooth; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin; +import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection; + +import java.io.IOException; + +@NotNullByDefault +interface BluetoothConnectionFactory { + + DuplexTransportConnection wrapSocket(DuplexPlugin plugin, S socket) + throws IOException; +} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java index 956dc293b..160368152 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java @@ -6,7 +6,6 @@ import org.briarproject.bramble.api.Pair; import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.event.EventListener; -import org.briarproject.bramble.api.io.TimeoutMonitor; import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection; import org.briarproject.bramble.api.keyagreement.KeyAgreementListener; import org.briarproject.bramble.api.keyagreement.event.KeyAgreementListeningEvent; @@ -70,13 +69,13 @@ import static org.briarproject.bramble.util.StringUtils.macToString; @MethodsNotNullByDefault @ParametersNotNullByDefault -abstract class BluetoothPlugin implements DuplexPlugin, EventListener { +abstract class BluetoothPlugin implements DuplexPlugin, EventListener { private static final Logger LOG = getLogger(BluetoothPlugin.class.getName()); final BluetoothConnectionLimiter connectionLimiter; - final TimeoutMonitor timeoutMonitor; + final BluetoothConnectionFactory connectionFactory; private final Executor ioExecutor; private final SecureRandom secureRandom; @@ -123,11 +122,15 @@ abstract class BluetoothPlugin implements DuplexPlugin, EventListener { abstract DuplexTransportConnection discoverAndConnect(String uuid); BluetoothPlugin(BluetoothConnectionLimiter connectionLimiter, - TimeoutMonitor timeoutMonitor, Executor ioExecutor, - SecureRandom secureRandom, Backoff backoff, - PluginCallback callback, int maxLatency, int maxIdleTime) { + BluetoothConnectionFactory connectionFactory, + Executor ioExecutor, + SecureRandom secureRandom, + Backoff backoff, + PluginCallback callback, + int maxLatency, + int maxIdleTime) { this.connectionLimiter = connectionLimiter; - this.timeoutMonitor = timeoutMonitor; + this.connectionFactory = connectionFactory; this.ioExecutor = ioExecutor; this.secureRandom = secureRandom; this.backoff = backoff; diff --git a/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothConnectionFactory.java b/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothConnectionFactory.java new file mode 100644 index 000000000..50f1514f2 --- /dev/null +++ b/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothConnectionFactory.java @@ -0,0 +1,34 @@ +package org.briarproject.bramble.plugin.bluetooth; + +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 java.io.IOException; + +import javax.annotation.concurrent.Immutable; +import javax.microedition.io.StreamConnection; + +@Immutable +@NotNullByDefault +class JavaBluetoothConnectionFactory + implements BluetoothConnectionFactory { + + private final BluetoothConnectionLimiter connectionLimiter; + private final TimeoutMonitor timeoutMonitor; + + JavaBluetoothConnectionFactory( + BluetoothConnectionLimiter connectionLimiter, + TimeoutMonitor timeoutMonitor) { + this.connectionLimiter = connectionLimiter; + this.timeoutMonitor = timeoutMonitor; + } + + @Override + public DuplexTransportConnection wrapSocket(DuplexPlugin plugin, + StreamConnection socket) throws IOException { + return new JavaBluetoothTransportConnection(plugin, connectionLimiter, + timeoutMonitor, socket); + } +} diff --git a/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothPlugin.java b/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothPlugin.java index ff9b7ee79..9115900ad 100644 --- a/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothPlugin.java +++ b/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothPlugin.java @@ -1,6 +1,5 @@ package org.briarproject.bramble.plugin.bluetooth; -import org.briarproject.bramble.api.io.TimeoutMonitor; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.bramble.api.plugin.Backoff; @@ -26,7 +25,8 @@ import static org.briarproject.bramble.util.StringUtils.isValidMac; @MethodsNotNullByDefault @ParametersNotNullByDefault -class JavaBluetoothPlugin extends BluetoothPlugin { +class JavaBluetoothPlugin + extends BluetoothPlugin { private static final Logger LOG = getLogger(JavaBluetoothPlugin.class.getName()); @@ -35,10 +35,10 @@ class JavaBluetoothPlugin extends BluetoothPlugin { private volatile LocalDevice localDevice = null; JavaBluetoothPlugin(BluetoothConnectionLimiter connectionManager, - TimeoutMonitor timeoutMonitor, Executor ioExecutor, - SecureRandom secureRandom, Backoff backoff, + BluetoothConnectionFactory connectionFactory, + Executor ioExecutor, SecureRandom secureRandom, Backoff backoff, PluginCallback callback, int maxLatency, int maxIdleTime) { - super(connectionManager, timeoutMonitor, ioExecutor, secureRandom, + super(connectionManager, connectionFactory, ioExecutor, secureRandom, backoff, callback, maxLatency, maxIdleTime); } @@ -96,7 +96,7 @@ class JavaBluetoothPlugin extends BluetoothPlugin { @Override DuplexTransportConnection acceptConnection(StreamConnectionNotifier ss) throws IOException { - return wrapSocket(ss.acceptAndOpen()); + return connectionFactory.wrapSocket(this, ss.acceptAndOpen()); } @Override @@ -108,7 +108,8 @@ class JavaBluetoothPlugin extends BluetoothPlugin { DuplexTransportConnection connectTo(String address, String uuid) throws IOException { String url = makeUrl(address, uuid); - return wrapSocket((StreamConnection) Connector.open(url)); + StreamConnection s = (StreamConnection) Connector.open(url); + return connectionFactory.wrapSocket(this, s); } @Override @@ -120,10 +121,4 @@ class JavaBluetoothPlugin extends BluetoothPlugin { private String makeUrl(String address, String uuid) { return "btspp://" + address + ":" + uuid + ";name=RFCOMM"; } - - private DuplexTransportConnection wrapSocket(StreamConnection s) - throws IOException { - return new JavaBluetoothTransportConnection(this, connectionLimiter, - timeoutMonitor, s); - } } diff --git a/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothPluginFactory.java b/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothPluginFactory.java index c931061cd..4f1bb93fd 100644 --- a/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothPluginFactory.java +++ b/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothPluginFactory.java @@ -14,6 +14,7 @@ import java.security.SecureRandom; import java.util.concurrent.Executor; import javax.annotation.concurrent.Immutable; +import javax.microedition.io.StreamConnection; import static org.briarproject.bramble.api.plugin.BluetoothConstants.ID; @@ -57,10 +58,13 @@ public class JavaBluetoothPluginFactory implements DuplexPluginFactory { public DuplexPlugin createPlugin(PluginCallback callback) { BluetoothConnectionLimiter connectionLimiter = new BluetoothConnectionLimiterImpl(eventBus); + BluetoothConnectionFactory connectionFactory = + new JavaBluetoothConnectionFactory(connectionLimiter, + timeoutMonitor); Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, MAX_POLLING_INTERVAL, BACKOFF_BASE); JavaBluetoothPlugin plugin = new JavaBluetoothPlugin(connectionLimiter, - timeoutMonitor, ioExecutor, secureRandom, backoff, callback, + connectionFactory, ioExecutor, secureRandom, backoff, callback, MAX_LATENCY, MAX_IDLE_TIME); eventBus.addListener(plugin); return plugin; diff --git a/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothTransportConnection.java b/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothTransportConnection.java index 319d9af76..2ac917c7b 100644 --- a/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothTransportConnection.java +++ b/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothTransportConnection.java @@ -16,18 +16,20 @@ class JavaBluetoothTransportConnection extends AbstractDuplexTransportConnection { private final BluetoothConnectionLimiter connectionLimiter; - private final StreamConnection stream; + private final StreamConnection socket; private final InputStream in; + private final OutputStream out; JavaBluetoothTransportConnection(Plugin plugin, BluetoothConnectionLimiter connectionLimiter, TimeoutMonitor timeoutMonitor, - StreamConnection stream) throws IOException { + StreamConnection socket) throws IOException { super(plugin); this.connectionLimiter = connectionLimiter; - this.stream = stream; + this.socket = socket; in = timeoutMonitor.createTimeoutInputStream( - stream.openInputStream(), plugin.getMaxIdleTime() * 2); + socket.openInputStream(), plugin.getMaxIdleTime() * 2); + out = socket.openOutputStream(); } @Override @@ -36,14 +38,14 @@ class JavaBluetoothTransportConnection } @Override - protected OutputStream getOutputStream() throws IOException { - return stream.openOutputStream(); + protected OutputStream getOutputStream() { + return out; } @Override protected void closeConnection(boolean exception) throws IOException { try { - stream.close(); + socket.close(); } finally { connectionLimiter.connectionClosed(this); } 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 f16773b4d..b8ba76a9e 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,10 +28,10 @@ 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.Clock; import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.ResourceProvider; -import org.briarproject.bramble.api.system.TaskScheduler; import org.briarproject.bramble.plugin.bluetooth.AndroidBluetoothPluginFactory; import org.briarproject.bramble.plugin.tcp.AndroidLanTcpPluginFactory; import org.briarproject.bramble.plugin.tor.AndroidTorPluginFactory; @@ -124,7 +124,6 @@ public class AppModule { @Provides PluginConfig providePluginConfig(@IoExecutor Executor ioExecutor, - TaskScheduler scheduler, AndroidExecutor androidExecutor, SecureRandom random, SocketFactory torSocketFactory, @@ -136,16 +135,17 @@ public class AppModule { ResourceProvider resourceProvider, CircumventionProvider circumventionProvider, BatteryManager batteryManager, + AndroidWakeLockFactory wakeLockFactory, Clock clock, TimeoutMonitor timeoutMonitor) { Context appContext = app.getApplicationContext(); DuplexPluginFactory bluetooth = new AndroidBluetoothPluginFactory( - ioExecutor, scheduler, androidExecutor, appContext, random, - eventBus, clock, timeoutMonitor, backoffFactory); + ioExecutor, androidExecutor, wakeLockFactory, appContext, + random, eventBus, clock, timeoutMonitor, backoffFactory); DuplexPluginFactory tor = new AndroidTorPluginFactory(ioExecutor, - scheduler, appContext, networkManager, locationUtils, eventBus, + appContext, networkManager, locationUtils, eventBus, torSocketFactory, backoffFactory, resourceProvider, - circumventionProvider, batteryManager, clock); + circumventionProvider, batteryManager, wakeLockFactory, clock); DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor, eventBus, backoffFactory, appContext); Collection duplex = asList(bluetooth, tor, lan);