diff --git a/briar-android/AndroidManifest.xml b/briar-android/AndroidManifest.xml
index 10b50aa4d7fb22e251f1d3a2b0ea5a02744518e1..92ae565c569f1d58bb0c8eaf2a4c54f57380b76c 100644
--- a/briar-android/AndroidManifest.xml
+++ b/briar-android/AndroidManifest.xml
@@ -29,7 +29,7 @@
 	<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
 
 	<application
-		android:name=".android.BriarApplication"
+		android:name=".android.BriarApplicationImp"
 		android:allowBackup="false"
 		android:icon="@drawable/ic_launcher"
 		android:label="@string/app_name"
diff --git a/briar-android/build.gradle b/briar-android/build.gradle
index 51b2584e05724d5cf7020903773165a701da5118..e32b70902afb2fc2269021da862318a341d79c23 100644
--- a/briar-android/build.gradle
+++ b/briar-android/build.gradle
@@ -48,14 +48,14 @@ dependencies {
 
 	testCompile 'junit:junit:4.12'
 	testCompile 'net.jodah:concurrentunit:0.4.2'
-	testApt 'com.google.dagger:dagger-compiler:2.4'
+	testApt 'com.google.dagger:dagger-compiler:2.0.2'
 	testCompile project(path: ':briar-tests')
-	testCompile 'org.robolectric:robolectric:3.1-SNAPSHOT'
+	testCompile 'org.robolectric:robolectric:3.0'
 	testCompile 'org.mockito:mockito-core:1.10.19'
 
 	androidTestCompile 'org.robolectric:robolectric:3.0'
 	androidTestCompile 'org.mockito:mockito-core:1.10.19'
-	androidTestApt 'com.google.dagger:dagger-compiler:2.4'
+	androidTestApt 'com.google.dagger:dagger-compiler:2.0.2'
 	androidTestCompile 'junit:junit:4.12'
 }
 
