Use general-purpose resource provider.

This commit is contained in:
akwizgran
2018-08-02 17:51:21 +01:00
parent 004467e84e
commit f812acb00b
11 changed files with 95 additions and 63 deletions

View File

@@ -9,6 +9,7 @@ import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin; import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.bramble.test.BrambleAndroidIntegrationTestComponent; import org.briarproject.bramble.test.BrambleAndroidIntegrationTestComponent;
import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.DaggerBrambleAndroidIntegrationTestComponent; import org.briarproject.bramble.test.DaggerBrambleAndroidIntegrationTestComponent;
@@ -45,6 +46,8 @@ public class BridgeTest extends BrambleTestCase {
@Inject @Inject
NetworkManager networkManager; NetworkManager networkManager;
@Inject @Inject
ResourceProvider resourceProvider;
@Inject
CircumventionProvider circumventionProvider; CircumventionProvider circumventionProvider;
@Inject @Inject
EventBus eventBus; EventBus eventBus;
@@ -59,7 +62,7 @@ public class BridgeTest extends BrambleTestCase {
private List<String> bridges; private List<String> bridges;
private AndroidTorPluginFactory factory; private AndroidTorPluginFactory factory;
private volatile int currentBridge = 0; private volatile String currentBridge = null;
@Before @Before
public void setUp() { public void setUp() {
@@ -73,7 +76,7 @@ public class BridgeTest extends BrambleTestCase {
SocketFactory torSocketFactory = SocketFactory.getDefault(); SocketFactory torSocketFactory = SocketFactory.getDefault();
bridges = circumventionProvider.getBridges(); bridges = circumventionProvider.getBridges();
CircumventionProvider testProvider = new CircumventionProvider() { CircumventionProvider bridgeProvider = new CircumventionProvider() {
@Override @Override
public boolean isTorProbablyBlocked(String countryCode) { public boolean isTorProbablyBlocked(String countryCode) {
return true; return true;
@@ -86,31 +89,29 @@ public class BridgeTest extends BrambleTestCase {
@Override @Override
public List<String> getBridges() { public List<String> getBridges() {
return singletonList(bridges.get(currentBridge)); return singletonList(currentBridge);
} }
}; };
factory = new AndroidTorPluginFactory(ioExecutor, scheduler, appContext, factory = new AndroidTorPluginFactory(ioExecutor, scheduler, appContext,
networkManager, locationUtils, eventBus, torSocketFactory, networkManager, locationUtils, eventBus, torSocketFactory,
backoffFactory, testProvider, clock); backoffFactory, resourceProvider, bridgeProvider, clock);
} }
@Test @Test
public void testBridges() throws Exception { public void testBridges() throws Exception {
assertTrue(bridges.size() > 0); assertTrue(bridges.size() > 0);
for (int i = 0; i < bridges.size(); i++) { for (String bridge : bridges) testBridge(bridge);
testBridge(i);
}
} }
private void testBridge(int bridge) throws Exception { private void testBridge(String bridge) throws Exception {
DuplexPlugin duplexPlugin = DuplexPlugin duplexPlugin =
factory.createPlugin(new TorPluginCallBack()); factory.createPlugin(new TorPluginCallBack());
assertNotNull(duplexPlugin); assertNotNull(duplexPlugin);
AndroidTorPlugin plugin = (AndroidTorPlugin) duplexPlugin; AndroidTorPlugin plugin = (AndroidTorPlugin) duplexPlugin;
currentBridge = bridge; currentBridge = bridge;
LOG.warning("Testing " + bridges.get(currentBridge)); LOG.warning("Testing " + bridge);
try { try {
plugin.start(); plugin.start();
long start = clock.currentTimeMillis(); long start = clock.currentTimeMillis();

View File

@@ -1,15 +1,15 @@
package org.briarproject.bramble; package org.briarproject.bramble;
import org.briarproject.bramble.network.AndroidNetworkModule; import org.briarproject.bramble.network.AndroidNetworkModule;
import org.briarproject.bramble.plugin.tor.AndroidCircumventionModule; import org.briarproject.bramble.plugin.tor.CircumventionModule;
import org.briarproject.bramble.system.AndroidSystemModule; import org.briarproject.bramble.system.AndroidSystemModule;
import dagger.Module; import dagger.Module;
@Module(includes = { @Module(includes = {
AndroidCircumventionModule.class,
AndroidNetworkModule.class, AndroidNetworkModule.class,
AndroidSystemModule.class AndroidSystemModule.class,
CircumventionModule.class
}) })
public class BrambleAndroidModule { public class BrambleAndroidModule {

View File

@@ -4,7 +4,6 @@ import android.content.Context;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.os.PowerManager; import android.os.PowerManager;
import org.briarproject.bramble.api.network.NetworkManager; import org.briarproject.bramble.api.network.NetworkManager;
@@ -14,10 +13,10 @@ import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback; import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.bramble.util.RenewableWakeLock; import org.briarproject.bramble.util.RenewableWakeLock;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
@@ -41,12 +40,13 @@ class AndroidTorPlugin extends TorPlugin {
AndroidTorPlugin(Executor ioExecutor, ScheduledExecutorService scheduler, AndroidTorPlugin(Executor ioExecutor, ScheduledExecutorService scheduler,
Context appContext, NetworkManager networkManager, Context appContext, NetworkManager networkManager,
LocationUtils locationUtils, SocketFactory torSocketFactory, LocationUtils locationUtils, SocketFactory torSocketFactory,
Clock clock, CircumventionProvider circumventionProvider, Clock clock, ResourceProvider resourceProvider,
Backoff backoff, DuplexPluginCallback callback, CircumventionProvider circumventionProvider, Backoff backoff,
String architecture, int maxLatency, int maxIdleTime) { DuplexPluginCallback callback, String architecture, int maxLatency,
int maxIdleTime) {
super(ioExecutor, networkManager, locationUtils, torSocketFactory, super(ioExecutor, networkManager, locationUtils, torSocketFactory,
clock, circumventionProvider, backoff, callback, architecture, clock, resourceProvider, circumventionProvider, backoff,
maxLatency, maxIdleTime, callback, architecture, maxLatency, maxIdleTime,
appContext.getDir("tor", MODE_PRIVATE)); appContext.getDir("tor", MODE_PRIVATE));
this.appContext = appContext; this.appContext = appContext;
PowerManager pm = (PowerManager) PowerManager pm = (PowerManager)
@@ -72,13 +72,6 @@ class AndroidTorPlugin extends TorPlugin {
} }
} }
@Override
protected InputStream getResourceInputStream(String name) {
Resources res = appContext.getResources();
int resId = res.getIdentifier(name, "raw", appContext.getPackageName());
return res.openRawResource(resId);
}
@Override @Override
protected void enableNetwork(boolean enable) throws IOException { protected void enableNetwork(boolean enable) throws IOException {
if (!running) return; if (!running) return;

View File

@@ -15,6 +15,7 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory; import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.bramble.util.AndroidUtils; import org.briarproject.bramble.util.AndroidUtils;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@@ -45,6 +46,7 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
private final EventBus eventBus; private final EventBus eventBus;
private final SocketFactory torSocketFactory; private final SocketFactory torSocketFactory;
private final BackoffFactory backoffFactory; private final BackoffFactory backoffFactory;
private final ResourceProvider resourceProvider;
private final CircumventionProvider circumventionProvider; private final CircumventionProvider circumventionProvider;
private final Clock clock; private final Clock clock;
@@ -52,7 +54,7 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
ScheduledExecutorService scheduler, Context appContext, ScheduledExecutorService scheduler, Context appContext,
NetworkManager networkManager, LocationUtils locationUtils, NetworkManager networkManager, LocationUtils locationUtils,
EventBus eventBus, SocketFactory torSocketFactory, EventBus eventBus, SocketFactory torSocketFactory,
BackoffFactory backoffFactory, BackoffFactory backoffFactory, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider, Clock clock) { CircumventionProvider circumventionProvider, Clock clock) {
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
this.scheduler = scheduler; this.scheduler = scheduler;
@@ -62,6 +64,7 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
this.eventBus = eventBus; this.eventBus = eventBus;
this.torSocketFactory = torSocketFactory; this.torSocketFactory = torSocketFactory;
this.backoffFactory = backoffFactory; this.backoffFactory = backoffFactory;
this.resourceProvider = resourceProvider;
this.circumventionProvider = circumventionProvider; this.circumventionProvider = circumventionProvider;
this.clock = clock; this.clock = clock;
} }
@@ -99,11 +102,10 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MAX_POLLING_INTERVAL, BACKOFF_BASE);
AndroidTorPlugin AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor, scheduler,
plugin = new AndroidTorPlugin(ioExecutor, scheduler, appContext, appContext, networkManager, locationUtils, torSocketFactory,
networkManager, locationUtils, torSocketFactory, clock, clock, resourceProvider, circumventionProvider, backoff,
circumventionProvider, backoff, callback, architecture, callback, architecture, MAX_LATENCY, MAX_IDLE_TIME);
MAX_LATENCY, MAX_IDLE_TIME);
eventBus.addListener(plugin); eventBus.addListener(plugin);
return plugin; return plugin;
} }

View File

@@ -1,24 +1,28 @@
package org.briarproject.bramble.plugin.tor; package org.briarproject.bramble.system;
import android.app.Application; import android.app.Application;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.ResourceProvider;
import java.io.InputStream; import java.io.InputStream;
import javax.inject.Inject; import javax.inject.Inject;
class AndroidCircumventionProvider extends CircumventionProviderImpl { @NotNullByDefault
class AndroidResourceProvider implements ResourceProvider {
private final Context appContext; private final Context appContext;
@Inject @Inject
AndroidCircumventionProvider(Application app) { AndroidResourceProvider(Application app) {
this.appContext = app.getApplicationContext(); this.appContext = app.getApplicationContext();
} }
@Override @Override
protected InputStream getResourceInputStream(String name) { public InputStream getResourceInputStream(String name) {
Resources res = appContext.getResources(); Resources res = appContext.getResources();
int resId = res.getIdentifier(name, "raw", appContext.getPackageName()); int resId = res.getIdentifier(name, "raw", appContext.getPackageName());
return res.openRawResource(resId); return res.openRawResource(resId);

View File

@@ -1,9 +1,8 @@
package org.briarproject.bramble.system; package org.briarproject.bramble.system;
import android.app.Application;
import org.briarproject.bramble.api.system.AndroidExecutor; import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.bramble.api.system.SecureRandomProvider; import org.briarproject.bramble.api.system.SecureRandomProvider;
import javax.inject.Singleton; import javax.inject.Singleton;
@@ -16,18 +15,26 @@ public class AndroidSystemModule {
@Provides @Provides
@Singleton @Singleton
SecureRandomProvider provideSecureRandomProvider(Application app) { SecureRandomProvider provideSecureRandomProvider(
return new AndroidSecureRandomProvider(app); AndroidSecureRandomProvider provider) {
return provider;
} }
@Provides @Provides
LocationUtils provideLocationUtils(Application app) { LocationUtils provideLocationUtils(AndroidLocationUtils locationUtils) {
return new AndroidLocationUtils(app); return locationUtils;
} }
@Provides @Provides
@Singleton @Singleton
AndroidExecutor provideAndroidExecutor(Application app) { AndroidExecutor provideAndroidExecutor(
return new AndroidExecutorImpl(app); AndroidExecutorImpl androidExecutor) {
return androidExecutor;
}
@Provides
@Singleton
ResourceProvider provideResourceProvider(AndroidResourceProvider provider) {
return provider;
} }
} }

View File

@@ -0,0 +1,11 @@
package org.briarproject.bramble.api.system;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.InputStream;
@NotNullByDefault
public interface ResourceProvider {
InputStream getResourceInputStream(String name);
}

View File

@@ -6,12 +6,12 @@ import dagger.Module;
import dagger.Provides; import dagger.Provides;
@Module @Module
public class AndroidCircumventionModule { public class CircumventionModule {
@Provides @Provides
@Singleton @Singleton
CircumventionProvider provideCircumventionProvider( CircumventionProvider provideCircumventionProvider(
AndroidCircumventionProvider circumventionProvider) { CircumventionProviderImpl provider) {
return circumventionProvider; return provider;
} }
} }

View File

@@ -1,6 +1,7 @@
package org.briarproject.bramble.plugin.tor; package org.briarproject.bramble.plugin.tor;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.system.ResourceProvider;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
@@ -10,10 +11,11 @@ import java.util.Scanner;
import java.util.Set; import java.util.Set;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.inject.Inject;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
abstract class CircumventionProviderImpl implements CircumventionProvider { class CircumventionProviderImpl implements CircumventionProvider {
private final static String BRIDGE_FILE_NAME = "bridges"; private final static String BRIDGE_FILE_NAME = "bridges";
@@ -22,10 +24,15 @@ abstract class CircumventionProviderImpl implements CircumventionProvider {
private static final Set<String> BRIDGES_WORK_IN_COUNTRIES = private static final Set<String> BRIDGES_WORK_IN_COUNTRIES =
new HashSet<>(asList(BRIDGES)); new HashSet<>(asList(BRIDGES));
private final ResourceProvider resourceProvider;
@Nullable @Nullable
private volatile List<String> bridges = null; private volatile List<String> bridges = null;
protected abstract InputStream getResourceInputStream(String name); @Inject
CircumventionProviderImpl(ResourceProvider resourceProvider) {
this.resourceProvider = resourceProvider;
}
@Override @Override
public boolean isTorProbablyBlocked(String countryCode) { public boolean isTorProbablyBlocked(String countryCode) {
@@ -40,12 +47,14 @@ abstract class CircumventionProviderImpl implements CircumventionProvider {
@Override @Override
@IoExecutor @IoExecutor
public List<String> getBridges() { public List<String> getBridges() {
if (this.bridges != null) return this.bridges; List<String> bridges = this.bridges;
if (bridges != null) return new ArrayList<>(bridges);
InputStream is = getResourceInputStream(BRIDGE_FILE_NAME); InputStream is =
resourceProvider.getResourceInputStream(BRIDGE_FILE_NAME);
Scanner scanner = new Scanner(is); Scanner scanner = new Scanner(is);
List<String> bridges = new ArrayList<>(); bridges = new ArrayList<>();
while (scanner.hasNextLine()) { while (scanner.hasNextLine()) {
String line = scanner.nextLine(); String line = scanner.nextLine();
if (!line.startsWith("#")) bridges.add(line); if (!line.startsWith("#")) bridges.add(line);

View File

@@ -26,6 +26,7 @@ import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent; import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.bramble.util.IoUtils; import org.briarproject.bramble.util.IoUtils;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
@@ -97,6 +98,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private final DuplexPluginCallback callback; private final DuplexPluginCallback callback;
private final String architecture; private final String architecture;
private final CircumventionProvider circumventionProvider; private final CircumventionProvider circumventionProvider;
private final ResourceProvider resourceProvider;
private final int maxLatency, maxIdleTime, socketTimeout; private final int maxLatency, maxIdleTime, socketTimeout;
private final File torDirectory, torFile, geoIpFile, configFile; private final File torDirectory, torFile, geoIpFile, configFile;
private final File doneFile, cookieFile; private final File doneFile, cookieFile;
@@ -113,23 +115,22 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
protected abstract long getLastUpdateTime(); protected abstract long getLastUpdateTime();
protected abstract InputStream getResourceInputStream(String name);
TorPlugin(Executor ioExecutor, NetworkManager networkManager, TorPlugin(Executor ioExecutor, NetworkManager networkManager,
LocationUtils locationUtils, SocketFactory torSocketFactory, LocationUtils locationUtils, SocketFactory torSocketFactory,
Clock clock, CircumventionProvider circumventionProvider, Clock clock, ResourceProvider resourceProvider,
Backoff backoff, DuplexPluginCallback callback, CircumventionProvider circumventionProvider, Backoff backoff,
String architecture, int maxLatency, int maxIdleTime, DuplexPluginCallback callback, String architecture, int maxLatency,
File torDirectory) { int maxIdleTime, File torDirectory) {
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
this.networkManager = networkManager; this.networkManager = networkManager;
this.locationUtils = locationUtils; this.locationUtils = locationUtils;
this.torSocketFactory = torSocketFactory; this.torSocketFactory = torSocketFactory;
this.clock = clock; this.clock = clock;
this.resourceProvider = resourceProvider;
this.circumventionProvider = circumventionProvider;
this.backoff = backoff; this.backoff = backoff;
this.callback = callback; this.callback = callback;
this.architecture = architecture; this.architecture = architecture;
this.circumventionProvider = circumventionProvider;
this.maxLatency = maxLatency; this.maxLatency = maxLatency;
this.maxIdleTime = maxIdleTime; this.maxIdleTime = maxIdleTime;
if (maxIdleTime > Integer.MAX_VALUE / 2) if (maxIdleTime > Integer.MAX_VALUE / 2)
@@ -285,21 +286,22 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private InputStream getTorInputStream() throws IOException { private InputStream getTorInputStream() throws IOException {
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info("Installing Tor binary for " + architecture); LOG.info("Installing Tor binary for " + architecture);
InputStream in = getResourceInputStream("tor_" + architecture); InputStream in =
resourceProvider.getResourceInputStream("tor_" + architecture);
ZipInputStream zin = new ZipInputStream(in); ZipInputStream zin = new ZipInputStream(in);
if (zin.getNextEntry() == null) throw new IOException(); if (zin.getNextEntry() == null) throw new IOException();
return zin; return zin;
} }
private InputStream getGeoIpInputStream() throws IOException { private InputStream getGeoIpInputStream() throws IOException {
InputStream in = getResourceInputStream("geoip"); InputStream in = resourceProvider.getResourceInputStream("geoip");
ZipInputStream zin = new ZipInputStream(in); ZipInputStream zin = new ZipInputStream(in);
if (zin.getNextEntry() == null) throw new IOException(); if (zin.getNextEntry() == null) throw new IOException();
return zin; return zin;
} }
private InputStream getConfigInputStream() { private InputStream getConfigInputStream() {
return getResourceInputStream("torrc"); return resourceProvider.getResourceInputStream("torrc");
} }
private void tryToClose(@Nullable Closeable c) { private void tryToClose(@Nullable Closeable c) {

View File

@@ -21,6 +21,7 @@ import org.briarproject.bramble.api.reporting.DevConfig;
import org.briarproject.bramble.api.system.AndroidExecutor; import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.bramble.api.system.Scheduler; import org.briarproject.bramble.api.system.Scheduler;
import org.briarproject.bramble.plugin.bluetooth.AndroidBluetoothPluginFactory; import org.briarproject.bramble.plugin.bluetooth.AndroidBluetoothPluginFactory;
import org.briarproject.bramble.plugin.tcp.AndroidLanTcpPluginFactory; import org.briarproject.bramble.plugin.tcp.AndroidLanTcpPluginFactory;
@@ -95,6 +96,7 @@ public class AppModule {
SocketFactory torSocketFactory, BackoffFactory backoffFactory, SocketFactory torSocketFactory, BackoffFactory backoffFactory,
Application app, NetworkManager networkManager, Application app, NetworkManager networkManager,
LocationUtils locationUtils, EventBus eventBus, LocationUtils locationUtils, EventBus eventBus,
ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider, Clock clock) { CircumventionProvider circumventionProvider, Clock clock) {
Context appContext = app.getApplicationContext(); Context appContext = app.getApplicationContext();
DuplexPluginFactory bluetooth = DuplexPluginFactory bluetooth =
@@ -102,7 +104,8 @@ public class AppModule {
appContext, random, eventBus, backoffFactory); appContext, random, eventBus, backoffFactory);
DuplexPluginFactory tor = new AndroidTorPluginFactory(ioExecutor, DuplexPluginFactory tor = new AndroidTorPluginFactory(ioExecutor,
scheduler, appContext, networkManager, locationUtils, eventBus, scheduler, appContext, networkManager, locationUtils, eventBus,
torSocketFactory, backoffFactory, circumventionProvider, clock); torSocketFactory, backoffFactory, resourceProvider,
circumventionProvider, clock);
DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor, DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor,
eventBus, backoffFactory, appContext); eventBus, backoffFactory, appContext);
Collection<DuplexPluginFactory> duplex = asList(bluetooth, tor, lan); Collection<DuplexPluginFactory> duplex = asList(bluetooth, tor, lan);