diff --git a/briar-android/src/org/briarproject/android/ActivityComponent.java b/briar-android/src/org/briarproject/android/ActivityComponent.java
index 37fd1f17cda8f1618582ffbd62e33a5e9226aafa..fcfd11761bf2eed528e7bfa82332efd69ebd9ad3 100644
--- a/briar-android/src/org/briarproject/android/ActivityComponent.java
+++ b/briar-android/src/org/briarproject/android/ActivityComponent.java
@@ -53,8 +53,6 @@ public interface ActivityComponent {
 
 	void inject(CreateIdentityActivity activity);
 
-	void inject(TestingActivity activity);
-
 	void inject(AvailableForumsActivity activity);
 
 	void inject(WriteForumPostActivity activity);
diff --git a/briar-android/src/org/briarproject/android/AndroidComponent.java b/briar-android/src/org/briarproject/android/AndroidComponent.java
index fe444a02f9718248310e98be36869a5203f51d87..57e584e3cc71d6a794e629c8463908fce6e4c3a9 100644
--- a/briar-android/src/org/briarproject/android/AndroidComponent.java
+++ b/briar-android/src/org/briarproject/android/AndroidComponent.java
@@ -2,8 +2,10 @@ package org.briarproject.android;
 
 import org.briarproject.CoreEagerSingletons;
 import org.briarproject.CoreModule;
+import org.briarproject.android.api.AndroidExecutor;
 import org.briarproject.android.api.AndroidNotificationManager;
 import org.briarproject.android.api.ReferenceManager;
+import org.briarproject.android.util.BriarReportSender;
 import org.briarproject.api.contact.ContactExchangeTask;
 import org.briarproject.api.contact.ContactManager;
 import org.briarproject.api.crypto.CryptoComponent;
@@ -22,6 +24,7 @@ import org.briarproject.api.invitation.InvitationTaskFactory;
 import org.briarproject.api.keyagreement.KeyAgreementTaskFactory;
 import org.briarproject.api.keyagreement.PayloadEncoder;
 import org.briarproject.api.keyagreement.PayloadParser;
+import org.briarproject.api.lifecycle.IoExecutor;
 import org.briarproject.api.lifecycle.LifecycleManager;
 import org.briarproject.api.messaging.MessagingManager;
 import org.briarproject.api.messaging.PrivateMessageFactory;
@@ -103,12 +106,21 @@ public interface AndroidComponent extends CoreEagerSingletons {
 
 	IntroductionManager introductionManager();
 
+	AndroidExecutor androidExecutor();
+
 	void inject(BriarService activity);
 
+	@IoExecutor
+	Executor ioExecutor();
+
 	void inject(ContactChooserFragment fragment);
 
 	void inject(IntroductionMessageFragment fragment);
 
+	void inject(DevReportActivity devReportActivity);
+
+	void inject(BriarService activity);
+
 	// Eager singleton load
 	void inject(AppModule.EagerSingletons init);
 
diff --git a/briar-android/src/org/briarproject/android/BriarApplication.java b/briar-android/src/org/briarproject/android/BriarApplication.java
index eec480309deb5f4ae863345868662f0a6d4d670c..cd28990adcaefb0cd28629747175e1b596629f13 100644
--- a/briar-android/src/org/briarproject/android/BriarApplication.java
+++ b/briar-android/src/org/briarproject/android/BriarApplication.java
@@ -1,56 +1,10 @@
 package org.briarproject.android;
 
-import android.app.Application;
-import android.content.Context;
+/**
+ * This exists so that the Application object will not necessarily be cast
+ * directly to the Briar application object.
+ */
+public interface BriarApplication {
 
-import org.acra.ACRA;
-import org.acra.ReportingInteractionMode;
-import org.acra.annotation.ReportsCrashes;
-import org.briarproject.CoreModule;
-import org.briarproject.R;
-import org.briarproject.android.util.BriarReportPrimer;
-import org.briarproject.android.util.BriarReportSenderFactory;
-
-import java.util.logging.Logger;
-
-@ReportsCrashes(
-		reportPrimerClass = BriarReportPrimer.class,
-		logcatArguments = {"-d", "-v", "time", "*:I"},
-		reportSenderFactoryClasses = {BriarReportSenderFactory.class},
-		mode = ReportingInteractionMode.DIALOG,
-		reportDialogClass = DevReportActivity.class,
-		resDialogOkToast = R.string.dev_report_saved,
-		deleteOldUnsentReportsOnApplicationStart = false
-)
-public class BriarApplication extends Application {
-
-	private static final Logger LOG =
-			Logger.getLogger(BriarApplication.class.getName());
-
-	private AndroidComponent applicationComponent;
-
-	@Override
-	protected void attachBaseContext(Context base) {
-		super.attachBaseContext(base);
-		ACRA.init(this);
-	}
-
-	@Override
-	public void onCreate() {
-		super.onCreate();
-		LOG.info("Created");
-
-		applicationComponent = DaggerAndroidComponent.builder()
-				.appModule(new AppModule(this))
-				.build();
-
-		// We need to load the eager singletons directly after making the
-		// dependency graphs
-		CoreModule.initEagerSingletons(applicationComponent);
-		AndroidEagerSingletons.initEagerSingletons(applicationComponent);
-	}
-
-	public AndroidComponent getApplicationComponent() {
-		return applicationComponent;
-	}
+	AndroidComponent getApplicationComponent();
 }
diff --git a/briar-android/src/org/briarproject/android/BriarApplicationImp.java b/briar-android/src/org/briarproject/android/BriarApplicationImp.java
new file mode 100644
index 0000000000000000000000000000000000000000..4281c778f43c4c90074e925642774d3c60ebaadb
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/BriarApplicationImp.java
@@ -0,0 +1,56 @@
+package org.briarproject.android;
+
+import android.app.Application;
+import android.content.Context;
+
+import org.acra.ACRA;
+import org.acra.ReportingInteractionMode;
+import org.acra.annotation.ReportsCrashes;
+import org.briarproject.CoreModule;
+import org.briarproject.R;
+import org.briarproject.android.util.BriarReportPrimer;
+import org.briarproject.android.util.BriarReportSenderFactory;
+
+import java.util.logging.Logger;
+
+@ReportsCrashes(
+		reportPrimerClass = BriarReportPrimer.class,
+		logcatArguments = {"-d", "-v", "time", "*:I"},
+		reportSenderFactoryClasses = {BriarReportSenderFactory.class},
+		mode = ReportingInteractionMode.DIALOG,
+		reportDialogClass = DevReportActivity.class,
+		resDialogOkToast = R.string.dev_report_saved,
+		deleteOldUnsentReportsOnApplicationStart = false
+)
+public class BriarApplicationImp extends Application implements BriarApplication {
+
+	private static final Logger LOG =
+			Logger.getLogger(BriarApplicationImp.class.getName());
+
+	private AndroidComponent applicationComponent;
+
+	@Override
+	protected void attachBaseContext(Context base) {
+		super.attachBaseContext(base);
+		ACRA.init(this);
+	}
+
+	@Override
+	public void onCreate() {
+		super.onCreate();
+		LOG.info("Created");
+
+		applicationComponent = DaggerAndroidComponent.builder()
+				.appModule(new AppModule(this))
+				.build();
+
+		// We need to load the eager singletons directly after making the
+		// dependency graphs
+		CoreModule.initEagerSingletons(applicationComponent);
+		AndroidEagerSingletons.initEagerSingletons(applicationComponent);
+	}
+
+	public AndroidComponent getApplicationComponent() {
+		return applicationComponent;
+	}
+}
diff --git a/briar-android/src/org/briarproject/android/DevReportActivity.java b/briar-android/src/org/briarproject/android/DevReportActivity.java
index 2ea4e07e370b558cef1e433bb3a2febb0fb1295a..8f94b5a07624c4e9cc6f4e42d9ad8e7e01ebeb0c 100644
--- a/briar-android/src/org/briarproject/android/DevReportActivity.java
+++ b/briar-android/src/org/briarproject/android/DevReportActivity.java
@@ -89,6 +89,7 @@ public class DevReportActivity extends BaseCrashReportDialog
 		((BriarApplication) getApplication()).getApplicationComponent()
 				.inject(this);
 
+
 		sharedPreferencesFactory =
 				new SharedPreferencesFactory(getApplicationContext(),
 						getConfig());
diff --git a/briar-android/src/org/briarproject/android/SplashScreenActivity.java b/briar-android/src/org/briarproject/android/SplashScreenActivity.java
index 2064c67d6fbd18ddf0713f0e51d0ae2c51f6fc6f..e2b8dcc8b090b54dcb6ce57ead7f64c7d7505bc9 100644
--- a/briar-android/src/org/briarproject/android/SplashScreenActivity.java
+++ b/briar-android/src/org/briarproject/android/SplashScreenActivity.java
@@ -9,6 +9,7 @@ import android.os.StrictMode.VmPolicy;
 import android.support.v7.preference.PreferenceManager;
 
 import org.briarproject.R;
+import org.briarproject.android.api.AndroidExecutor;
 import org.briarproject.android.controller.ConfigController;
 import org.briarproject.android.util.AndroidUtils;
 
@@ -29,6 +30,8 @@ public class SplashScreenActivity extends BaseActivity {
 
 	@Inject
 	ConfigController configController;
+	@Inject
+	protected AndroidExecutor androidExecutor;
 
 	public SplashScreenActivity() {
 		Logger.getLogger("").setLevel(DEFAULT_LOG_LEVEL);
diff --git a/briar-android/src/org/briarproject/android/contact/ContactListFragment.java b/briar-android/src/org/briarproject/android/contact/ContactListFragment.java
index bb22af3bf7cf90e068b57f3f7107c58f33096b9b..5e7e017cd6139f37769bfc4e0bee392947aa7be4 100644
--- a/briar-android/src/org/briarproject/android/contact/ContactListFragment.java
+++ b/briar-android/src/org/briarproject/android/contact/ContactListFragment.java
@@ -12,16 +12,12 @@ import android.view.View;
 import android.view.ViewGroup;
 
 import org.briarproject.R;
-import org.briarproject.android.AndroidComponent;
-import org.briarproject.android.BriarApplication;
-import org.briarproject.android.fragment.BaseEventFragment;
 import org.briarproject.android.fragment.BaseFragment;
 import org.briarproject.android.keyagreement.KeyAgreementActivity;
 import org.briarproject.android.util.BriarRecyclerView;
 import org.briarproject.api.contact.Contact;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.crypto.CryptoComponent;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.db.NoSuchContactException;
 import org.briarproject.api.event.ContactAddedEvent;
diff --git a/briar-android/src/org/briarproject/android/controller/SetupControllerImp.java b/briar-android/src/org/briarproject/android/controller/SetupControllerImp.java
index 22eeeb84f90fbe0a99f65ebcd02578465c8be5ee..61a933e677188ea89440110582d2c75651e6232a 100644
--- a/briar-android/src/org/briarproject/android/controller/SetupControllerImp.java
+++ b/briar-android/src/org/briarproject/android/controller/SetupControllerImp.java
@@ -84,23 +84,15 @@ public class SetupControllerImp implements SetupController {
 	@Override
 	public void createIdentity(final String nickname, final String password,
 			final ResultHandler<Long> resultHandler) {
-		LOG.info("createIdentity called");
 		cryptoExecutor.execute(new Runnable() {
 			public void run() {
-				LOG.info("createIdentity running");
 				SecretKey key = crypto.generateSecretKey();
-				LOG.info("createIdentity 1");
 				databaseConfig.setEncryptionKey(key);
-				LOG.info("createIdentity 2");
 				String hex = encryptDatabaseKey(key, password);
-				LOG.info("createIdentity 3");
 				storeEncryptedDatabaseKey(hex);
-				LOG.info("createIdentity 4");
 				final LocalAuthor localAuthor = createLocalAuthor(nickname);
-				LOG.info("createIdentity 5");
 				long handle = referenceManager.putReference(localAuthor,
 						LocalAuthor.class);
-				LOG.info("createIdentity 6");
 				resultHandler.onResult(handle);
 			}
 		});
diff --git a/briar-android/src/org/briarproject/android/forum/ForumListFragment.java b/briar-android/src/org/briarproject/android/forum/ForumListFragment.java
index a6ba633f7a40b2d5cdd3ef64b01b1a1b54bff0d2..0129990936a525b30ee901014cec39cb06faa345 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumListFragment.java
+++ b/briar-android/src/org/briarproject/android/forum/ForumListFragment.java
@@ -51,16 +51,6 @@ public class ForumListFragment extends BaseEventFragment implements
 	private static final Logger LOG =
 			Logger.getLogger(ForumListFragment.class.getName());
 
-	/*
-	public static ForumListFragment newInstance() {
-
-		Bundle args = new Bundle();
-
-		ForumListFragment fragment = new ForumListFragment();
-		fragment.setArguments(args);
-		return fragment;
-	}
-	*/
 
 	private BriarRecyclerView list;
 	private ForumListAdapter adapter;
@@ -107,11 +97,6 @@ public class ForumListFragment extends BaseEventFragment implements
 		return TAG;
 	}
 
-//	@Override
-//	public void injectActivity(ActivityComponent component) {
-//		component.inject(this);
-//	}
-
 	@Override
 	public void onResume() {
 		super.onResume();
diff --git a/briar-android/src/org/briarproject/android/fragment/BaseFragment.java b/briar-android/src/org/briarproject/android/fragment/BaseFragment.java
index 34e00e0c3f0c887c1b568c512c8128d4c7f29f5e..96efaad58c2a7201c795daefaf66d3dd326d2ba1 100644
--- a/briar-android/src/org/briarproject/android/fragment/BaseFragment.java
+++ b/briar-android/src/org/briarproject/android/fragment/BaseFragment.java
@@ -4,9 +4,6 @@ import android.content.Context;
 import android.os.Bundle;
 import android.support.v4.app.Fragment;
 
-import org.briarproject.android.AndroidComponent;
-import org.briarproject.android.BriarApplication;
-
 public abstract class BaseFragment extends Fragment {
 
 	public abstract String getUniqueTag();
diff --git a/briar-android/src/org/briarproject/android/panic/PanicResponderActivity.java b/briar-android/src/org/briarproject/android/panic/PanicResponderActivity.java
index bdb037785072b8c2d6ee14a9879e045a21ba8b0c..0b08f7f5a49338fd4b3786e0b8051b12c81668ee 100644
--- a/briar-android/src/org/briarproject/android/panic/PanicResponderActivity.java
+++ b/briar-android/src/org/briarproject/android/panic/PanicResponderActivity.java
@@ -9,6 +9,7 @@ import android.support.v7.preference.PreferenceManager;
 
 import org.briarproject.android.ActivityComponent;
 import org.briarproject.android.BriarActivity;
+import org.briarproject.android.api.AndroidExecutor;
 import org.briarproject.android.controller.ConfigController;
 import org.briarproject.android.util.AndroidUtils;
 import org.iilab.IilabEngineeringRSA2048Pin;
@@ -22,6 +23,7 @@ import info.guardianproject.panic.Panic;
 import info.guardianproject.panic.PanicResponder;
 import info.guardianproject.trustedintents.TrustedIntents;
 
+import static android.content.Intent.ACTION_DELETE;
 import static org.briarproject.android.panic.PanicPreferencesFragment.KEY_LOCK;
 import static org.briarproject.android.panic.PanicPreferencesFragment.KEY_PURGE;
 import static org.briarproject.android.panic.PanicPreferencesFragment.KEY_UNINSTALL;
@@ -31,6 +33,8 @@ public class PanicResponderActivity extends BriarActivity {
 	private static final Logger LOG =
 			Logger.getLogger(PanicResponderActivity.class.getName());
 	@Inject protected ConfigController configController;
+	@Inject
+	protected AndroidExecutor androidExecutor;
 
 	@Override
 	public void onCreate(Bundle savedInstanceState) {
diff --git a/briar-android/src/org/briarproject/android/util/BriarReportSenderFactory.java b/briar-android/src/org/briarproject/android/util/BriarReportSenderFactory.java
index 6dc106f743e9b7d6309d144964bd208b0c6e9fd1..73108ae4ae544b256e99bac2f868d67190c6dcfd 100644
--- a/briar-android/src/org/briarproject/android/util/BriarReportSenderFactory.java
+++ b/briar-android/src/org/briarproject/android/util/BriarReportSenderFactory.java
@@ -7,6 +7,7 @@ import org.acra.config.ACRAConfiguration;
 import org.acra.sender.ReportSender;
 import org.acra.sender.ReportSenderFactory;
 import org.briarproject.android.BriarApplication;
+import org.briarproject.android.BriarApplicationImp;
 
 public class BriarReportSenderFactory implements ReportSenderFactory {
 	@NonNull
diff --git a/briar-android/test/java/briarproject/IntroductionIntegrationTest.java b/briar-android/test/java/briarproject/IntroductionIntegrationTest.java
deleted file mode 100644
index e92b545461dc428f5baeacf415e97b6c434a331c..0000000000000000000000000000000000000000
--- a/briar-android/test/java/briarproject/IntroductionIntegrationTest.java
+++ /dev/null
@@ -1,859 +0,0 @@
-package briarproject;
-
-import net.jodah.concurrentunit.Waiter;
-
-import org.briarproject.BriarTestCase;
-import org.briarproject.TestDatabaseModule;
-import org.briarproject.TestUtils;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.IntroductionAbortedEvent;
-import org.briarproject.api.event.IntroductionRequestReceivedEvent;
-import org.briarproject.api.event.IntroductionResponseReceivedEvent;
-import org.briarproject.api.event.IntroductionSucceededEvent;
-import org.briarproject.api.event.MessageValidatedEvent;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.introduction.IntroductionManager;
-import org.briarproject.api.introduction.IntroductionRequest;
-import org.briarproject.api.introduction.SessionId;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.properties.TransportProperties;
-import org.briarproject.api.properties.TransportPropertyManager;
-import org.briarproject.api.sync.SyncSession;
-import org.briarproject.api.sync.SyncSessionFactory;
-import org.briarproject.api.system.Clock;
-import org.briarproject.contact.ContactModule;
-import org.briarproject.crypto.CryptoModule;
-import org.briarproject.introduction.IntroductionModule;
-import org.briarproject.lifecycle.LifecycleModule;
-import org.briarproject.properties.PropertiesModule;
-import org.briarproject.sync.SyncModule;
-import org.briarproject.transport.TransportModule;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.concurrent.TimeoutException;
-import java.util.logging.Logger;
-
-import javax.inject.Inject;
-
-import static org.briarproject.TestPluginsModule.MAX_LATENCY;
-import static org.briarproject.TestPluginsModule.TRANSPORT_ID;
-import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class IntroductionIntegrationTest extends BriarTestCase {
-
-	LifecycleManager lifecycleManager0, lifecycleManager1, lifecycleManager2;
-	SyncSessionFactory sync0, sync1, sync2;
-	ContactManager contactManager0, contactManager1, contactManager2;
-	ContactId contactId0, contactId1, contactId2;
-	IdentityManager identityManager0, identityManager1, identityManager2;
-	LocalAuthor author0, author1, author2;
-
-	@Inject
-	Clock clock;
-	@Inject
-	AuthorFactory authorFactory;
-
-	// objects accessed from background threads need to be volatile
-	private volatile IntroductionManager introductionManager0;
-	private volatile IntroductionManager introductionManager1;
-	private volatile IntroductionManager introductionManager2;
-	private volatile Waiter eventWaiter;
-	private volatile Waiter msgWaiter;
-
-	private final File testDir = TestUtils.getTestDirectory();
-	private final SecretKey master = TestUtils.getSecretKey();
-	private final int TIMEOUT = 15000;
-	private final String INTRODUCER = "Introducer";
-	private final String INTRODUCEE1 = "Introducee1";
-	private final String INTRODUCEE2 = "Introducee2";
-
-	private static final Logger LOG =
-			Logger.getLogger(IntroductionIntegrationTest.class.getName());
-
-	private IntroductionIntegrationTestComponent t0, t1, t2;
-
-	@Before
-	public void setUp() {
-		IntroductionIntegrationTestComponent component =
-				DaggerIntroductionIntegrationTestComponent.builder().build();
-		component.inject(this);
-		injectEagerSingletons(component);
-
-		assertTrue(testDir.mkdirs());
-		File t0Dir = new File(testDir, INTRODUCER);
-		t0 = DaggerIntroductionIntegrationTestComponent.builder()
-				.testDatabaseModule(new TestDatabaseModule(t0Dir)).build();
-		injectEagerSingletons(t0);
-		File t1Dir = new File(testDir, INTRODUCEE1);
-		t1 = DaggerIntroductionIntegrationTestComponent.builder()
-				.testDatabaseModule(new TestDatabaseModule(t1Dir)).build();
-		injectEagerSingletons(t1);
-		File t2Dir = new File(testDir, INTRODUCEE2);
-		t2 = DaggerIntroductionIntegrationTestComponent.builder()
-				.testDatabaseModule(new TestDatabaseModule(t2Dir)).build();
-		injectEagerSingletons(t2);
-
-		identityManager0 = t0.getIdentityManager();
-		identityManager1 = t1.getIdentityManager();
-		identityManager2 = t2.getIdentityManager();
-		contactManager0 = t0.getContactManager();
-		contactManager1 = t1.getContactManager();
-		contactManager2 = t2.getContactManager();
-		introductionManager0 = t0.getIntroductionManager();
-		introductionManager1 = t1.getIntroductionManager();
-		introductionManager2 = t2.getIntroductionManager();
-		sync0 = t0.getSyncSessionFactory();
-		sync1 = t1.getSyncSessionFactory();
-		sync2 = t2.getSyncSessionFactory();
-
-		// initialize waiters fresh for each test
-		eventWaiter = new Waiter();
-		msgWaiter = new Waiter();
-	}
-
-	@Test
-	public void testIntroductionSession() throws Exception {
-		startLifecycles();
-		try {
-			// Add Identities
-			addDefaultIdentities();
-
-			// Add Transport Properties
-			addTransportProperties();
-
-			// Add introducees as contacts
-			contactId1 = contactManager0.addContact(author1,
-					author0.getId(), master, clock.currentTimeMillis(), true,
-					true
-			);
-			contactId2 = contactManager0.addContact(author2,
-					author0.getId(), master, clock.currentTimeMillis(), true,
-					true
-			);
-			// Add introducer back
-			contactId0 = contactManager1.addContact(author0,
-					author1.getId(), master, clock.currentTimeMillis(), true,
-					true
-			);
-			ContactId contactId02 = contactManager2.addContact(author0,
-					author2.getId(), master, clock.currentTimeMillis(), true,
-					true
-			);
-			assertTrue(contactId0.equals(contactId02));
-
-			// listen to events
-			IntroducerListener listener0 = new IntroducerListener();
-			t0.getEventBus().addListener(listener0);
-			IntroduceeListener listener1 = new IntroduceeListener(1, true);
-			t1.getEventBus().addListener(listener1);
-			IntroduceeListener listener2 = new IntroduceeListener(2, true);
-			t2.getEventBus().addListener(listener2);
-
-			// make introduction
-			long time = clock.currentTimeMillis();
-			Contact introducee1 = contactManager0.getContact(contactId1);
-			Contact introducee2 = contactManager0.getContact(contactId2);
-			introductionManager0
-					.makeIntroduction(introducee1, introducee2, "Hi!", time);
-
-			// sync first request message
-			deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1");
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener1.requestReceived);
-
-			// sync second request message
-			deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2");
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener2.requestReceived);
-
-			// sync first response
-			deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0");
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener0.response1Received);
-
-			// sync second response
-			deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0");
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener0.response2Received);
-
-			// sync forwarded responses to introducees
-			deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1");
-			deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2");
-
-			// sync first ACK and its forward
-			deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0");
-			deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2");
-
-			// sync second ACK and its forward
-			deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0");
-			deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 2");
-
-			// wait for introduction to succeed
-			eventWaiter.await(TIMEOUT, 2);
-			assertTrue(listener1.succeeded);
-			assertTrue(listener2.succeeded);
-
-			assertTrue(contactManager1
-					.contactExists(author2.getId(), author1.getId()));
-			assertTrue(contactManager2
-					.contactExists(author1.getId(), author2.getId()));
-
-			assertDefaultUiMessages();
-		} finally {
-			stopLifecycles();
-		}
-	}
-
-	@Test
-	public void testIntroductionSessionFirstDecline() throws Exception {
-		startLifecycles();
-		try {
-			// Add Identities
-			addDefaultIdentities();
-
-			// Add Transport Properties
-			addTransportProperties();
-
-			// Add introducees as contacts
-			contactId1 = contactManager0.addContact(author1, author0.getId(),
-					master, clock.currentTimeMillis(), true, true
-			);
-			contactId2 = contactManager0.addContact(author2, author0.getId(),
-					master, clock.currentTimeMillis(), true, true
-			);
-			// Add introducer back
-			contactId0 = contactManager1.addContact(author0, author1.getId(),
-					master, clock.currentTimeMillis(), true, true
-			);
-			ContactId contactId02 = contactManager2.addContact(author0,
-					author2.getId(), master, clock.currentTimeMillis(), true,
-					true
-			);
-			assertTrue(contactId0.equals(contactId02));
-
-			// listen to events
-			IntroducerListener listener0 = new IntroducerListener();
-			t0.getEventBus().addListener(listener0);
-			IntroduceeListener listener1 = new IntroduceeListener(1, false);
-			t1.getEventBus().addListener(listener1);
-			IntroduceeListener listener2 = new IntroduceeListener(2, true);
-			t2.getEventBus().addListener(listener2);
-
-			// make introduction
-			long time = clock.currentTimeMillis();
-			Contact introducee1 = contactManager0.getContact(contactId1);
-			Contact introducee2 = contactManager0.getContact(contactId2);
-			introductionManager0
-					.makeIntroduction(introducee1, introducee2, null, time);
-
-			// sync request messages
-			deliverMessage(sync0, contactId0, sync1, contactId1);
-			deliverMessage(sync0, contactId0, sync2, contactId2);
-
-			// wait for requests to arrive
-			eventWaiter.await(TIMEOUT, 2);
-			assertTrue(listener1.requestReceived);
-			assertTrue(listener2.requestReceived);
-
-			// sync first response
-			deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0");
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener0.response1Received);
-
-			// sync second response
-			deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0");
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener0.response2Received);
-
-			// sync first forwarded response
-			deliverMessage(sync0, contactId0, sync2, contactId2);
-
-			// note how the introducer does not forward the second response,
-			// because after the first decline the protocol finished
-
-			assertFalse(listener1.succeeded);
-			assertFalse(listener2.succeeded);
-
-			assertFalse(contactManager1
-					.contactExists(author2.getId(), author1.getId()));
-			assertFalse(contactManager2
-					.contactExists(author1.getId(), author2.getId()));
-
-			assertEquals(2,
-					introductionManager0.getIntroductionMessages(contactId1)
-							.size());
-			assertEquals(2,
-					introductionManager0.getIntroductionMessages(contactId2)
-							.size());
-			assertEquals(2,
-					introductionManager1.getIntroductionMessages(contactId0)
-							.size());
-			// introducee2 should also have the decline response of introducee1
-			assertEquals(3,
-					introductionManager2.getIntroductionMessages(contactId0)
-							.size());
-		} finally {
-			stopLifecycles();
-		}
-	}
-
-	@Test
-	public void testIntroductionSessionSecondDecline() throws Exception {
-		startLifecycles();
-		try {
-			// Add Identities
-			addDefaultIdentities();
-
-			// Add Transport Properties
-			addTransportProperties();
-
-			// Add introducees as contacts
-			contactId1 = contactManager0.addContact(author1, author0.getId(),
-					master, clock.currentTimeMillis(), true, true
-			);
-			contactId2 = contactManager0.addContact(author2, author0.getId(),
-					master, clock.currentTimeMillis(), true, true
-			);
-			// Add introducer back
-			contactId0 = contactManager1.addContact(author0, author1.getId(),
-					master, clock.currentTimeMillis(), false, true
-			);
-			ContactId contactId02 = contactManager2.addContact(author0,
-					author2.getId(), master, clock.currentTimeMillis(), false,
-					true
-			);
-			assertTrue(contactId0.equals(contactId02));
-
-			// listen to events
-			IntroducerListener listener0 = new IntroducerListener();
-			t0.getEventBus().addListener(listener0);
-			IntroduceeListener listener1 = new IntroduceeListener(1, true);
-			t1.getEventBus().addListener(listener1);
-			IntroduceeListener listener2 = new IntroduceeListener(2, false);
-			t2.getEventBus().addListener(listener2);
-
-			// make introduction
-			long time = clock.currentTimeMillis();
-			Contact introducee1 = contactManager0.getContact(contactId1);
-			Contact introducee2 = contactManager0.getContact(contactId2);
-			introductionManager0
-					.makeIntroduction(introducee1, introducee2, null, time);
-
-			// sync request messages
-			deliverMessage(sync0, contactId0, sync1, contactId1);
-			deliverMessage(sync0, contactId0, sync2, contactId2);
-
-			// wait for requests to arrive
-			eventWaiter.await(TIMEOUT, 2);
-			assertTrue(listener1.requestReceived);
-			assertTrue(listener2.requestReceived);
-
-			// sync first response
-			deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0");
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener0.response1Received);
-
-			// sync second response
-			deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0");
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener0.response2Received);
-
-			// sync both forwarded response
-			deliverMessage(sync0, contactId0, sync2, contactId2);
-			deliverMessage(sync0, contactId0, sync1, contactId1);
-
-			assertFalse(contactManager1
-					.contactExists(author2.getId(), author1.getId()));
-			assertFalse(contactManager2
-					.contactExists(author1.getId(), author2.getId()));
-
-			assertEquals(2,
-					introductionManager0.getIntroductionMessages(contactId1)
-							.size());
-			assertEquals(2,
-					introductionManager0.getIntroductionMessages(contactId2)
-							.size());
-			// introducee1 also sees the decline response from introducee2
-			assertEquals(3,
-					introductionManager1.getIntroductionMessages(contactId0)
-							.size());
-			assertEquals(2,
-					introductionManager2.getIntroductionMessages(contactId0)
-							.size());
-		} finally {
-			stopLifecycles();
-		}
-	}
-
-	@Test
-	public void testIntroductionSessionDelayedFirstDecline() throws Exception {
-		startLifecycles();
-		try {
-			// Add Identities
-			addDefaultIdentities();
-
-			// Add Transport Properties
-			addTransportProperties();
-
-			// Add introducees as contacts
-			contactId1 = contactManager0.addContact(author1, author0.getId(),
-					master, clock.currentTimeMillis(), true, true
-			);
-			contactId2 = contactManager0.addContact(author2, author0.getId(),
-					master, clock.currentTimeMillis(), true, true
-			);
-			// Add introducer back
-			contactId0 = contactManager1.addContact(author0, author1.getId(),
-					master, clock.currentTimeMillis(), false, true
-			);
-			ContactId contactId02 = contactManager2.addContact(author0,
-					author2.getId(), master, clock.currentTimeMillis(), false,
-					true
-			);
-			assertTrue(contactId0.equals(contactId02));
-
-			// listen to events
-			IntroducerListener listener0 = new IntroducerListener();
-			t0.getEventBus().addListener(listener0);
-			IntroduceeListener listener1 = new IntroduceeListener(1, false);
-			t1.getEventBus().addListener(listener1);
-			IntroduceeListener listener2 = new IntroduceeListener(2, false);
-			t2.getEventBus().addListener(listener2);
-
-			// make introduction
-			long time = clock.currentTimeMillis();
-			Contact introducee1 = contactManager0.getContact(contactId1);
-			Contact introducee2 = contactManager0.getContact(contactId2);
-			introductionManager0
-					.makeIntroduction(introducee1, introducee2, null, time);
-
-			// sync request messages
-			deliverMessage(sync0, contactId0, sync1, contactId1);
-			deliverMessage(sync0, contactId0, sync2, contactId2);
-
-			// wait for requests to arrive
-			eventWaiter.await(TIMEOUT, 2);
-			assertTrue(listener1.requestReceived);
-			assertTrue(listener2.requestReceived);
-
-			// sync first response
-			deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0");
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener0.response1Received);
-
-			// sync second response
-			deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0");
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener0.response2Received);
-
-			// sync first forwarded response
-			deliverMessage(sync0, contactId0, sync2, contactId2);
-
-			// note how the second response will not be forwarded anymore
-
-			assertFalse(contactManager1
-					.contactExists(author2.getId(), author1.getId()));
-			assertFalse(contactManager2
-					.contactExists(author1.getId(), author2.getId()));
-
-			// since introducee2 was already in FINISHED state when
-			// introducee1's response arrived, she ignores and deletes it
-			assertDefaultUiMessages();
-		} finally {
-			stopLifecycles();
-		}
-	}
-
-	@Test
-	public void testIntroductionToSameContact() throws Exception {
-		startLifecycles();
-		try {
-			// Add Identities
-			addDefaultIdentities();
-
-			// Add Transport Properties
-			addTransportProperties();
-
-			// Add introducee as contact
-			contactId1 = contactManager0.addContact(author1, author0.getId(),
-					master, clock.currentTimeMillis(), true, true
-			);
-			// Add introducer back
-			contactId0 = contactManager1.addContact(author0, author1.getId(),
-					master, clock.currentTimeMillis(), true, true
-			);
-
-			// listen to events
-			IntroducerListener listener0 = new IntroducerListener();
-			t0.getEventBus().addListener(listener0);
-			IntroduceeListener listener1 = new IntroduceeListener(1, true);
-			t1.getEventBus().addListener(listener1);
-
-			// make introduction
-			long time = clock.currentTimeMillis();
-			Contact introducee1 = contactManager0.getContact(contactId1);
-			introductionManager0
-					.makeIntroduction(introducee1, introducee1, null, time);
-
-			// sync request messages
-			deliverMessage(sync0, contactId0, sync1, contactId1);
-
-			// we should not get any event, because the request will be discarded
-			assertFalse(listener1.requestReceived);
-
-			// make really sure we don't have that request
-			assertTrue(introductionManager1.getIntroductionMessages(contactId0)
-					.isEmpty());
-		} finally {
-			stopLifecycles();
-		}
-	}
-
-	@Test
-	public void testIntroductionToIdentitiesOfSameContact() throws Exception {
-		startLifecycles();
-		try {
-			// Add Identities
-			author0 = authorFactory.createLocalAuthor(INTRODUCER,
-					TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
-					TestUtils.getRandomBytes(123));
-			identityManager0.addLocalAuthor(author0);
-			author1 = authorFactory.createLocalAuthor(INTRODUCEE1,
-					TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
-					TestUtils.getRandomBytes(123));
-			identityManager1.addLocalAuthor(author1);
-			author2 = authorFactory.createLocalAuthor(INTRODUCEE2,
-					TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
-					TestUtils.getRandomBytes(123));
-			identityManager1.addLocalAuthor(author2);
-
-			// Add Transport Properties
-			addTransportProperties();
-
-			// Add introducees' authors as contacts
-			contactId1 = contactManager0.addContact(author1,
-					author0.getId(), master, clock.currentTimeMillis(), true,
-					true
-			);
-			contactId2 = contactManager0.addContact(author2,
-					author0.getId(), master, clock.currentTimeMillis(), true,
-					true
-			);
-			// Add introducer back
-			contactId0 = null;
-			ContactId contactId01 = contactManager1.addContact(author0,
-					author1.getId(), master, clock.currentTimeMillis(), false,
-					true
-			);
-			ContactId contactId02 = contactManager1.addContact(author0,
-					author2.getId(), master, clock.currentTimeMillis(), false,
-					true
-			);
-
-			// listen to events
-			IntroducerListener listener0 = new IntroducerListener();
-			t0.getEventBus().addListener(listener0);
-			IntroduceeListener listener1 = new IntroduceeListener(1, true);
-			t1.getEventBus().addListener(listener1);
-
-			// make introduction
-			long time = clock.currentTimeMillis();
-			Contact introducee1 = contactManager0.getContact(contactId1);
-			Contact introducee2 = contactManager0.getContact(contactId2);
-			introductionManager0
-					.makeIntroduction(introducee1, introducee2, "Hi!", time);
-
-			// sync request messages
-			deliverMessage(sync0, contactId01, sync1, contactId1);
-			deliverMessage(sync0, contactId02, sync1, contactId2);
-
-			// wait for request to arrive
-			eventWaiter.await(TIMEOUT, 2);
-			assertTrue(listener1.requestReceived);
-
-			// sync responses
-			deliverMessage(sync1, contactId1, sync0, contactId01);
-			deliverMessage(sync1, contactId2, sync0, contactId02);
-
-			// wait for two responses to arrive
-			eventWaiter.await(TIMEOUT, 2);
-			assertTrue(listener0.response1Received);
-			assertTrue(listener0.response2Received);
-
-			// sync forwarded responses to introducees
-			deliverMessage(sync0, contactId01, sync1, contactId1);
-			deliverMessage(sync0, contactId02, sync1, contactId2);
-
-			// wait for "both" introducees to abort session
-			eventWaiter.await(TIMEOUT, 2);
-			assertTrue(listener1.aborted);
-
-			// sync abort message
-			deliverMessage(sync1, contactId1, sync0, contactId01);
-			deliverMessage(sync1, contactId2, sync0, contactId02);
-
-			// wait for introducer to abort session (gets event twice)
-			eventWaiter.await(TIMEOUT, 2);
-			assertTrue(listener0.aborted);
-
-			assertFalse(contactManager1
-					.contactExists(author1.getId(), author2.getId()));
-			assertFalse(contactManager1
-					.contactExists(author2.getId(), author1.getId()));
-
-			assertEquals(2, introductionManager0.getIntroductionMessages(
-					contactId1).size());
-			assertEquals(2, introductionManager0.getIntroductionMessages(
-					contactId2).size());
-			assertEquals(2, introductionManager1.getIntroductionMessages(
-					contactId01).size());
-			assertEquals(2, introductionManager1.getIntroductionMessages(
-					contactId02).size());
-		} finally {
-			stopLifecycles();
-		}
-	}
-
-	// TODO add a test for faking responses when #256 is implemented
-
-	@After
-	public void tearDown() throws InterruptedException {
-		TestUtils.deleteTestDirectory(testDir);
-	}
-
-	private void startLifecycles() throws InterruptedException {
-		// Start the lifecycle manager and wait for it to finish
-		lifecycleManager0 = t0.getLifecycleManager();
-		lifecycleManager1 = t1.getLifecycleManager();
-		lifecycleManager2 = t2.getLifecycleManager();
-		lifecycleManager0.startServices();
-		lifecycleManager1.startServices();
-		lifecycleManager2.startServices();
-		lifecycleManager0.waitForStartup();
-		lifecycleManager1.waitForStartup();
-		lifecycleManager2.waitForStartup();
-	}
-
-	private void stopLifecycles() throws InterruptedException {
-		// Clean up
-		lifecycleManager0.stopServices();
-		lifecycleManager1.stopServices();
-		lifecycleManager2.stopServices();
-		lifecycleManager0.waitForShutdown();
-		lifecycleManager1.waitForShutdown();
-		lifecycleManager2.waitForShutdown();
-	}
-
-	private void addTransportProperties() throws DbException {
-		TransportPropertyManager tpm0 = t0.getTransportPropertyManager();
-		TransportPropertyManager tpm1 = t1.getTransportPropertyManager();
-		TransportPropertyManager tpm2 = t2.getTransportPropertyManager();
-
-		TransportProperties tp = new TransportProperties(
-				Collections.singletonMap("key", "value"));
-		tpm0.mergeLocalProperties(TRANSPORT_ID, tp);
-		tpm1.mergeLocalProperties(TRANSPORT_ID, tp);
-		tpm2.mergeLocalProperties(TRANSPORT_ID, tp);
-	}
-
-	private void addDefaultIdentities() throws DbException {
-		author0 = authorFactory.createLocalAuthor(INTRODUCER,
-				TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
-				TestUtils.getRandomBytes(123));
-		identityManager0.addLocalAuthor(author0);
-		author1 = authorFactory.createLocalAuthor(INTRODUCEE1,
-				TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
-				TestUtils.getRandomBytes(123));
-		identityManager1.addLocalAuthor(author1);
-		author2 = authorFactory.createLocalAuthor(INTRODUCEE2,
-				TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
-				TestUtils.getRandomBytes(123));
-		identityManager2.addLocalAuthor(author2);
-	}
-
-	private void deliverMessage(SyncSessionFactory fromSync, ContactId fromId,
-			SyncSessionFactory toSync, ContactId toId)
-			throws IOException, TimeoutException {
-		deliverMessage(fromSync, fromId, toSync, toId, null);
-	}
-
-	private void deliverMessage(SyncSessionFactory fromSync, ContactId fromId,
-			SyncSessionFactory toSync, ContactId toId, String debug)
-			throws IOException, TimeoutException {
-
-		if (debug != null) LOG.info("TEST: Sending message from " + debug);
-
-		ByteArrayOutputStream out = new ByteArrayOutputStream();
-		// Create an outgoing sync session
-		SyncSession sessionFrom =
-				fromSync.createSimplexOutgoingSession(toId, MAX_LATENCY, out);
-		// Write whatever needs to be written
-		sessionFrom.run();
-		out.close();
-
-		ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
-		// Create an incoming sync session
-		SyncSession sessionTo = toSync.createIncomingSession(fromId, in);
-		// Read whatever needs to be read
-		sessionTo.run();
-		in.close();
-
-		// wait for message to actually arrive
-		msgWaiter.await(TIMEOUT, 1);
-	}
-
-	private void assertDefaultUiMessages() throws DbException {
-		assertEquals(2, introductionManager0.getIntroductionMessages(
-				contactId1).size());
-		assertEquals(2, introductionManager0.getIntroductionMessages(
-				contactId2).size());
-		assertEquals(2, introductionManager1.getIntroductionMessages(
-				contactId0).size());
-		assertEquals(2, introductionManager2.getIntroductionMessages(
-				contactId0).size());
-	}
-
-	private class IntroduceeListener implements EventListener {
-
-		public volatile boolean requestReceived = false;
-		public volatile boolean succeeded = false;
-		public volatile boolean aborted = false;
-
-		private final int introducee;
-		private final boolean accept;
-
-		IntroduceeListener(int introducee, boolean accept) {
-			this.introducee = introducee;
-			this.accept = accept;
-		}
-
-		public void eventOccurred(Event e) {
-			if (e instanceof MessageValidatedEvent) {
-				MessageValidatedEvent event = (MessageValidatedEvent) e;
-				if (event.getClientId()
-						.equals(introductionManager0.getClientId()) &&
-						!event.isLocal()) {
-					LOG.info("TEST: Introducee" + introducee +
-							" received message in group " +
-							((MessageValidatedEvent) e).getMessage()
-									.getGroupId().hashCode());
-					msgWaiter.resume();
-				}
-			} else if (e instanceof IntroductionRequestReceivedEvent) {
-				IntroductionRequestReceivedEvent introEvent =
-						((IntroductionRequestReceivedEvent) e);
-				requestReceived = true;
-				IntroductionRequest ir = introEvent.getIntroductionRequest();
-				ContactId contactId = introEvent.getContactId();
-				SessionId sessionId = ir.getSessionId();
-				long time = clock.currentTimeMillis();
-				try {
-					if (introducee == 1) {
-						if (accept) {
-							introductionManager1
-									.acceptIntroduction(contactId, sessionId,
-											time);
-						} else {
-							introductionManager1
-									.declineIntroduction(contactId, sessionId,
-											time);
-						}
-					} else if (introducee == 2) {
-						if (accept) {
-							introductionManager2
-									.acceptIntroduction(contactId, sessionId,
-											time);
-						} else {
-							introductionManager2
-									.declineIntroduction(contactId, sessionId,
-											time);
-						}
-					}
-				} catch (DbException exception) {
-					eventWaiter.rethrow(exception);
-				} catch (IOException exception) {
-					eventWaiter.rethrow(exception);
-				} finally {
-					eventWaiter.resume();
-				}
-			} else if (e instanceof IntroductionSucceededEvent) {
-				succeeded = true;
-				Contact contact = ((IntroductionSucceededEvent) e).getContact();
-				eventWaiter.assertFalse(contact.getId().equals(contactId0));
-				eventWaiter.assertTrue(contact.isActive());
-				eventWaiter.resume();
-			} else if (e instanceof IntroductionAbortedEvent) {
-				aborted = true;
-				eventWaiter.resume();
-			}
-		}
-	}
-
-	private class IntroducerListener implements EventListener {
-
-		public volatile boolean response1Received = false;
-		public volatile boolean response2Received = false;
-		public volatile boolean aborted = false;
-
-		public void eventOccurred(Event e) {
-			if (e instanceof MessageValidatedEvent) {
-				MessageValidatedEvent event = (MessageValidatedEvent) e;
-				if (event.getClientId()
-						.equals(introductionManager0.getClientId()) &&
-						!event.isLocal()) {
-					LOG.info("TEST: Introducer received message in group " +
-							((MessageValidatedEvent) e).getMessage()
-									.getGroupId().hashCode());
-					msgWaiter.resume();
-				}
-			} else if (e instanceof IntroductionResponseReceivedEvent) {
-				ContactId c =
-						((IntroductionResponseReceivedEvent) e).getContactId();
-				try {
-					if (c.equals(contactId1)) {
-						response1Received = true;
-					} else if (c.equals(contactId2)) {
-						response2Received = true;
-					}
-				} finally {
-					eventWaiter.resume();
-				}
-			} else if (e instanceof IntroductionAbortedEvent) {
-				aborted = true;
-				eventWaiter.resume();
-			}
-		}
-	}
-
-	private void injectEagerSingletons(
-			IntroductionIntegrationTestComponent component) {
-
-		component.inject(new LifecycleModule.EagerSingletons());
-		component.inject(new LifecycleModule.EagerSingletons());
-		component.inject(new IntroductionModule.EagerSingletons());
-		component.inject(new CryptoModule.EagerSingletons());
-		component.inject(new ContactModule.EagerSingletons());
-		component.inject(new TransportModule.EagerSingletons());
-		component.inject(new SyncModule.EagerSingletons());
-		component.inject(new PropertiesModule.EagerSingletons());
-	}
-
-}
diff --git a/briar-android/test/java/briarproject/IntroductionIntegrationTestComponent.java b/briar-android/test/java/briarproject/IntroductionIntegrationTestComponent.java
deleted file mode 100644
index d86b50d7c9fc0421b51f628f024a0173e3e2a48f..0000000000000000000000000000000000000000
--- a/briar-android/test/java/briarproject/IntroductionIntegrationTestComponent.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package briarproject;
-
-import org.briarproject.TestDatabaseModule;
-import org.briarproject.TestPluginsModule;
-import org.briarproject.TestSystemModule;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.introduction.IntroductionManager;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.properties.TransportPropertyManager;
-import org.briarproject.api.sync.SyncSessionFactory;
-import org.briarproject.clients.ClientsModule;
-import org.briarproject.contact.ContactModule;
-import org.briarproject.crypto.CryptoModule;
-import org.briarproject.data.DataModule;
-import org.briarproject.db.DatabaseModule;
-import org.briarproject.event.EventModule;
-import org.briarproject.identity.IdentityModule;
-import org.briarproject.introduction.IntroductionModule;
-import org.briarproject.lifecycle.LifecycleModule;
-import org.briarproject.properties.PropertiesModule;
-import org.briarproject.sync.SyncModule;
-import org.briarproject.transport.TransportModule;
-
-import javax.inject.Singleton;
-
-import dagger.Component;
-
-@Singleton
-@Component(modules = {
-		TestSystemModule.class,
-		TestDatabaseModule.class,
-		TestPluginsModule.class,
-		LifecycleModule.class,
-		IntroductionModule.class,
-		DatabaseModule.class,
-		CryptoModule.class,
-		EventModule.class,
-		ContactModule.class,
-		IdentityModule.class,
-		TransportModule.class,
-		ClientsModule.class,
-		SyncModule.class,
-		DataModule.class,
-		PropertiesModule.class
-})
-public interface IntroductionIntegrationTestComponent {
-
-	void inject(IntroductionIntegrationTest testCase);
-
-	void inject(ContactModule.EagerSingletons init);
-
-	void inject(CryptoModule.EagerSingletons init);
-
-	void inject(IntroductionModule.EagerSingletons init);
-
-	void inject(LifecycleModule.EagerSingletons init);
-
-	void inject(PropertiesModule.EagerSingletons init);
-
-	void inject(SyncModule.EagerSingletons init);
-
-	void inject(TransportModule.EagerSingletons init);
-
-	LifecycleManager getLifecycleManager();
-
-	EventBus getEventBus();
-
-	IdentityManager getIdentityManager();
-
-	ContactManager getContactManager();
-
-	IntroductionManager getIntroductionManager();
-
-	TransportPropertyManager getTransportPropertyManager();
-
-	SyncSessionFactory getSyncSessionFactory();
-
-}
diff --git a/briar-android/test/java/briarproject/MessageSizeIntegrationTest.java b/briar-android/test/java/briarproject/MessageSizeIntegrationTest.java
deleted file mode 100644
index d46c26f434423879ff9e8b1662b6198a37fddffa..0000000000000000000000000000000000000000
--- a/briar-android/test/java/briarproject/MessageSizeIntegrationTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package briarproject;
-
-import org.briarproject.BriarTestCase;
-import org.briarproject.TestUtils;
-import org.briarproject.api.UniqueId;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.PrivateKey;
-import org.briarproject.api.forum.ForumConstants;
-import org.briarproject.api.forum.ForumPost;
-import org.briarproject.api.forum.ForumPostFactory;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.messaging.MessagingConstants;
-import org.briarproject.api.messaging.PrivateMessage;
-import org.briarproject.api.messaging.PrivateMessageFactory;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.junit.Test;
-
-import javax.inject.Inject;
-
-import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
-import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
-import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
-import static org.briarproject.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
-import static org.briarproject.api.sync.SyncConstants.MAX_PACKET_PAYLOAD_LENGTH;
-import static org.junit.Assert.assertTrue;
-
-public class MessageSizeIntegrationTest extends BriarTestCase {
-
-	@Inject
-	CryptoComponent crypto;
-	@Inject
-	AuthorFactory authorFactory;
-	@Inject
-	PrivateMessageFactory privateMessageFactory;
-	@Inject
-	ForumPostFactory forumPostFactory;
-
-	public MessageSizeIntegrationTest() throws Exception {
-		MessageSizeIntegrationTestComponent component =
-				DaggerMessageSizeIntegrationTestComponent.builder().build();
-		component.inject(this);
-	}
-
-	@Test
-	public void testPrivateMessageFitsIntoPacket() throws Exception {
-		// Create a maximum-length private message
-		GroupId groupId = new GroupId(TestUtils.getRandomId());
-		long timestamp = Long.MAX_VALUE;
-		MessageId parent = new MessageId(TestUtils.getRandomId());
-		String contentType = TestUtils.getRandomString(
-				MessagingConstants.MAX_CONTENT_TYPE_LENGTH);
-		byte[] body = new byte[MAX_PRIVATE_MESSAGE_BODY_LENGTH];
-		PrivateMessage message = privateMessageFactory.createPrivateMessage(
-				groupId, timestamp, parent, contentType, body);
-		// Check the size of the serialised message
-		int length = message.getMessage().getRaw().length;
-		assertTrue(length > UniqueId.LENGTH + 8 + UniqueId.LENGTH
-				+ MessagingConstants.MAX_CONTENT_TYPE_LENGTH
-				+ MAX_PRIVATE_MESSAGE_BODY_LENGTH);
-		assertTrue(length <= MAX_PACKET_PAYLOAD_LENGTH);
-	}
-
-	@Test
-	public void testForumPostFitsIntoPacket() throws Exception {
-		// Create a maximum-length author
-		String authorName = TestUtils.getRandomString(
-				MAX_AUTHOR_NAME_LENGTH);
-		byte[] authorPublic = new byte[MAX_PUBLIC_KEY_LENGTH];
-		Author author = authorFactory.createAuthor(authorName, authorPublic);
-		// Create a maximum-length forum post
-		GroupId groupId = new GroupId(TestUtils.getRandomId());
-		long timestamp = Long.MAX_VALUE;
-		MessageId parent = new MessageId(TestUtils.getRandomId());
-		String contentType = TestUtils.getRandomString(
-				ForumConstants.MAX_CONTENT_TYPE_LENGTH);
-		byte[] body = new byte[MAX_FORUM_POST_BODY_LENGTH];
-		PrivateKey privateKey = crypto.generateSignatureKeyPair().getPrivate();
-		ForumPost post = forumPostFactory.createPseudonymousPost(groupId,
-				timestamp, parent, author, contentType, body, privateKey);
-		// Check the size of the serialised message
-		int length = post.getMessage().getRaw().length;
-		assertTrue(length > UniqueId.LENGTH + 8 + UniqueId.LENGTH
-				+ MAX_AUTHOR_NAME_LENGTH + MAX_PUBLIC_KEY_LENGTH
-				+ ForumConstants.MAX_CONTENT_TYPE_LENGTH
-				+ MAX_FORUM_POST_BODY_LENGTH);
-		assertTrue(length <= MAX_PACKET_PAYLOAD_LENGTH);
-	}
-}
diff --git a/briar-android/test/java/briarproject/MessageSizeIntegrationTestComponent.java b/briar-android/test/java/briarproject/MessageSizeIntegrationTestComponent.java
deleted file mode 100644
index 9f112fb6b90fba0275edf85e81494ea37116284f..0000000000000000000000000000000000000000
--- a/briar-android/test/java/briarproject/MessageSizeIntegrationTestComponent.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package briarproject;
-
-import org.briarproject.TestDatabaseModule;
-import org.briarproject.TestLifecycleModule;
-import org.briarproject.TestSystemModule;
-import org.briarproject.clients.ClientsModule;
-import org.briarproject.crypto.CryptoModule;
-import org.briarproject.data.DataModule;
-import org.briarproject.db.DatabaseModule;
-import org.briarproject.event.EventModule;
-import org.briarproject.forum.ForumModule;
-import org.briarproject.identity.IdentityModule;
-import org.briarproject.messaging.MessagingModule;
-import org.briarproject.sync.SyncModule;
-
-import javax.inject.Singleton;
-
-import dagger.Component;
-
-@Singleton
-@Component(modules = {
-		TestDatabaseModule.class,
-		TestLifecycleModule.class,
-		TestSystemModule.class,
-		ClientsModule.class,
-		CryptoModule.class,
-		DataModule.class,
-		DatabaseModule.class,
-		EventModule.class,
-		ForumModule.class,
-		IdentityModule.class,
-		MessagingModule.class,
-		SyncModule.class
-})
-public interface MessageSizeIntegrationTestComponent {
-	void inject(MessageSizeIntegrationTest testCase);
-}
diff --git a/briar-android/test/java/briarproject/SimplexMessagingIntegrationTest.java b/briar-android/test/java/briarproject/SimplexMessagingIntegrationTest.java
deleted file mode 100644
index 53e7d03a3a6b9bf59f61be5d568823b1b927e3c9..0000000000000000000000000000000000000000
--- a/briar-android/test/java/briarproject/SimplexMessagingIntegrationTest.java
+++ /dev/null
@@ -1,193 +0,0 @@
-package briarproject;
-
-import org.briarproject.BriarTestCase;
-import org.briarproject.TestDatabaseModule;
-import org.briarproject.TestUtils;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.MessageAddedEvent;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.messaging.MessagingManager;
-import org.briarproject.api.messaging.PrivateMessage;
-import org.briarproject.api.messaging.PrivateMessageFactory;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.SyncSession;
-import org.briarproject.api.sync.SyncSessionFactory;
-import org.briarproject.api.transport.KeyManager;
-import org.briarproject.api.transport.StreamContext;
-import org.briarproject.api.transport.StreamReaderFactory;
-import org.briarproject.api.transport.StreamWriterFactory;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import static org.briarproject.TestPluginsModule.MAX_LATENCY;
-import static org.briarproject.TestPluginsModule.TRANSPORT_ID;
-import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-public class SimplexMessagingIntegrationTest extends BriarTestCase {
-
-	private final File testDir = TestUtils.getTestDirectory();
-	private final File aliceDir = new File(testDir, "alice");
-	private final File bobDir = new File(testDir, "bob");
-	private final SecretKey master = TestUtils.getSecretKey();
-	private final long timestamp = System.currentTimeMillis();
-	private final AuthorId aliceId = new AuthorId(TestUtils.getRandomId());
-	private final AuthorId bobId = new AuthorId(TestUtils.getRandomId());
-
-	private SimplexMessagingIntegrationTestComponent alice, bob;
-
-	@Before
-	public void setUp() {
-		assertTrue(testDir.mkdirs());
-		alice = DaggerSimplexMessagingIntegrationTestComponent.builder()
-				.testDatabaseModule(new TestDatabaseModule(aliceDir)).build();
-		bob = DaggerSimplexMessagingIntegrationTestComponent.builder()
-				.testDatabaseModule(new TestDatabaseModule(bobDir)).build();
-	}
-
-	@Test
-	public void testWriteAndRead() throws Exception {
-		read(write());
-	}
-
-	private byte[] write() throws Exception {
-		// Instantiate Alice's services
-		LifecycleManager lifecycleManager = alice.getLifecycleManager();
-		IdentityManager identityManager = alice.getIdentityManager();
-		ContactManager contactManager = alice.getContactManager();
-		MessagingManager messagingManager = alice.getMessagingManager();
-		KeyManager keyManager = alice.getKeyManager();
-		PrivateMessageFactory privateMessageFactory =
-				alice.getPrivateMessageFactory();
-		StreamWriterFactory streamWriterFactory =
-				alice.getStreamWriterFactory();
-		SyncSessionFactory syncSessionFactory = alice.getSyncSessionFactory();
-
-		// Start the lifecycle manager
-		lifecycleManager.startServices();
-		lifecycleManager.waitForStartup();
-		// Add an identity for Alice
-		LocalAuthor aliceAuthor = new LocalAuthor(aliceId, "Alice",
-				new byte[MAX_PUBLIC_KEY_LENGTH], new byte[123], timestamp);
-		identityManager.addLocalAuthor(aliceAuthor);
-		// Add Bob as a contact
-		Author bobAuthor = new Author(bobId, "Bob",
-				new byte[MAX_PUBLIC_KEY_LENGTH]);
-		ContactId contactId = contactManager.addContact(bobAuthor, aliceId,
-				master, timestamp, true, true);
-
-		// Send Bob a message
-		GroupId groupId = messagingManager.getConversationId(contactId);
-		byte[] body = "Hi Bob!".getBytes("UTF-8");
-		PrivateMessage message = privateMessageFactory.createPrivateMessage(
-				groupId, timestamp, null, "text/plain", body);
-		messagingManager.addLocalMessage(message);
-		// Get a stream context
-		StreamContext ctx = keyManager.getStreamContext(contactId,
-				TRANSPORT_ID);
-		assertNotNull(ctx);
-		// Create a stream writer
-		ByteArrayOutputStream out = new ByteArrayOutputStream();
-		OutputStream streamWriter = streamWriterFactory.createStreamWriter(
-				out, ctx);
-		// Create an outgoing sync session
-		SyncSession session = syncSessionFactory.createSimplexOutgoingSession(
-				contactId, MAX_LATENCY, streamWriter);
-		// Write whatever needs to be written
-		session.run();
-		streamWriter.close();
-
-		// Clean up
-		lifecycleManager.stopServices();
-		lifecycleManager.waitForShutdown();
-
-		// Return the contents of the stream
-		return out.toByteArray();
-	}
-
-	private void read(byte[] stream) throws Exception {
-		// Instantiate Bob's services
-		LifecycleManager lifecycleManager = bob.getLifecycleManager();
-		IdentityManager identityManager = bob.getIdentityManager();
-		ContactManager contactManager = bob.getContactManager();
-		KeyManager keyManager = bob.getKeyManager();
-		StreamReaderFactory streamReaderFactory = bob.getStreamReaderFactory();
-		SyncSessionFactory syncSessionFactory = bob.getSyncSessionFactory();
-		// Bob needs a MessagingManager even though we're not using it directly
-		bob.getMessagingManager();
-
-		// Start the lifecyle manager
-		lifecycleManager.startServices();
-		lifecycleManager.waitForStartup();
-		// Add an identity for Bob
-		LocalAuthor bobAuthor = new LocalAuthor(bobId, "Bob",
-				new byte[MAX_PUBLIC_KEY_LENGTH], new byte[123], timestamp);
-		identityManager.addLocalAuthor(bobAuthor);
-		// Add Alice as a contact
-		Author aliceAuthor = new Author(aliceId, "Alice",
-				new byte[MAX_PUBLIC_KEY_LENGTH]);
-		ContactId contactId = contactManager.addContact(aliceAuthor, bobId,
-				master, timestamp, false, true);
-
-		// Set up an event listener
-		MessageListener listener = new MessageListener();
-		bob.getEventBus().addListener(listener);
-		// Read and recognise the tag
-		ByteArrayInputStream in = new ByteArrayInputStream(stream);
-		byte[] tag = new byte[TAG_LENGTH];
-		int read = in.read(tag);
-		assertEquals(tag.length, read);
-		StreamContext ctx = keyManager.getStreamContext(TRANSPORT_ID, tag);
-		assertNotNull(ctx);
-		// Create a stream reader
-		InputStream streamReader = streamReaderFactory.createStreamReader(
-				in, ctx);
-		// Create an incoming sync session
-		SyncSession session = syncSessionFactory.createIncomingSession(
-				contactId, streamReader);
-		// No messages should have been added yet
-		assertFalse(listener.messageAdded);
-		// Read whatever needs to be read
-		session.run();
-		streamReader.close();
-		// The private message from Alice should have been added
-		assertTrue(listener.messageAdded);
-
-		// Clean up
-		lifecycleManager.stopServices();
-		lifecycleManager.waitForShutdown();
-	}
-
-	@After
-	public void tearDown() {
-		TestUtils.deleteTestDirectory(testDir);
-	}
-
-	private static class MessageListener implements EventListener {
-
-		private volatile boolean messageAdded = false;
-
-		public void eventOccurred(Event e) {
-			if (e instanceof MessageAddedEvent) messageAdded = true;
-		}
-	}
-}
diff --git a/briar-android/test/java/briarproject/SimplexMessagingIntegrationTestComponent.java b/briar-android/test/java/briarproject/SimplexMessagingIntegrationTestComponent.java
deleted file mode 100644
index 7691b81924be4882a19a2e26500345cd722e2436..0000000000000000000000000000000000000000
--- a/briar-android/test/java/briarproject/SimplexMessagingIntegrationTestComponent.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package briarproject;
-
-import org.briarproject.TestDatabaseModule;
-import org.briarproject.TestPluginsModule;
-import org.briarproject.TestSystemModule;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.messaging.MessagingManager;
-import org.briarproject.api.messaging.PrivateMessageFactory;
-import org.briarproject.api.sync.SyncSessionFactory;
-import org.briarproject.api.transport.KeyManager;
-import org.briarproject.api.transport.StreamReaderFactory;
-import org.briarproject.api.transport.StreamWriterFactory;
-import org.briarproject.clients.ClientsModule;
-import org.briarproject.contact.ContactModule;
-import org.briarproject.crypto.CryptoModule;
-import org.briarproject.data.DataModule;
-import org.briarproject.db.DatabaseModule;
-import org.briarproject.event.EventModule;
-import org.briarproject.identity.IdentityModule;
-import org.briarproject.lifecycle.LifecycleModule;
-import org.briarproject.messaging.MessagingModule;
-import org.briarproject.plugins.PluginsModule;
-import org.briarproject.sync.SyncModule;
-import org.briarproject.transport.TransportModule;
-
-import javax.inject.Singleton;
-
-import dagger.Component;
-
-@Singleton
-@Component(modules = {
-		TestDatabaseModule.class,
-		TestPluginsModule.class,
-		TestSystemModule.class,
-		ClientsModule.class,
-		ContactModule.class,
-		CryptoModule.class,
-		DataModule.class,
-		DatabaseModule.class,
-		EventModule.class,
-		IdentityModule.class,
-		LifecycleModule.class,
-		MessagingModule.class,
-		PluginsModule.class,
-		SyncModule.class,
-		TransportModule.class
-})
-public interface SimplexMessagingIntegrationTestComponent {
-
-	void inject(SimplexMessagingIntegrationTest testCase);
-
-	LifecycleManager getLifecycleManager();
-
-	IdentityManager getIdentityManager();
-
-	ContactManager getContactManager();
-
-	MessagingManager getMessagingManager();
-
-	KeyManager getKeyManager();
-
-	PrivateMessageFactory getPrivateMessageFactory();
-
-	EventBus getEventBus();
-
-	StreamWriterFactory getStreamWriterFactory();
-
-	StreamReaderFactory getStreamReaderFactory();
-
-	SyncSessionFactory getSyncSessionFactory();
-}
diff --git a/briar-android/test/java/briarproject/SyncIntegrationTest.java b/briar-android/test/java/briarproject/SyncIntegrationTest.java
deleted file mode 100644
index 8d5dabfc33fe352d4af2511d0d3bd4f3c80a34b1..0000000000000000000000000000000000000000
--- a/briar-android/test/java/briarproject/SyncIntegrationTest.java
+++ /dev/null
@@ -1,169 +0,0 @@
-package briarproject;
-
-import org.briarproject.BriarTestCase;
-import org.briarproject.TestUtils;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.sync.Ack;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupFactory;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageFactory;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.sync.Offer;
-import org.briarproject.api.sync.PacketReader;
-import org.briarproject.api.sync.PacketReaderFactory;
-import org.briarproject.api.sync.PacketWriter;
-import org.briarproject.api.sync.PacketWriterFactory;
-import org.briarproject.api.sync.Request;
-import org.briarproject.api.transport.StreamContext;
-import org.briarproject.api.transport.StreamReaderFactory;
-import org.briarproject.api.transport.StreamWriterFactory;
-import org.junit.Test;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Arrays;
-import java.util.Collection;
-
-import javax.inject.Inject;
-
-import static org.briarproject.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class SyncIntegrationTest extends BriarTestCase {
-
-	@Inject
-	GroupFactory groupFactory;
-	@Inject
-	MessageFactory messageFactory;
-	@Inject
-	StreamReaderFactory streamReaderFactory;
-	@Inject
-	StreamWriterFactory streamWriterFactory;
-	@Inject
-	PacketReaderFactory packetReaderFactory;
-	@Inject
-	PacketWriterFactory packetWriterFactory;
-	@Inject
-	CryptoComponent crypto;
-
-	private final ContactId contactId;
-	private final TransportId transportId;
-	private final SecretKey tagKey, headerKey;
-	private final long streamNumber;
-	private final Message message, message1;
-	private final Collection<MessageId> messageIds;
-
-	public SyncIntegrationTest() throws Exception {
-
-		SyncIntegrationTestComponent component =
-				DaggerSyncIntegrationTestComponent.builder().build();
-		component.inject(this);
-
-		contactId = new ContactId(234);
-		transportId = new TransportId("id");
-		// Create the transport keys
-		tagKey = TestUtils.getSecretKey();
-		headerKey = TestUtils.getSecretKey();
-		streamNumber = 123;
-		// Create a group
-		ClientId clientId = new ClientId(TestUtils.getRandomId());
-		byte[] descriptor = new byte[MAX_GROUP_DESCRIPTOR_LENGTH];
-		Group group = groupFactory.createGroup(clientId, descriptor);
-		// Add two messages to the group
-		long timestamp = System.currentTimeMillis();
-		byte[] body = "Hello world".getBytes("UTF-8");
-		message = messageFactory.createMessage(group.getId(), timestamp, body);
-		message1 = messageFactory.createMessage(group.getId(), timestamp, body);
-		messageIds = Arrays.asList(message.getId(), message1.getId());
-	}
-
-	@Test
-	public void testWriteAndRead() throws Exception {
-		read(write());
-	}
-
-	private byte[] write() throws Exception {
-		ByteArrayOutputStream out = new ByteArrayOutputStream();
-		StreamContext ctx = new StreamContext(contactId, transportId, tagKey,
-				headerKey, streamNumber);
-		OutputStream streamWriter = streamWriterFactory.createStreamWriter(out,
-				ctx);
-		PacketWriter packetWriter = packetWriterFactory.createPacketWriter(
-				streamWriter);
-
-		packetWriter.writeAck(new Ack(messageIds));
-		packetWriter.writeMessage(message.getRaw());
-		packetWriter.writeMessage(message1.getRaw());
-		packetWriter.writeOffer(new Offer(messageIds));
-		packetWriter.writeRequest(new Request(messageIds));
-
-		streamWriter.flush();
-		return out.toByteArray();
-	}
-
-	private void read(byte[] connectionData) throws Exception {
-		// Calculate the expected tag
-		byte[] expectedTag = new byte[TAG_LENGTH];
-		crypto.encodeTag(expectedTag, tagKey, streamNumber);
-
-		// Read the tag
-		InputStream in = new ByteArrayInputStream(connectionData);
-		byte[] tag = new byte[TAG_LENGTH];
-		assertEquals(TAG_LENGTH, in.read(tag, 0, TAG_LENGTH));
-		assertArrayEquals(expectedTag, tag);
-
-		// Create the readers
-		StreamContext ctx = new StreamContext(contactId, transportId, tagKey,
-				headerKey, 0);
-		InputStream streamReader = streamReaderFactory.createStreamReader(in,
-				ctx);
-		PacketReader packetReader = packetReaderFactory.createPacketReader(
-				streamReader);
-
-		// Read the ack
-		assertTrue(packetReader.hasAck());
-		Ack a = packetReader.readAck();
-		assertEquals(messageIds, a.getMessageIds());
-
-		// Read the messages
-		assertTrue(packetReader.hasMessage());
-		Message m = packetReader.readMessage();
-		checkMessageEquality(message, m);
-		assertTrue(packetReader.hasMessage());
-		m = packetReader.readMessage();
-		checkMessageEquality(message1, m);
-		assertFalse(packetReader.hasMessage());
-
-		// Read the offer
-		assertTrue(packetReader.hasOffer());
-		Offer o = packetReader.readOffer();
-		assertEquals(messageIds, o.getMessageIds());
-
-		// Read the request
-		assertTrue(packetReader.hasRequest());
-		Request req = packetReader.readRequest();
-		assertEquals(messageIds, req.getMessageIds());
-
-		in.close();
-	}
-
-	private void checkMessageEquality(Message m1, Message m2) {
-		assertArrayEquals(m1.getId().getBytes(), m2.getId().getBytes());
-		assertArrayEquals(m1.getGroupId().getBytes(),
-				m2.getGroupId().getBytes());
-		assertEquals(m1.getTimestamp(), m2.getTimestamp());
-		assertEquals(m1.getLength(), m2.getLength());
-		assertArrayEquals(m1.getRaw(), m2.getRaw());
-	}
-}
diff --git a/briar-android/test/java/briarproject/SyncIntegrationTestComponent.java b/briar-android/test/java/briarproject/SyncIntegrationTestComponent.java
deleted file mode 100644
index ad3d4dfde1b5540991a2258a007ed7e7b84fd978..0000000000000000000000000000000000000000
--- a/briar-android/test/java/briarproject/SyncIntegrationTestComponent.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package briarproject;
-
-import org.briarproject.TestSystemModule;
-import org.briarproject.crypto.CryptoModule;
-import org.briarproject.sync.SyncModule;
-import org.briarproject.transport.TransportModule;
-
-import javax.inject.Singleton;
-
-import dagger.Component;
-
-@Singleton
-@Component(modules = {
-		TestSystemModule.class,
-		CryptoModule.class,
-		SyncModule.class,
-		TransportModule.class
-})
-public interface SyncIntegrationTestComponent {
-	void inject(SyncIntegrationTest testCase);
-}
diff --git a/briar-android/test/java/briarproject/activity/SetupActivityTest.java b/briar-android/test/java/briarproject/activity/SetupActivityTest.java
index 586cec9895fe297d54a92690355668e689ee5917..5adf7483d01bad749a552f62b6c3a2865f7bc611 100644
--- a/briar-android/test/java/briarproject/activity/SetupActivityTest.java
+++ b/briar-android/test/java/briarproject/activity/SetupActivityTest.java
@@ -47,7 +47,8 @@ import static org.mockito.Mockito.when;
 import static org.robolectric.Shadows.shadowOf;
 
 @RunWith(RobolectricGradleTestRunner.class)
-@Config(constants = BuildConfig.class, sdk = 21)
+@Config(constants = BuildConfig.class, sdk = 21,
+		application = TestBriarApplicationImp.class)
 public class SetupActivityTest {
 
 	TestSetupActivity setupActivity;
diff --git a/briar-android/test/java/briarproject/activity/TestBriarApplicationImp.java b/briar-android/test/java/briarproject/activity/TestBriarApplicationImp.java
new file mode 100644
index 0000000000000000000000000000000000000000..8e29d9efd238946a641c836aec944196f7ddd97c
--- /dev/null
+++ b/briar-android/test/java/briarproject/activity/TestBriarApplicationImp.java
@@ -0,0 +1,43 @@
+package briarproject.activity;
+
+import android.app.Application;
+
+import org.briarproject.CoreModule;
+import org.briarproject.android.AndroidComponent;
+import org.briarproject.android.AndroidEagerSingletons;
+import org.briarproject.android.AppModule;
+import org.briarproject.android.BriarApplication;
+import org.briarproject.android.DaggerAndroidComponent;
+
+import java.util.logging.Logger;
+
+/**
+ * This Class only exists to get around ACRA
+ */
+public class TestBriarApplicationImp extends Application implements
+		BriarApplication{
+
+	private static final Logger LOG =
+			Logger.getLogger(TestBriarApplicationImp.class.getName());
+
+	private AndroidComponent applicationComponent;
+
+	@Override
+	public void onCreate() {
+		super.onCreate();
+		LOG.info("Created");
+
+		applicationComponent = DaggerAndroidComponent.builder()
+				.appModule(new AppModule(this))
+				.build();
+
+		// We need to load the eager singletons directly after making the
+		// dependency graphs
+		CoreModule.initEagerSingletons(applicationComponent);
+		AndroidEagerSingletons.initEagerSingletons(applicationComponent);
+	}
+
+	public AndroidComponent getApplicationComponent() {
+		return applicationComponent;
+	}
+}
diff --git a/briar-core/src/org/briarproject/system/LinuxSeedProvider.java b/briar-core/src/org/briarproject/system/LinuxSeedProvider.java
index 6481b4a5f2f3d8eec0d2e8357898eeab7dc45713..d4bc00b5d24c02baff4f8b39eaa31dfd95706209 100644
--- a/briar-core/src/org/briarproject/system/LinuxSeedProvider.java
+++ b/briar-core/src/org/briarproject/system/LinuxSeedProvider.java
@@ -17,9 +17,6 @@ import static java.util.logging.Level.WARNING;
 
 class LinuxSeedProvider implements SeedProvider {
 
-	private static final Logger LOG =
-			Logger.getLogger(LinuxSeedProvider.class.getName());
-
 	private final String outputFile, inputFile;
 
 	LinuxSeedProvider() {