diff --git a/.gitignore b/.gitignore
index a436295beaa0d175f7f56f9f33f7cd81d1266f70..bf85d9ca1320a4f856d591d6a8144830076d91e4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,5 @@ local.properties
 .gradle
 build/
 *.iml
+.gitignore
+src/test/
diff --git a/bramble-android/.gitignore b/bramble-android/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..6653bfd64fcd8e20bd2075582b5d3148e5a77f39
--- /dev/null
+++ b/bramble-android/.gitignore
@@ -0,0 +1,5 @@
+bin
+gen
+build
+.settings
+src/main/res/raw/*.zip
diff --git a/bramble-android/build.gradle b/bramble-android/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..d161cee904f767496e85c24ba3af807f448009bb
--- /dev/null
+++ b/bramble-android/build.gradle
@@ -0,0 +1,104 @@
+import de.undercouch.gradle.tasks.download.Download
+import de.undercouch.gradle.tasks.download.Verify
+
+apply plugin: 'com.android.library'
+apply plugin: 'witness'
+apply plugin: 'de.undercouch.download'
+
+android {
+	compileSdkVersion 23
+	buildToolsVersion "23.0.3"
+
+	defaultConfig {
+		minSdkVersion 14
+		targetSdkVersion 22
+		versionCode 1
+		versionName "1.0"
+		consumerProguardFiles 'proguard-rules.txt'
+	}
+
+	compileOptions {
+		sourceCompatibility JavaVersion.VERSION_1_7
+		targetCompatibility JavaVersion.VERSION_1_7
+	}
+}
+
+dependencies {
+	compile project(':bramble-core')
+	compile fileTree(dir: 'libs', include: ['*.jar'])
+	provided 'javax.annotation:jsr250-api:1.0'
+}
+
+def torBinaryDir = 'src/main/res/raw'
+
+task downloadTorGeoIp(type: Download) {
+	src 'https://briarproject.org/build/geoip-2015-12-01.zip'
+	dest "$torBinaryDir/geoip.zip"
+	onlyIfNewer true
+}
+
+task downloadTorBinaryArm(type: Download) {
+	src 'https://briarproject.org/build/tor-0.2.7.6-arm.zip'
+	dest "$torBinaryDir/tor_arm.zip"
+	onlyIfNewer true
+}
+
+task downloadTorBinaryArmPie(type: Download) {
+	src 'https://briarproject.org/build/tor-0.2.7.6-arm-pie.zip'
+	dest "$torBinaryDir/tor_arm_pie.zip"
+	onlyIfNewer true
+}
+
+task downloadTorBinaryX86(type: Download) {
+	src 'https://briarproject.org/build/tor-0.2.7.6-x86.zip'
+	dest "$torBinaryDir/tor_x86.zip"
+	onlyIfNewer true
+}
+
+task downloadTorBinaryX86Pie(type: Download) {
+	src 'https://briarproject.org/build/tor-0.2.7.6-x86-pie.zip'
+	dest "$torBinaryDir/tor_x86_pie.zip"
+	onlyIfNewer true
+}
+
+task verifyTorGeoIp(type: Verify, dependsOn: 'downloadTorGeoIp') {
+	src "$torBinaryDir/geoip.zip"
+	algorithm 'SHA-256'
+	checksum '9bcdaf0a7ba0933735328d8ec466c25c25dbb459efc2bce9e55c774eabea5162'
+}
+
+task verifyTorBinaryArm(type: Verify, dependsOn: 'downloadTorBinaryArm') {
+	src "$torBinaryDir/tor_arm.zip"
+	algorithm 'SHA-256'
+	checksum '83272962eda701cd5d74d2418651c4ff0f0b1dff51f558a292d1a1c42bf12146'
+}
+
+task verifyTorBinaryArmPie(type: Verify, dependsOn: 'downloadTorBinaryArmPie') {
+	src "$torBinaryDir/tor_arm_pie.zip"
+	algorithm 'SHA-256'
+	checksum 'd0300d1e45de11ebb24ed62b9c492be9c2e88590b7822195ab38c7a76ffcf646'
+}
+
+task verifyTorBinaryX86(type: Verify, dependsOn: 'downloadTorBinaryX86') {
+	src "$torBinaryDir/tor_x86.zip"
+	algorithm 'SHA-256'
+	checksum 'b8813d97b01ee1b9c9a4233c1b9bbe9f9f6b494ae6f9cbd84de8a3911911615e'
+}
+
+task verifyTorBinaryX86Pie(type: Verify, dependsOn: 'downloadTorBinaryX86Pie') {
+	src "$torBinaryDir/tor_x86_pie.zip"
+	algorithm 'SHA-256'
+	checksum '9c66e765aa196dc089951a1b2140cc8290305c2fcbf365121f99e01a233baf4e'
+}
+
+project.afterEvaluate {
+	preBuild.dependsOn {
+		[
+				'verifyTorGeoIp',
+				'verifyTorBinaryArm',
+				'verifyTorBinaryArmPie',
+				'verifyTorBinaryX86',
+				'verifyTorBinaryX86Pie'
+		]
+	}
+}
diff --git a/briar-android/libs/jtorctl-briar.jar b/bramble-android/libs/jtorctl-briar.jar
similarity index 100%
rename from briar-android/libs/jtorctl-briar.jar
rename to bramble-android/libs/jtorctl-briar.jar
diff --git a/bramble-android/proguard-rules.txt b/bramble-android/proguard-rules.txt
new file mode 100644
index 0000000000000000000000000000000000000000..30918ebc48e141f21555ca5019ba12dc7563fad1
--- /dev/null
+++ b/bramble-android/proguard-rules.txt
@@ -0,0 +1,15 @@
+-keep,includedescriptorclasses class org.briarproject.** { *; }
+
+-keep class org.h2.** { *; }
+-dontwarn org.h2.**
+-dontnote org.h2.**
+
+-keep class dagger.** { *; }
+-dontwarn dagger.**
+-dontnote dagger.**
+
+-dontwarn sun.misc.Unsafe
+-dontnote com.google.common.**
+
+# UPnP library isn't used
+-dontwarn org.bitlet.weupnp.**
diff --git a/bramble-android/src/main/AndroidManifest.xml b/bramble-android/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..eeb86de52b9bb1b5a91f8355865b21f9a4c466cf
--- /dev/null
+++ b/bramble-android/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<manifest
+	package="org.briarproject.bramble"
+	xmlns:android="http://schemas.android.com/apk/res/android">
+
+	<uses-feature android:name="android.hardware.bluetooth"/>
+
+	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+	<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+	<uses-permission android:name="android.permission.BLUETOOTH"/>
+	<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
+	<uses-permission android:name="android.permission.INTERNET"/>
+	<uses-permission android:name="android.permission.READ_LOGS"/>
+	<uses-permission android:name="android.permission.WAKE_LOCK"/>
+	<!-- Since API 23, this is needed to add contacts via Bluetooth -->
+	<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+
+	<application
+		android:allowBackup="false"
+		android:label="@string/app_name"
+		android:supportsRtl="true">
+
+	</application>
+
+</manifest>
diff --git a/bramble-android/src/main/java/org/briarproject/bramble/BrambleAndroidModule.java b/bramble-android/src/main/java/org/briarproject/bramble/BrambleAndroidModule.java
new file mode 100644
index 0000000000000000000000000000000000000000..dd5e9c39425dea9cd8621a5c45b4802dced3eca9
--- /dev/null
+++ b/bramble-android/src/main/java/org/briarproject/bramble/BrambleAndroidModule.java
@@ -0,0 +1,13 @@
+package org.briarproject.bramble;
+
+import org.briarproject.bramble.plugin.AndroidPluginModule;
+import org.briarproject.bramble.system.AndroidSystemModule;
+
+import dagger.Module;
+
+@Module(includes = {
+		AndroidPluginModule.class,
+		AndroidSystemModule.class
+})
+public class BrambleAndroidModule {
+}
diff --git a/briar-android/src/org/briarproject/android/api/AndroidExecutor.java b/bramble-android/src/main/java/org/briarproject/bramble/api/system/AndroidExecutor.java
similarity index 94%
rename from briar-android/src/org/briarproject/android/api/AndroidExecutor.java
rename to bramble-android/src/main/java/org/briarproject/bramble/api/system/AndroidExecutor.java
index 7ea06bc2bd020841367da67fc2cb27b73367a911..facb76382eec8dc63a05474d1efd4c05f003ea3d 100644
--- a/briar-android/src/org/briarproject/android/api/AndroidExecutor.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/api/system/AndroidExecutor.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.api;
+package org.briarproject.bramble.api.system;
 
 import java.util.concurrent.Callable;
 import java.util.concurrent.Future;
diff --git a/briar-android/src/org/briarproject/plugins/AndroidPluginsModule.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/AndroidPluginModule.java
similarity index 55%
rename from briar-android/src/org/briarproject/plugins/AndroidPluginsModule.java
rename to bramble-android/src/main/java/org/briarproject/bramble/plugin/AndroidPluginModule.java
index 4d49a13ac71e204fd45678065439aaf636d4f84b..1f0055ae71b3dc7d34ecf22f26b74cc392dec505 100644
--- a/briar-android/src/org/briarproject/plugins/AndroidPluginsModule.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/AndroidPluginModule.java
@@ -1,20 +1,21 @@
-package org.briarproject.plugins;
+package org.briarproject.bramble.plugin;
 
 import android.app.Application;
 import android.content.Context;
 
-import org.briarproject.android.api.AndroidExecutor;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.lifecycle.IoExecutor;
-import org.briarproject.api.plugins.BackoffFactory;
-import org.briarproject.api.plugins.PluginConfig;
-import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
-import org.briarproject.api.plugins.simplex.SimplexPluginFactory;
-import org.briarproject.api.reporting.DevReporter;
-import org.briarproject.api.system.LocationUtils;
-import org.briarproject.plugins.droidtooth.DroidtoothPluginFactory;
-import org.briarproject.plugins.tcp.AndroidLanTcpPluginFactory;
-import org.briarproject.plugins.tor.TorPluginFactory;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.lifecycle.IoExecutor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.BackoffFactory;
+import org.briarproject.bramble.api.plugin.PluginConfig;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
+import org.briarproject.bramble.api.reporting.DevReporter;
+import org.briarproject.bramble.api.system.AndroidExecutor;
+import org.briarproject.bramble.api.system.LocationUtils;
+import org.briarproject.bramble.plugin.droidtooth.DroidtoothPluginFactory;
+import org.briarproject.bramble.plugin.tcp.AndroidLanTcpPluginFactory;
+import org.briarproject.bramble.plugin.tor.TorPluginFactory;
 
 import java.security.SecureRandom;
 import java.util.Arrays;
@@ -28,10 +29,10 @@ import dagger.Module;
 import dagger.Provides;
 
 @Module
-public class AndroidPluginsModule {
+public class AndroidPluginModule {
 
 	@Provides
-	public PluginConfig providePluginConfig(@IoExecutor Executor ioExecutor,
+	PluginConfig providePluginConfig(@IoExecutor Executor ioExecutor,
 			AndroidExecutor androidExecutor, SecureRandom random,
 			SocketFactory torSocketFactory, BackoffFactory backoffFactory,
 			Application app, LocationUtils locationUtils, DevReporter reporter,
@@ -46,7 +47,8 @@ public class AndroidPluginsModule {
 				backoffFactory, appContext);
 		final Collection<DuplexPluginFactory> duplex =
 				Arrays.asList(bluetooth, tor, lan);
-		return new PluginConfig() {
+		@NotNullByDefault
+		PluginConfig pluginConfig = new PluginConfig() {
 
 			@Override
 			public Collection<DuplexPluginFactory> getDuplexFactories() {
@@ -58,5 +60,6 @@ public class AndroidPluginsModule {
 				return Collections.emptyList();
 			}
 		};
+		return pluginConfig;
 	}
 }
diff --git a/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/droidtooth/DroidtoothPlugin.java
similarity index 92%
rename from briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java
rename to bramble-android/src/main/java/org/briarproject/bramble/plugin/droidtooth/DroidtoothPlugin.java
index 3d964ecbe5f871477862201333f5a7175d71e13b..ccd0fdf41f6b9ca7a7f7e10528d372171b00cb32 100644
--- a/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/droidtooth/DroidtoothPlugin.java
@@ -1,4 +1,4 @@
-package org.briarproject.plugins.droidtooth;
+package org.briarproject.bramble.plugin.droidtooth;
 
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
@@ -9,23 +9,23 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 
-import org.briarproject.android.api.AndroidExecutor;
-import org.briarproject.android.util.AndroidUtils;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.crypto.PseudoRandom;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.keyagreement.KeyAgreementConnection;
-import org.briarproject.api.keyagreement.KeyAgreementListener;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.plugins.Backoff;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
-import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
-import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
-import org.briarproject.api.properties.TransportProperties;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.crypto.PseudoRandom;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.plugin.Backoff;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
+import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
+import org.briarproject.bramble.api.properties.TransportProperties;
+import org.briarproject.bramble.api.system.AndroidExecutor;
+import org.briarproject.bramble.util.AndroidUtils;
+import org.briarproject.bramble.util.StringUtils;
 
 import java.io.Closeable;
 import java.io.IOException;
@@ -64,12 +64,12 @@ import static android.bluetooth.BluetoothDevice.EXTRA_DEVICE;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_BLUETOOTH;
-import static org.briarproject.api.plugins.BluetoothConstants.ID;
-import static org.briarproject.api.plugins.BluetoothConstants.PROP_ADDRESS;
-import static org.briarproject.api.plugins.BluetoothConstants.PROP_UUID;
-import static org.briarproject.api.plugins.BluetoothConstants.UUID_BYTES;
-import static org.briarproject.util.PrivacyUtils.scrubMacAddress;
+import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_BLUETOOTH;
+import static org.briarproject.bramble.api.plugin.BluetoothConstants.ID;
+import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_ADDRESS;
+import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_UUID;
+import static org.briarproject.bramble.api.plugin.BluetoothConstants.UUID_BYTES;
+import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
diff --git a/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPluginFactory.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/droidtooth/DroidtoothPluginFactory.java
similarity index 67%
rename from briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPluginFactory.java
rename to bramble-android/src/main/java/org/briarproject/bramble/plugin/droidtooth/DroidtoothPluginFactory.java
index ff166ea4f2fbae7fcc5a4ab6d6e79550f53ad494..f612ad9e72cde1d0b4651bb18eb99b97af77edc4 100644
--- a/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPluginFactory.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/droidtooth/DroidtoothPluginFactory.java
@@ -1,20 +1,25 @@
-package org.briarproject.plugins.droidtooth;
+package org.briarproject.bramble.plugin.droidtooth;
 
 import android.content.Context;
 
-import org.briarproject.android.api.AndroidExecutor;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.plugins.Backoff;
-import org.briarproject.api.plugins.BackoffFactory;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
-import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
-import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.Backoff;
+import org.briarproject.bramble.api.plugin.BackoffFactory;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
+import org.briarproject.bramble.api.system.AndroidExecutor;
 
 import java.security.SecureRandom;
 import java.util.concurrent.Executor;
 
-import static org.briarproject.api.plugins.BluetoothConstants.ID;
+import javax.annotation.concurrent.Immutable;
 
+import static org.briarproject.bramble.api.plugin.BluetoothConstants.ID;
+
+@Immutable
+@NotNullByDefault
 public class DroidtoothPluginFactory implements DuplexPluginFactory {
 
 	private static final int MAX_LATENCY = 30 * 1000; // 30 seconds
diff --git a/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothTransportConnection.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/droidtooth/DroidtoothTransportConnection.java
similarity index 72%
rename from briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothTransportConnection.java
rename to bramble-android/src/main/java/org/briarproject/bramble/plugin/droidtooth/DroidtoothTransportConnection.java
index 60520b563c9355c62a922ef8039d267d1bd44885..bebae98ef719d6ab28a431a8e0cba064ba18df43 100644
--- a/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothTransportConnection.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/droidtooth/DroidtoothTransportConnection.java
@@ -1,14 +1,16 @@
-package org.briarproject.plugins.droidtooth;
+package org.briarproject.bramble.plugin.droidtooth;
 
 import android.bluetooth.BluetoothSocket;
 
-import org.briarproject.api.plugins.Plugin;
-import org.briarproject.api.plugins.duplex.AbstractDuplexTransportConnection;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.Plugin;
+import org.briarproject.bramble.api.plugin.duplex.AbstractDuplexTransportConnection;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 
+@NotNullByDefault
 class DroidtoothTransportConnection extends AbstractDuplexTransportConnection {
 
 	private final BluetoothSocket socket;
diff --git a/briar-android/src/org/briarproject/plugins/tcp/AndroidLanTcpPlugin.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tcp/AndroidLanTcpPlugin.java
similarity index 90%
rename from briar-android/src/org/briarproject/plugins/tcp/AndroidLanTcpPlugin.java
rename to bramble-android/src/main/java/org/briarproject/bramble/plugin/tcp/AndroidLanTcpPlugin.java
index b96aefa0893fa8c2dcf1e87d02649500d9fc7841..b3daa5f13605cc67e71ea35a7a8fcf6507497b9f 100644
--- a/briar-android/src/org/briarproject/plugins/tcp/AndroidLanTcpPlugin.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tcp/AndroidLanTcpPlugin.java
@@ -1,4 +1,4 @@
-package org.briarproject.plugins.tcp;
+package org.briarproject.bramble.plugin.tcp;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -7,9 +7,9 @@ import android.content.IntentFilter;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.plugins.Backoff;
-import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.Backoff;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
 
 import java.util.concurrent.Executor;
 import java.util.logging.Logger;
diff --git a/briar-android/src/org/briarproject/plugins/tcp/AndroidLanTcpPluginFactory.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tcp/AndroidLanTcpPluginFactory.java
similarity index 66%
rename from briar-android/src/org/briarproject/plugins/tcp/AndroidLanTcpPluginFactory.java
rename to bramble-android/src/main/java/org/briarproject/bramble/plugin/tcp/AndroidLanTcpPluginFactory.java
index 74f98c17a82ea17804a20c40f56232f7987c4855..311219a66562ef91edad3a81ee7207f828f42e2f 100644
--- a/briar-android/src/org/briarproject/plugins/tcp/AndroidLanTcpPluginFactory.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tcp/AndroidLanTcpPluginFactory.java
@@ -1,18 +1,23 @@
-package org.briarproject.plugins.tcp;
+package org.briarproject.bramble.plugin.tcp;
 
 import android.content.Context;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.plugins.Backoff;
-import org.briarproject.api.plugins.BackoffFactory;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
-import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
-import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.Backoff;
+import org.briarproject.bramble.api.plugin.BackoffFactory;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
 
 import java.util.concurrent.Executor;
 
-import static org.briarproject.api.plugins.LanTcpConstants.ID;
+import javax.annotation.concurrent.Immutable;
 
+import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
+
+@Immutable
+@NotNullByDefault
 public class AndroidLanTcpPluginFactory implements DuplexPluginFactory {
 
 	private static final int MAX_LATENCY = 30 * 1000; // 30 seconds
diff --git a/briar-android/src/org/briarproject/plugins/tor/TorNetworkMetadata.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorNetworkMetadata.java
similarity index 64%
rename from briar-android/src/org/briarproject/plugins/tor/TorNetworkMetadata.java
rename to bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorNetworkMetadata.java
index ae238564720bd385d63ccd9829adbabb9cfe2081..e6151d57402152c170e4df476bd66080c2f62d3d 100644
--- a/briar-android/src/org/briarproject/plugins/tor/TorNetworkMetadata.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorNetworkMetadata.java
@@ -1,18 +1,18 @@
-package org.briarproject.plugins.tor;
+package org.briarproject.bramble.plugin.tor;
 
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Set;
 
-public class TorNetworkMetadata {
+class TorNetworkMetadata {
 
 	// See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
 	// and https://trac.torproject.org/projects/tor/wiki/doc/OONI/censorshipwiki
 	// TODO: get a more complete list
 	private static final Set<String> BLOCKED_IN_COUNTRIES =
-			new HashSet<String>(Arrays.asList("CN", "IR", "SY", "ZZ"));
+			new HashSet<>(Arrays.asList("CN", "IR", "SY", "ZZ"));
 
-	public static boolean isTorProbablyBlocked(String countryCode) {
+	static boolean isTorProbablyBlocked(String countryCode) {
 		return BLOCKED_IN_COUNTRIES.contains(countryCode);
 	}
 }
diff --git a/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java
similarity index 91%
rename from briar-android/src/org/briarproject/plugins/tor/TorPlugin.java
rename to bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java
index 2a8b58991bcafe11f4b2e4ed24d33286aca18519..4d9ddbcbcdff42cea281407698d38e8407970db0 100644
--- a/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java
@@ -1,4 +1,4 @@
-package org.briarproject.plugins.tor;
+package org.briarproject.bramble.plugin.tor;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -7,6 +7,7 @@ import android.content.IntentFilter;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.os.FileObserver;
@@ -15,27 +16,28 @@ import android.os.PowerManager;
 import net.freehaven.tor.control.EventHandler;
 import net.freehaven.tor.control.TorControlConnection;
 
-import org.briarproject.android.util.AndroidUtils;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.crypto.PseudoRandom;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.SettingsUpdatedEvent;
-import org.briarproject.api.keyagreement.KeyAgreementListener;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.plugins.Backoff;
-import org.briarproject.api.plugins.TorConstants;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
-import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
-import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
-import org.briarproject.api.properties.TransportProperties;
-import org.briarproject.api.reporting.DevReporter;
-import org.briarproject.api.settings.Settings;
-import org.briarproject.api.system.LocationUtils;
-import org.briarproject.util.IoUtils;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.crypto.PseudoRandom;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.plugin.Backoff;
+import org.briarproject.bramble.api.plugin.TorConstants;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
+import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
+import org.briarproject.bramble.api.properties.TransportProperties;
+import org.briarproject.bramble.api.reporting.DevReporter;
+import org.briarproject.bramble.api.settings.Settings;
+import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
+import org.briarproject.bramble.api.system.LocationUtils;
+import org.briarproject.bramble.util.AndroidUtils;
+import org.briarproject.bramble.util.IoUtils;
+import org.briarproject.bramble.util.StringUtils;
 
 import java.io.Closeable;
 import java.io.EOFException;
@@ -75,10 +77,11 @@ import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
 import static net.freehaven.tor.control.TorControlCommands.HS_ADDRESS;
 import static net.freehaven.tor.control.TorControlCommands.HS_PRIVKEY;
-import static org.briarproject.api.plugins.TorConstants.CONTROL_PORT;
-import static org.briarproject.util.PrivacyUtils.scrubOnion;
+import static org.briarproject.bramble.api.plugin.TorConstants.CONTROL_PORT;
+import static org.briarproject.bramble.util.PrivacyUtils.scrubOnion;
 
-@NotNullByDefault
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
 
 	private static final String PROP_ONION = "onion";
@@ -107,13 +110,9 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
 	private final AtomicBoolean used = new AtomicBoolean(false);
 
 	private volatile boolean running = false;
-	@Nullable
 	private volatile ServerSocket socket = null;
-	@Nullable
 	private volatile Socket controlSocket = null;
-	@Nullable
 	private volatile TorControlConnection controlConnection = null;
-	@Nullable
 	private volatile BroadcastReceiver networkStateReceiver = null;
 
 	TorPlugin(Executor ioExecutor, Context appContext,
@@ -277,23 +276,29 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
 	private InputStream getTorInputStream() throws IOException {
 		if (LOG.isLoggable(INFO))
 			LOG.info("Installing Tor binary for " + architecture);
-		String filename = "tor-" + architecture + ".zip";
-		InputStream in = appContext.getResources().getAssets().open(filename);
+		int resId = getResourceId("tor_" + architecture);
+		InputStream in = appContext.getResources().openRawResource(resId);
 		ZipInputStream zin = new ZipInputStream(in);
 		if (zin.getNextEntry() == null) throw new IOException();
 		return zin;
 	}
 
 	private InputStream getGeoIpInputStream() throws IOException {
-		String filename = "geoip.zip";
-		InputStream in = appContext.getResources().getAssets().open(filename);
+		int resId = getResourceId("geoip");
+		InputStream in = appContext.getResources().openRawResource(resId);
 		ZipInputStream zin = new ZipInputStream(in);
 		if (zin.getNextEntry() == null) throw new IOException();
 		return zin;
 	}
 
 	private InputStream getConfigInputStream() throws IOException {
-		return appContext.getResources().getAssets().open("torrc");
+		int resId = getResourceId("torrc");
+		return appContext.getResources().openRawResource(resId);
+	}
+
+	private int getResourceId(String filename) {
+		Resources res = appContext.getResources();
+		return res.getIdentifier(filename, "raw", appContext.getPackageName());
 	}
 
 	private void tryToClose(@Nullable Closeable c) {
diff --git a/briar-android/src/org/briarproject/plugins/tor/TorPluginFactory.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPluginFactory.java
similarity index 72%
rename from briar-android/src/org/briarproject/plugins/tor/TorPluginFactory.java
rename to bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPluginFactory.java
index c85405f676ad3afad530fabfcb2ef0cd1fcecd04..2f479d4ef8a147b755c9b3f0a17fe83359dfdbc9 100644
--- a/briar-android/src/org/briarproject/plugins/tor/TorPluginFactory.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPluginFactory.java
@@ -1,25 +1,29 @@
-package org.briarproject.plugins.tor;
+package org.briarproject.bramble.plugin.tor;
 
 import android.content.Context;
 import android.os.Build;
 
-import org.briarproject.android.util.AndroidUtils;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.plugins.Backoff;
-import org.briarproject.api.plugins.BackoffFactory;
-import org.briarproject.api.plugins.TorConstants;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
-import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
-import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
-import org.briarproject.api.reporting.DevReporter;
-import org.briarproject.api.system.LocationUtils;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.Backoff;
+import org.briarproject.bramble.api.plugin.BackoffFactory;
+import org.briarproject.bramble.api.plugin.TorConstants;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
+import org.briarproject.bramble.api.reporting.DevReporter;
+import org.briarproject.bramble.api.system.LocationUtils;
+import org.briarproject.bramble.util.AndroidUtils;
 
 import java.util.concurrent.Executor;
 import java.util.logging.Logger;
 
+import javax.annotation.concurrent.Immutable;
 import javax.net.SocketFactory;
 
+@Immutable
+@NotNullByDefault
 public class TorPluginFactory implements DuplexPluginFactory {
 
 	private static final Logger LOG =
@@ -81,7 +85,7 @@ public class TorPluginFactory implements DuplexPluginFactory {
 			return null;
 		}
 		// Use position-independent executable for SDK >= 16
-		if (Build.VERSION.SDK_INT >= 16) architecture += "-pie";
+		if (Build.VERSION.SDK_INT >= 16) architecture += "_pie";
 
 		Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
 				MAX_POLLING_INTERVAL, BACKOFF_BASE);
diff --git a/briar-android/src/org/briarproject/plugins/tor/TorTransportConnection.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorTransportConnection.java
similarity index 71%
rename from briar-android/src/org/briarproject/plugins/tor/TorTransportConnection.java
rename to bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorTransportConnection.java
index f44669188e3dd8531ae22dfd9cdffc4f23d849c2..1763784104b5c8b3f72679e00d23c63ec65d6b1b 100644
--- a/briar-android/src/org/briarproject/plugins/tor/TorTransportConnection.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorTransportConnection.java
@@ -1,13 +1,15 @@
-package org.briarproject.plugins.tor;
+package org.briarproject.bramble.plugin.tor;
 
-import org.briarproject.api.plugins.Plugin;
-import org.briarproject.api.plugins.duplex.AbstractDuplexTransportConnection;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.Plugin;
+import org.briarproject.bramble.api.plugin.duplex.AbstractDuplexTransportConnection;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.Socket;
 
+@NotNullByDefault
 class TorTransportConnection extends AbstractDuplexTransportConnection {
 
 	private final Socket socket;
diff --git a/briar-android/src/org/briarproject/system/AndroidExecutorImpl.java b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidExecutorImpl.java
similarity index 94%
rename from briar-android/src/org/briarproject/system/AndroidExecutorImpl.java
rename to bramble-android/src/main/java/org/briarproject/bramble/system/AndroidExecutorImpl.java
index ba6bee3657d93d163a0193ed557be72047586ebb..f07b2d721fc7a5cc5c66a53bd37a701242d11317 100644
--- a/briar-android/src/org/briarproject/system/AndroidExecutorImpl.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidExecutorImpl.java
@@ -1,10 +1,10 @@
-package org.briarproject.system;
+package org.briarproject.bramble.system;
 
 import android.app.Application;
 import android.os.Handler;
 import android.os.Looper;
 
-import org.briarproject.android.api.AndroidExecutor;
+import org.briarproject.bramble.api.system.AndroidExecutor;
 
 import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
diff --git a/briar-android/src/org/briarproject/system/AndroidLocationUtils.java b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidLocationUtils.java
similarity index 90%
rename from briar-android/src/org/briarproject/system/AndroidLocationUtils.java
rename to bramble-android/src/main/java/org/briarproject/bramble/system/AndroidLocationUtils.java
index e5907c9c003a5317947b11e9986a3d5a11b42d50..226064d6f2286887a8802e0ec806a160a8a3c0b8 100644
--- a/briar-android/src/org/briarproject/system/AndroidLocationUtils.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidLocationUtils.java
@@ -1,4 +1,4 @@
-package org.briarproject.system;
+package org.briarproject.bramble.system;
 
 import android.annotation.SuppressLint;
 import android.app.Application;
@@ -6,7 +6,8 @@ import android.content.Context;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 
-import org.briarproject.api.system.LocationUtils;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.system.LocationUtils;
 
 import java.util.Locale;
 import java.util.logging.Logger;
@@ -15,6 +16,7 @@ import javax.inject.Inject;
 
 import static android.content.Context.TELEPHONY_SERVICE;
 
+@NotNullByDefault
 class AndroidLocationUtils implements LocationUtils {
 
 	private static final Logger LOG =
@@ -23,7 +25,7 @@ class AndroidLocationUtils implements LocationUtils {
 	private final Context appContext;
 
 	@Inject
-	public AndroidLocationUtils(Application app) {
+	AndroidLocationUtils(Application app) {
 		appContext = app.getApplicationContext();
 	}
 
@@ -44,6 +46,7 @@ class AndroidLocationUtils implements LocationUtils {
 	 * some reason - both that class and {@code Context.COUNTRY_CODE} are
 	 * annotated {@code @hide}.
 	 */
+	@Override
 	@SuppressLint("DefaultLocale")
 	public String getCurrentCountry() {
 		String countryCode = getCountryFromPhoneNetwork();
diff --git a/briar-android/src/org/briarproject/system/AndroidSeedProvider.java b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSeedProvider.java
similarity index 85%
rename from briar-android/src/org/briarproject/system/AndroidSeedProvider.java
rename to bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSeedProvider.java
index ea40d43feff48db4de7445c77189a4269b75e51a..52d15db5e30e1e88a43de7e705ea7d48d27bf5e4 100644
--- a/briar-android/src/org/briarproject/system/AndroidSeedProvider.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSeedProvider.java
@@ -1,4 +1,4 @@
-package org.briarproject.system;
+package org.briarproject.bramble.system;
 
 import android.app.Application;
 import android.content.ContentResolver;
@@ -6,13 +6,18 @@ import android.content.Context;
 import android.os.Build;
 import android.provider.Settings;
 
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
 import java.io.DataOutputStream;
 import java.io.IOException;
 
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
 import static android.provider.Settings.Secure.ANDROID_ID;
 
+@Immutable
+@NotNullByDefault
 class AndroidSeedProvider extends LinuxSeedProvider {
 
 	private final Context appContext;
diff --git a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSystemModule.java b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSystemModule.java
new file mode 100644
index 0000000000000000000000000000000000000000..e5976ff995b75858b9fda7f91413ac89c2195de2
--- /dev/null
+++ b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSystemModule.java
@@ -0,0 +1,33 @@
+package org.briarproject.bramble.system;
+
+import android.app.Application;
+
+import org.briarproject.bramble.api.system.AndroidExecutor;
+import org.briarproject.bramble.api.system.LocationUtils;
+import org.briarproject.bramble.api.system.SeedProvider;
+
+import javax.inject.Singleton;
+
+import dagger.Module;
+import dagger.Provides;
+
+@Module
+public class AndroidSystemModule {
+
+	@Provides
+	@Singleton
+	SeedProvider provideSeedProvider(Application app) {
+		return new AndroidSeedProvider(app);
+	}
+
+	@Provides
+	LocationUtils provideLocationUtils(Application app) {
+		return new AndroidLocationUtils(app);
+	}
+
+	@Provides
+	@Singleton
+	AndroidExecutor provideAndroidExecutor(Application app) {
+		return new AndroidExecutorImpl(app);
+	}
+}
diff --git a/bramble-android/src/main/java/org/briarproject/bramble/util/AndroidUtils.java b/bramble-android/src/main/java/org/briarproject/bramble/util/AndroidUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..15edba9c49be5d825c2944d19422d30264b20700
--- /dev/null
+++ b/bramble-android/src/main/java/org/briarproject/bramble/util/AndroidUtils.java
@@ -0,0 +1,70 @@
+package org.briarproject.bramble.util;
+
+import android.bluetooth.BluetoothAdapter;
+import android.content.Context;
+import android.os.Build;
+import android.provider.Settings;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import static android.content.Context.MODE_PRIVATE;
+
+public class AndroidUtils {
+
+	// Fake Bluetooth address returned by BluetoothAdapter on API 23 and later
+	private static final String FAKE_BLUETOOTH_ADDRESS = "02:00:00:00:00:00";
+
+	private static final String STORED_REPORTS = "dev-reports";
+
+	@SuppressWarnings("deprecation")
+	public static Collection<String> getSupportedArchitectures() {
+		List<String> abis = new ArrayList<>();
+		if (Build.VERSION.SDK_INT >= 21) {
+			abis.addAll(Arrays.asList(Build.SUPPORTED_ABIS));
+		} else {
+			abis.add(Build.CPU_ABI);
+			if (Build.CPU_ABI2 != null) abis.add(Build.CPU_ABI2);
+		}
+		return abis;
+	}
+
+	public static String getBluetoothAddress(Context ctx,
+			BluetoothAdapter adapter) {
+		// Return the adapter's address if it's valid and not fake
+		String address = adapter.getAddress();
+		if (isValidBluetoothAddress(address)) return address;
+		// Return the address from settings if it's valid and not fake
+		address = Settings.Secure.getString(ctx.getContentResolver(),
+				"bluetooth_address");
+		if (isValidBluetoothAddress(address)) return address;
+		// Let the caller know we can't find the address
+		return "";
+	}
+
+	private static boolean isValidBluetoothAddress(String address) {
+		return !StringUtils.isNullOrEmpty(address)
+				&& BluetoothAdapter.checkBluetoothAddress(address)
+				&& !address.equals(FAKE_BLUETOOTH_ADDRESS);
+	}
+
+	public static void deleteAppData(Context ctx) {
+		File dataDir = new File(ctx.getApplicationInfo().dataDir);
+		File[] children = dataDir.listFiles();
+		if (children != null) {
+			for (File child : children) {
+				if (!child.getName().equals("lib"))
+					IoUtils.deleteFileOrDir(child);
+			}
+		}
+		// Recreate the cache dir as some OpenGL drivers expect it to exist
+		new File(dataDir, "cache").mkdir();
+	}
+
+	public static File getReportDir(Context ctx) {
+		return ctx.getDir(STORED_REPORTS, MODE_PRIVATE);
+	}
+}
diff --git a/briar-android/assets/torrc b/bramble-android/src/main/res/raw/torrc
similarity index 100%
rename from briar-android/assets/torrc
rename to bramble-android/src/main/res/raw/torrc
diff --git a/bramble-android/src/main/res/values/strings.xml b/bramble-android/src/main/res/values/strings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e0b5cd4739475a7a5209f5ece6a7f1de0aac4526
--- /dev/null
+++ b/bramble-android/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+<resources>
+	<string name="app_name">Bramble</string>
+</resources>
diff --git a/briar-desktop/.gitignore b/bramble-api/.gitignore
similarity index 100%
rename from briar-desktop/.gitignore
rename to bramble-api/.gitignore
diff --git a/bramble-api/build.gradle b/bramble-api/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..138b9484c42499641050b92a65f2a5974ca30364
--- /dev/null
+++ b/bramble-api/build.gradle
@@ -0,0 +1,22 @@
+apply plugin: 'java'
+sourceCompatibility = 1.6
+targetCompatibility = 1.6
+
+apply plugin: 'witness'
+
+dependencies {
+	compile "com.google.dagger:dagger:2.0.2"
+	compile 'com.google.dagger:dagger-compiler:2.0.2'
+	compile 'com.google.code.findbugs:jsr305:3.0.1'
+}
+
+dependencyVerification {
+	verify = [
+			'com.google.dagger:dagger:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
+			'com.google.dagger:dagger-compiler:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
+			'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
+			'com.google.dagger:dagger-producers:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
+			'com.google.guava:guava:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
+			'com.google.code.findbugs:jsr305:c885ce34249682bc0236b4a7d56efcc12048e6135a5baf7a9cde8ad8cda13fcd'
+	]
+}
diff --git a/briar-api/src/org/briarproject/api/Bytes.java b/bramble-api/src/main/java/org/briarproject/bramble/api/Bytes.java
similarity index 87%
rename from briar-api/src/org/briarproject/api/Bytes.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/Bytes.java
index 7fce90ad706471abf2e90132dd5bb1337dbb64b2..5c9b61f40873694903dfb9a393ede6af72069fcb 100644
--- a/briar-api/src/org/briarproject/api/Bytes.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/Bytes.java
@@ -1,11 +1,17 @@
-package org.briarproject.api;
+package org.briarproject.bramble.api;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.util.Arrays;
 import java.util.Comparator;
 
+import javax.annotation.concurrent.ThreadSafe;
+
 /**
  * A wrapper around a byte array, to allow it to be stored in maps etc.
  */
+@ThreadSafe
+@NotNullByDefault
 public class Bytes implements Comparable<Bytes> {
 
 	public static final BytesComparator COMPARATOR = new BytesComparator();
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/FormatException.java b/bramble-api/src/main/java/org/briarproject/bramble/api/FormatException.java
new file mode 100644
index 0000000000000000000000000000000000000000..357deaf7d5d48ba9606b9aee16f7f4603d4a0282
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/FormatException.java
@@ -0,0 +1,9 @@
+package org.briarproject.bramble.api;
+
+import java.io.IOException;
+
+/**
+ * An exception that indicates an unrecoverable formatting error.
+ */
+public class FormatException extends IOException {
+}
diff --git a/briar-api/src/org/briarproject/api/StringMap.java b/bramble-api/src/main/java/org/briarproject/bramble/api/StringMap.java
similarity index 89%
rename from briar-api/src/org/briarproject/api/StringMap.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/StringMap.java
index 299f8f3f125e10cb393e0fd550221e1e42d770bc..aeb9823a1775194eb34316c272e885914b5eb427 100644
--- a/briar-api/src/org/briarproject/api/StringMap.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/StringMap.java
@@ -1,12 +1,10 @@
-package org.briarproject.api;
+package org.briarproject.bramble.api;
 
 import java.util.Hashtable;
 import java.util.Map;
 
 public abstract class StringMap extends Hashtable<String, String> {
 
-	private static final long serialVersionUID = 2497176435908100448L;
-
 	protected StringMap(Map<String, String> m) {
 		super(m);
 	}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/UniqueId.java b/bramble-api/src/main/java/org/briarproject/bramble/api/UniqueId.java
new file mode 100644
index 0000000000000000000000000000000000000000..efa69358ff0f1d32eaaf864cde243bd09644bfaa
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/UniqueId.java
@@ -0,0 +1,20 @@
+package org.briarproject.bramble.api;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.ThreadSafe;
+
+@ThreadSafe
+@NotNullByDefault
+public abstract class UniqueId extends Bytes {
+
+	/**
+	 * The length of a unique identifier in bytes.
+	 */
+	public static final int LENGTH = 32;
+
+	protected UniqueId(byte[] id) {
+		super(id);
+		if (id.length != LENGTH) throw new IllegalArgumentException();
+	}
+}
diff --git a/briar-api/src/org/briarproject/api/clients/BdfMessageContext.java b/bramble-api/src/main/java/org/briarproject/bramble/api/client/BdfMessageContext.java
similarity index 75%
rename from briar-api/src/org/briarproject/api/clients/BdfMessageContext.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/client/BdfMessageContext.java
index 6eceac96d00c7f6b5d51375e20068cf41aea899c..4cc02f3a247fbcf1b32f09e3266b8a1cb4cecba7 100644
--- a/briar-api/src/org/briarproject/api/clients/BdfMessageContext.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/client/BdfMessageContext.java
@@ -1,8 +1,8 @@
-package org.briarproject.api.clients;
+package org.briarproject.bramble.api.client;
 
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.MessageId;
 
 import java.util.Collection;
 import java.util.Collections;
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/client/BdfMessageValidator.java b/bramble-api/src/main/java/org/briarproject/bramble/api/client/BdfMessageValidator.java
new file mode 100644
index 0000000000000000000000000000000000000000..63f34185704b6a2f4dab643304ed0bcde7610aeb
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/client/BdfMessageValidator.java
@@ -0,0 +1,66 @@
+package org.briarproject.bramble.api.client;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.InvalidMessageException;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageContext;
+import org.briarproject.bramble.api.sync.ValidationManager.MessageValidator;
+import org.briarproject.bramble.api.system.Clock;
+
+import java.util.logging.Logger;
+
+import javax.annotation.concurrent.Immutable;
+
+import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
+
+@Immutable
+@NotNullByDefault
+public abstract class BdfMessageValidator implements MessageValidator {
+
+	protected static final Logger LOG =
+			Logger.getLogger(BdfMessageValidator.class.getName());
+
+	protected final ClientHelper clientHelper;
+	protected final MetadataEncoder metadataEncoder;
+	protected final Clock clock;
+
+	protected BdfMessageValidator(ClientHelper clientHelper,
+			MetadataEncoder metadataEncoder, Clock clock) {
+		this.clientHelper = clientHelper;
+		this.metadataEncoder = metadataEncoder;
+		this.clock = clock;
+	}
+
+	protected abstract BdfMessageContext validateMessage(Message m, Group g,
+			BdfList body) throws InvalidMessageException, FormatException;
+
+	@Override
+	public MessageContext validateMessage(Message m, Group g)
+			throws InvalidMessageException {
+		// Reject the message if it's too far in the future
+		long now = clock.currentTimeMillis();
+		if (m.getTimestamp() - now > MAX_CLOCK_DIFFERENCE) {
+			throw new InvalidMessageException(
+					"Timestamp is too far in the future");
+		}
+		byte[] raw = m.getRaw();
+		if (raw.length <= MESSAGE_HEADER_LENGTH) {
+			throw new InvalidMessageException("Message is too short");
+		}
+		try {
+			BdfList body = clientHelper.toList(raw, MESSAGE_HEADER_LENGTH,
+					raw.length - MESSAGE_HEADER_LENGTH);
+			BdfMessageContext result = validateMessage(m, g, body);
+			Metadata meta = metadataEncoder.encode(result.getDictionary());
+			return new MessageContext(meta, result.getDependencies());
+		} catch (FormatException e) {
+			throw new InvalidMessageException(e);
+		}
+	}
+}
diff --git a/briar-api/src/org/briarproject/api/clients/ClientHelper.java b/bramble-api/src/main/java/org/briarproject/bramble/api/client/ClientHelper.java
similarity index 82%
rename from briar-api/src/org/briarproject/api/clients/ClientHelper.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/client/ClientHelper.java
index 32af81f627d94021792f0451cd5bf90857142fa2..74aea4ac4cd0c276584a58000f4a58d17adb000a 100644
--- a/briar-api/src/org/briarproject/api/clients/ClientHelper.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/client/ClientHelper.java
@@ -1,14 +1,14 @@
-package org.briarproject.api.clients;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
+package org.briarproject.bramble.api.client;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
 
 import java.security.GeneralSecurityException;
 import java.util.Map;
@@ -48,7 +48,8 @@ public interface ClientHelper {
 	BdfDictionary getGroupMetadataAsDictionary(Transaction txn, GroupId g)
 			throws DbException, FormatException;
 
-	BdfDictionary getMessageMetadataAsDictionary(MessageId m) throws DbException,
+	BdfDictionary getMessageMetadataAsDictionary(MessageId m)
+			throws DbException,
 			FormatException;
 
 	BdfDictionary getMessageMetadataAsDictionary(Transaction txn, MessageId m)
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/client/ContactGroupFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/client/ContactGroupFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..d68f115fdc454f85013b8daecd5fd670145880cc
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/client/ContactGroupFactory.java
@@ -0,0 +1,29 @@
+package org.briarproject.bramble.api.client;
+
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+
+@NotNullByDefault
+public interface ContactGroupFactory {
+
+	/**
+	 * Creates a group that is not shared with any contacts.
+	 */
+	Group createLocalGroup(ClientId clientId);
+
+	/**
+	 * Creates a group for the given client to share with the given contact.
+	 */
+	Group createContactGroup(ClientId clientId, Contact contact);
+
+	/**
+	 * Creates a group for the given client to share between the given authors
+	 * identified by their AuthorIds.
+	 */
+	Group createContactGroup(ClientId clientId, AuthorId authorId1,
+			AuthorId authorId2);
+
+}
diff --git a/briar-api/src/org/briarproject/api/contact/Contact.java b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/Contact.java
similarity index 74%
rename from briar-api/src/org/briarproject/api/contact/Contact.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/contact/Contact.java
index 4de12c21c856a77d42eac20354345435f0416ece..1d921e8017f62e03100fda3e16f53692eac31155 100644
--- a/briar-api/src/org/briarproject/api/contact/Contact.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/Contact.java
@@ -1,8 +1,13 @@
-package org.briarproject.api.contact;
+package org.briarproject.bramble.api.contact;
 
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 public class Contact {
 
 	private final ContactId id;
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactExchangeListener.java b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactExchangeListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..66a79c1e25a6d0ca72d37605428da2e69691eec6
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactExchangeListener.java
@@ -0,0 +1,20 @@
+package org.briarproject.bramble.api.contact;
+
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+public interface ContactExchangeListener {
+
+	void contactExchangeSucceeded(Author remoteAuthor);
+
+	/**
+	 * The exchange failed because the contact already exists.
+	 */
+	void duplicateContact(Author remoteAuthor);
+
+	/**
+	 * A general failure.
+	 */
+	void contactExchangeFailed();
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactExchangeTask.java b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactExchangeTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..3ee8d70af467ff5e18bc73c7cddd6c941af5bd4b
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactExchangeTask.java
@@ -0,0 +1,22 @@
+package org.briarproject.bramble.api.contact;
+
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
+
+/**
+ * A task for conducting a contact information exchange with a remote peer.
+ */
+@NotNullByDefault
+public interface ContactExchangeTask {
+
+	/**
+	 * Exchanges contact information with a remote peer.
+	 */
+	void startExchange(ContactExchangeListener listener,
+			LocalAuthor localAuthor, SecretKey masterSecret,
+			DuplexTransportConnection conn, TransportId transportId,
+			boolean alice);
+}
diff --git a/briar-api/src/org/briarproject/api/contact/ContactId.java b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactId.java
similarity index 69%
rename from briar-api/src/org/briarproject/api/contact/ContactId.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactId.java
index 736597a388a7b729ccf85bc4e078526fd3ec2b49..9e11e555783018e242eef89a7141e8565f68ea12 100644
--- a/briar-api/src/org/briarproject/api/contact/ContactId.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactId.java
@@ -1,9 +1,15 @@
-package org.briarproject.api.contact;
+package org.briarproject.bramble.api.contact;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.Immutable;
 
 /**
  * Type-safe wrapper for an integer that uniquely identifies a contact within
  * the scope of a single node.
  */
+@Immutable
+@NotNullByDefault
 public class ContactId {
 
 	private final int id;
diff --git a/briar-api/src/org/briarproject/api/contact/ContactManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java
similarity index 61%
rename from briar-api/src/org/briarproject/api/contact/ContactManager.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java
index 5203da3004764c7d36909ca354a559d8e2905b7c..f864fa7f371d393139fc4a87353ef6495a8ee5db 100644
--- a/briar-api/src/org/briarproject/api/contact/ContactManager.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java
@@ -1,19 +1,25 @@
-package org.briarproject.api.contact;
+package org.briarproject.bramble.api.contact;
 
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.util.Collection;
 
+@NotNullByDefault
 public interface ContactManager {
 
-	/** Registers a hook to be called whenever a contact is added. */
+	/**
+	 * Registers a hook to be called whenever a contact is added.
+	 */
 	void registerAddContactHook(AddContactHook hook);
 
-	/** Registers a hook to be called whenever a contact is removed. */
+	/**
+	 * Registers a hook to be called whenever a contact is removed.
+	 */
 	void registerRemoveContactHook(RemoveContactHook hook);
 
 	/**
@@ -32,27 +38,41 @@ public interface ContactManager {
 			SecretKey master, long timestamp, boolean alice, boolean verified,
 			boolean active) throws DbException;
 
-	/** Returns the contact with the given ID. */
+	/**
+	 * Returns the contact with the given ID.
+	 */
 	Contact getContact(ContactId c) throws DbException;
 
-	/** Returns all active contacts. */
+	/**
+	 * Returns all active contacts.
+	 */
 	Collection<Contact> getActiveContacts() throws DbException;
 
-	/** Removes a contact and all associated state. */
+	/**
+	 * Removes a contact and all associated state.
+	 */
 	void removeContact(ContactId c) throws DbException;
 
-	/** Removes a contact and all associated state. */
+	/**
+	 * Removes a contact and all associated state.
+	 */
 	void removeContact(Transaction txn, ContactId c) throws DbException;
 
-	/** Marks a contact as active or inactive. */
+	/**
+	 * Marks a contact as active or inactive.
+	 */
 	void setContactActive(Transaction txn, ContactId c, boolean active)
 			throws DbException;
 
-	/** Return true if a contact with this name and public key already exists */
+	/**
+	 * Return true if a contact with this name and public key already exists
+	 */
 	boolean contactExists(Transaction txn, AuthorId remoteAuthorId,
 			AuthorId localAuthorId) throws DbException;
 
-	/** Return true if a contact with this name and public key already exists */
+	/**
+	 * Return true if a contact with this name and public key already exists
+	 */
 	boolean contactExists(AuthorId remoteAuthorId, AuthorId localAuthorId)
 			throws DbException;
 
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/event/ContactAddedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/event/ContactAddedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..a8c67dd0600d64bd18181c0f32d47ef1017333aa
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/event/ContactAddedEvent.java
@@ -0,0 +1,31 @@
+package org.briarproject.bramble.api.contact.event;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when a contact is added.
+ */
+@Immutable
+@NotNullByDefault
+public class ContactAddedEvent extends Event {
+
+	private final ContactId contactId;
+	private final boolean active;
+
+	public ContactAddedEvent(ContactId contactId, boolean active) {
+		this.contactId = contactId;
+		this.active = active;
+	}
+
+	public ContactId getContactId() {
+		return contactId;
+	}
+
+	public boolean isActive() {
+		return active;
+	}
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/event/ContactRemovedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/event/ContactRemovedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..703c87a85c3423123d2dc9afcc1dcbf786b1c4fa
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/event/ContactRemovedEvent.java
@@ -0,0 +1,25 @@
+package org.briarproject.bramble.api.contact.event;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when a contact is removed.
+ */
+@Immutable
+@NotNullByDefault
+public class ContactRemovedEvent extends Event {
+
+	private final ContactId contactId;
+
+	public ContactRemovedEvent(ContactId contactId) {
+		this.contactId = contactId;
+	}
+
+	public ContactId getContactId() {
+		return contactId;
+	}
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/event/ContactStatusChangedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/event/ContactStatusChangedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..99211f68174558f92b88727112d6368907ef5bd1
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/event/ContactStatusChangedEvent.java
@@ -0,0 +1,31 @@
+package org.briarproject.bramble.api.contact.event;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when a contact is marked active or inactive.
+ */
+@Immutable
+@NotNullByDefault
+public class ContactStatusChangedEvent extends Event {
+
+	private final ContactId contactId;
+	private final boolean active;
+
+	public ContactStatusChangedEvent(ContactId contactId, boolean active) {
+		this.contactId = contactId;
+		this.active = active;
+	}
+
+	public ContactId getContactId() {
+		return contactId;
+	}
+
+	public boolean isActive() {
+		return active;
+	}
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/event/ContactVerifiedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/event/ContactVerifiedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..d2db5985ea3ec72dd383644b02421ab688aa9f47
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/event/ContactVerifiedEvent.java
@@ -0,0 +1,26 @@
+package org.briarproject.bramble.api.contact.event;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when a contact is verified.
+ */
+@Immutable
+@NotNullByDefault
+public class ContactVerifiedEvent extends Event {
+
+	private final ContactId contactId;
+
+	public ContactVerifiedEvent(ContactId contactId) {
+		this.contactId = contactId;
+	}
+
+	public ContactId getContactId() {
+		return contactId;
+	}
+
+}
diff --git a/briar-api/src/org/briarproject/api/crypto/CryptoComponent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/CryptoComponent.java
similarity index 97%
rename from briar-api/src/org/briarproject/api/crypto/CryptoComponent.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/crypto/CryptoComponent.java
index 60a606889a14f1ab846f0c512c467eb96b924561..a1573ec7a9b88053f2366acb79f222c044c252c4 100644
--- a/briar-api/src/org/briarproject/api/crypto/CryptoComponent.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/CryptoComponent.java
@@ -1,7 +1,7 @@
-package org.briarproject.api.crypto;
+package org.briarproject.bramble.api.crypto;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.transport.TransportKeys;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.transport.TransportKeys;
 
 import java.security.GeneralSecurityException;
 import java.security.SecureRandom;
diff --git a/briar-api/src/org/briarproject/api/crypto/CryptoExecutor.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/CryptoExecutor.java
similarity index 94%
rename from briar-api/src/org/briarproject/api/crypto/CryptoExecutor.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/crypto/CryptoExecutor.java
index f1002e66b9d424cfbadc7199c65a42bc48911678..96c815ca7c926bd8e7e731eca3fd0d66308964fa 100644
--- a/briar-api/src/org/briarproject/api/crypto/CryptoExecutor.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/CryptoExecutor.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.crypto;
+package org.briarproject.bramble.api.crypto;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
diff --git a/briar-api/src/org/briarproject/api/crypto/KeyPair.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/KeyPair.java
similarity index 56%
rename from briar-api/src/org/briarproject/api/crypto/KeyPair.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/crypto/KeyPair.java
index 9af5da4cfd8fc61237561c03c1a0e2a730e5d185..16843b5aed211141711fef1e9db8d320ad4c9330 100644
--- a/briar-api/src/org/briarproject/api/crypto/KeyPair.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/KeyPair.java
@@ -1,6 +1,14 @@
-package org.briarproject.api.crypto;
+package org.briarproject.bramble.api.crypto;
 
-/** A key pair consisting of a {@link PublicKey} and a {@link PrivateKey). */
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * A key pair consisting of a {@link PublicKey} and a {@link PrivateKey).
+ */
+@Immutable
+@NotNullByDefault
 public class KeyPair {
 
 	private final PublicKey publicKey;
diff --git a/briar-api/src/org/briarproject/api/crypto/KeyParser.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/KeyParser.java
similarity index 65%
rename from briar-api/src/org/briarproject/api/crypto/KeyParser.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/crypto/KeyParser.java
index 89258be5e733c1512db5f05d0577731e787afd12..7f416d31acc9d037f79aea6877a3b7c03ac46eca 100644
--- a/briar-api/src/org/briarproject/api/crypto/KeyParser.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/KeyParser.java
@@ -1,7 +1,10 @@
-package org.briarproject.api.crypto;
+package org.briarproject.bramble.api.crypto;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.security.GeneralSecurityException;
 
+@NotNullByDefault
 public interface KeyParser {
 
 	PublicKey parsePublicKey(byte[] encodedKey) throws GeneralSecurityException;
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/MessageDigest.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/MessageDigest.java
new file mode 100644
index 0000000000000000000000000000000000000000..f55e169d0ecc1ba86decdb87b46abc3a894479bd
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/MessageDigest.java
@@ -0,0 +1,47 @@
+package org.briarproject.bramble.api.crypto;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+public interface MessageDigest {
+
+	/**
+	 * @see {@link java.security.MessageDigest#digest()}
+	 */
+	byte[] digest();
+
+	/**
+	 * @see {@link java.security.MessageDigest#digest(byte[])}
+	 */
+	byte[] digest(byte[] input);
+
+	/**
+	 * @see {@link java.security.MessageDigest#digest(byte[], int, int)}
+	 */
+	int digest(byte[] buf, int offset, int len);
+
+	/**
+	 * @see {@link java.security.MessageDigest#getDigestLength()}
+	 */
+	int getDigestLength();
+
+	/**
+	 * @see {@link java.security.MessageDigest#reset()}
+	 */
+	void reset();
+
+	/**
+	 * @see {@link java.security.MessageDigest#update(byte)}
+	 */
+	void update(byte input);
+
+	/**
+	 * @see {@link java.security.MessageDigest#update(byte[])}
+	 */
+	void update(byte[] input);
+
+	/**
+	 * @see {@link java.security.MessageDigest#update(byte[], int, int)}
+	 */
+	void update(byte[] input, int offset, int len);
+}
diff --git a/briar-api/src/org/briarproject/api/crypto/PasswordStrengthEstimator.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PasswordStrengthEstimator.java
similarity index 71%
rename from briar-api/src/org/briarproject/api/crypto/PasswordStrengthEstimator.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PasswordStrengthEstimator.java
index 93d27a6b32aaa142a86cfd4c53f054900cf7fc4d..0fdb4a8ba55402c9cc005a53a6974c7a2f7926b8 100644
--- a/briar-api/src/org/briarproject/api/crypto/PasswordStrengthEstimator.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PasswordStrengthEstimator.java
@@ -1,5 +1,8 @@
-package org.briarproject.api.crypto;
+package org.briarproject.bramble.api.crypto;
 
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
 public interface PasswordStrengthEstimator {
 
 	float NONE = 0;
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PrivateKey.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PrivateKey.java
new file mode 100644
index 0000000000000000000000000000000000000000..edf478c40eac30cdb7d803417b3947ff1e45e482
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PrivateKey.java
@@ -0,0 +1,15 @@
+package org.briarproject.bramble.api.crypto;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+/**
+ * The private half of a public/private {@link KeyPair}.
+ */
+@NotNullByDefault
+public interface PrivateKey {
+
+	/**
+	 * Returns the encoded representation of this key.
+	 */
+	byte[] getEncoded();
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PseudoRandom.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PseudoRandom.java
new file mode 100644
index 0000000000000000000000000000000000000000..8e61027d6f15201a1066c3529c6de99c884c3d2e
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PseudoRandom.java
@@ -0,0 +1,12 @@
+package org.briarproject.bramble.api.crypto;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+/**
+ * A deterministic pseudo-random number generator.
+ */
+@NotNullByDefault
+public interface PseudoRandom {
+
+	byte[] nextBytes(int bytes);
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PublicKey.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PublicKey.java
new file mode 100644
index 0000000000000000000000000000000000000000..e5cc522ca605546aa156fd6f922c60bb106ff575
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PublicKey.java
@@ -0,0 +1,15 @@
+package org.briarproject.bramble.api.crypto;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+/**
+ * The public half of a public/private {@link KeyPair}.
+ */
+@NotNullByDefault
+public interface PublicKey {
+
+	/**
+	 * Returns the encoded representation of this key.
+	 */
+	byte[] getEncoded();
+}
diff --git a/briar-api/src/org/briarproject/api/crypto/SecretKey.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/SecretKey.java
similarity index 52%
rename from briar-api/src/org/briarproject/api/crypto/SecretKey.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/crypto/SecretKey.java
index 9c34e91a056a1a1aa50ad01313e203ba3a140dc9..319f9305b6810f06372f7938418e829914b8dea5 100644
--- a/briar-api/src/org/briarproject/api/crypto/SecretKey.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/SecretKey.java
@@ -1,9 +1,14 @@
-package org.briarproject.api.crypto;
+package org.briarproject.bramble.api.crypto;
 
-/** A secret key used for encryption and/or authentication. */
+/**
+ * A secret key used for encryption and/or authentication.
+ */
 public class SecretKey {
 
-	public static final int LENGTH = 32; // Bytes
+	/**
+	 * The length of a secret key in bytes.
+	 */
+	public static final int LENGTH = 32;
 
 	private final byte[] key;
 
diff --git a/briar-api/src/org/briarproject/api/crypto/StreamDecrypter.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/StreamDecrypter.java
similarity index 61%
rename from briar-api/src/org/briarproject/api/crypto/StreamDecrypter.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/crypto/StreamDecrypter.java
index 9f217c13861ba4cc6525c7c69ddcc4abcfae3d0f..131fb7496931f2d90763b15e8c9fa9afba9f39bd 100644
--- a/briar-api/src/org/briarproject/api/crypto/StreamDecrypter.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/StreamDecrypter.java
@@ -1,13 +1,17 @@
-package org.briarproject.api.crypto;
+package org.briarproject.bramble.api.crypto;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.IOException;
 
+@NotNullByDefault
 public interface StreamDecrypter {
 
 	/**
 	 * Reads a frame, decrypts its payload into the given buffer and returns
 	 * the payload length, or -1 if no more frames can be read from the stream.
-	 * @throws java.io.IOException if an error occurs while reading the frame,
+	 *
+	 * @throws IOException if an error occurs while reading the frame,
 	 * or if authenticated decryption fails.
 	 */
 	int readFrame(byte[] payload) throws IOException;
diff --git a/briar-api/src/org/briarproject/api/crypto/StreamDecrypterFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/StreamDecrypterFactory.java
similarity index 54%
rename from briar-api/src/org/briarproject/api/crypto/StreamDecrypterFactory.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/crypto/StreamDecrypterFactory.java
index 0d75a94287cbd13ed3dbab8b395c9f2207b74bfd..b07c3239a1cb63232392f5e6d7fc5fa64de3974c 100644
--- a/briar-api/src/org/briarproject/api/crypto/StreamDecrypterFactory.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/StreamDecrypterFactory.java
@@ -1,12 +1,16 @@
-package org.briarproject.api.crypto;
+package org.briarproject.bramble.api.crypto;
 
-import java.io.InputStream;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.transport.StreamContext;
 
-import org.briarproject.api.transport.StreamContext;
+import java.io.InputStream;
 
+@NotNullByDefault
 public interface StreamDecrypterFactory {
 
-	/** Creates a {@link StreamDecrypter} for decrypting a transport stream. */
+	/**
+	 * Creates a {@link StreamDecrypter} for decrypting a transport stream.
+	 */
 	StreamDecrypter createStreamDecrypter(InputStream in, StreamContext ctx);
 
 	/**
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/StreamEncrypter.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/StreamEncrypter.java
new file mode 100644
index 0000000000000000000000000000000000000000..7a1e3ed77b2c6bbbb3b032db0851ea6c19fcc460
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/StreamEncrypter.java
@@ -0,0 +1,20 @@
+package org.briarproject.bramble.api.crypto;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import java.io.IOException;
+
+@NotNullByDefault
+public interface StreamEncrypter {
+
+	/**
+	 * Encrypts the given frame and writes it to the stream.
+	 */
+	void writeFrame(byte[] payload, int payloadLength, int paddingLength,
+			boolean finalFrame) throws IOException;
+
+	/**
+	 * Flushes the stream.
+	 */
+	void flush() throws IOException;
+}
diff --git a/briar-api/src/org/briarproject/api/crypto/StreamEncrypterFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/StreamEncrypterFactory.java
similarity index 54%
rename from briar-api/src/org/briarproject/api/crypto/StreamEncrypterFactory.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/crypto/StreamEncrypterFactory.java
index 6c94ee7f0c2ef2161bb3a94edaca252353b7b1e8..74340133740b6c6d1243f3b402c0591da7b5e5d5 100644
--- a/briar-api/src/org/briarproject/api/crypto/StreamEncrypterFactory.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/StreamEncrypterFactory.java
@@ -1,12 +1,16 @@
-package org.briarproject.api.crypto;
+package org.briarproject.bramble.api.crypto;
 
-import java.io.OutputStream;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.transport.StreamContext;
 
-import org.briarproject.api.transport.StreamContext;
+import java.io.OutputStream;
 
+@NotNullByDefault
 public interface StreamEncrypterFactory {
 
-	/** Creates a {@link StreamEncrypter} for encrypting a transport stream. */
+	/**
+	 * Creates a {@link StreamEncrypter} for encrypting a transport stream.
+	 */
 	StreamEncrypter createStreamEncrypter(OutputStream out, StreamContext ctx);
 
 	/**
diff --git a/briar-api/src/org/briarproject/api/data/BdfDictionary.java b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfDictionary.java
similarity index 97%
rename from briar-api/src/org/briarproject/api/data/BdfDictionary.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfDictionary.java
index cae6f728d66dd4fe07866579135c9198a66a627c..704e1e312e7d1c33fa0feb434beedd16f44c2d46 100644
--- a/briar-api/src/org/briarproject/api/data/BdfDictionary.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfDictionary.java
@@ -1,7 +1,7 @@
-package org.briarproject.api.data;
+package org.briarproject.bramble.api.data;
 
-import org.briarproject.api.Bytes;
-import org.briarproject.api.FormatException;
+import org.briarproject.bramble.api.Bytes;
+import org.briarproject.bramble.api.FormatException;
 
 import java.util.Map;
 import java.util.concurrent.ConcurrentSkipListMap;
diff --git a/briar-api/src/org/briarproject/api/data/BdfEntry.java b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfEntry.java
similarity index 75%
rename from briar-api/src/org/briarproject/api/data/BdfEntry.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfEntry.java
index 6b3176ee71ece55689d458c4aed73a91e180acbd..d915a85d2f1dc20fb541c3c8615215c174ec1424 100644
--- a/briar-api/src/org/briarproject/api/data/BdfEntry.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfEntry.java
@@ -1,7 +1,13 @@
-package org.briarproject.api.data;
+package org.briarproject.bramble.api.data;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.util.Map.Entry;
 
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 public class BdfEntry implements Entry<String, Object>, Comparable<BdfEntry> {
 
 	private final String key;
diff --git a/briar-api/src/org/briarproject/api/data/BdfList.java b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfList.java
similarity index 96%
rename from briar-api/src/org/briarproject/api/data/BdfList.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfList.java
index 39b7bd89e98c750802334eac56e4436576c81a70..8f1d47e4ec39eb258a604fbd02714578164cf3e7 100644
--- a/briar-api/src/org/briarproject/api/data/BdfList.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfList.java
@@ -1,14 +1,15 @@
-package org.briarproject.api.data;
+package org.briarproject.bramble.api.data;
 
-import org.briarproject.api.Bytes;
-import org.briarproject.api.FormatException;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.Bytes;
+import org.briarproject.bramble.api.FormatException;
 
 import java.util.Arrays;
 import java.util.List;
 import java.util.Vector;
 
-import static org.briarproject.api.data.BdfDictionary.NULL_VALUE;
+import javax.annotation.Nullable;
+
+import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
 
 public class BdfList extends Vector<Object> {
 
diff --git a/briar-api/src/org/briarproject/api/data/BdfReader.java b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfReader.java
similarity index 90%
rename from briar-api/src/org/briarproject/api/data/BdfReader.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfReader.java
index 531806beb8ee348f69eb1d751af5732b18eb005b..a2a3ec9e9e28d25e21b76e86a4237dfb7a6ba313 100644
--- a/briar-api/src/org/briarproject/api/data/BdfReader.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfReader.java
@@ -1,49 +1,75 @@
-package org.briarproject.api.data;
+package org.briarproject.bramble.api.data;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.IOException;
 
+@NotNullByDefault
 public interface BdfReader {
 
 	int DEFAULT_NESTED_LIMIT = 5;
 
 	boolean eof() throws IOException;
+
 	void close() throws IOException;
 
 	boolean hasNull() throws IOException;
+
 	void readNull() throws IOException;
+
 	void skipNull() throws IOException;
 
 	boolean hasBoolean() throws IOException;
+
 	boolean readBoolean() throws IOException;
+
 	void skipBoolean() throws IOException;
 
 	boolean hasLong() throws IOException;
+
 	long readLong() throws IOException;
+
 	void skipLong() throws IOException;
 
 	boolean hasDouble() throws IOException;
+
 	double readDouble() throws IOException;
+
 	void skipDouble() throws IOException;
 
 	boolean hasString() throws IOException;
+
 	String readString(int maxLength) throws IOException;
+
 	void skipString() throws IOException;
 
 	boolean hasRaw() throws IOException;
+
 	byte[] readRaw(int maxLength) throws IOException;
+
 	void skipRaw() throws IOException;
 
 	boolean hasList() throws IOException;
+
 	BdfList readList() throws IOException;
+
 	void readListStart() throws IOException;
+
 	boolean hasListEnd() throws IOException;
+
 	void readListEnd() throws IOException;
+
 	void skipList() throws IOException;
 
 	boolean hasDictionary() throws IOException;
+
 	BdfDictionary readDictionary() throws IOException;
+
 	void readDictionaryStart() throws IOException;
+
 	boolean hasDictionaryEnd() throws IOException;
+
 	void readDictionaryEnd() throws IOException;
+
 	void skipDictionary() throws IOException;
 }
diff --git a/briar-api/src/org/briarproject/api/data/BdfReaderFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfReaderFactory.java
similarity index 57%
rename from briar-api/src/org/briarproject/api/data/BdfReaderFactory.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfReaderFactory.java
index f8a53c1fbf6287bab7644a64ce6ba8f07a95c708..7eb1847ba11a3acca0fd3658a2a929ed8b95b118 100644
--- a/briar-api/src/org/briarproject/api/data/BdfReaderFactory.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfReaderFactory.java
@@ -1,7 +1,10 @@
-package org.briarproject.api.data;
+package org.briarproject.bramble.api.data;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.InputStream;
 
+@NotNullByDefault
 public interface BdfReaderFactory {
 
 	BdfReader createReader(InputStream in);
diff --git a/briar-api/src/org/briarproject/api/data/BdfWriter.java b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfWriter.java
similarity index 93%
rename from briar-api/src/org/briarproject/api/data/BdfWriter.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfWriter.java
index df0eb676df5c2d0ffaefed8277562312cae4225d..8e0e11d73ffc76170b48a7fe570500b4fcab432b 100644
--- a/briar-api/src/org/briarproject/api/data/BdfWriter.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfWriter.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.data;
+package org.briarproject.bramble.api.data;
 
 import java.io.IOException;
 import java.util.Collection;
@@ -7,20 +7,30 @@ import java.util.Map;
 public interface BdfWriter {
 
 	void flush() throws IOException;
+
 	void close() throws IOException;
 
 	void writeNull() throws IOException;
+
 	void writeBoolean(boolean b) throws IOException;
+
 	void writeLong(long l) throws IOException;
+
 	void writeDouble(double d) throws IOException;
+
 	void writeString(String s) throws IOException;
+
 	void writeRaw(byte[] b) throws IOException;
 
 	void writeList(Collection<?> c) throws IOException;
+
 	void writeListStart() throws IOException;
+
 	void writeListEnd() throws IOException;
 
 	void writeDictionary(Map<?, ?> m) throws IOException;
+
 	void writeDictionaryStart() throws IOException;
+
 	void writeDictionaryEnd() throws IOException;
 }
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfWriterFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfWriterFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..669c5dfa38b2eff5a5d718458bb7208426feaf29
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfWriterFactory.java
@@ -0,0 +1,11 @@
+package org.briarproject.bramble.api.data;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import java.io.OutputStream;
+
+@NotNullByDefault
+public interface BdfWriterFactory {
+
+	BdfWriter createWriter(OutputStream out);
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/data/MetadataEncoder.java b/bramble-api/src/main/java/org/briarproject/bramble/api/data/MetadataEncoder.java
new file mode 100644
index 0000000000000000000000000000000000000000..fe9864a7e635de28ee81ae5d78a4beca2da9b386
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/data/MetadataEncoder.java
@@ -0,0 +1,11 @@
+package org.briarproject.bramble.api.data;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+public interface MetadataEncoder {
+
+	Metadata encode(BdfDictionary d) throws FormatException;
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/data/MetadataParser.java b/bramble-api/src/main/java/org/briarproject/bramble/api/data/MetadataParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..94428e0e5ce3b1addb49873a8244378844b3fa26
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/data/MetadataParser.java
@@ -0,0 +1,11 @@
+package org.briarproject.bramble.api.data;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+public interface MetadataParser {
+
+	BdfDictionary parse(Metadata m) throws FormatException;
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/data/ObjectReader.java b/bramble-api/src/main/java/org/briarproject/bramble/api/data/ObjectReader.java
new file mode 100644
index 0000000000000000000000000000000000000000..acbf1434da7add2576090fbc0e8119fce6fa247d
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/data/ObjectReader.java
@@ -0,0 +1,11 @@
+package org.briarproject.bramble.api.data;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import java.io.IOException;
+
+@NotNullByDefault
+public interface ObjectReader<T> {
+
+	T readObject(BdfReader r) throws IOException;
+}
diff --git a/briar-api/src/org/briarproject/api/db/ContactExistsException.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/ContactExistsException.java
similarity index 84%
rename from briar-api/src/org/briarproject/api/db/ContactExistsException.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/db/ContactExistsException.java
index 8e27d9cc8b867f92862c62a6e1ee6d6b0322f7bb..6b51ce5b67673d0d674da8ab7e4f0b6473716154 100644
--- a/briar-api/src/org/briarproject/api/db/ContactExistsException.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/ContactExistsException.java
@@ -1,9 +1,8 @@
-package org.briarproject.api.db;
+package org.briarproject.bramble.api.db;
 
 /**
  * Thrown when a duplicate contact is added to the database. This exception may
  * occur due to concurrent updates and does not indicate a database error.
  */
 public class ContactExistsException extends DbException {
-
 }
diff --git a/briar-api/src/org/briarproject/api/db/DatabaseComponent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java
similarity index 90%
rename from briar-api/src/org/briarproject/api/db/DatabaseComponent.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java
index d2a0b28210ceef4bfa445baa0813fb407ff5d032..1de66e93425f58943a8f33cb1f746b7a27ffc307 100644
--- a/briar-api/src/org/briarproject/api/db/DatabaseComponent.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java
@@ -1,34 +1,38 @@
-package org.briarproject.api.db;
-
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.settings.Settings;
-import org.briarproject.api.sync.Ack;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.Group.Visibility;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.sync.MessageStatus;
-import org.briarproject.api.sync.Offer;
-import org.briarproject.api.sync.Request;
-import org.briarproject.api.transport.TransportKeys;
-import org.jetbrains.annotations.Nullable;
+package org.briarproject.bramble.api.db;
+
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.settings.Settings;
+import org.briarproject.bramble.api.sync.Ack;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.Group.Visibility;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.MessageStatus;
+import org.briarproject.bramble.api.sync.Offer;
+import org.briarproject.bramble.api.sync.Request;
+import org.briarproject.bramble.api.sync.ValidationManager;
+import org.briarproject.bramble.api.transport.TransportKeys;
 
 import java.util.Collection;
 import java.util.Map;
 
-import static org.briarproject.api.sync.ValidationManager.State;
+import javax.annotation.Nullable;
+
+import static org.briarproject.bramble.api.sync.ValidationManager.State;
 
 /**
  * Encapsulates the database implementation and exposes high-level operations
  * to other components.
  */
+@NotNullByDefault
 public interface DatabaseComponent {
 
 	/**
@@ -330,10 +334,10 @@ public interface DatabaseComponent {
 
 	/**
 	 * Returns the IDs and states of all dependencies of the given message.
-	 * Missing dependencies have the state {@link
-	 * org.briarproject.api.sync.ValidationManager.State UNKNOWN}.
-	 * Dependencies in other groups have the state {@link
-	 * org.briarproject.api.sync.ValidationManager.State INVALID}.
+	 * Missing dependencies have the state
+	 * {@link ValidationManager.State UNKNOWN}.
+	 * Dependencies in other groups have the state
+	 * {@link ValidationManager.State INVALID}.
 	 * Note that these states are not set on the dependencies themselves; the
 	 * returned states should only be taken in the context of the given message.
 	 * <p/>
diff --git a/briar-api/src/org/briarproject/api/db/DatabaseConfig.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseConfig.java
similarity index 54%
rename from briar-api/src/org/briarproject/api/db/DatabaseConfig.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseConfig.java
index 3233f687302ba443dba22513e6d7f8440249bec9..6a8aa19aa651dfbd6f6f08875b3c0a1dff9e3cf9 100644
--- a/briar-api/src/org/briarproject/api/db/DatabaseConfig.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseConfig.java
@@ -1,9 +1,13 @@
-package org.briarproject.api.db;
+package org.briarproject.bramble.api.db;
 
-import org.briarproject.api.crypto.SecretKey;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.File;
 
+import javax.annotation.Nullable;
+
+@NotNullByDefault
 public interface DatabaseConfig {
 
 	boolean databaseExists();
@@ -12,10 +16,12 @@ public interface DatabaseConfig {
 
 	void setEncryptionKey(SecretKey key);
 
+	@Nullable
 	SecretKey getEncryptionKey();
 
 	void setLocalAuthorName(String nickname);
 
+	@Nullable
 	String getLocalAuthorName();
 
 	long getMaxSize();
diff --git a/briar-api/src/org/briarproject/api/db/DatabaseExecutor.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseExecutor.java
similarity index 86%
rename from briar-api/src/org/briarproject/api/db/DatabaseExecutor.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseExecutor.java
index 5421f451f872684ab02305f42a0261aa87203010..256be229ad62eb934903d7e32a09bbe562666dec 100644
--- a/briar-api/src/org/briarproject/api/db/DatabaseExecutor.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseExecutor.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.db;
+package org.briarproject.bramble.api.db;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
@@ -20,6 +20,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
  * discarded.
  */
 @Qualifier
-@Target({ FIELD, METHOD, PARAMETER })
+@Target({FIELD, METHOD, PARAMETER})
 @Retention(RUNTIME)
-public @interface DatabaseExecutor {}
+public @interface DatabaseExecutor {
+}
diff --git a/briar-api/src/org/briarproject/api/db/DbClosedException.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DbClosedException.java
similarity index 77%
rename from briar-api/src/org/briarproject/api/db/DbClosedException.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/db/DbClosedException.java
index c8fbf68233cc1383d3d169526287a964455c7869..218c0a0b1e664fe0c04d8cbe2f36196957a1ac13 100644
--- a/briar-api/src/org/briarproject/api/db/DbClosedException.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DbClosedException.java
@@ -1,8 +1,7 @@
-package org.briarproject.api.db;
+package org.briarproject.bramble.api.db;
 
 /**
  * Thrown when a database operation is attempted and the database is closed.
  */
 public class DbClosedException extends DbException {
-
 }
diff --git a/briar-api/src/org/briarproject/api/db/DbException.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DbException.java
similarity index 75%
rename from briar-api/src/org/briarproject/api/db/DbException.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/db/DbException.java
index f111f9517bcc11d3b78b06a75563e006582b7439..a56f03302d9f09cfe2e290892d306e3cc5ad2154 100644
--- a/briar-api/src/org/briarproject/api/db/DbException.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DbException.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.db;
+package org.briarproject.bramble.api.db;
 
 public class DbException extends Exception {
 
diff --git a/briar-api/src/org/briarproject/api/db/Metadata.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/Metadata.java
similarity index 67%
rename from briar-api/src/org/briarproject/api/db/Metadata.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/db/Metadata.java
index b70df227f9d4573a69af8315dfcadbdc71da0fea..0b70a067f449418f67b8653fe497be072231144d 100644
--- a/briar-api/src/org/briarproject/api/db/Metadata.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/Metadata.java
@@ -1,7 +1,10 @@
-package org.briarproject.api.db;
+package org.briarproject.bramble.api.db;
 
 import java.util.Hashtable;
 
+import javax.annotation.concurrent.ThreadSafe;
+
+@ThreadSafe
 public class Metadata extends Hashtable<String, byte[]> {
 
 	/**
diff --git a/briar-api/src/org/briarproject/api/db/NoSuchContactException.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/NoSuchContactException.java
similarity index 86%
rename from briar-api/src/org/briarproject/api/db/NoSuchContactException.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/db/NoSuchContactException.java
index 9c2f5400b9da3520fd138014487b487b05c6f8be..d24ae11f0c762e3dd7d9fccb089f7d76b1071a27 100644
--- a/briar-api/src/org/briarproject/api/db/NoSuchContactException.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/NoSuchContactException.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.db;
+package org.briarproject.bramble.api.db;
 
 /**
  * Thrown when a database operation is attempted for a contact that is not in
@@ -6,5 +6,4 @@ package org.briarproject.api.db;
  * not indicate a database error.
  */
 public class NoSuchContactException extends DbException {
-
 }
diff --git a/briar-api/src/org/briarproject/api/db/NoSuchGroupException.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/NoSuchGroupException.java
similarity index 86%
rename from briar-api/src/org/briarproject/api/db/NoSuchGroupException.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/db/NoSuchGroupException.java
index 89222f58c79b6e880ddb324868850f949e4f3801..c40a64f3e610302177da915ff8aa3b2692f591a1 100644
--- a/briar-api/src/org/briarproject/api/db/NoSuchGroupException.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/NoSuchGroupException.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.db;
+package org.briarproject.bramble.api.db;
 
 /**
  * Thrown when a database operation is attempted for a group that is not in the
@@ -6,5 +6,4 @@ package org.briarproject.api.db;
  * indicate a database error.
  */
 public class NoSuchGroupException extends DbException {
-
 }
diff --git a/briar-api/src/org/briarproject/api/db/NoSuchLocalAuthorException.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/NoSuchLocalAuthorException.java
similarity index 86%
rename from briar-api/src/org/briarproject/api/db/NoSuchLocalAuthorException.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/db/NoSuchLocalAuthorException.java
index 91f4aabe9195348e62b22d8766a2b5d37f11e4ab..3ce99c1db2930ca91600d8057d2c014b352aa1ef 100644
--- a/briar-api/src/org/briarproject/api/db/NoSuchLocalAuthorException.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/NoSuchLocalAuthorException.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.db;
+package org.briarproject.bramble.api.db;
 
 /**
  * Thrown when a database operation is attempted for a pseudonym that is not in
@@ -6,5 +6,4 @@ package org.briarproject.api.db;
  * not indicate a database error.
  */
 public class NoSuchLocalAuthorException extends DbException {
-
 }
diff --git a/briar-api/src/org/briarproject/api/db/NoSuchMessageException.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/NoSuchMessageException.java
similarity index 86%
rename from briar-api/src/org/briarproject/api/db/NoSuchMessageException.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/db/NoSuchMessageException.java
index d7a5909e93409815377b1d50125656d7e58c5ca6..7f8b3ca5b44f196a990009ca1e03c3d5dfa4ddcb 100644
--- a/briar-api/src/org/briarproject/api/db/NoSuchMessageException.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/NoSuchMessageException.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.db;
+package org.briarproject.bramble.api.db;
 
 /**
  * Thrown when a database operation is attempted for a message that is not in
@@ -6,5 +6,4 @@ package org.briarproject.api.db;
  * not indicate a database error.
  */
 public class NoSuchMessageException extends DbException {
-
 }
diff --git a/briar-api/src/org/briarproject/api/db/NoSuchTransportException.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/NoSuchTransportException.java
similarity index 86%
rename from briar-api/src/org/briarproject/api/db/NoSuchTransportException.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/db/NoSuchTransportException.java
index d68a2cc30b2fd17a3b9f6333bbddae7853ccce13..68ac567ce90085e19b46f911548a1f29eb4eab19 100644
--- a/briar-api/src/org/briarproject/api/db/NoSuchTransportException.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/NoSuchTransportException.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.db;
+package org.briarproject.bramble.api.db;
 
 /**
  * Thrown when a database operation is attempted for a transport that is not in
@@ -6,5 +6,4 @@ package org.briarproject.api.db;
  * not indicate a database error.
  */
 public class NoSuchTransportException extends DbException {
-
 }
diff --git a/briar-api/src/org/briarproject/api/db/Transaction.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/Transaction.java
similarity index 90%
rename from briar-api/src/org/briarproject/api/db/Transaction.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/db/Transaction.java
index 9d6d473c9d4833e1d750e02b7f36d2831cff07a1..e228c84ec49b5ce986764b92c23ba4497465c7c5 100644
--- a/briar-api/src/org/briarproject/api/db/Transaction.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/Transaction.java
@@ -1,14 +1,17 @@
-package org.briarproject.api.db;
+package org.briarproject.bramble.api.db;
 
-import org.briarproject.api.event.Event;
+import org.briarproject.bramble.api.event.Event;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
+import javax.annotation.concurrent.NotThreadSafe;
+
 /**
  * A wrapper around a database transaction. Transactions are not thread-safe.
  */
+@NotThreadSafe
 public class Transaction {
 
 	private final Object txn;
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/event/Event.java b/bramble-api/src/main/java/org/briarproject/bramble/api/event/Event.java
new file mode 100644
index 0000000000000000000000000000000000000000..b93f209ea0af6a888f0139e14edec95f2c34397b
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/event/Event.java
@@ -0,0 +1,7 @@
+package org.briarproject.bramble.api.event;
+
+/**
+ * An abstract superclass for events.
+ */
+public abstract class Event {
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/event/EventBus.java b/bramble-api/src/main/java/org/briarproject/bramble/api/event/EventBus.java
new file mode 100644
index 0000000000000000000000000000000000000000..af00f8b1ba5c69e417be4206e8cae740ca536704
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/event/EventBus.java
@@ -0,0 +1,22 @@
+package org.briarproject.bramble.api.event;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+public interface EventBus {
+
+	/**
+	 * Adds a listener to be notified when events occur.
+	 */
+	void addListener(EventListener l);
+
+	/**
+	 * Removes a listener.
+	 */
+	void removeListener(EventListener l);
+
+	/**
+	 * Notifies all listeners of an event.
+	 */
+	void broadcast(Event e);
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/event/EventListener.java b/bramble-api/src/main/java/org/briarproject/bramble/api/event/EventListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..6dd330eadaf06065901c6ec7adee614466ea821b
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/event/EventListener.java
@@ -0,0 +1,16 @@
+package org.briarproject.bramble.api.event;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+/**
+ * An interface for receiving notifications when events occur.
+ */
+@NotNullByDefault
+public interface EventListener {
+
+	/**
+	 * Called when an event is broadcast. Implementations of this method must
+	 * not block.
+	 */
+	void eventOccurred(Event e);
+}
diff --git a/briar-api/src/org/briarproject/api/identity/Author.java b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/Author.java
similarity index 64%
rename from briar-api/src/org/briarproject/api/identity/Author.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/identity/Author.java
index de15869d3ebcbdf646580e177128cffea130eac7..7e89a7a7bf17c8ae7cb4eb78576c54a4ece1f720 100644
--- a/briar-api/src/org/briarproject/api/identity/Author.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/Author.java
@@ -1,11 +1,19 @@
-package org.briarproject.api.identity;
+package org.briarproject.bramble.api.identity;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.UnsupportedEncodingException;
 
-/** A pseudonym for a user. */
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * A pseudonym for a user.
+ */
+@Immutable
+@NotNullByDefault
 public class Author {
 
-	public enum Status { ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES }
+	public enum Status {ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES}
 
 	private final AuthorId id;
 	private final String name;
@@ -25,17 +33,23 @@ public class Author {
 		this.publicKey = publicKey;
 	}
 
-	/** Returns the author's unique identifier. */
+	/**
+	 * Returns the author's unique identifier.
+	 */
 	public AuthorId getId() {
 		return id;
 	}
 
-	/** Returns the author's name. */
+	/**
+	 * Returns the author's name.
+	 */
 	public String getName() {
 		return name;
 	}
 
-	/** Returns the public key used to verify the pseudonym's signatures. */
+	/**
+	 * Returns the public key used to verify the pseudonym's signatures.
+	 */
 	public byte[] getPublicKey() {
 		return publicKey;
 	}
diff --git a/briar-api/src/org/briarproject/api/identity/AuthorConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/AuthorConstants.java
similarity index 88%
rename from briar-api/src/org/briarproject/api/identity/AuthorConstants.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/identity/AuthorConstants.java
index 58fd9c4a84490566ab0945769c1f614ab3b70928..0699f972dc894120d9ea3a088ab83b7463c222f9 100644
--- a/briar-api/src/org/briarproject/api/identity/AuthorConstants.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/AuthorConstants.java
@@ -1,8 +1,10 @@
-package org.briarproject.api.identity;
+package org.briarproject.bramble.api.identity;
 
 public interface AuthorConstants {
 
-	/** The maximum length of an author's name in UTF-8 bytes. */
+	/**
+	 * The maximum length of an author's name in UTF-8 bytes.
+	 */
 	int MAX_AUTHOR_NAME_LENGTH = 50;
 
 	/**
diff --git a/briar-api/src/org/briarproject/api/identity/AuthorFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/AuthorFactory.java
similarity index 57%
rename from briar-api/src/org/briarproject/api/identity/AuthorFactory.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/identity/AuthorFactory.java
index 2c474b7cd7569f8649c29e60e873342b1b1a9cc9..aaf151dc17b6806ee4f98a3759aba70b11a71c53 100644
--- a/briar-api/src/org/briarproject/api/identity/AuthorFactory.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/AuthorFactory.java
@@ -1,5 +1,8 @@
-package org.briarproject.api.identity;
+package org.briarproject.bramble.api.identity;
 
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
 public interface AuthorFactory {
 
 	Author createAuthor(String name, byte[] publicKey);
diff --git a/briar-api/src/org/briarproject/api/identity/AuthorId.java b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/AuthorId.java
similarity index 64%
rename from briar-api/src/org/briarproject/api/identity/AuthorId.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/identity/AuthorId.java
index 00f35db0e9acd2192281cc488f9bf00bec516e23..c035a0ce089be9d014f70459125504c23750132e 100644
--- a/briar-api/src/org/briarproject/api/identity/AuthorId.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/AuthorId.java
@@ -1,13 +1,18 @@
-package org.briarproject.api.identity;
+package org.briarproject.bramble.api.identity;
 
-import org.briarproject.api.UniqueId;
+import org.briarproject.bramble.api.UniqueId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.nio.charset.Charset;
 
+import javax.annotation.concurrent.ThreadSafe;
+
 /**
  * Type-safe wrapper for a byte array that uniquely identifies an
- * {@link org.briarproject.api.identity.Author Author}.
+ * {@link Author}.
  */
+@ThreadSafe
+@NotNullByDefault
 public class AuthorId extends UniqueId {
 
 	/**
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/identity/IdentityManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/IdentityManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..bb584fec45dc2f9734aff102718ef412577dafa4
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/IdentityManager.java
@@ -0,0 +1,38 @@
+package org.briarproject.bramble.api.identity;
+
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+public interface IdentityManager {
+
+	/**
+	 * Stores the local pseudonym.
+	 */
+	void registerLocalAuthor(LocalAuthor a) throws DbException;
+
+	/**
+	 * Returns the cached main local identity, non-blocking, or loads it from
+	 * the db, blocking
+	 */
+	LocalAuthor getLocalAuthor() throws DbException;
+
+	/**
+	 * Returns the cached main local identity, non-blocking, or loads it from
+	 * the db, blocking, within the given Transaction.
+	 */
+	LocalAuthor getLocalAuthor(Transaction txn) throws DbException;
+
+	/**
+	 * Returns the trust-level status of the author
+	 */
+	Status getAuthorStatus(AuthorId a) throws DbException;
+
+	/**
+	 * Returns the trust-level status of the author
+	 */
+	Status getAuthorStatus(Transaction txn, AuthorId a) throws DbException;
+
+}
diff --git a/briar-api/src/org/briarproject/api/identity/LocalAuthor.java b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/LocalAuthor.java
similarity index 62%
rename from briar-api/src/org/briarproject/api/identity/LocalAuthor.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/identity/LocalAuthor.java
index cdcfdc788a4932c62625935f13fbcd1eebecd72c..ae217b19fdfe00c6090f9979964965f69dac37b2 100644
--- a/briar-api/src/org/briarproject/api/identity/LocalAuthor.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/LocalAuthor.java
@@ -1,6 +1,14 @@
-package org.briarproject.api.identity;
+package org.briarproject.bramble.api.identity;
 
-/** A pseudonym for the local user. */
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * A pseudonym for the local user.
+ */
+@Immutable
+@NotNullByDefault
 public class LocalAuthor extends Author {
 
 	private final byte[] privateKey;
@@ -13,7 +21,9 @@ public class LocalAuthor extends Author {
 		this.created = created;
 	}
 
-	/**  Returns the private key used to generate the pseudonym's signatures. */
+	/**
+	 * Returns the private key used to generate the pseudonym's signatures.
+	 */
 	public byte[] getPrivateKey() {
 		return privateKey;
 	}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/identity/event/LocalAuthorAddedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/event/LocalAuthorAddedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..a12d232f26fcaabbd0ca91f8b412842dcc8a9865
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/event/LocalAuthorAddedEvent.java
@@ -0,0 +1,25 @@
+package org.briarproject.bramble.api.identity.event;
+
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when a local pseudonym is added.
+ */
+@Immutable
+@NotNullByDefault
+public class LocalAuthorAddedEvent extends Event {
+
+	private final AuthorId authorId;
+
+	public LocalAuthorAddedEvent(AuthorId authorId) {
+		this.authorId = authorId;
+	}
+
+	public AuthorId getAuthorId() {
+		return authorId;
+	}
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/identity/event/LocalAuthorRemovedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/event/LocalAuthorRemovedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..31c93c3005e3dff3b50676cf85d7a0efd088f80d
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/event/LocalAuthorRemovedEvent.java
@@ -0,0 +1,25 @@
+package org.briarproject.bramble.api.identity.event;
+
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when a local pseudonym is removed.
+ */
+@Immutable
+@NotNullByDefault
+public class LocalAuthorRemovedEvent extends Event {
+
+	private final AuthorId authorId;
+
+	public LocalAuthorRemovedEvent(AuthorId authorId) {
+		this.authorId = authorId;
+	}
+
+	public AuthorId getAuthorId() {
+		return authorId;
+	}
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/invitation/InvitationConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/invitation/InvitationConstants.java
new file mode 100644
index 0000000000000000000000000000000000000000..f7c6ed3319bb00ce0c59ea1d82541d6209ba6752
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/invitation/InvitationConstants.java
@@ -0,0 +1,20 @@
+package org.briarproject.bramble.api.invitation;
+
+public interface InvitationConstants {
+
+	/**
+	 * The connection timeout in milliseconds.
+	 */
+	long CONNECTION_TIMEOUT = 60 * 1000;
+
+	/**
+	 * The confirmation timeout in milliseconds.
+	 */
+	long CONFIRMATION_TIMEOUT = 60 * 1000;
+
+	/**
+	 * The number of bits in an invitation or confirmation code. Codes must fit
+	 * into six decimal digits.
+	 */
+	int CODE_BITS = 19;
+}
diff --git a/briar-api/src/org/briarproject/api/invitation/InvitationListener.java b/bramble-api/src/main/java/org/briarproject/bramble/api/invitation/InvitationListener.java
similarity index 96%
rename from briar-api/src/org/briarproject/api/invitation/InvitationListener.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/invitation/InvitationListener.java
index 67af91ae4390343b5812f1814997652080990755..acf545f1a77368cf72ddc30292c06a92f97eb965 100644
--- a/briar-api/src/org/briarproject/api/invitation/InvitationListener.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/invitation/InvitationListener.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.invitation;
+package org.briarproject.bramble.api.invitation;
 
 /**
  * An interface for receiving updates about the state of an
diff --git a/briar-api/src/org/briarproject/api/invitation/InvitationState.java b/bramble-api/src/main/java/org/briarproject/bramble/api/invitation/InvitationState.java
similarity index 83%
rename from briar-api/src/org/briarproject/api/invitation/InvitationState.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/invitation/InvitationState.java
index e99ac16d0601407e6b116a6157e3fa0effd6c45b..456230837ca89048fdee981c85bb34b92808b86d 100644
--- a/briar-api/src/org/briarproject/api/invitation/InvitationState.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/invitation/InvitationState.java
@@ -1,5 +1,15 @@
-package org.briarproject.api.invitation;
+package org.briarproject.bramble.api.invitation;
 
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * A snapshot of the state of an {@link InvitationTask}.
+ */
+@Immutable
+@NotNullByDefault
 public class InvitationState {
 
 	private final int localInvitationCode, remoteInvitationCode;
@@ -7,13 +17,14 @@ public class InvitationState {
 	private final boolean connected, connectionFailed;
 	private final boolean localCompared, remoteCompared;
 	private final boolean localMatched, remoteMatched;
+	@Nullable
 	private final String contactName;
 
 	public InvitationState(int localInvitationCode, int remoteInvitationCode,
 			int localConfirmationCode, int remoteConfirmationCode,
 			boolean connected, boolean connectionFailed, boolean localCompared,
 			boolean remoteCompared, boolean localMatched,
-			boolean remoteMatched, String contactName) {
+			boolean remoteMatched, @Nullable String contactName) {
 		this.localInvitationCode = localInvitationCode;
 		this.remoteInvitationCode = remoteInvitationCode;
 		this.localConfirmationCode = localConfirmationCode;
@@ -67,6 +78,7 @@ public class InvitationState {
 		return remoteMatched;
 	}
 
+	@Nullable
 	public String getContactName() {
 		return contactName;
 	}
diff --git a/briar-api/src/org/briarproject/api/invitation/InvitationTask.java b/bramble-api/src/main/java/org/briarproject/bramble/api/invitation/InvitationTask.java
similarity index 64%
rename from briar-api/src/org/briarproject/api/invitation/InvitationTask.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/invitation/InvitationTask.java
index d188de5a5959c7bdeb500012ccd071ae296717b4..b09d940f308f678b783bf752b61ee9f0eca4823f 100644
--- a/briar-api/src/org/briarproject/api/invitation/InvitationTask.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/invitation/InvitationTask.java
@@ -1,6 +1,11 @@
-package org.briarproject.api.invitation;
+package org.briarproject.bramble.api.invitation;
 
-/** A task for exchanging invitations with a remote peer. */
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+/**
+ * A task for exchanging invitations with a remote peer.
+ */
+@NotNullByDefault
 public interface InvitationTask {
 
 	/**
@@ -9,10 +14,14 @@ public interface InvitationTask {
 	 */
 	InvitationState addListener(InvitationListener l);
 
-	/** Removes the given listener. */
+	/**
+	 * Removes the given listener.
+	 */
 	void removeListener(InvitationListener l);
 
-	/** Asynchronously starts the connection process. */
+	/**
+	 * Asynchronously starts the connection process.
+	 */
 	void connect();
 
 	/**
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/invitation/InvitationTaskFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/invitation/InvitationTaskFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..76f94908a3af51af770304922f5d554ec90f5cc5
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/invitation/InvitationTaskFactory.java
@@ -0,0 +1,15 @@
+package org.briarproject.bramble.api.invitation;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+/**
+ * Creates tasks for exchanging invitations with remote peers.
+ */
+@NotNullByDefault
+public interface InvitationTaskFactory {
+
+	/**
+	 * Creates a task using the given local and remote invitation codes.
+	 */
+	InvitationTask createTask(int localCode, int remoteCode);
+}
diff --git a/briar-api/src/org/briarproject/api/keyagreement/KeyAgreementConnection.java b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementConnection.java
similarity index 53%
rename from briar-api/src/org/briarproject/api/keyagreement/KeyAgreementConnection.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementConnection.java
index 7dfa3bc689d4a288ce01b90de6e10f3e3bd50e7f..8a381ae09ec70057b67033a4d0fc0618bf2d296e 100644
--- a/briar-api/src/org/briarproject/api/keyagreement/KeyAgreementConnection.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementConnection.java
@@ -1,9 +1,15 @@
-package org.briarproject.api.keyagreement;
+package org.briarproject.bramble.api.keyagreement;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
 
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 public class KeyAgreementConnection {
+
 	private final DuplexTransportConnection conn;
 	private final TransportId id;
 
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementConstants.java
new file mode 100644
index 0000000000000000000000000000000000000000..76204bdfbeb2b48f7bad458bd82801eb7f39df42
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementConstants.java
@@ -0,0 +1,36 @@
+package org.briarproject.bramble.api.keyagreement;
+
+public interface KeyAgreementConstants {
+
+	/**
+	 * The current version of the BQP protocol.
+	 */
+	byte PROTOCOL_VERSION = 2;
+
+	/**
+	 * The length of the record header in bytes.
+	 */
+	int RECORD_HEADER_LENGTH = 4;
+
+	/**
+	 * The offset of the payload length in the record header, in bytes.
+	 */
+	int RECORD_HEADER_PAYLOAD_LENGTH_OFFSET = 2;
+
+	/**
+	 * The length of the BQP key commitment in bytes.
+	 */
+	int COMMIT_LENGTH = 16;
+
+	long CONNECTION_TIMEOUT = 20 * 1000; // Milliseconds
+
+	/**
+	 * The transport identifier for Bluetooth.
+	 */
+	int TRANSPORT_ID_BLUETOOTH = 0;
+
+	/**
+	 * The transport identifier for LAN.
+	 */
+	int TRANSPORT_ID_LAN = 1;
+}
diff --git a/briar-api/src/org/briarproject/api/keyagreement/KeyAgreementListener.java b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementListener.java
similarity index 88%
rename from briar-api/src/org/briarproject/api/keyagreement/KeyAgreementListener.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementListener.java
index 41b18a7de3264de851655550a3ba2db41f00ed4b..42fda82f9f858eb0bf360b0ee6a60042a77f951a 100644
--- a/briar-api/src/org/briarproject/api/keyagreement/KeyAgreementListener.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementListener.java
@@ -1,6 +1,6 @@
-package org.briarproject.api.keyagreement;
+package org.briarproject.bramble.api.keyagreement;
 
-import org.briarproject.api.data.BdfList;
+import org.briarproject.bramble.api.data.BdfList;
 
 import java.util.concurrent.Callable;
 
diff --git a/briar-api/src/org/briarproject/api/keyagreement/KeyAgreementResult.java b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementResult.java
similarity index 74%
rename from briar-api/src/org/briarproject/api/keyagreement/KeyAgreementResult.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementResult.java
index 3f772ca28792d58571a82b5da7b6b65a1ab27624..9d7ac20c22a938bd6d914bf0df081cb28d606020 100644
--- a/briar-api/src/org/briarproject/api/keyagreement/KeyAgreementResult.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementResult.java
@@ -1,8 +1,8 @@
-package org.briarproject.api.keyagreement;
+package org.briarproject.bramble.api.keyagreement;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
 
 public class KeyAgreementResult {
 
diff --git a/briar-api/src/org/briarproject/api/keyagreement/KeyAgreementTask.java b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementTask.java
similarity index 60%
rename from briar-api/src/org/briarproject/api/keyagreement/KeyAgreementTask.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementTask.java
index 443ef42bd68d11f7bae75cf576d8e2721bc0a63f..f5d5150c44957be32102b99d60eeea0684eefb3e 100644
--- a/briar-api/src/org/briarproject/api/keyagreement/KeyAgreementTask.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementTask.java
@@ -1,6 +1,11 @@
-package org.briarproject.api.keyagreement;
+package org.briarproject.bramble.api.keyagreement;
 
-/** A task for conducting a key agreement with a remote peer. */
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+/**
+ * A task for conducting a key agreement with a remote peer.
+ */
+@NotNullByDefault
 public interface KeyAgreementTask {
 
 	/**
@@ -16,6 +21,8 @@ public interface KeyAgreementTask {
 	 */
 	void stopListening();
 
-	/** Asynchronously start the connection process. */
+	/**
+	 * Asynchronously start the connection process.
+	 */
 	void connectAndRunProtocol(Payload remotePayload);
 }
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementTaskFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementTaskFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..40d875cc9d792e53a34c3d6f52ac6611c6fd9dea
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementTaskFactory.java
@@ -0,0 +1,15 @@
+package org.briarproject.bramble.api.keyagreement;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+/**
+ * Manages tasks for conducting key agreements with remote peers.
+ */
+@NotNullByDefault
+public interface KeyAgreementTaskFactory {
+
+	/**
+	 * Gets the current key agreement task.
+	 */
+	KeyAgreementTask createTask();
+}
diff --git a/briar-api/src/org/briarproject/api/keyagreement/Payload.java b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/Payload.java
similarity index 83%
rename from briar-api/src/org/briarproject/api/keyagreement/Payload.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/Payload.java
index 14cb82421f27f4f55689f61c0b0dd400d185da82..c554d24e934c6fbac26cd8eb235c5c9bfa01043a 100644
--- a/briar-api/src/org/briarproject/api/keyagreement/Payload.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/Payload.java
@@ -1,7 +1,7 @@
-package org.briarproject.api.keyagreement;
+package org.briarproject.bramble.api.keyagreement;
 
-import org.briarproject.api.Bytes;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.Bytes;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.util.List;
 
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/PayloadEncoder.java b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/PayloadEncoder.java
new file mode 100644
index 0000000000000000000000000000000000000000..4744d4640083fc0e3b2ba0157395985f4480c580
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/PayloadEncoder.java
@@ -0,0 +1,9 @@
+package org.briarproject.bramble.api.keyagreement;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+public interface PayloadEncoder {
+
+	byte[] encode(Payload p);
+}
diff --git a/briar-api/src/org/briarproject/api/keyagreement/PayloadParser.java b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/PayloadParser.java
similarity index 53%
rename from briar-api/src/org/briarproject/api/keyagreement/PayloadParser.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/PayloadParser.java
index 0ada113f360d046ed81100f4a3fe83a3b7bbb1eb..90403669d471d92ff35ac81c51c20cf0fd7d8625 100644
--- a/briar-api/src/org/briarproject/api/keyagreement/PayloadParser.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/PayloadParser.java
@@ -1,6 +1,6 @@
-package org.briarproject.api.keyagreement;
+package org.briarproject.bramble.api.keyagreement;
 
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.IOException;
 
diff --git a/briar-api/src/org/briarproject/api/keyagreement/RecordTypes.java b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/RecordTypes.java
similarity index 50%
rename from briar-api/src/org/briarproject/api/keyagreement/RecordTypes.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/RecordTypes.java
index ef1d2ff51feb21d04b9e995474e091aede397379..36f3359f535a6b11a1e0b6725511578b5fda758e 100644
--- a/briar-api/src/org/briarproject/api/keyagreement/RecordTypes.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/RecordTypes.java
@@ -1,6 +1,8 @@
-package org.briarproject.api.keyagreement;
+package org.briarproject.bramble.api.keyagreement;
 
-/** Record types for BQP. */
+/**
+ * Record types for BQP.
+ */
 public interface RecordTypes {
 
 	byte KEY = 0;
diff --git a/briar-api/src/org/briarproject/api/keyagreement/TransportDescriptor.java b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/TransportDescriptor.java
similarity index 64%
rename from briar-api/src/org/briarproject/api/keyagreement/TransportDescriptor.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/TransportDescriptor.java
index 7b61d74ffda18973e4a5514acd168b7292050639..329bf27ab922c4eaf4ca0b4465908663553fb475 100644
--- a/briar-api/src/org/briarproject/api/keyagreement/TransportDescriptor.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/TransportDescriptor.java
@@ -1,8 +1,8 @@
-package org.briarproject.api.keyagreement;
+package org.briarproject.bramble.api.keyagreement;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
 
 import javax.annotation.concurrent.Immutable;
 
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementAbortedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementAbortedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..b0b8bf2c3c5e1c0c5763a808fcdbea6dbe854e5c
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementAbortedEvent.java
@@ -0,0 +1,24 @@
+package org.briarproject.bramble.api.keyagreement.event;
+
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when a BQP protocol aborts.
+ */
+@Immutable
+@NotNullByDefault
+public class KeyAgreementAbortedEvent extends Event {
+
+	private final boolean remoteAborted;
+
+	public KeyAgreementAbortedEvent(boolean remoteAborted) {
+		this.remoteAborted = remoteAborted;
+	}
+
+	public boolean didRemoteAbort() {
+		return remoteAborted;
+	}
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementFailedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementFailedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..e8f3dff7958b303739cbb4eb502dc06e9d28326e
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementFailedEvent.java
@@ -0,0 +1,9 @@
+package org.briarproject.bramble.api.keyagreement.event;
+
+import org.briarproject.bramble.api.event.Event;
+
+/**
+ * An event that is broadcast when a BQP connection cannot be created.
+ */
+public class KeyAgreementFailedEvent extends Event {
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementFinishedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementFinishedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..81950fbcb2f0b05edb01ecaa02fa7c0b972f16f0
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementFinishedEvent.java
@@ -0,0 +1,25 @@
+package org.briarproject.bramble.api.keyagreement.event;
+
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementResult;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when a BQP protocol completes.
+ */
+@Immutable
+@NotNullByDefault
+public class KeyAgreementFinishedEvent extends Event {
+
+	private final KeyAgreementResult result;
+
+	public KeyAgreementFinishedEvent(KeyAgreementResult result) {
+		this.result = result;
+	}
+
+	public KeyAgreementResult getResult() {
+		return result;
+	}
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementListeningEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementListeningEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..6d8da3aeff52f40fd5e3acec47c71ca34603d44e
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementListeningEvent.java
@@ -0,0 +1,25 @@
+package org.briarproject.bramble.api.keyagreement.event;
+
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.keyagreement.Payload;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when a BQP task is listening.
+ */
+@Immutable
+@NotNullByDefault
+public class KeyAgreementListeningEvent extends Event {
+
+	private final Payload localPayload;
+
+	public KeyAgreementListeningEvent(Payload localPayload) {
+		this.localPayload = localPayload;
+	}
+
+	public Payload getLocalPayload() {
+		return localPayload;
+	}
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementStartedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementStartedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..289077cb86b4ea279b89c035a8a62eada61dc56e
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementStartedEvent.java
@@ -0,0 +1,9 @@
+package org.briarproject.bramble.api.keyagreement.event;
+
+import org.briarproject.bramble.api.event.Event;
+
+/**
+ * An event that is broadcast when a BQP protocol completes.
+ */
+public class KeyAgreementStartedEvent extends Event {
+}
diff --git a/briar-api/src/org/briarproject/api/event/KeyAgreementWaitingEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementWaitingEvent.java
similarity index 60%
rename from briar-api/src/org/briarproject/api/event/KeyAgreementWaitingEvent.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementWaitingEvent.java
index 473c6538adb053d4aeb0551621ebf8a8b2c97aa2..d671804d2af303a464659ab0b12e25f6d8a9ce6e 100644
--- a/briar-api/src/org/briarproject/api/event/KeyAgreementWaitingEvent.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementWaitingEvent.java
@@ -1,9 +1,10 @@
-package org.briarproject.api.event;
+package org.briarproject.bramble.api.keyagreement.event;
+
+import org.briarproject.bramble.api.event.Event;
 
 /**
  * An event that is broadcast when a BQP protocol is waiting on the remote
  * peer to start.
  */
 public class KeyAgreementWaitingEvent extends Event {
-
 }
diff --git a/briar-api/src/org/briarproject/api/lifecycle/IoExecutor.java b/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/IoExecutor.java
similarity index 94%
rename from briar-api/src/org/briarproject/api/lifecycle/IoExecutor.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/IoExecutor.java
index 1bffc3c3cc73c9fa9f32b48c87e65d014c9f5b87..c63e6a8c7f2d79408bddceafe87edb4e48d67bd6 100644
--- a/briar-api/src/org/briarproject/api/lifecycle/IoExecutor.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/IoExecutor.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.lifecycle;
+package org.briarproject.bramble.api.lifecycle;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/LifecycleManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/LifecycleManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..2c680b1018e73882016a3eddf6c325a423e9a209
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/LifecycleManager.java
@@ -0,0 +1,74 @@
+package org.briarproject.bramble.api.lifecycle;
+
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Client;
+
+import java.util.concurrent.ExecutorService;
+
+import javax.annotation.Nullable;
+
+/**
+ * Manages the lifecycle of the app, starting {@link Client Clients}, starting
+ * and stopping {@link Service Services}, shutting down
+ * {@link ExecutorService ExecutorServices}, and opening and closing the
+ * {@link DatabaseComponent}.
+ */
+@NotNullByDefault
+public interface LifecycleManager {
+
+	/**
+	 * The result of calling {@link #startServices(String)}.
+	 */
+	enum StartResult {
+		ALREADY_RUNNING, DB_ERROR, SERVICE_ERROR, SUCCESS
+	}
+
+	/**
+	 * Registers a {@link Service} to be started and stopped.
+	 */
+	void registerService(Service s);
+
+	/**
+	 * Registers a {@link Client} to be started.
+	 */
+	void registerClient(Client c);
+
+	/**
+	 * Registers an {@link ExecutorService} to be shut down.
+	 */
+	void registerForShutdown(ExecutorService e);
+
+	/**
+	 * Opens the {@link DatabaseComponent}, optionally creates a local author
+	 * with the provided nickname, and starts any registered
+	 * {@link Client Clients} and {@link Service Services}.
+	 */
+	StartResult startServices(@Nullable String nickname);
+
+	/**
+	 * Stops any registered {@link Service Services}, shuts down any
+	 * registered {@link ExecutorService ExecutorServices}, and closes the
+	 * {@link DatabaseComponent}.
+	 */
+	void stopServices();
+
+	/**
+	 * Waits for the {@link DatabaseComponent} to be opened before returning.
+	 */
+	void waitForDatabase() throws InterruptedException;
+
+	/**
+	 * Waits for the {@link DatabaseComponent} to be opened and all registered
+	 * {@link Client Clients} and {@link Service Services} to start before
+	 * returning.
+	 */
+	void waitForStartup() throws InterruptedException;
+
+	/**
+	 * Waits for all registered {@link Service Services} to stop, all
+	 * registered {@link ExecutorService ExecutorServices} to shut down, and
+	 * the {@link DatabaseComponent} to be closed before returning.
+	 */
+	void waitForShutdown() throws InterruptedException;
+}
\ No newline at end of file
diff --git a/briar-api/src/org/briarproject/api/lifecycle/Service.java b/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/Service.java
similarity index 87%
rename from briar-api/src/org/briarproject/api/lifecycle/Service.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/Service.java
index 5489435a4a7eefd2fce155406976f1be91bad99c..fcdcab91280b045b946a5bfe5849bfbd7d0778fb 100644
--- a/briar-api/src/org/briarproject/api/lifecycle/Service.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/Service.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.lifecycle;
+package org.briarproject.bramble.api.lifecycle;
 
 public interface Service {
 
diff --git a/briar-api/src/org/briarproject/api/lifecycle/ServiceException.java b/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/ServiceException.java
similarity index 83%
rename from briar-api/src/org/briarproject/api/lifecycle/ServiceException.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/ServiceException.java
index 55a0b939ab51332ba86743064bf8dbba25509cc9..932f0b22555509c410adb509b6d0bf8b9f3ca22e 100644
--- a/briar-api/src/org/briarproject/api/lifecycle/ServiceException.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/ServiceException.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.lifecycle;
+package org.briarproject.bramble.api.lifecycle;
 
 /**
  * An exception that indicates an error starting or stopping a {@link Service}.
diff --git a/briar-api/src/org/briarproject/api/lifecycle/ShutdownManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/ShutdownManager.java
similarity index 73%
rename from briar-api/src/org/briarproject/api/lifecycle/ShutdownManager.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/ShutdownManager.java
index 27550c7e8a8a9321d23db534312173fc8cc607ec..78e2ee60b2e54bff5926aeaeb2f6bedc2aba7a04 100644
--- a/briar-api/src/org/briarproject/api/lifecycle/ShutdownManager.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/ShutdownManager.java
@@ -1,5 +1,8 @@
-package org.briarproject.api.lifecycle;
+package org.briarproject.bramble.api.lifecycle;
 
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
 public interface ShutdownManager {
 
 	/**
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/event/ShutdownEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/event/ShutdownEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..ba0c4d37f03e963483432eb115070379d2abbcc5
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/event/ShutdownEvent.java
@@ -0,0 +1,9 @@
+package org.briarproject.bramble.api.lifecycle.event;
+
+import org.briarproject.bramble.api.event.Event;
+
+/**
+ * An event that is broadcast when the app is shutting down.
+ */
+public class ShutdownEvent extends Event {
+}
diff --git a/briar-api/src/org/briarproject/api/nullsafety/FieldsNotNullByDefault.java b/bramble-api/src/main/java/org/briarproject/bramble/api/nullsafety/FieldsNotNullByDefault.java
similarity index 93%
rename from briar-api/src/org/briarproject/api/nullsafety/FieldsNotNullByDefault.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/nullsafety/FieldsNotNullByDefault.java
index bdfd8f523bd1a3bc3fcec886aebcb69911ed752f..54d04f43fdfc73377dc2495ba38e305fe01546c9 100644
--- a/briar-api/src/org/briarproject/api/nullsafety/FieldsNotNullByDefault.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/nullsafety/FieldsNotNullByDefault.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.nullsafety;
+package org.briarproject.bramble.api.nullsafety;
 
 import java.lang.annotation.Documented;
 import java.lang.annotation.Retention;
diff --git a/briar-api/src/org/briarproject/api/nullsafety/MethodsNotNullByDefault.java b/bramble-api/src/main/java/org/briarproject/bramble/api/nullsafety/MethodsNotNullByDefault.java
similarity index 94%
rename from briar-api/src/org/briarproject/api/nullsafety/MethodsNotNullByDefault.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/nullsafety/MethodsNotNullByDefault.java
index 417e792de0af0dbdfa9e4328dc3f34b48fb01592..9fbfe4f0b0bb4084e9e1b02ca930c077eced9998 100644
--- a/briar-api/src/org/briarproject/api/nullsafety/MethodsNotNullByDefault.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/nullsafety/MethodsNotNullByDefault.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.nullsafety;
+package org.briarproject.bramble.api.nullsafety;
 
 import java.lang.annotation.Documented;
 import java.lang.annotation.Retention;
diff --git a/briar-api/src/org/briarproject/api/nullsafety/NotNullByDefault.java b/bramble-api/src/main/java/org/briarproject/bramble/api/nullsafety/NotNullByDefault.java
similarity index 95%
rename from briar-api/src/org/briarproject/api/nullsafety/NotNullByDefault.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/nullsafety/NotNullByDefault.java
index 29ae96b7cc2452294888c9de6643417ef6c675be..23fd38c7e7752a98cf1562875897c74ce56500dd 100644
--- a/briar-api/src/org/briarproject/api/nullsafety/NotNullByDefault.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/nullsafety/NotNullByDefault.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.nullsafety;
+package org.briarproject.bramble.api.nullsafety;
 
 import java.lang.annotation.Documented;
 import java.lang.annotation.Retention;
diff --git a/briar-api/src/org/briarproject/api/nullsafety/ParametersNotNullByDefault.java b/bramble-api/src/main/java/org/briarproject/bramble/api/nullsafety/ParametersNotNullByDefault.java
similarity index 94%
rename from briar-api/src/org/briarproject/api/nullsafety/ParametersNotNullByDefault.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/nullsafety/ParametersNotNullByDefault.java
index ac5de25e25c61715d8b70b7a06dd430bbc1fcc74..eb183de2eba2e330c4b60a0dd82f45d8b67d9783 100644
--- a/briar-api/src/org/briarproject/api/nullsafety/ParametersNotNullByDefault.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/nullsafety/ParametersNotNullByDefault.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.nullsafety;
+package org.briarproject.bramble.api.nullsafety;
 
 import java.lang.annotation.Documented;
 import java.lang.annotation.Retention;
diff --git a/briar-api/src/org/briarproject/api/plugins/Backoff.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/Backoff.java
similarity index 87%
rename from briar-api/src/org/briarproject/api/plugins/Backoff.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/Backoff.java
index 927e8a737bec33bd9eda33022d4521d309699e02..0158108d2a80cf9d581bf3f98082f8d104bdaaa7 100644
--- a/briar-api/src/org/briarproject/api/plugins/Backoff.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/Backoff.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.plugins;
+package org.briarproject.bramble.api.plugin;
 
 /**
  * Calculates polling intervals for transport plugins that use backoff.
diff --git a/briar-api/src/org/briarproject/api/plugins/BackoffFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/BackoffFactory.java
similarity index 71%
rename from briar-api/src/org/briarproject/api/plugins/BackoffFactory.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/BackoffFactory.java
index 4633ba3a5df5cee19979abbfe1be5fb368adf6cf..0a60b5626bcf0351ae0551d595da808a21961fb8 100644
--- a/briar-api/src/org/briarproject/api/plugins/BackoffFactory.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/BackoffFactory.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.plugins;
+package org.briarproject.bramble.api.plugin;
 
 public interface BackoffFactory {
 
diff --git a/briar-api/src/org/briarproject/api/plugins/BluetoothConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/BluetoothConstants.java
similarity index 71%
rename from briar-api/src/org/briarproject/api/plugins/BluetoothConstants.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/BluetoothConstants.java
index 3708df560a586a979f3b1858b1eb970ca383ba53..b8660d0f716d89db105b48b0ab8b661e9f6c508c 100644
--- a/briar-api/src/org/briarproject/api/plugins/BluetoothConstants.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/BluetoothConstants.java
@@ -1,6 +1,4 @@
-package org.briarproject.api.plugins;
-
-import org.briarproject.api.TransportId;
+package org.briarproject.bramble.api.plugin;
 
 public interface BluetoothConstants {
 
diff --git a/briar-api/src/org/briarproject/api/plugins/ConnectionManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/ConnectionManager.java
similarity index 66%
rename from briar-api/src/org/briarproject/api/plugins/ConnectionManager.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/ConnectionManager.java
index da7940187a6438c3b8ea8952d1a8b751fb9cd91d..c29e5721eb1560080f9d51bbd063b241128a64ed 100644
--- a/briar-api/src/org/briarproject/api/plugins/ConnectionManager.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/ConnectionManager.java
@@ -1,8 +1,7 @@
-package org.briarproject.api.plugins;
+package org.briarproject.bramble.api.plugin;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
 
 public interface ConnectionManager {
 
diff --git a/briar-api/src/org/briarproject/api/plugins/ConnectionRegistry.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/ConnectionRegistry.java
similarity index 71%
rename from briar-api/src/org/briarproject/api/plugins/ConnectionRegistry.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/ConnectionRegistry.java
index 6afc50acecd28015f61e0c92502faffdaae28ad9..776e0507429350c84635aaf0077211a84678f17b 100644
--- a/briar-api/src/org/briarproject/api/plugins/ConnectionRegistry.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/ConnectionRegistry.java
@@ -1,13 +1,14 @@
-package org.briarproject.api.plugins;
+package org.briarproject.bramble.api.plugin;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.util.Collection;
 
 /**
  * Keeps track of which contacts are currently connected by which transports.
  */
+@NotNullByDefault
 public interface ConnectionRegistry {
 
 	void registerConnection(ContactId c, TransportId t, boolean incoming);
diff --git a/briar-api/src/org/briarproject/api/plugins/LanTcpConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/LanTcpConstants.java
similarity index 57%
rename from briar-api/src/org/briarproject/api/plugins/LanTcpConstants.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/LanTcpConstants.java
index 6ea2ceb514bd4689947e1de9be569d91afd8a95c..056d53713263be448c57dccfc735570e6bc2906b 100644
--- a/briar-api/src/org/briarproject/api/plugins/LanTcpConstants.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/LanTcpConstants.java
@@ -1,6 +1,4 @@
-package org.briarproject.api.plugins;
-
-import org.briarproject.api.TransportId;
+package org.briarproject.bramble.api.plugin;
 
 public interface LanTcpConstants {
 
diff --git a/briar-api/src/org/briarproject/api/plugins/Plugin.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/Plugin.java
similarity index 86%
rename from briar-api/src/org/briarproject/api/plugins/Plugin.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/Plugin.java
index e54822cceccd94854febc9be2cc247bb9fd17f0e..89cd78640a1c8d0ef1a2b69656bc8abd3f405c6b 100644
--- a/briar-api/src/org/briarproject/api/plugins/Plugin.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/Plugin.java
@@ -1,8 +1,7 @@
-package org.briarproject.api.plugins;
+package org.briarproject.bramble.api.plugin;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.IOException;
 import java.util.Collection;
diff --git a/briar-api/src/org/briarproject/api/plugins/PluginCallback.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/PluginCallback.java
similarity index 65%
rename from briar-api/src/org/briarproject/api/plugins/PluginCallback.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/PluginCallback.java
index 6e3d0e4fa61e57ac04b0e561937feefb634bdd34..954db7b149b6c414c1e95af049d66bbfb4698804 100644
--- a/briar-api/src/org/briarproject/api/plugins/PluginCallback.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/PluginCallback.java
@@ -1,8 +1,9 @@
-package org.briarproject.api.plugins;
+package org.briarproject.bramble.api.plugin;
 
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.properties.TransportProperties;
-import org.briarproject.api.settings.Settings;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.properties.TransportProperties;
+import org.briarproject.bramble.api.settings.Settings;
 
 import java.util.Map;
 
@@ -10,18 +11,27 @@ import java.util.Map;
  * An interface through which a transport plugin interacts with the rest of
  * the application.
  */
+@NotNullByDefault
 public interface PluginCallback {
 
-	/** Returns the plugin's settings */
+	/**
+	 * Returns the plugin's settings
+	 */
 	Settings getSettings();
 
-	/** Returns the plugin's local transport properties. */
+	/**
+	 * Returns the plugin's local transport properties.
+	 */
 	TransportProperties getLocalProperties();
 
-	/** Returns the plugin's remote transport properties. */
+	/**
+	 * Returns the plugin's remote transport properties.
+	 */
 	Map<ContactId, TransportProperties> getRemoteProperties();
 
-	/** Merges the given settings with the namespaced settings */
+	/**
+	 * Merges the given settings with the namespaced settings
+	 */
 	void mergeSettings(Settings s);
 
 	/**
@@ -33,6 +43,7 @@ public interface PluginCallback {
 	 * Presents the user with a choice among two or more named options and
 	 * returns the user's response. The message may consist of a translatable
 	 * format string and arguments.
+	 *
 	 * @return an index into the array of options indicating the user's choice,
 	 * or -1 if the user cancelled the choice.
 	 */
@@ -50,9 +61,13 @@ public interface PluginCallback {
 	 */
 	void showMessage(String... message);
 
-	/** Signal that the transport got enabled. */
+	/**
+	 * Signal that the transport got enabled.
+	 */
 	void transportEnabled();
 
-	/** Signal that the transport got disabled. */
+	/**
+	 * Signal that the transport got disabled.
+	 */
 	void transportDisabled();
 }
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/PluginConfig.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/PluginConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..5518b7c6bc59bc5413cd774947c03213503a9e9e
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/PluginConfig.java
@@ -0,0 +1,15 @@
+package org.briarproject.bramble.api.plugin;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
+
+import java.util.Collection;
+
+@NotNullByDefault
+public interface PluginConfig {
+
+	Collection<DuplexPluginFactory> getDuplexFactories();
+
+	Collection<SimplexPluginFactory> getSimplexFactories();
+}
diff --git a/briar-api/src/org/briarproject/api/plugins/PluginManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/PluginManager.java
similarity index 76%
rename from briar-api/src/org/briarproject/api/plugins/PluginManager.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/PluginManager.java
index 3f1fcf31a22d3a00833b944c64f78622e73ed9f6..1056a6438c967a6470a3887a1637ad4b7ec03c47 100644
--- a/briar-api/src/org/briarproject/api/plugins/PluginManager.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/PluginManager.java
@@ -1,9 +1,8 @@
-package org.briarproject.api.plugins;
+package org.briarproject.bramble.api.plugin;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
-import org.briarproject.api.plugins.simplex.SimplexPlugin;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
 
 import java.util.Collection;
 
diff --git a/briar-api/src/org/briarproject/api/plugins/TorConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TorConstants.java
similarity index 63%
rename from briar-api/src/org/briarproject/api/plugins/TorConstants.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TorConstants.java
index 27624c7a8d55e2ea391a16bb12e84d41e0a3c76a..28f3e438e3735c89c9a3f9181a3e1aeb4931e027 100644
--- a/briar-api/src/org/briarproject/api/plugins/TorConstants.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TorConstants.java
@@ -1,12 +1,10 @@
-package org.briarproject.api.plugins;
-
-import org.briarproject.api.TransportId;
+package org.briarproject.bramble.api.plugin;
 
 public interface TorConstants {
 
 	TransportId ID = new TransportId("org.briarproject.bramble.tor");
 
-	int SOCKS_PORT   = 59050;
+	int SOCKS_PORT = 59050;
 	int CONTROL_PORT = 59051;
 
 	int CONNECT_TO_PROXY_TIMEOUT = 5000; // Milliseconds
diff --git a/briar-api/src/org/briarproject/api/plugins/TransportConnectionReader.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TransportConnectionReader.java
similarity index 71%
rename from briar-api/src/org/briarproject/api/plugins/TransportConnectionReader.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TransportConnectionReader.java
index e2b2855dea9bec5c5a764946f59c8ccbc256bd2f..941bb59d8a6ca6d118f5feb45c1f366a02b1090a 100644
--- a/briar-api/src/org/briarproject/api/plugins/TransportConnectionReader.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TransportConnectionReader.java
@@ -1,4 +1,6 @@
-package org.briarproject.api.plugins;
+package org.briarproject.bramble.api.plugin;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -7,6 +9,7 @@ import java.io.InputStream;
  * An interface for reading data from a transport connection. The reader is not
  * responsible for decrypting or authenticating the data.
  */
+@NotNullByDefault
 public interface TransportConnectionReader {
 
 	/**
@@ -20,12 +23,10 @@ public interface TransportConnectionReader {
 	 * connection is closed if <tt>exception</tt> is true or the other side of
 	 * the connection has been marked as closed.
 	 *
-	 * @param exception  true if the connection is being closed because of an
-	 *                   exception. This may affect how resources are disposed
-	 *                   of.
+	 * @param exception true if the connection is being closed because of an
+	 * exception. This may affect how resources are disposed of.
 	 * @param recognised true if the connection is definitely a Briar transport
-	 *                   connection. This may affect how resources are disposed
-	 *                   of.
+	 * connection. This may affect how resources are disposed of.
 	 */
 	void dispose(boolean exception, boolean recognised) throws IOException;
 }
diff --git a/briar-api/src/org/briarproject/api/plugins/TransportConnectionWriter.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TransportConnectionWriter.java
similarity index 65%
rename from briar-api/src/org/briarproject/api/plugins/TransportConnectionWriter.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TransportConnectionWriter.java
index d75522f1bb2c48f6541909864008e4bbf876ddb9..a066f6422e3985dbc65ca1d80bec61fd3ecdb8f3 100644
--- a/briar-api/src/org/briarproject/api/plugins/TransportConnectionWriter.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TransportConnectionWriter.java
@@ -1,4 +1,6 @@
-package org.briarproject.api.plugins;
+package org.briarproject.bramble.api.plugin;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.IOException;
 import java.io.OutputStream;
@@ -7,18 +9,27 @@ import java.io.OutputStream;
  * An interface for writing data to a transport connection. The writer is not
  * responsible for authenticating or encrypting the data.
  */
+@NotNullByDefault
 public interface TransportConnectionWriter {
 
-	/** Returns the maximum latency of the transport in milliseconds. */
+	/**
+	 * Returns the maximum latency of the transport in milliseconds.
+	 */
 	int getMaxLatency();
 
-	/** Returns the maximum idle time of the transport in milliseconds. */
+	/**
+	 * Returns the maximum idle time of the transport in milliseconds.
+	 */
 	int getMaxIdleTime();
 
-	/** Returns the capacity of the transport connection in bytes. */
+	/**
+	 * Returns the capacity of the transport connection in bytes.
+	 */
 	long getCapacity();
 
-	/** Returns an output stream for writing to the transport connection. */
+	/**
+	 * Returns an output stream for writing to the transport connection.
+	 */
 	OutputStream getOutputStream() throws IOException;
 
 	/**
@@ -26,6 +37,7 @@ public interface TransportConnectionWriter {
 	 * simplex, the connection is closed. If the transport is duplex, the
 	 * connection is closed if <tt>exception</tt> is true or the other side of
 	 * the connection has been marked as closed.
+	 *
 	 * @param exception true if the connection is being closed because of an
 	 * exception. This may affect how resources are disposed of.
 	 */
diff --git a/briar-api/src/org/briarproject/api/TransportId.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TransportId.java
similarity index 94%
rename from briar-api/src/org/briarproject/api/TransportId.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TransportId.java
index b0ad34b094df5fa81e6e9ba388b863f5542073ad..352e946a0aa51e48ae1712f0aa3aa1c1f719c9a7 100644
--- a/briar-api/src/org/briarproject/api/TransportId.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TransportId.java
@@ -1,4 +1,4 @@
-package org.briarproject.api;
+package org.briarproject.bramble.api.plugin;
 
 import java.nio.charset.Charset;
 
diff --git a/briar-api/src/org/briarproject/api/plugins/WanTcpConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/WanTcpConstants.java
similarity index 57%
rename from briar-api/src/org/briarproject/api/plugins/WanTcpConstants.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/WanTcpConstants.java
index cf8f649486c702730291c1e887c9f03853437435..abb11b9a6ce1b39bae85ba050f2b3b71e721137f 100644
--- a/briar-api/src/org/briarproject/api/plugins/WanTcpConstants.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/WanTcpConstants.java
@@ -1,6 +1,4 @@
-package org.briarproject.api.plugins;
-
-import org.briarproject.api.TransportId;
+package org.briarproject.bramble.api.plugin;
 
 public interface WanTcpConstants {
 
diff --git a/briar-api/src/org/briarproject/api/plugins/duplex/AbstractDuplexTransportConnection.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/AbstractDuplexTransportConnection.java
similarity index 82%
rename from briar-api/src/org/briarproject/api/plugins/duplex/AbstractDuplexTransportConnection.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/AbstractDuplexTransportConnection.java
index 575e43dc6829cfb897451d0347f88db40cb712c5..cdad52612966d9cbf8b68ec353470cf2626ce893 100644
--- a/briar-api/src/org/briarproject/api/plugins/duplex/AbstractDuplexTransportConnection.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/AbstractDuplexTransportConnection.java
@@ -1,14 +1,16 @@
-package org.briarproject.api.plugins.duplex;
+package org.briarproject.bramble.api.plugin.duplex;
 
-import org.briarproject.api.plugins.Plugin;
-import org.briarproject.api.plugins.TransportConnectionReader;
-import org.briarproject.api.plugins.TransportConnectionWriter;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.Plugin;
+import org.briarproject.bramble.api.plugin.TransportConnectionReader;
+import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+@NotNullByDefault
 public abstract class AbstractDuplexTransportConnection
 		implements DuplexTransportConnection {
 
@@ -41,12 +43,15 @@ public abstract class AbstractDuplexTransportConnection
 	public TransportConnectionWriter getWriter() {
 		return writer;
 	}
+
 	private class Reader implements TransportConnectionReader {
 
+		@Override
 		public InputStream getInputStream() throws IOException {
 			return AbstractDuplexTransportConnection.this.getInputStream();
 		}
 
+		@Override
 		public void dispose(boolean exception, boolean recognised)
 				throws IOException {
 			if (halfClosed.getAndSet(true) || exception || !recognised)
@@ -56,22 +61,27 @@ public abstract class AbstractDuplexTransportConnection
 
 	private class Writer implements TransportConnectionWriter {
 
+		@Override
 		public int getMaxLatency() {
 			return plugin.getMaxLatency();
 		}
 
+		@Override
 		public int getMaxIdleTime() {
 			return plugin.getMaxIdleTime();
 		}
 
+		@Override
 		public long getCapacity() {
 			return Long.MAX_VALUE;
 		}
 
+		@Override
 		public OutputStream getOutputStream() throws IOException {
 			return AbstractDuplexTransportConnection.this.getOutputStream();
 		}
 
+		@Override
 		public void dispose(boolean exception) throws IOException {
 			if (halfClosed.getAndSet(true) || exception)
 				if (!closed.getAndSet(true)) closeConnection(exception);
diff --git a/briar-api/src/org/briarproject/api/plugins/duplex/DuplexPlugin.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/DuplexPlugin.java
similarity index 78%
rename from briar-api/src/org/briarproject/api/plugins/duplex/DuplexPlugin.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/DuplexPlugin.java
index c45d5bab3b53ff69b5f712b7d0d8b71ddc3f2cd1..f2c2027f902b0b7ba3a39d3d019dc056c3f5cb35 100644
--- a/briar-api/src/org/briarproject/api/plugins/duplex/DuplexPlugin.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/DuplexPlugin.java
@@ -1,11 +1,11 @@
-package org.briarproject.api.plugins.duplex;
-
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.crypto.PseudoRandom;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.keyagreement.KeyAgreementListener;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.plugins.Plugin;
+package org.briarproject.bramble.api.plugin.duplex;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.crypto.PseudoRandom;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.Plugin;
 
 import javax.annotation.Nullable;
 
diff --git a/briar-api/src/org/briarproject/api/plugins/duplex/DuplexPluginCallback.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/DuplexPluginCallback.java
similarity index 54%
rename from briar-api/src/org/briarproject/api/plugins/duplex/DuplexPluginCallback.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/DuplexPluginCallback.java
index eb88626b88965bff84588dda4efe80341c6e4de2..00f1acdc65718ca974c5bfa78149a78900538e63 100644
--- a/briar-api/src/org/briarproject/api/plugins/duplex/DuplexPluginCallback.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/DuplexPluginCallback.java
@@ -1,11 +1,13 @@
-package org.briarproject.api.plugins.duplex;
+package org.briarproject.bramble.api.plugin.duplex;
 
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.plugins.PluginCallback;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.PluginCallback;
 
 /**
  * An interface for handling connections created by a duplex transport plugin.
  */
+@NotNullByDefault
 public interface DuplexPluginCallback extends PluginCallback {
 
 	void incomingConnectionCreated(DuplexTransportConnection d);
diff --git a/briar-api/src/org/briarproject/api/plugins/duplex/DuplexPluginFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/DuplexPluginFactory.java
similarity index 64%
rename from briar-api/src/org/briarproject/api/plugins/duplex/DuplexPluginFactory.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/DuplexPluginFactory.java
index 914402e3ca8f5666ee428a267bc2487d4260102a..9a3aa28b25572a40b2d196f695bc8f5573253756 100644
--- a/briar-api/src/org/briarproject/api/plugins/duplex/DuplexPluginFactory.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/DuplexPluginFactory.java
@@ -1,10 +1,14 @@
-package org.briarproject.api.plugins.duplex;
+package org.briarproject.bramble.api.plugin.duplex;
 
-import org.briarproject.api.TransportId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+
+import javax.annotation.Nullable;
 
 /**
  * Factory for creating a plugin for a duplex transport.
  */
+@NotNullByDefault
 public interface DuplexPluginFactory {
 
 	/**
@@ -20,5 +24,6 @@ public interface DuplexPluginFactory {
 	/**
 	 * Creates and returns a plugin, or null if no plugin can be created.
 	 */
+	@Nullable
 	DuplexPlugin createPlugin(DuplexPluginCallback callback);
 }
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/DuplexTransportConnection.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/DuplexTransportConnection.java
new file mode 100644
index 0000000000000000000000000000000000000000..f235e240b2f7b3cd9b5367a3385c68d838af9ad5
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/DuplexTransportConnection.java
@@ -0,0 +1,26 @@
+package org.briarproject.bramble.api.plugin.duplex;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportConnectionReader;
+import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
+
+/**
+ * An interface for reading and writing data over a duplex transport. The
+ * connection is not responsible for encrypting/decrypting or authenticating
+ * the data.
+ */
+@NotNullByDefault
+public interface DuplexTransportConnection {
+
+	/**
+	 * Returns a {@link TransportConnectionReader TransportConnectionReader}
+	 * for reading from the connection.
+	 */
+	TransportConnectionReader getReader();
+
+	/**
+	 * Returns a {@link TransportConnectionWriter TransportConnectionWriter}
+	 * for writing to the connection.
+	 */
+	TransportConnectionWriter getWriter();
+}
diff --git a/briar-api/src/org/briarproject/api/event/ConnectionClosedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/ConnectionClosedEvent.java
similarity index 60%
rename from briar-api/src/org/briarproject/api/event/ConnectionClosedEvent.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/ConnectionClosedEvent.java
index 29030edcc4e382b0aa3392823fc51fe7a1ec2862..05c4cbdd712e520e0c9a8d6469bca9b74c258847 100644
--- a/briar-api/src/org/briarproject/api/event/ConnectionClosedEvent.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/ConnectionClosedEvent.java
@@ -1,8 +1,14 @@
-package org.briarproject.api.event;
+package org.briarproject.bramble.api.plugin.event;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
 
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 public class ConnectionClosedEvent extends Event {
 
 	private final ContactId contactId;
diff --git a/briar-api/src/org/briarproject/api/event/ConnectionOpenedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/ConnectionOpenedEvent.java
similarity index 60%
rename from briar-api/src/org/briarproject/api/event/ConnectionOpenedEvent.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/ConnectionOpenedEvent.java
index 2143eb37a035b4e79c7887354cc38115b891cdfb..ba21c185d86cad03fcd5c28dd370812a84971ba5 100644
--- a/briar-api/src/org/briarproject/api/event/ConnectionOpenedEvent.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/ConnectionOpenedEvent.java
@@ -1,8 +1,14 @@
-package org.briarproject.api.event;
+package org.briarproject.bramble.api.plugin.event;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
 
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 public class ConnectionOpenedEvent extends Event {
 
 	private final ContactId contactId;
diff --git a/briar-api/src/org/briarproject/api/event/ContactConnectedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/ContactConnectedEvent.java
similarity index 54%
rename from briar-api/src/org/briarproject/api/event/ContactConnectedEvent.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/ContactConnectedEvent.java
index 0f0f90bac93e18af6de09e4397080923f4492bfb..46f6b46bc9599076889edaf0abd9255e2c747d14 100644
--- a/briar-api/src/org/briarproject/api/event/ContactConnectedEvent.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/ContactConnectedEvent.java
@@ -1,11 +1,17 @@
-package org.briarproject.api.event;
+package org.briarproject.bramble.api.plugin.event;
 
-import org.briarproject.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.Immutable;
 
 /**
  * An event that is broadcast when a contact connects that was not previously
  * connected via any transport.
  */
+@Immutable
+@NotNullByDefault
 public class ContactConnectedEvent extends Event {
 
 	private final ContactId contactId;
diff --git a/briar-api/src/org/briarproject/api/event/ContactDisconnectedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/ContactDisconnectedEvent.java
similarity index 54%
rename from briar-api/src/org/briarproject/api/event/ContactDisconnectedEvent.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/ContactDisconnectedEvent.java
index 2cef4d167b6fb39dd34fc131f6e7e7ffb5cfe181..77b17648406635fb27109a33f78c9b731e8846c2 100644
--- a/briar-api/src/org/briarproject/api/event/ContactDisconnectedEvent.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/ContactDisconnectedEvent.java
@@ -1,11 +1,17 @@
-package org.briarproject.api.event;
+package org.briarproject.bramble.api.plugin.event;
 
-import org.briarproject.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.Immutable;
 
 /**
  * An event that is broadcast when a contact disconnects and is no longer
  * connected via any transport.
  */
+@Immutable
+@NotNullByDefault
 public class ContactDisconnectedEvent extends Event {
 
 	private final ContactId contactId;
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/TransportDisabledEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/TransportDisabledEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..1d415ca9fd36baaf94a075880a7c718e1f453e70
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/TransportDisabledEvent.java
@@ -0,0 +1,25 @@
+package org.briarproject.bramble.api.plugin.event;
+
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when a transport is disabled.
+ */
+@Immutable
+@NotNullByDefault
+public class TransportDisabledEvent extends Event {
+
+	private final TransportId transportId;
+
+	public TransportDisabledEvent(TransportId transportId) {
+		this.transportId = transportId;
+	}
+
+	public TransportId getTransportId() {
+		return transportId;
+	}
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/TransportEnabledEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/TransportEnabledEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..7064c9b9ab7bb8649b3f884b958dfe10ac00e91b
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/TransportEnabledEvent.java
@@ -0,0 +1,25 @@
+package org.briarproject.bramble.api.plugin.event;
+
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when a transport is enabled.
+ */
+@Immutable
+@NotNullByDefault
+public class TransportEnabledEvent extends Event {
+
+	private final TransportId transportId;
+
+	public TransportEnabledEvent(TransportId transportId) {
+		this.transportId = transportId;
+	}
+
+	public TransportId getTransportId() {
+		return transportId;
+	}
+}
diff --git a/briar-api/src/org/briarproject/api/plugins/simplex/SimplexPlugin.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/simplex/SimplexPlugin.java
similarity index 65%
rename from briar-api/src/org/briarproject/api/plugins/simplex/SimplexPlugin.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/simplex/SimplexPlugin.java
index cf9f5ebec3543cad0407d9c25d0c72d44bffc831..3778918c2505cf5f5edb22747d14950f336e46f3 100644
--- a/briar-api/src/org/briarproject/api/plugins/simplex/SimplexPlugin.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/simplex/SimplexPlugin.java
@@ -1,10 +1,10 @@
-package org.briarproject.api.plugins.simplex;
+package org.briarproject.bramble.api.plugin.simplex;
 
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.plugins.Plugin;
-import org.briarproject.api.plugins.TransportConnectionReader;
-import org.briarproject.api.plugins.TransportConnectionWriter;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.Plugin;
+import org.briarproject.bramble.api.plugin.TransportConnectionReader;
+import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
 
 import javax.annotation.Nullable;
 
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/simplex/SimplexPluginCallback.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/simplex/SimplexPluginCallback.java
new file mode 100644
index 0000000000000000000000000000000000000000..d36a5d5e88801be258f126761ddb15098b0c5efd
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/simplex/SimplexPluginCallback.java
@@ -0,0 +1,19 @@
+package org.briarproject.bramble.api.plugin.simplex;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.PluginCallback;
+import org.briarproject.bramble.api.plugin.TransportConnectionReader;
+import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
+
+/**
+ * An interface for handling readers and writers created by a simplex transport
+ * plugin.
+ */
+@NotNullByDefault
+public interface SimplexPluginCallback extends PluginCallback {
+
+	void readerCreated(TransportConnectionReader r);
+
+	void writerCreated(ContactId c, TransportConnectionWriter w);
+}
diff --git a/briar-api/src/org/briarproject/api/plugins/simplex/SimplexPluginFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/simplex/SimplexPluginFactory.java
similarity index 64%
rename from briar-api/src/org/briarproject/api/plugins/simplex/SimplexPluginFactory.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/plugin/simplex/SimplexPluginFactory.java
index 38277550abfdc61311b68ac1e7975e0a6aff748d..a2c12b5f759a5edae6289d99749844d065d50510 100644
--- a/briar-api/src/org/briarproject/api/plugins/simplex/SimplexPluginFactory.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/simplex/SimplexPluginFactory.java
@@ -1,10 +1,14 @@
-package org.briarproject.api.plugins.simplex;
+package org.briarproject.bramble.api.plugin.simplex;
 
-import org.briarproject.api.TransportId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+
+import javax.annotation.Nullable;
 
 /**
  * Factory for creating a plugin for a simplex transport.
  */
+@NotNullByDefault
 public interface SimplexPluginFactory {
 
 	/**
@@ -20,5 +24,6 @@ public interface SimplexPluginFactory {
 	/**
 	 * Creates and returns a plugin, or null if no plugin can be created.
 	 */
+	@Nullable
 	SimplexPlugin createPlugin(SimplexPluginCallback callback);
 }
diff --git a/briar-api/src/org/briarproject/api/properties/TransportProperties.java b/bramble-api/src/main/java/org/briarproject/bramble/api/properties/TransportProperties.java
similarity index 56%
rename from briar-api/src/org/briarproject/api/properties/TransportProperties.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/properties/TransportProperties.java
index 512f3917c92df931ed5414955e53d699540176a9..dee9586f4ca00eb6277a65551a43389c8d47b057 100644
--- a/briar-api/src/org/briarproject/api/properties/TransportProperties.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/properties/TransportProperties.java
@@ -1,13 +1,11 @@
-package org.briarproject.api.properties;
+package org.briarproject.bramble.api.properties;
 
-import org.briarproject.api.StringMap;
+import org.briarproject.bramble.api.StringMap;
 
 import java.util.Map;
 
 public class TransportProperties extends StringMap {
 
-	private static final long serialVersionUID = 7533739534204953625L;
-
 	public TransportProperties(Map<String, String> m) {
 		super(m);
 	}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/properties/TransportPropertyConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/properties/TransportPropertyConstants.java
new file mode 100644
index 0000000000000000000000000000000000000000..9a46624e5495a8e379c70979de2bee6df2fe63cd
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/properties/TransportPropertyConstants.java
@@ -0,0 +1,14 @@
+package org.briarproject.bramble.api.properties;
+
+public interface TransportPropertyConstants {
+
+	/**
+	 * The maximum number of properties per transport.
+	 */
+	int MAX_PROPERTIES_PER_TRANSPORT = 100;
+
+	/**
+	 * The maximum length of a property's key or value in UTF-8 bytes.
+	 */
+	int MAX_PROPERTY_LENGTH = 100;
+}
diff --git a/briar-api/src/org/briarproject/api/properties/TransportPropertyManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/properties/TransportPropertyManager.java
similarity index 60%
rename from briar-api/src/org/briarproject/api/properties/TransportPropertyManager.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/properties/TransportPropertyManager.java
index b7da722fdbc85be496987afcddae7dc7cfd3383f..98e889a128a895040f03c6eb0865feb5eeee34d0 100644
--- a/briar-api/src/org/briarproject/api/properties/TransportPropertyManager.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/properties/TransportPropertyManager.java
@@ -1,16 +1,20 @@
-package org.briarproject.api.properties;
+package org.briarproject.bramble.api.properties;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.sync.ClientId;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.sync.ClientId;
 
 import java.util.Map;
 
+@NotNullByDefault
 public interface TransportPropertyManager {
 
-	/** The unique ID of the transport property client. */
+	/**
+	 * The unique ID of the transport property client.
+	 */
 	ClientId CLIENT_ID = new ClientId("org.briarproject.briar.properties");
 
 	/**
@@ -20,7 +24,9 @@ public interface TransportPropertyManager {
 	void addRemoteProperties(Transaction txn, ContactId c,
 			Map<TransportId, TransportProperties> props) throws DbException;
 
-	/** Returns the local transport properties for all transports. */
+	/**
+	 * Returns the local transport properties for all transports.
+	 */
 	Map<TransportId, TransportProperties> getLocalProperties()
 			throws DbException;
 
@@ -28,14 +34,18 @@ public interface TransportPropertyManager {
 	 * Returns the local transport properties for all transports.
 	 * <br/>
 	 * Read-Only
-	 * */
+	 */
 	Map<TransportId, TransportProperties> getLocalProperties(Transaction txn)
 			throws DbException;
 
-	/** Returns the local transport properties for the given transport. */
+	/**
+	 * Returns the local transport properties for the given transport.
+	 */
 	TransportProperties getLocalProperties(TransportId t) throws DbException;
 
-	/** Returns all remote transport properties for the given transport. */
+	/**
+	 * Returns all remote transport properties for the given transport.
+	 */
 	Map<ContactId, TransportProperties> getRemoteProperties(TransportId t)
 			throws DbException;
 
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/reliability/ReadHandler.java b/bramble-api/src/main/java/org/briarproject/bramble/api/reliability/ReadHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..6a8176516c70139bf71f3a6caf89807686ae0f8d
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/reliability/ReadHandler.java
@@ -0,0 +1,11 @@
+package org.briarproject.bramble.api.reliability;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import java.io.IOException;
+
+@NotNullByDefault
+public interface ReadHandler {
+
+	void handleRead(byte[] b) throws IOException;
+}
diff --git a/briar-api/src/org/briarproject/api/reliability/ReliabilityLayer.java b/bramble-api/src/main/java/org/briarproject/bramble/api/reliability/ReliabilityLayer.java
similarity index 73%
rename from briar-api/src/org/briarproject/api/reliability/ReliabilityLayer.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/reliability/ReliabilityLayer.java
index 13d41f646df711f66c8d6a9e7ab1f4ada23ed0b5..bdf066bee45db0b29df3430965b8693930a6ec7a 100644
--- a/briar-api/src/org/briarproject/api/reliability/ReliabilityLayer.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/reliability/ReliabilityLayer.java
@@ -1,4 +1,6 @@
-package org.briarproject.api.reliability;
+package org.briarproject.bramble.api.reliability;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -7,13 +9,15 @@ import java.io.OutputStream;
  * A protocol layer that attempts to ensure reliable, ordered delivery of data
  * across an unreliable lower layer. Interactions with the lower layer use the
  * buffer-oriented {@link ReadHandler} and {@link WriteHandler} interfaces; the
- * reliability layer presents stream-oriented
- * {@link java.io.InputStream InputStream} and
- * {@link java.io.OutputStream OutputStream} interfaces to higher layers.
+ * reliability layer presents stream-oriented {@link InputStream} and
+ * {@link OutputStream} interfaces to higher layers.
  */
+@NotNullByDefault
 public interface ReliabilityLayer extends ReadHandler {
 
-	/** Starts the reliability layer. */
+	/**
+	 * Starts the reliability layer.
+	 */
 	void start();
 
 	/**
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/reliability/ReliabilityLayerFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/reliability/ReliabilityLayerFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..89a06a07ffa60f35ce32afa50b86419130e8c41e
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/reliability/ReliabilityLayerFactory.java
@@ -0,0 +1,12 @@
+package org.briarproject.bramble.api.reliability;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+public interface ReliabilityLayerFactory {
+
+	/**
+	 * Returns a reliability layer that writes to the given lower layer.
+	 */
+	ReliabilityLayer createReliabilityLayer(WriteHandler writeHandler);
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/reliability/WriteHandler.java b/bramble-api/src/main/java/org/briarproject/bramble/api/reliability/WriteHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..395e208a77465bb825643bafb65e238c318a21d3
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/reliability/WriteHandler.java
@@ -0,0 +1,11 @@
+package org.briarproject.bramble.api.reliability;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import java.io.IOException;
+
+@NotNullByDefault
+public interface WriteHandler {
+
+	void handleWrite(byte[] b) throws IOException;
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/reporting/DevConfig.java b/bramble-api/src/main/java/org/briarproject/bramble/api/reporting/DevConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..3418299af1321ed2a4ae4199e346f441ce1d73c3
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/reporting/DevConfig.java
@@ -0,0 +1,12 @@
+package org.briarproject.bramble.api.reporting;
+
+import org.briarproject.bramble.api.crypto.PublicKey;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+public interface DevConfig {
+
+	PublicKey getDevPublicKey();
+
+	String getDevOnionAddress();
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/reporting/DevReporter.java b/bramble-api/src/main/java/org/briarproject/bramble/api/reporting/DevReporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..1d671525ff649c02d2acb827dd683157ebeda6fb
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/reporting/DevReporter.java
@@ -0,0 +1,30 @@
+package org.briarproject.bramble.api.reporting;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+/**
+ * A task for reporting back to the developers.
+ */
+@NotNullByDefault
+public interface DevReporter {
+
+	/**
+	 * Stores an encrypted report on disk to be sent later.
+	 *
+	 * @param reportDir the directory where reports are stored.
+	 * @param report the report in the form expected by the server.
+	 * @throws FileNotFoundException if the report could not be written.
+	 */
+	void encryptReportToFile(File reportDir, String filename, String report)
+			throws FileNotFoundException;
+
+	/**
+	 * Sends any reports previously stored on disk.
+	 *
+	 * @param reportDir the directory where reports are stored.
+	 */
+	void sendReports(File reportDir);
+}
diff --git a/briar-api/src/org/briarproject/api/reporting/ReportingConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/reporting/ReportingConstants.java
similarity index 93%
rename from briar-api/src/org/briarproject/api/reporting/ReportingConstants.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/reporting/ReportingConstants.java
index 28dca8bca4c673828beb30800e439d7c14b526de..e5f28b6ba9a2199689847eb4bb06e2e1a821aa19 100644
--- a/briar-api/src/org/briarproject/api/reporting/ReportingConstants.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/reporting/ReportingConstants.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.reporting;
+package org.briarproject.bramble.api.reporting;
 
 public interface ReportingConstants {
 
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/settings/Settings.java b/bramble-api/src/main/java/org/briarproject/bramble/api/settings/Settings.java
new file mode 100644
index 0000000000000000000000000000000000000000..9c9806ea7b2c6775c35865636c9555b1a0aabab1
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/settings/Settings.java
@@ -0,0 +1,6 @@
+package org.briarproject.bramble.api.settings;
+
+import org.briarproject.bramble.api.StringMap;
+
+public class Settings extends StringMap {
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/settings/SettingsManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/settings/SettingsManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..c8283640b56d11be8748e6e32e4340676c339b70
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/settings/SettingsManager.java
@@ -0,0 +1,19 @@
+package org.briarproject.bramble.api.settings;
+
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+public interface SettingsManager {
+
+	/**
+	 * Returns all settings in the given namespace.
+	 */
+	Settings getSettings(String namespace) throws DbException;
+
+	/**
+	 * Merges the given settings with any existing settings in the given
+	 * namespace.
+	 */
+	void mergeSettings(Settings s, String namespace) throws DbException;
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/settings/event/SettingsUpdatedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/settings/event/SettingsUpdatedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..8886574bb2d9e12dbcf9292842ead5286474ad67
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/settings/event/SettingsUpdatedEvent.java
@@ -0,0 +1,24 @@
+package org.briarproject.bramble.api.settings.event;
+
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when one or more settings are updated.
+ */
+@Immutable
+@NotNullByDefault
+public class SettingsUpdatedEvent extends Event {
+
+	private final String namespace;
+
+	public SettingsUpdatedEvent(String namespace) {
+		this.namespace = namespace;
+	}
+
+	public String getNamespace() {
+		return namespace;
+	}
+}
diff --git a/briar-api/src/org/briarproject/api/sync/Ack.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Ack.java
similarity index 54%
rename from briar-api/src/org/briarproject/api/sync/Ack.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/sync/Ack.java
index 21486a4ae23cf75d132d7f06f1d03400bd1089da..8c56067d80b47ced69b9a26babeb12a2c521a857 100644
--- a/briar-api/src/org/briarproject/api/sync/Ack.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Ack.java
@@ -1,8 +1,10 @@
-package org.briarproject.api.sync;
+package org.briarproject.bramble.api.sync;
 
 import java.util.Collection;
 
-/** A packet acknowledging receipt of one or more {@link Message Messages}. */
+/**
+ * A packet acknowledging receipt of one or more {@link Message Messages}.
+ */
 public class Ack {
 
 	private final Collection<MessageId> acked;
@@ -11,7 +13,9 @@ public class Ack {
 		this.acked = acked;
 	}
 
-	/** Returns the identifiers of the acknowledged messages. */
+	/**
+	 * Returns the identifiers of the acknowledged messages.
+	 */
 	public Collection<MessageId> getMessageIds() {
 		return acked;
 	}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Client.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Client.java
new file mode 100644
index 0000000000000000000000000000000000000000..956d876a349259b33090560fbb5f4fadbd1ef099
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Client.java
@@ -0,0 +1,14 @@
+package org.briarproject.bramble.api.sync;
+
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+public interface Client {
+
+	/**
+	 * Called at startup to create any local state needed by the client.
+	 */
+	void createLocalState(Transaction txn) throws DbException;
+}
diff --git a/briar-api/src/org/briarproject/api/sync/ClientId.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/ClientId.java
similarity index 85%
rename from briar-api/src/org/briarproject/api/sync/ClientId.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/sync/ClientId.java
index 7101b31069e3424d0f7a495a4e29f53a86536e4e..ee2b3b0ad9f99d61ee20ae9cd971b5c2279e4af0 100644
--- a/briar-api/src/org/briarproject/api/sync/ClientId.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/ClientId.java
@@ -1,6 +1,6 @@
-package org.briarproject.api.sync;
+package org.briarproject.bramble.api.sync;
 
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import javax.annotation.concurrent.Immutable;
 
diff --git a/briar-api/src/org/briarproject/api/sync/Group.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Group.java
similarity index 78%
rename from briar-api/src/org/briarproject/api/sync/Group.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/sync/Group.java
index 9ffd3b9cac2464316c4eb7a353e5c274a252dd1e..009ef7dbd2a5f154bea4764888c182e3fc9ee372 100644
--- a/briar-api/src/org/briarproject/api/sync/Group.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Group.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.sync;
+package org.briarproject.bramble.api.sync;
 
 public class Group {
 
@@ -18,17 +18,23 @@ public class Group {
 		this.descriptor = descriptor;
 	}
 
-	/** Returns the group's unique identifier. */
+	/**
+	 * Returns the group's unique identifier.
+	 */
 	public GroupId getId() {
 		return id;
 	}
 
-	/** Returns the ID of the client to which the group belongs. */
+	/**
+	 * Returns the ID of the client to which the group belongs.
+	 */
 	public ClientId getClientId() {
 		return clientId;
 	}
 
-	/** Returns the group's descriptor. */
+	/**
+	 * Returns the group's descriptor.
+	 */
 	public byte[] getDescriptor() {
 		return descriptor;
 	}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/GroupFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/GroupFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..999e1f93666933c124d492dcacd7dad1f352532a
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/GroupFactory.java
@@ -0,0 +1,12 @@
+package org.briarproject.bramble.api.sync;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+public interface GroupFactory {
+
+	/**
+	 * Creates a group with the given client ID and descriptor.
+	 */
+	Group createGroup(ClientId c, byte[] descriptor);
+}
diff --git a/briar-api/src/org/briarproject/api/sync/GroupId.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/GroupId.java
similarity index 67%
rename from briar-api/src/org/briarproject/api/sync/GroupId.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/sync/GroupId.java
index 8a5ed3fe713b1c7455a2da14c4f25372dc6fee1a..bea1186f13768373d04af940dc445e4f79441160 100644
--- a/briar-api/src/org/briarproject/api/sync/GroupId.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/GroupId.java
@@ -1,12 +1,17 @@
-package org.briarproject.api.sync;
+package org.briarproject.bramble.api.sync;
 
-import org.briarproject.api.UniqueId;
+import org.briarproject.bramble.api.UniqueId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.nio.charset.Charset;
 
+import javax.annotation.concurrent.ThreadSafe;
+
 /**
  * Type-safe wrapper for a byte array that uniquely identifies a {@link Group}.
  */
+@ThreadSafe
+@NotNullByDefault
 public class GroupId extends UniqueId {
 
 	/**
diff --git a/briar-api/src/org/briarproject/api/sync/InvalidMessageException.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/InvalidMessageException.java
similarity index 72%
rename from briar-api/src/org/briarproject/api/sync/InvalidMessageException.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/sync/InvalidMessageException.java
index fa8b669ca79ef9e6af53acc4a06ab5f6cb804890..577d4916e05e9ef3afeccf3cde5e95c301880495 100644
--- a/briar-api/src/org/briarproject/api/sync/InvalidMessageException.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/InvalidMessageException.java
@@ -1,8 +1,10 @@
-package org.briarproject.api.sync;
+package org.briarproject.bramble.api.sync;
 
 import java.io.IOException;
 
-/** An exception that indicates an invalid message. */
+/**
+ * An exception that indicates an invalid message.
+ */
 public class InvalidMessageException extends IOException {
 
 	public InvalidMessageException() {
diff --git a/briar-api/src/org/briarproject/api/sync/Message.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Message.java
similarity index 63%
rename from briar-api/src/org/briarproject/api/sync/Message.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/sync/Message.java
index 049807ac4b25ead9554860ce1229635bd6d23fc3..3d4216270fae5d2d910ba6a2093eb1da4b62cbec 100644
--- a/briar-api/src/org/briarproject/api/sync/Message.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Message.java
@@ -1,7 +1,7 @@
-package org.briarproject.api.sync;
+package org.briarproject.bramble.api.sync;
 
-import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_LENGTH;
-import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
 
 public class Message {
 
@@ -21,27 +21,37 @@ public class Message {
 		this.raw = raw;
 	}
 
-	/** Returns the message's unique identifier. */
+	/**
+	 * Returns the message's unique identifier.
+	 */
 	public MessageId getId() {
 		return id;
 	}
 
-	/** Returns the ID of the {@link Group} to which the message belongs. */
+	/**
+	 * Returns the ID of the {@link Group} to which the message belongs.
+	 */
 	public GroupId getGroupId() {
 		return groupId;
 	}
 
-	/** Returns the message's timestamp in milliseconds since the Unix epoch. */
+	/**
+	 * Returns the message's timestamp in milliseconds since the Unix epoch.
+	 */
 	public long getTimestamp() {
 		return timestamp;
 	}
 
-	/** Returns the length of the raw message in bytes. */
+	/**
+	 * Returns the length of the raw message in bytes.
+	 */
 	public int getLength() {
 		return raw.length;
 	}
 
-	/** Returns the raw message. */
+	/**
+	 * Returns the raw message.
+	 */
 	public byte[] getRaw() {
 		return raw;
 	}
diff --git a/briar-api/src/org/briarproject/api/sync/MessageContext.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageContext.java
similarity index 80%
rename from briar-api/src/org/briarproject/api/sync/MessageContext.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageContext.java
index ce789422138ecf49a3344e4a200794069bc41ed7..c11f630e4b9b87e07b58f2783b2e4bfe7b64115a 100644
--- a/briar-api/src/org/briarproject/api/sync/MessageContext.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageContext.java
@@ -1,7 +1,7 @@
-package org.briarproject.api.sync;
+package org.briarproject.bramble.api.sync;
 
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.util.Collection;
 import java.util.Collections;
diff --git a/briar-api/src/org/briarproject/api/sync/MessageFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageFactory.java
similarity index 61%
rename from briar-api/src/org/briarproject/api/sync/MessageFactory.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageFactory.java
index 191770e2c269cc6f447f132bdd349319e3f7054e..e85b15d7df3426298fd5139bf05d12041a4da2b7 100644
--- a/briar-api/src/org/briarproject/api/sync/MessageFactory.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageFactory.java
@@ -1,6 +1,6 @@
-package org.briarproject.api.sync;
+package org.briarproject.bramble.api.sync;
 
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 @NotNullByDefault
 public interface MessageFactory {
diff --git a/briar-api/src/org/briarproject/api/sync/MessageId.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageId.java
similarity index 67%
rename from briar-api/src/org/briarproject/api/sync/MessageId.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageId.java
index 3543460f645644b31f65f5bf218332fb04a31b18..3a1075dd9c77c1262fdf7a95c858d8d6a2095355 100644
--- a/briar-api/src/org/briarproject/api/sync/MessageId.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageId.java
@@ -1,13 +1,18 @@
-package org.briarproject.api.sync;
+package org.briarproject.bramble.api.sync;
 
-import org.briarproject.api.UniqueId;
+import org.briarproject.bramble.api.UniqueId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.nio.charset.Charset;
 
+import javax.annotation.concurrent.ThreadSafe;
+
 /**
  * Type-safe wrapper for a byte array that uniquely identifies a
  * {@link Message}.
  */
+@ThreadSafe
+@NotNullByDefault
 public class MessageId extends UniqueId {
 
 	/**
diff --git a/briar-api/src/org/briarproject/api/sync/MessageStatus.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageStatus.java
similarity index 62%
rename from briar-api/src/org/briarproject/api/sync/MessageStatus.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageStatus.java
index ec1df8cc4879751e1445e27c3da0bd82d05815e7..86b9065aeea87fe6f48b22622688aaa0787ae138 100644
--- a/briar-api/src/org/briarproject/api/sync/MessageStatus.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageStatus.java
@@ -1,6 +1,6 @@
-package org.briarproject.api.sync;
+package org.briarproject.bramble.api.sync;
 
-import org.briarproject.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactId;
 
 public class MessageStatus {
 
@@ -16,22 +16,30 @@ public class MessageStatus {
 		this.seen = seen;
 	}
 
-	/** Returns the ID of the message. */
+	/**
+	 * Returns the ID of the message.
+	 */
 	public MessageId getMessageId() {
 		return messageId;
 	}
 
-	/** Returns the ID of the contact. */
+	/**
+	 * Returns the ID of the contact.
+	 */
 	public ContactId getContactId() {
 		return contactId;
 	}
 
-	/** Returns true if the message has been sent to the contact. */
+	/**
+	 * Returns true if the message has been sent to the contact.
+	 */
 	public boolean isSent() {
 		return sent;
 	}
 
-	/** Returns true if the message has been seen by the contact. */
+	/**
+	 * Returns true if the message has been seen by the contact.
+	 */
 	public boolean isSeen() {
 		return seen;
 	}
diff --git a/briar-api/src/org/briarproject/api/sync/Offer.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Offer.java
similarity index 57%
rename from briar-api/src/org/briarproject/api/sync/Offer.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/sync/Offer.java
index dc107ed4ab00b3532f0e4edf60068b81ef8de7cb..b70df3dbaed3aa19b4ebb1f574ce17a6364120f6 100644
--- a/briar-api/src/org/briarproject/api/sync/Offer.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Offer.java
@@ -1,8 +1,10 @@
-package org.briarproject.api.sync;
+package org.briarproject.bramble.api.sync;
 
 import java.util.Collection;
 
-/** A packet offering the recipient one or more {@link Message Messages}. */
+/**
+ * A packet offering the recipient one or more {@link Message Messages}.
+ */
 public class Offer {
 
 	private final Collection<MessageId> offered;
@@ -11,7 +13,9 @@ public class Offer {
 		this.offered = offered;
 	}
 
-	/** Returns the identifiers of the offered messages. */
+	/**
+	 * Returns the identifiers of the offered messages.
+	 */
 	public Collection<MessageId> getMessageIds() {
 		return offered;
 	}
diff --git a/briar-api/src/org/briarproject/api/sync/PacketReader.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/PacketReader.java
similarity index 76%
rename from briar-api/src/org/briarproject/api/sync/PacketReader.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/sync/PacketReader.java
index e8893fbf9ddd687a69e179508deb64809005887d..65708e0a0c030e8a9ba0980fdf4e6092c3de9558 100644
--- a/briar-api/src/org/briarproject/api/sync/PacketReader.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/PacketReader.java
@@ -1,20 +1,27 @@
-package org.briarproject.api.sync;
+package org.briarproject.bramble.api.sync;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.IOException;
 
+@NotNullByDefault
 public interface PacketReader {
 
 	boolean eof() throws IOException;
 
 	boolean hasAck() throws IOException;
+
 	Ack readAck() throws IOException;
 
 	boolean hasMessage() throws IOException;
+
 	Message readMessage() throws IOException;
 
 	boolean hasOffer() throws IOException;
+
 	Offer readOffer() throws IOException;
 
 	boolean hasRequest() throws IOException;
+
 	Request readRequest() throws IOException;
 }
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/PacketReaderFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/PacketReaderFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..9eb84fa5496603e5c89d04b91fd2563043cd3a2e
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/PacketReaderFactory.java
@@ -0,0 +1,11 @@
+package org.briarproject.bramble.api.sync;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import java.io.InputStream;
+
+@NotNullByDefault
+public interface PacketReaderFactory {
+
+	PacketReader createPacketReader(InputStream in);
+}
diff --git a/briar-api/src/org/briarproject/api/sync/PacketTypes.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/PacketTypes.java
similarity index 53%
rename from briar-api/src/org/briarproject/api/sync/PacketTypes.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/sync/PacketTypes.java
index 214af877a32b19839d4cad8378f56ccc13d60ddc..537cb7e594bfa66c06f6fe28a895f83c5cd8977d 100644
--- a/briar-api/src/org/briarproject/api/sync/PacketTypes.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/PacketTypes.java
@@ -1,6 +1,8 @@
-package org.briarproject.api.sync;
+package org.briarproject.bramble.api.sync;
 
-/** Packet types for the sync protocol. */
+/**
+ * Packet types for the sync protocol.
+ */
 public interface PacketTypes {
 
 	byte ACK = 0;
diff --git a/briar-api/src/org/briarproject/api/sync/PacketWriter.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/PacketWriter.java
similarity index 69%
rename from briar-api/src/org/briarproject/api/sync/PacketWriter.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/sync/PacketWriter.java
index a7e89bb64a574ca225fd0aae3c8deb04263a4f41..8741c55539a7bdb63a8614c60799a27d68ce7a53 100644
--- a/briar-api/src/org/briarproject/api/sync/PacketWriter.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/PacketWriter.java
@@ -1,7 +1,10 @@
-package org.briarproject.api.sync;
+package org.briarproject.bramble.api.sync;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.IOException;
 
+@NotNullByDefault
 public interface PacketWriter {
 
 	void writeAck(Ack a) throws IOException;
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/PacketWriterFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/PacketWriterFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..9afab7d5ca8252345291f950151d9344e64ed5d9
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/PacketWriterFactory.java
@@ -0,0 +1,11 @@
+package org.briarproject.bramble.api.sync;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import java.io.OutputStream;
+
+@NotNullByDefault
+public interface PacketWriterFactory {
+
+	PacketWriter createPacketWriter(OutputStream out);
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Request.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Request.java
new file mode 100644
index 0000000000000000000000000000000000000000..0f03fed252659c6bfb730e50b0d6ad1fb3b84286
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Request.java
@@ -0,0 +1,22 @@
+package org.briarproject.bramble.api.sync;
+
+import java.util.Collection;
+
+/**
+ * A packet requesting one or more {@link Message Messages} from the recipient.
+ */
+public class Request {
+
+	private final Collection<MessageId> requested;
+
+	public Request(Collection<MessageId> requested) {
+		this.requested = requested;
+	}
+
+	/**
+	 * Returns the identifiers of the requested messages.
+	 */
+	public Collection<MessageId> getMessageIds() {
+		return requested;
+	}
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncConstants.java
new file mode 100644
index 0000000000000000000000000000000000000000..23f22beb1ee571d81a612a15c1388b0432bc4601
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncConstants.java
@@ -0,0 +1,41 @@
+package org.briarproject.bramble.api.sync;
+
+import org.briarproject.bramble.api.UniqueId;
+
+public interface SyncConstants {
+
+	/**
+	 * The current version of the sync protocol.
+	 */
+	byte PROTOCOL_VERSION = 0;
+
+	/**
+	 * The length of the packet header in bytes.
+	 */
+	int PACKET_HEADER_LENGTH = 4;
+
+	/**
+	 * The maximum length of the packet payload in bytes.
+	 */
+	int MAX_PACKET_PAYLOAD_LENGTH = 32 * 1024; // 32 KiB
+
+	/**
+	 * The maximum length of a message in bytes.
+	 */
+	int MAX_MESSAGE_LENGTH = MAX_PACKET_PAYLOAD_LENGTH - PACKET_HEADER_LENGTH;
+
+	/**
+	 * The length of the message header in bytes.
+	 */
+	int MESSAGE_HEADER_LENGTH = UniqueId.LENGTH + 8;
+
+	/**
+	 * The maximum length of a message body in bytes.
+	 */
+	int MAX_MESSAGE_BODY_LENGTH = MAX_MESSAGE_LENGTH - MESSAGE_HEADER_LENGTH;
+
+	/**
+	 * The maximum number of message IDs in an ack, offer or request packet.
+	 */
+	int MAX_MESSAGE_IDS = MAX_PACKET_PAYLOAD_LENGTH / UniqueId.LENGTH;
+}
diff --git a/briar-api/src/org/briarproject/api/sync/SyncSession.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncSession.java
similarity index 90%
rename from briar-api/src/org/briarproject/api/sync/SyncSession.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncSession.java
index 29378814170e4cd588ba308c4157fefa7a021744..9a860d13fe3bdae42fd0f11787efb41a3e7422b4 100644
--- a/briar-api/src/org/briarproject/api/sync/SyncSession.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncSession.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.sync;
+package org.briarproject.bramble.api.sync;
 
 import java.io.IOException;
 
diff --git a/briar-api/src/org/briarproject/api/sync/SyncSessionFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncSessionFactory.java
similarity index 67%
rename from briar-api/src/org/briarproject/api/sync/SyncSessionFactory.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncSessionFactory.java
index db5954ffedff642501d50301273972fc01521dd8..19b38cb8a348ad5140e18a0261bd665fea1fbb3d 100644
--- a/briar-api/src/org/briarproject/api/sync/SyncSessionFactory.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncSessionFactory.java
@@ -1,10 +1,12 @@
-package org.briarproject.api.sync;
+package org.briarproject.bramble.api.sync;
 
-import org.briarproject.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.InputStream;
 import java.io.OutputStream;
 
+@NotNullByDefault
 public interface SyncSessionFactory {
 
 	SyncSession createIncomingSession(ContactId c, InputStream in);
diff --git a/briar-api/src/org/briarproject/api/sync/ValidationManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/ValidationManager.java
similarity index 89%
rename from briar-api/src/org/briarproject/api/sync/ValidationManager.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/sync/ValidationManager.java
index b35a0bd8fd85ba0972f164ab8b675953370e735d..d80042b41521aada66365f1bd21cdb1c620c114b 100644
--- a/briar-api/src/org/briarproject/api/sync/ValidationManager.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/ValidationManager.java
@@ -1,9 +1,9 @@
-package org.briarproject.api.sync;
+package org.briarproject.bramble.api.sync;
 
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 /**
  * Responsible for managing message validators and passing them messages to
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/GroupAddedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/GroupAddedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..3ff5b795c6f750ead69f26de9b0762479bbd5fcb
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/GroupAddedEvent.java
@@ -0,0 +1,25 @@
+package org.briarproject.bramble.api.sync.event;
+
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when a group is added to the database.
+ */
+@Immutable
+@NotNullByDefault
+public class GroupAddedEvent extends Event {
+
+	private final Group group;
+
+	public GroupAddedEvent(Group group) {
+		this.group = group;
+	}
+
+	public Group getGroup() {
+		return group;
+	}
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/GroupRemovedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/GroupRemovedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..9804547169578420d73184dd885893162a91a398
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/GroupRemovedEvent.java
@@ -0,0 +1,25 @@
+package org.briarproject.bramble.api.sync.event;
+
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when a group is removed from the database.
+ */
+@Immutable
+@NotNullByDefault
+public class GroupRemovedEvent extends Event {
+
+	private final Group group;
+
+	public GroupRemovedEvent(Group group) {
+		this.group = group;
+	}
+
+	public Group getGroup() {
+		return group;
+	}
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/GroupVisibilityUpdatedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/GroupVisibilityUpdatedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..1bcca2c66fef8d1a9d3a81d8f62055b9162c64e4
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/GroupVisibilityUpdatedEvent.java
@@ -0,0 +1,30 @@
+package org.briarproject.bramble.api.sync.event;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import java.util.Collection;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when the visibility of a group is updated.
+ */
+@Immutable
+@NotNullByDefault
+public class GroupVisibilityUpdatedEvent extends Event {
+
+	private final Collection<ContactId> affected;
+
+	public GroupVisibilityUpdatedEvent(Collection<ContactId> affected) {
+		this.affected = affected;
+	}
+
+	/**
+	 * Returns the contacts affected by the update.
+	 */
+	public Collection<ContactId> getAffectedContacts() {
+		return affected;
+	}
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessageAddedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessageAddedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..960dddc6610dd6c2e5a0306a10ba59d5efa1e28d
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessageAddedEvent.java
@@ -0,0 +1,50 @@
+package org.briarproject.bramble.api.sync.event;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when a message is added to the database.
+ */
+@Immutable
+@NotNullByDefault
+public class MessageAddedEvent extends Event {
+
+	private final Message message;
+	@Nullable
+	private final ContactId contactId;
+
+	public MessageAddedEvent(Message message, @Nullable ContactId contactId) {
+		this.message = message;
+		this.contactId = contactId;
+	}
+
+	/**
+	 * Returns the message that was added.
+	 */
+	public Message getMessage() {
+		return message;
+	}
+
+	/**
+	 * Returns the ID of the group to which the message belongs.
+	 */
+	public GroupId getGroupId() {
+		return message.getGroupId();
+	}
+
+	/**
+	 * Returns the ID of the contact from which the message was received, or
+	 * null if the message was locally generated.
+	 */
+	@Nullable
+	public ContactId getContactId() {
+		return contactId;
+	}
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessageRequestedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessageRequestedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..eab1405425f147086b699726f345a4fd2e0e767f
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessageRequestedEvent.java
@@ -0,0 +1,25 @@
+package org.briarproject.bramble.api.sync.event;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when a message is requested by a contact.
+ */
+@Immutable
+@NotNullByDefault
+public class MessageRequestedEvent extends Event {
+
+	private final ContactId contactId;
+
+	public MessageRequestedEvent(ContactId contactId) {
+		this.contactId = contactId;
+	}
+
+	public ContactId getContactId() {
+		return contactId;
+	}
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessageSharedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessageSharedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..e3745fd90e2a5a863537ff7be9198273f81174ac
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessageSharedEvent.java
@@ -0,0 +1,25 @@
+package org.briarproject.bramble.api.sync.event;
+
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.MessageId;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when a message is shared.
+ */
+@Immutable
+@NotNullByDefault
+public class MessageSharedEvent extends Event {
+
+	private final MessageId messageId;
+
+	public MessageSharedEvent(MessageId message) {
+		this.messageId = message;
+	}
+
+	public MessageId getMessageId() {
+		return messageId;
+	}
+}
diff --git a/briar-api/src/org/briarproject/api/event/MessageStateChangedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessageStateChangedEvent.java
similarity index 59%
rename from briar-api/src/org/briarproject/api/event/MessageStateChangedEvent.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessageStateChangedEvent.java
index 4ad29e01025d8d74bbe3b85dcfd113e3440bbfb0..450512e53b4be9b46c7d950e26ea081ebc71dce2 100644
--- a/briar-api/src/org/briarproject/api/event/MessageStateChangedEvent.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessageStateChangedEvent.java
@@ -1,12 +1,18 @@
-package org.briarproject.api.event;
+package org.briarproject.bramble.api.sync.event;
 
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.MessageId;
 
-import static org.briarproject.api.sync.ValidationManager.State;
+import javax.annotation.concurrent.Immutable;
+
+import static org.briarproject.bramble.api.sync.ValidationManager.State;
 
 /**
  * An event that is broadcast when a message state changed.
  */
+@Immutable
+@NotNullByDefault
 public class MessageStateChangedEvent extends Event {
 
 	private final MessageId messageId;
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessageToAckEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessageToAckEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..cc35d59a957fa6fab1c0239220fb4bf9ad3b1b1d
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessageToAckEvent.java
@@ -0,0 +1,26 @@
+package org.briarproject.bramble.api.sync.event;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when a message is received from, or offered by, a
+ * contact and needs to be acknowledged.
+ */
+@Immutable
+@NotNullByDefault
+public class MessageToAckEvent extends Event {
+
+	private final ContactId contactId;
+
+	public MessageToAckEvent(ContactId contactId) {
+		this.contactId = contactId;
+	}
+
+	public ContactId getContactId() {
+		return contactId;
+	}
+}
diff --git a/briar-api/src/org/briarproject/api/event/MessageToRequestEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessageToRequestEvent.java
similarity index 53%
rename from briar-api/src/org/briarproject/api/event/MessageToRequestEvent.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessageToRequestEvent.java
index 812fb0ad3716400c89b57a39e4639e37720ba9e6..e1a7fb969f22fbd95e0db0be6609f2145ca76f40 100644
--- a/briar-api/src/org/briarproject/api/event/MessageToRequestEvent.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessageToRequestEvent.java
@@ -1,11 +1,17 @@
-package org.briarproject.api.event;
+package org.briarproject.bramble.api.sync.event;
 
-import org.briarproject.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.Immutable;
 
 /**
  * An event that is broadcast when a message is offered by a contact and needs
  * to be requested.
  */
+@Immutable
+@NotNullByDefault
 public class MessageToRequestEvent extends Event {
 
 	private final ContactId contactId;
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessagesAckedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessagesAckedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..fb1b1dd21d4b72d0a5d5e0349bc75bd5382f23cd
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessagesAckedEvent.java
@@ -0,0 +1,35 @@
+package org.briarproject.bramble.api.sync.event;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.MessageId;
+
+import java.util.Collection;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when messages are acked by a contact.
+ */
+@Immutable
+@NotNullByDefault
+public class MessagesAckedEvent extends Event {
+
+	private final ContactId contactId;
+	private final Collection<MessageId> acked;
+
+	public MessagesAckedEvent(ContactId contactId,
+			Collection<MessageId> acked) {
+		this.contactId = contactId;
+		this.acked = acked;
+	}
+
+	public ContactId getContactId() {
+		return contactId;
+	}
+
+	public Collection<MessageId> getMessageIds() {
+		return acked;
+	}
+}
diff --git a/briar-api/src/org/briarproject/api/event/MessagesSentEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessagesSentEvent.java
similarity index 51%
rename from briar-api/src/org/briarproject/api/event/MessagesSentEvent.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessagesSentEvent.java
index 8066c196f637357f5b03b13f7e8c2392ed88e057..1f392417db1574fea600d127b06f9db79b5c247b 100644
--- a/briar-api/src/org/briarproject/api/event/MessagesSentEvent.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessagesSentEvent.java
@@ -1,11 +1,19 @@
-package org.briarproject.api.event;
+package org.briarproject.bramble.api.sync.event;
 
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.MessageId;
 
 import java.util.Collection;
 
-/** An event that is broadcast when messages are sent to a contact. */
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when messages are sent to a contact.
+ */
+@Immutable
+@NotNullByDefault
 public class MessagesSentEvent extends Event {
 
 	private final ContactId contactId;
diff --git a/briar-api/src/org/briarproject/api/system/Clock.java b/bramble-api/src/main/java/org/briarproject/bramble/api/system/Clock.java
similarity index 60%
rename from briar-api/src/org/briarproject/api/system/Clock.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/system/Clock.java
index 1fcb250d6bd9f832eb5fd16a1113ccc02b10172f..a2ee764452b575636d36efd98e17c1ec537903cd 100644
--- a/briar-api/src/org/briarproject/api/system/Clock.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/system/Clock.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.system;
+package org.briarproject.bramble.api.system;
 
 /**
  * An interface for time-related system functions that allows them to be
@@ -6,9 +6,13 @@ package org.briarproject.api.system;
  */
 public interface Clock {
 
-	/** @see {@link java.lang.System#currentTimeMillis()} */
+	/**
+	 * @see {@link System#currentTimeMillis()}
+	 */
 	long currentTimeMillis();
 
-	/** @see {@link java.lang.Thread.sleep(long)} */
+	/**
+	 * @see {@link Thread#sleep(long)}
+	 */
 	void sleep(long milliseconds) throws InterruptedException;
 }
diff --git a/briar-api/src/org/briarproject/api/system/LocationUtils.java b/bramble-api/src/main/java/org/briarproject/bramble/api/system/LocationUtils.java
similarity index 67%
rename from briar-api/src/org/briarproject/api/system/LocationUtils.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/system/LocationUtils.java
index 33057e839b04c14ccf7b3d9be1816b28b71395c0..61a83d95c0d1ec788286eb707e935644a77a6cb4 100644
--- a/briar-api/src/org/briarproject/api/system/LocationUtils.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/system/LocationUtils.java
@@ -1,10 +1,13 @@
-package org.briarproject.api.system;
+package org.briarproject.bramble.api.system;
 
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
 public interface LocationUtils {
-	
+
 	/**
 	 * Get the country the device is currently located in, or "" if it cannot
-	 * be determined. Should never return {@code null}.
+	 * be determined.
 	 * <p>
 	 * The country codes are formatted upper-case and as per <a href="
 	 * https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2">ISO 3166-1 alpha 2</a>.
diff --git a/briar-api/src/org/briarproject/api/system/Scheduler.java b/bramble-api/src/main/java/org/briarproject/bramble/api/system/Scheduler.java
similarity index 94%
rename from briar-api/src/org/briarproject/api/system/Scheduler.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/system/Scheduler.java
index 0b1e225da2a474dc508ce3c9022156599767b8e2..67466cdb037504760c3a2a5414238aac9fe3c39e 100644
--- a/briar-api/src/org/briarproject/api/system/Scheduler.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/system/Scheduler.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.system;
+package org.briarproject.bramble.api.system;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
diff --git a/briar-api/src/org/briarproject/api/system/SeedProvider.java b/bramble-api/src/main/java/org/briarproject/bramble/api/system/SeedProvider.java
similarity index 50%
rename from briar-api/src/org/briarproject/api/system/SeedProvider.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/system/SeedProvider.java
index 886fa2df3c397b2c40e46b98be5b36c92408a1bf..2d5c147f1612354d1b7b2df76dfb4518d6839318 100644
--- a/briar-api/src/org/briarproject/api/system/SeedProvider.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/system/SeedProvider.java
@@ -1,11 +1,17 @@
-package org.briarproject.api.system;
+package org.briarproject.bramble.api.system;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 /**
  * Uses a platform-specific source to provide a seed for a pseudo-random
  * number generator.
  */
+@NotNullByDefault
 public interface SeedProvider {
 
+	/**
+	 * The length of the seed in bytes.
+	 */
 	int SEED_BYTES = 32;
 
 	byte[] getSeed();
diff --git a/briar-api/src/org/briarproject/api/transport/IncomingKeys.java b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/IncomingKeys.java
similarity index 84%
rename from briar-api/src/org/briarproject/api/transport/IncomingKeys.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/transport/IncomingKeys.java
index 6ee30759e55227abdc53e17850d2412b0d0d6103..ef444561f6910074b823e057821d71e08896dbca 100644
--- a/briar-api/src/org/briarproject/api/transport/IncomingKeys.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/IncomingKeys.java
@@ -1,8 +1,8 @@
-package org.briarproject.api.transport;
+package org.briarproject.bramble.api.transport;
 
-import org.briarproject.api.crypto.SecretKey;
+import org.briarproject.bramble.api.crypto.SecretKey;
 
-import static org.briarproject.api.transport.TransportConstants.REORDERING_WINDOW_SIZE;
+import static org.briarproject.bramble.api.transport.TransportConstants.REORDERING_WINDOW_SIZE;
 
 /**
  * Contains transport keys for receiving streams from a given contact over a
diff --git a/briar-api/src/org/briarproject/api/transport/KeyManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/KeyManager.java
similarity index 73%
rename from briar-api/src/org/briarproject/api/transport/KeyManager.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/transport/KeyManager.java
index 8ee0578a860ab84eedde2a456d38822c3ee9338a..97afdc133e1a672ecfcd5bda9959aa64ca619e2f 100644
--- a/briar-api/src/org/briarproject/api/transport/KeyManager.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/KeyManager.java
@@ -1,10 +1,12 @@
-package org.briarproject.api.transport;
+package org.briarproject.bramble.api.transport;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.plugin.TransportId;
+
+import javax.annotation.Nullable;
 
 /**
  * Responsible for managing transport keys and recognising the pseudo-random
@@ -26,6 +28,7 @@ public interface KeyManager {
 	 * contact over the given transport, or null if an error occurs or the
 	 * contact does not support the transport.
 	 */
+	@Nullable
 	StreamContext getStreamContext(ContactId c, TransportId t)
 			throws DbException;
 
@@ -34,6 +37,7 @@ public interface KeyManager {
 	 * from the corresponding stream, or null if an error occurs or the tag was
 	 * unexpected.
 	 */
+	@Nullable
 	StreamContext getStreamContext(TransportId t, byte[] tag)
 			throws DbException;
 }
diff --git a/briar-api/src/org/briarproject/api/transport/OutgoingKeys.java b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/OutgoingKeys.java
similarity index 89%
rename from briar-api/src/org/briarproject/api/transport/OutgoingKeys.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/transport/OutgoingKeys.java
index 08a06d2d9c513bce262001ea8ba99b573fa76755..202c46e6a0ec7abd40f4aa7d381f10cca6590b53 100644
--- a/briar-api/src/org/briarproject/api/transport/OutgoingKeys.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/OutgoingKeys.java
@@ -1,6 +1,6 @@
-package org.briarproject.api.transport;
+package org.briarproject.bramble.api.transport;
 
-import org.briarproject.api.crypto.SecretKey;
+import org.briarproject.bramble.api.crypto.SecretKey;
 
 /**
  * Contains transport keys for sending streams to a given contact over a given
diff --git a/briar-api/src/org/briarproject/api/transport/StreamContext.java b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/StreamContext.java
similarity index 78%
rename from briar-api/src/org/briarproject/api/transport/StreamContext.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/transport/StreamContext.java
index d9dbe9cd1550fb747c7383c23612aca2c1f943cb..b5205999beef64e6c8f625ad8a41107260bc0cd1 100644
--- a/briar-api/src/org/briarproject/api/transport/StreamContext.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/StreamContext.java
@@ -1,8 +1,8 @@
-package org.briarproject.api.transport;
+package org.briarproject.bramble.api.transport;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.crypto.SecretKey;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.plugin.TransportId;
 
 public class StreamContext {
 
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/transport/StreamReaderFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/StreamReaderFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..44e31a671b6019567450eded400300010c8e3f37
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/StreamReaderFactory.java
@@ -0,0 +1,23 @@
+package org.briarproject.bramble.api.transport;
+
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import java.io.InputStream;
+
+@NotNullByDefault
+public interface StreamReaderFactory {
+
+	/**
+	 * Creates an {@link InputStream InputStream} for reading from a
+	 * transport stream.
+	 */
+	InputStream createStreamReader(InputStream in, StreamContext ctx);
+
+	/**
+	 * Creates an {@link InputStream InputStream} for reading from an
+	 * invitation stream.
+	 */
+	InputStream createInvitationStreamReader(InputStream in,
+			SecretKey headerKey);
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/transport/StreamWriterFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/StreamWriterFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..134bde50e7924332543c0d138f4ddd2193caf516
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/StreamWriterFactory.java
@@ -0,0 +1,23 @@
+package org.briarproject.bramble.api.transport;
+
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import java.io.OutputStream;
+
+@NotNullByDefault
+public interface StreamWriterFactory {
+
+	/**
+	 * Creates an {@link OutputStream OutputStream} for writing to a
+	 * transport stream
+	 */
+	OutputStream createStreamWriter(OutputStream out, StreamContext ctx);
+
+	/**
+	 * Creates an {@link OutputStream OutputStream} for writing to an
+	 * invitation stream.
+	 */
+	OutputStream createInvitationStreamWriter(OutputStream out,
+			SecretKey headerKey);
+}
diff --git a/briar-api/src/org/briarproject/api/transport/TransportConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/TransportConstants.java
similarity index 54%
rename from briar-api/src/org/briarproject/api/transport/TransportConstants.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/transport/TransportConstants.java
index 9166bcf0ca387c82f366cc50706d9197727158df..5bd47f0a0ac83a0e97069d78b9c8fb135b13246c 100644
--- a/briar-api/src/org/briarproject/api/transport/TransportConstants.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/TransportConstants.java
@@ -1,33 +1,48 @@
-package org.briarproject.api.transport;
+package org.briarproject.bramble.api.transport;
 
-
-import org.briarproject.api.crypto.SecretKey;
+import org.briarproject.bramble.api.crypto.SecretKey;
 
 public interface TransportConstants {
 
-	/** The length of the pseudo-random tag in bytes. */
+	/**
+	 * The length of the pseudo-random tag in bytes.
+	 */
 	int TAG_LENGTH = 16;
 
-	/** The length of the stream header nonce in bytes. */
+	/**
+	 * The length of the stream header nonce in bytes.
+	 */
 	int STREAM_HEADER_NONCE_LENGTH = 24;
 
-	/** The length of the stream header initialisation vector (IV) in bytes. */
+	/**
+	 * The length of the stream header initialisation vector (IV) in bytes.
+	 */
 	int STREAM_HEADER_IV_LENGTH = STREAM_HEADER_NONCE_LENGTH - 8;
 
-	/** The length of the message authentication code (MAC) in bytes. */
+	/**
+	 * The length of the message authentication code (MAC) in bytes.
+	 */
 	int MAC_LENGTH = 16;
 
-	/** The length of the stream header in bytes. */
+	/**
+	 * The length of the stream header in bytes.
+	 */
 	int STREAM_HEADER_LENGTH = STREAM_HEADER_IV_LENGTH + SecretKey.LENGTH
 			+ MAC_LENGTH;
 
-	/** The length of the frame nonce in bytes. */
+	/**
+	 * The length of the frame nonce in bytes.
+	 */
 	int FRAME_NONCE_LENGTH = 24;
 
-	/** The length of the plaintext frame header in bytes. */
+	/**
+	 * The length of the plaintext frame header in bytes.
+	 */
 	int FRAME_HEADER_PLAINTEXT_LENGTH = 4;
 
-	/** The length of the encrypted and authenticated frame header in bytes. */
+	/**
+	 * The length of the encrypted and authenticated frame header in bytes.
+	 */
 	int FRAME_HEADER_LENGTH = FRAME_HEADER_PLAINTEXT_LENGTH + MAC_LENGTH;
 
 	/**
@@ -36,7 +51,9 @@ public interface TransportConstants {
 	 */
 	int MAX_FRAME_LENGTH = 1024;
 
-	/** The maximum total length of the frame payload and padding in bytes. */
+	/**
+	 * The maximum total length of the frame payload and padding in bytes.
+	 */
 	int MAX_PAYLOAD_LENGTH = MAX_FRAME_LENGTH - FRAME_HEADER_LENGTH
 			- MAC_LENGTH;
 
@@ -48,9 +65,13 @@ public interface TransportConstants {
 	int MIN_STREAM_LENGTH = STREAM_HEADER_LENGTH + FRAME_HEADER_LENGTH
 			+ MAC_LENGTH;
 
-	/** The maximum difference in milliseconds between two peers' clocks. */
+	/**
+	 * The maximum difference in milliseconds between two peers' clocks.
+	 */
 	int MAX_CLOCK_DIFFERENCE = 24 * 60 * 60 * 1000; // 24 hours
 
-	/** The size of the reordering window. */
+	/**
+	 * The size of the reordering window.
+	 */
 	int REORDERING_WINDOW_SIZE = 32;
 }
diff --git a/briar-api/src/org/briarproject/api/transport/TransportKeys.java b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/TransportKeys.java
similarity index 86%
rename from briar-api/src/org/briarproject/api/transport/TransportKeys.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/transport/TransportKeys.java
index ec550b52a646a54b6433c08d5ae71378dd0568e7..40aeed9a3bba5b0e43875db4a13c37c7d682d3f7 100644
--- a/briar-api/src/org/briarproject/api/transport/TransportKeys.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/TransportKeys.java
@@ -1,8 +1,10 @@
-package org.briarproject.api.transport;
+package org.briarproject.bramble.api.transport;
 
-import org.briarproject.api.TransportId;
+import org.briarproject.bramble.api.plugin.TransportId;
 
-/** Keys for communicating with a given contact over a given transport. */
+/**
+ * Keys for communicating with a given contact over a given transport.
+ */
 public class TransportKeys {
 
 	private final TransportId transportId;
diff --git a/briar-api/src/org/briarproject/api/ui/UiCallback.java b/bramble-api/src/main/java/org/briarproject/bramble/api/ui/UiCallback.java
similarity index 94%
rename from briar-api/src/org/briarproject/api/ui/UiCallback.java
rename to bramble-api/src/main/java/org/briarproject/bramble/api/ui/UiCallback.java
index e3608950fcba49651594a1ac022e7b1d63f56d35..c5ad6d1fc21f6f492ce3aaad41b1c17e5b43279b 100644
--- a/briar-api/src/org/briarproject/api/ui/UiCallback.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/ui/UiCallback.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.ui;
+package org.briarproject.bramble.api.ui;
 
 public interface UiCallback {
 
@@ -6,6 +6,7 @@ public interface UiCallback {
 	 * Presents the user with a choice among two or more named options and
 	 * returns the user's response. The message may consist of a translatable
 	 * format string and arguments.
+	 *
 	 * @return an index into the array of options indicating the user's choice,
 	 * or -1 if the user cancelled the choice.
 	 */
diff --git a/briar-core/src/org/briarproject/util/ByteUtils.java b/bramble-api/src/main/java/org/briarproject/bramble/util/ByteUtils.java
similarity index 96%
rename from briar-core/src/org/briarproject/util/ByteUtils.java
rename to bramble-api/src/main/java/org/briarproject/bramble/util/ByteUtils.java
index 061a4780db9d5bf5c9f6eee71e87ad3c6f06b8df..61b2378292e8389465e970fc2aa662642ad2412a 100644
--- a/briar-core/src/org/briarproject/util/ByteUtils.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/util/ByteUtils.java
@@ -1,4 +1,4 @@
-package org.briarproject.util;
+package org.briarproject.bramble.util;
 
 public class ByteUtils {
 
@@ -89,8 +89,8 @@ public class ByteUtils {
 		for (int i = 0; i < bits; i++) {
 			if ((src[i >> 3] & 128 >> (i & 7)) != 0) dest |= 1 << bits - i - 1;
 		}
-		assert dest >= 0;
-		assert dest < 1 << bits;
+		if (dest < 0) throw new AssertionError();
+		if (dest >= 1 << bits) throw new AssertionError();
 		return dest;
 	}
 }
diff --git a/briar-core/src/org/briarproject/util/IoUtils.java b/bramble-api/src/main/java/org/briarproject/bramble/util/IoUtils.java
similarity index 84%
rename from briar-core/src/org/briarproject/util/IoUtils.java
rename to bramble-api/src/main/java/org/briarproject/bramble/util/IoUtils.java
index cb76c9d5fe838b0557e3761fc826eac969f5c2f7..eb682e16798d00ca02e21b4a2ec6fac106025311 100644
--- a/briar-core/src/org/briarproject/util/IoUtils.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/util/IoUtils.java
@@ -1,4 +1,6 @@
-package org.briarproject.util;
+package org.briarproject.bramble.util;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.Closeable;
 import java.io.EOFException;
@@ -7,6 +9,9 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 
+import javax.annotation.Nullable;
+
+@NotNullByDefault
 public class IoUtils {
 
 	public static void deleteFileOrDir(File f) {
@@ -38,7 +43,7 @@ public class IoUtils {
 		}
 	}
 
-	private static void tryToClose(Closeable c) {
+	private static void tryToClose(@Nullable Closeable c) {
 		try {
 			if (c != null) c.close();
 		} catch (IOException e) {
diff --git a/briar-core/src/org/briarproject/util/OsUtils.java b/bramble-api/src/main/java/org/briarproject/bramble/util/OsUtils.java
similarity index 65%
rename from briar-core/src/org/briarproject/util/OsUtils.java
rename to bramble-api/src/main/java/org/briarproject/bramble/util/OsUtils.java
index 547db92e1a696f2de13f5d7a43cce2b4a380b686..66ee8f256cdd45d410546a17794219b1efe3414e 100644
--- a/briar-core/src/org/briarproject/util/OsUtils.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/util/OsUtils.java
@@ -1,17 +1,25 @@
-package org.briarproject.util;
+package org.briarproject.bramble.util;
 
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.Nullable;
+
+@NotNullByDefault
 public class OsUtils {
 
+	@Nullable
 	private static final String os = System.getProperty("os.name");
+	@Nullable
 	private static final String version = System.getProperty("os.version");
+	@Nullable
 	private static final String vendor = System.getProperty("java.vendor");
 
 	public static boolean isWindows() {
-		return os != null && os.indexOf("Windows") != -1;
+		return os != null && os.contains("Windows");
 	}
 
 	public static boolean isMac() {
-		return os != null && os.indexOf("Mac OS") != -1;
+		return os != null && os.contains("Mac OS");
 	}
 
 	public static boolean isMacLeopardOrNewer() {
@@ -28,10 +36,10 @@ public class OsUtils {
 	}
 
 	public static boolean isLinux() {
-		return os != null && os.indexOf("Linux") != -1 && !isAndroid();
+		return os != null && os.contains("Linux") && !isAndroid();
 	}
 
 	public static boolean isAndroid() {
-		return vendor != null && vendor.indexOf("Android") != -1;
+		return vendor != null && vendor.contains("Android");
 	}
 }
diff --git a/briar-core/src/org/briarproject/util/PrivacyUtils.java b/bramble-api/src/main/java/org/briarproject/bramble/util/PrivacyUtils.java
similarity index 76%
rename from briar-core/src/org/briarproject/util/PrivacyUtils.java
rename to bramble-api/src/main/java/org/briarproject/bramble/util/PrivacyUtils.java
index c2bf426287d6afb4d0ded848796e018edcb67f85..50c4e792a2d942df4eb55e3651555593ea605863 100644
--- a/briar-core/src/org/briarproject/util/PrivacyUtils.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/util/PrivacyUtils.java
@@ -1,27 +1,33 @@
-package org.briarproject.util;
+package org.briarproject.bramble.util;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
 
+import javax.annotation.Nullable;
+
+@NotNullByDefault
 public class PrivacyUtils {
 
 	public static String scrubOnion(String onion) {
 		// keep first three characters of onion address
-		return onion.substring(0, 3) + "[_scrubbed_]";
+		return onion.substring(0, 3) + "[scrubbed]";
 	}
 
-	public static String scrubMacAddress(String address) {
+	@Nullable
+	public static String scrubMacAddress(@Nullable String address) {
 		if (address == null) return null;
 		// this is a fake address we need to know about
 		if (address.equals("02:00:00:00:00:00")) return address;
 		// keep first and last octet of MAC address
-		return address.substring(0, 3) +
-				"[scrubbed]" +
-				address.substring(14, 17);
+		return address.substring(0, 3) + "[scrubbed]"
+				+ address.substring(14, 17);
 	}
 
+	@Nullable
 	public static String scrubInetAddress(InetAddress address) {
 		// don't scrub link and site local addresses
 		if (address.isLinkLocalAddress() || address.isSiteLocalAddress())
@@ -32,7 +38,8 @@ public class PrivacyUtils {
 		return scrubInetAddress(address.toString());
 	}
 
-	public static String scrubInetAddress(String address) {
+	@Nullable
+	public static String scrubInetAddress(@Nullable String address) {
 		if (address == null) return null;
 
 		int firstDot = address.indexOf(".");
@@ -43,11 +50,13 @@ public class PrivacyUtils {
 		return prefix + "[scrubbed]" + suffix;
 	}
 
+	@Nullable
 	public static String scrubSocketAddress(InetSocketAddress address) {
 		InetAddress inetAddress = address.getAddress();
 		return scrubInetAddress(inetAddress);
 	}
 
+	@Nullable
 	public static String scrubSocketAddress(SocketAddress address) {
 		if (address instanceof InetSocketAddress)
 			return scrubSocketAddress((InetSocketAddress) address);
diff --git a/briar-core/src/org/briarproject/util/StringUtils.java b/bramble-api/src/main/java/org/briarproject/bramble/util/StringUtils.java
similarity index 97%
rename from briar-core/src/org/briarproject/util/StringUtils.java
rename to bramble-api/src/main/java/org/briarproject/bramble/util/StringUtils.java
index af622cc270130458cf276941667b011ca55db5d6..4cfe34ee98cf1fc80a4837ac4418307db7f12974 100644
--- a/briar-core/src/org/briarproject/util/StringUtils.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/util/StringUtils.java
@@ -1,6 +1,6 @@
-package org.briarproject.util;
+package org.briarproject.bramble.util;
 
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.UnsupportedEncodingException;
 import java.nio.ByteBuffer;
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/util/ValidationUtils.java b/bramble-api/src/main/java/org/briarproject/bramble/util/ValidationUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..fffacae0c3ea6b02d34974ee095905b7480369e4
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/util/ValidationUtils.java
@@ -0,0 +1,67 @@
+package org.briarproject.bramble.util;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.Nullable;
+
+@NotNullByDefault
+public class ValidationUtils {
+
+	public static void checkLength(@Nullable String s, int minLength,
+			int maxLength) throws FormatException {
+		if (s != null) {
+			int length = StringUtils.toUtf8(s).length;
+			if (length < minLength) throw new FormatException();
+			if (length > maxLength) throw new FormatException();
+		}
+	}
+
+	public static void checkLength(@Nullable String s, int length)
+			throws FormatException {
+		if (s != null && StringUtils.toUtf8(s).length != length)
+			throw new FormatException();
+	}
+
+	public static void checkLength(@Nullable byte[] b, int minLength,
+			int maxLength) throws FormatException {
+		if (b != null) {
+			if (b.length < minLength) throw new FormatException();
+			if (b.length > maxLength) throw new FormatException();
+		}
+	}
+
+	public static void checkLength(@Nullable byte[] b, int length)
+			throws FormatException {
+		if (b != null && b.length != length) throw new FormatException();
+	}
+
+	public static void checkSize(@Nullable BdfList list, int minSize,
+			int maxSize) throws FormatException {
+		if (list != null) {
+			if (list.size() < minSize) throw new FormatException();
+			if (list.size() > maxSize) throw new FormatException();
+		}
+	}
+
+	public static void checkSize(@Nullable BdfList list, int size)
+			throws FormatException {
+		if (list != null && list.size() != size) throw new FormatException();
+	}
+
+	public static void checkSize(@Nullable BdfDictionary dictionary,
+			int minSize, int maxSize) throws FormatException {
+		if (dictionary != null) {
+			if (dictionary.size() < minSize) throw new FormatException();
+			if (dictionary.size() > maxSize) throw new FormatException();
+		}
+	}
+
+	public static void checkSize(@Nullable BdfDictionary dictionary, int size)
+			throws FormatException {
+		if (dictionary != null && dictionary.size() != size)
+			throw new FormatException();
+	}
+}
diff --git a/bramble-core/.gitignore b/bramble-core/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..eeb02632a0a71dc53ad5bbb4f04aff39855b50e6
--- /dev/null
+++ b/bramble-core/.gitignore
@@ -0,0 +1,3 @@
+bin
+build
+.settings
diff --git a/bramble-core/build.gradle b/bramble-core/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..a281b0bd10f691808132c3fe5ffceca130ebb987
--- /dev/null
+++ b/bramble-core/build.gradle
@@ -0,0 +1,19 @@
+apply plugin: 'java'
+sourceCompatibility = 1.6
+targetCompatibility = 1.6
+
+apply plugin: 'witness'
+
+dependencies {
+	compile project(':bramble-api')
+	compile fileTree(dir: 'libs', include: '*.jar')
+	compile 'com.madgag.spongycastle:core:1.54.0.0'
+	compile 'com.h2database:h2:1.4.190'
+}
+
+dependencyVerification {
+	verify = [
+			'com.madgag.spongycastle:core:1e7fa4b19ccccd1011364ab838d0b4702470c178bbbdd94c5c90b2d4d749ea1e',
+			'com.h2database:h2:23ba495a07bbbb3bd6c3084d10a96dad7a23741b8b6d64b213459a784195a98c'
+	]
+}
diff --git a/briar-core/libs/weupnp-0.1.3-SNAPSHOT-briar.jar b/bramble-core/libs/weupnp-0.1.3-SNAPSHOT-briar.jar
similarity index 100%
rename from briar-core/libs/weupnp-0.1.3-SNAPSHOT-briar.jar
rename to bramble-core/libs/weupnp-0.1.3-SNAPSHOT-briar.jar
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/BrambleCoreEagerSingletons.java b/bramble-core/src/main/java/org/briarproject/bramble/BrambleCoreEagerSingletons.java
new file mode 100644
index 0000000000000000000000000000000000000000..e7a211e294761124ebb5313dfa2adee1bf9c3381
--- /dev/null
+++ b/bramble-core/src/main/java/org/briarproject/bramble/BrambleCoreEagerSingletons.java
@@ -0,0 +1,35 @@
+package org.briarproject.bramble;
+
+import org.briarproject.bramble.contact.ContactModule;
+import org.briarproject.bramble.crypto.CryptoModule;
+import org.briarproject.bramble.db.DatabaseExecutorModule;
+import org.briarproject.bramble.identity.IdentityModule;
+import org.briarproject.bramble.lifecycle.LifecycleModule;
+import org.briarproject.bramble.plugin.PluginModule;
+import org.briarproject.bramble.properties.PropertiesModule;
+import org.briarproject.bramble.sync.SyncModule;
+import org.briarproject.bramble.system.SystemModule;
+import org.briarproject.bramble.transport.TransportModule;
+
+public interface BrambleCoreEagerSingletons {
+
+	void inject(ContactModule.EagerSingletons init);
+
+	void inject(CryptoModule.EagerSingletons init);
+
+	void inject(DatabaseExecutorModule.EagerSingletons init);
+
+	void inject(IdentityModule.EagerSingletons init);
+
+	void inject(LifecycleModule.EagerSingletons init);
+
+	void inject(PluginModule.EagerSingletons init);
+
+	void inject(PropertiesModule.EagerSingletons init);
+
+	void inject(SyncModule.EagerSingletons init);
+
+	void inject(SystemModule.EagerSingletons init);
+
+	void inject(TransportModule.EagerSingletons init);
+}
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/BrambleCoreModule.java b/bramble-core/src/main/java/org/briarproject/bramble/BrambleCoreModule.java
new file mode 100644
index 0000000000000000000000000000000000000000..250b8be2aad0d35670b4c1b91b95d045f821d17f
--- /dev/null
+++ b/bramble-core/src/main/java/org/briarproject/bramble/BrambleCoreModule.java
@@ -0,0 +1,61 @@
+package org.briarproject.bramble;
+
+import org.briarproject.bramble.client.ClientModule;
+import org.briarproject.bramble.contact.ContactModule;
+import org.briarproject.bramble.crypto.CryptoModule;
+import org.briarproject.bramble.data.DataModule;
+import org.briarproject.bramble.db.DatabaseExecutorModule;
+import org.briarproject.bramble.db.DatabaseModule;
+import org.briarproject.bramble.event.EventModule;
+import org.briarproject.bramble.identity.IdentityModule;
+import org.briarproject.bramble.invitation.InvitationModule;
+import org.briarproject.bramble.keyagreement.KeyAgreementModule;
+import org.briarproject.bramble.lifecycle.LifecycleModule;
+import org.briarproject.bramble.plugin.PluginModule;
+import org.briarproject.bramble.properties.PropertiesModule;
+import org.briarproject.bramble.reliability.ReliabilityModule;
+import org.briarproject.bramble.reporting.ReportingModule;
+import org.briarproject.bramble.settings.SettingsModule;
+import org.briarproject.bramble.socks.SocksModule;
+import org.briarproject.bramble.sync.SyncModule;
+import org.briarproject.bramble.system.SystemModule;
+import org.briarproject.bramble.transport.TransportModule;
+
+import dagger.Module;
+
+@Module(includes = {
+		ClientModule.class,
+		ContactModule.class,
+		CryptoModule.class,
+		DataModule.class,
+		DatabaseModule.class,
+		DatabaseExecutorModule.class,
+		EventModule.class,
+		IdentityModule.class,
+		InvitationModule.class,
+		KeyAgreementModule.class,
+		LifecycleModule.class,
+		PluginModule.class,
+		PropertiesModule.class,
+		ReliabilityModule.class,
+		ReportingModule.class,
+		SettingsModule.class,
+		SocksModule.class,
+		SyncModule.class,
+		SystemModule.class,
+		TransportModule.class
+})
+public class BrambleCoreModule {
+
+	public static void initEagerSingletons(BrambleCoreEagerSingletons c) {
+		c.inject(new ContactModule.EagerSingletons());
+		c.inject(new CryptoModule.EagerSingletons());
+		c.inject(new DatabaseExecutorModule.EagerSingletons());
+		c.inject(new IdentityModule.EagerSingletons());
+		c.inject(new LifecycleModule.EagerSingletons());
+		c.inject(new PluginModule.EagerSingletons());
+		c.inject(new SyncModule.EagerSingletons());
+		c.inject(new SystemModule.EagerSingletons());
+		c.inject(new TransportModule.EagerSingletons());
+	}
+}
diff --git a/briar-core/src/org/briarproject/clients/ClientHelperImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/client/ClientHelperImpl.java
similarity index 88%
rename from briar-core/src/org/briarproject/clients/ClientHelperImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/client/ClientHelperImpl.java
index bca3812f35a16366c1b570c58df898c8c0adc16d..55847365f435f44aed5debcca054aad098aa5ff7 100644
--- a/briar-core/src/org/briarproject/clients/ClientHelperImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/client/ClientHelperImpl.java
@@ -1,25 +1,25 @@
-package org.briarproject.clients;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.BdfReader;
-import org.briarproject.api.data.BdfReaderFactory;
-import org.briarproject.api.data.BdfWriter;
-import org.briarproject.api.data.BdfWriterFactory;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.data.MetadataParser;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageFactory;
-import org.briarproject.api.sync.MessageId;
+package org.briarproject.bramble.client;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.BdfReader;
+import org.briarproject.bramble.api.data.BdfReaderFactory;
+import org.briarproject.bramble.api.data.BdfWriter;
+import org.briarproject.bramble.api.data.BdfWriterFactory;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.data.MetadataParser;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageFactory;
+import org.briarproject.bramble.api.sync.MessageId;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -29,10 +29,12 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
 
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
 
+@Immutable
 @NotNullByDefault
 class ClientHelperImpl implements ClientHelper {
 
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/client/ClientModule.java b/bramble-core/src/main/java/org/briarproject/bramble/client/ClientModule.java
new file mode 100644
index 0000000000000000000000000000000000000000..c5ec20f83503565f635c9512deb269d34b4c6f20
--- /dev/null
+++ b/bramble-core/src/main/java/org/briarproject/bramble/client/ClientModule.java
@@ -0,0 +1,36 @@
+package org.briarproject.bramble.client;
+
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.client.ContactGroupFactory;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.data.BdfReaderFactory;
+import org.briarproject.bramble.api.data.BdfWriterFactory;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.data.MetadataParser;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.sync.GroupFactory;
+import org.briarproject.bramble.api.sync.MessageFactory;
+
+import dagger.Module;
+import dagger.Provides;
+
+@Module
+public class ClientModule {
+
+	@Provides
+	ClientHelper provideClientHelper(DatabaseComponent db,
+			MessageFactory messageFactory, BdfReaderFactory bdfReaderFactory,
+			BdfWriterFactory bdfWriterFactory, MetadataParser metadataParser,
+			MetadataEncoder metadataEncoder, CryptoComponent cryptoComponent) {
+		return new ClientHelperImpl(db, messageFactory, bdfReaderFactory,
+				bdfWriterFactory, metadataParser, metadataEncoder,
+				cryptoComponent);
+	}
+
+	@Provides
+	ContactGroupFactory provideContactGroupFactory(GroupFactory groupFactory,
+			ClientHelper clientHelper) {
+		return new ContactGroupFactoryImpl(groupFactory, clientHelper);
+	}
+
+}
diff --git a/briar-core/src/org/briarproject/clients/ContactGroupFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/client/ContactGroupFactoryImpl.java
similarity index 66%
rename from briar-core/src/org/briarproject/clients/ContactGroupFactoryImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/client/ContactGroupFactoryImpl.java
index f5cbaf8e9d33d48d26d2b76f8ad2a11afe92e7a0..0690553479ff74cfc67c95264c193115714152a8 100644
--- a/briar-core/src/org/briarproject/clients/ContactGroupFactoryImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/client/ContactGroupFactoryImpl.java
@@ -1,19 +1,22 @@
-package org.briarproject.clients;
-
-
-import org.briarproject.api.Bytes;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.ContactGroupFactory;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupFactory;
-
+package org.briarproject.bramble.client;
+
+import org.briarproject.bramble.api.Bytes;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.client.ContactGroupFactory;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupFactory;
+
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
+@Immutable
+@NotNullByDefault
 class ContactGroupFactoryImpl implements ContactGroupFactory {
 
 	private static final byte[] LOCAL_GROUP_DESCRIPTOR = new byte[0];
diff --git a/briar-core/src/org/briarproject/contact/ContactExchangeTaskImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactExchangeTaskImpl.java
similarity index 79%
rename from briar-core/src/org/briarproject/contact/ContactExchangeTaskImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/contact/ContactExchangeTaskImpl.java
index ec825052cc7643795930e40ab89d55b73c205484..e33b1deb0c2ad90d8b12dd6eca31f98d056b53ef 100644
--- a/briar-core/src/org/briarproject/contact/ContactExchangeTaskImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactExchangeTaskImpl.java
@@ -1,32 +1,34 @@
-package org.briarproject.contact;
+package org.briarproject.bramble.contact;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactExchangeListener;
-import org.briarproject.api.contact.ContactExchangeTask;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.BdfReader;
-import org.briarproject.api.data.BdfReaderFactory;
-import org.briarproject.api.data.BdfWriter;
-import org.briarproject.api.data.BdfWriterFactory;
-import org.briarproject.api.db.ContactExistsException;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.plugins.ConnectionManager;
-import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
-import org.briarproject.api.properties.TransportProperties;
-import org.briarproject.api.properties.TransportPropertyManager;
-import org.briarproject.api.system.Clock;
-import org.briarproject.api.transport.StreamReaderFactory;
-import org.briarproject.api.transport.StreamWriterFactory;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.contact.ContactExchangeListener;
+import org.briarproject.bramble.api.contact.ContactExchangeTask;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.BdfReader;
+import org.briarproject.bramble.api.data.BdfReaderFactory;
+import org.briarproject.bramble.api.data.BdfWriter;
+import org.briarproject.bramble.api.data.BdfWriterFactory;
+import org.briarproject.bramble.api.db.ContactExistsException;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.plugin.ConnectionManager;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
+import org.briarproject.bramble.api.properties.TransportProperties;
+import org.briarproject.bramble.api.properties.TransportPropertyManager;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.bramble.api.transport.StreamReaderFactory;
+import org.briarproject.bramble.api.transport.StreamWriterFactory;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -41,18 +43,20 @@ import javax.inject.Inject;
 
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.TransportId.MAX_TRANSPORT_ID_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.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
-import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTIES_PER_TRANSPORT;
-import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
+import static org.briarproject.bramble.api.plugin.TransportId.MAX_TRANSPORT_ID_LENGTH;
+import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MAX_PROPERTIES_PER_TRANSPORT;
+import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
 
-public class ContactExchangeTaskImpl extends Thread
-		implements ContactExchangeTask {
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
+class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
 
 	private static final Logger LOG =
 			Logger.getLogger(ContactExchangeTaskImpl.class.getName());
+
 	private static final String SIGNING_LABEL_EXCHANGE =
 			"org.briarproject.briar.contact/EXCHANGE";
 
diff --git a/briar-core/src/org/briarproject/contact/ContactManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java
similarity index 83%
rename from briar-core/src/org/briarproject/contact/ContactManagerImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java
index c0d13a44f8de2f1b3bbaebebe63eca0bffbf88da..c4c3152b7a6d65fbc295bdc57e1b5d21c7d48fda 100644
--- a/briar-core/src/org/briarproject/contact/ContactManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java
@@ -1,24 +1,27 @@
-package org.briarproject.contact;
-
-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.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.transport.KeyManager;
+package org.briarproject.bramble.contact;
+
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.transport.KeyManager;
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 
+import javax.annotation.concurrent.ThreadSafe;
 import javax.inject.Inject;
 
+@ThreadSafe
+@NotNullByDefault
 class ContactManagerImpl implements ContactManager {
 
 	private final DatabaseComponent db;
diff --git a/briar-core/src/org/briarproject/contact/ContactModule.java b/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactModule.java
similarity index 75%
rename from briar-core/src/org/briarproject/contact/ContactModule.java
rename to bramble-core/src/main/java/org/briarproject/bramble/contact/ContactModule.java
index 800b8e57f9c0134bc5ca0802a33ecb4c014d54ac..2cb610972caac67f87f197aaafd15016fe7472d7 100644
--- a/briar-core/src/org/briarproject/contact/ContactModule.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactModule.java
@@ -1,7 +1,7 @@
-package org.briarproject.contact;
+package org.briarproject.bramble.contact;
 
-import org.briarproject.api.contact.ContactExchangeTask;
-import org.briarproject.api.contact.ContactManager;
+import org.briarproject.bramble.api.contact.ContactExchangeTask;
+import org.briarproject.bramble.api.contact.ContactManager;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
diff --git a/briar-core/src/org/briarproject/crypto/AsciiArmour.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/AsciiArmour.java
similarity index 72%
rename from briar-core/src/org/briarproject/crypto/AsciiArmour.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/AsciiArmour.java
index 5e00461d475ecab8d107bee86f95908e57a8d792..2bf79875ef1c0232839a58d2b0b09b5141155454 100644
--- a/briar-core/src/org/briarproject/crypto/AsciiArmour.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/AsciiArmour.java
@@ -1,8 +1,10 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.util.StringUtils;
 
+@NotNullByDefault
 class AsciiArmour {
 
 	static String wrap(byte[] b, int lineLength) {
diff --git a/briar-core/src/org/briarproject/crypto/AuthenticatedCipher.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/AuthenticatedCipher.java
similarity index 66%
rename from briar-core/src/org/briarproject/crypto/AuthenticatedCipher.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/AuthenticatedCipher.java
index fe4f8bee006711dfd0ad12ec5d1298eaf5e4508d..b70358e5dabe04477c80c85ac7bb9ad5ee2006d5 100644
--- a/briar-core/src/org/briarproject/crypto/AuthenticatedCipher.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/AuthenticatedCipher.java
@@ -1,9 +1,11 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
-import org.briarproject.api.crypto.SecretKey;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.security.GeneralSecurityException;
 
+@NotNullByDefault
 interface AuthenticatedCipher {
 
 	/**
@@ -22,23 +24,25 @@ interface AuthenticatedCipher {
 	 * Encrypts or decrypts data in a single-part operation.
 	 *
 	 * @param input the input byte array. If encrypting, the plaintext to be
-	 *              encrypted. If decrypting, the ciphertext to be decrypted
-	 *              including the MAC.
+	 * encrypted. If decrypting, the ciphertext to be decrypted
+	 * including the MAC.
 	 * @param inputOff the offset into the input array where the data to be
-	 *                 processed starts.
+	 * processed starts.
 	 * @param len the length of the input. If decrypting, includes the MAC
-	 *            length.
+	 * length.
 	 * @param output the output byte array. If encrypting, the ciphertext
-	 *               including the MAC. If decrypting, the plaintext.
+	 * including the MAC. If decrypting, the plaintext.
 	 * @param outputOff the offset into the output byte array where the
-	 *                  processed data starts.
-	 * @return  the length of the output. If encrypting, includes the MAC
-	 *          length.
+	 * processed data starts.
+	 * @return the length of the output. If encrypting, includes the MAC
+	 * length.
 	 * @throws GeneralSecurityException on invalid input.
 	 */
 	int process(byte[] input, int inputOff, int len, byte[] output,
 			int outputOff) throws GeneralSecurityException;
 
-	/** Returns the length of the message authentication code (MAC) in bytes. */
+	/**
+	 * Returns the length of the message authentication code (MAC) in bytes.
+	 */
 	int getMacBytes();
 }
diff --git a/briar-core/src/org/briarproject/crypto/Blake2sDigest.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/Blake2sDigest.java
similarity index 99%
rename from briar-core/src/org/briarproject/crypto/Blake2sDigest.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/Blake2sDigest.java
index 33f3545d5921434a3fced86ae72c9f9c49b8a7a0..a8e132a9b15a88c743f032228be0aa36bc6ec1e3 100644
--- a/briar-core/src/org/briarproject/crypto/Blake2sDigest.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/Blake2sDigest.java
@@ -1,4 +1,4 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
 /*
   The BLAKE2 cryptographic hash function was designed by Jean-
diff --git a/briar-core/src/org/briarproject/crypto/CombinedSecureRandom.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/CombinedSecureRandom.java
similarity index 79%
rename from briar-core/src/org/briarproject/crypto/CombinedSecureRandom.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/CombinedSecureRandom.java
index 9e8631fd3b162d6378277427ddef0ad482e89bdb..82c9d50d606b97602ad3dd212153532d7fc20660 100644
--- a/briar-core/src/org/briarproject/crypto/CombinedSecureRandom.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/CombinedSecureRandom.java
@@ -1,16 +1,15 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
 import java.security.Provider;
 import java.security.SecureRandom;
 import java.security.SecureRandomSpi;
 
 /**
- * A {@link java.security.SecureRandom SecureRandom} implementation that
- * combines the outputs of two or more other implementations using XOR.
+ * A {@link SecureRandom} implementation that combines the outputs of two or
+ * more other implementations using XOR.
  */
 class CombinedSecureRandom extends SecureRandom {
 
-	private static final long serialVersionUID = -605269609862397104L;
 	private static final Provider PROVIDER = new CombinedProvider();
 
 	CombinedSecureRandom(SecureRandom... randoms) {
@@ -19,8 +18,6 @@ class CombinedSecureRandom extends SecureRandom {
 
 	private static class CombinedSecureRandomSpi extends SecureRandomSpi {
 
-		private static final long serialVersionUID = 483801767899979081L;
-
 		private final SecureRandom[] randoms;
 
 		private CombinedSecureRandomSpi(SecureRandom... randoms) {
@@ -58,8 +55,6 @@ class CombinedSecureRandom extends SecureRandom {
 
 	private static class CombinedProvider extends Provider {
 
-		private static final long serialVersionUID = -4678501890053703844L;
-
 		private CombinedProvider() {
 			super("Combined", 1.0, "");
 		}
diff --git a/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/CryptoComponentImpl.java
similarity index 94%
rename from briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/CryptoComponentImpl.java
index b18cea9f82af876aea138b40106e802de3cb1c82..879ee259541f51fd42e45be70150527b718711fe 100644
--- a/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/CryptoComponentImpl.java
@@ -1,20 +1,20 @@
-package org.briarproject.crypto;
-
-import org.briarproject.api.TransportId;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.KeyPair;
-import org.briarproject.api.crypto.KeyParser;
-import org.briarproject.api.crypto.MessageDigest;
-import org.briarproject.api.crypto.PrivateKey;
-import org.briarproject.api.crypto.PseudoRandom;
-import org.briarproject.api.crypto.PublicKey;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.system.SeedProvider;
-import org.briarproject.api.transport.IncomingKeys;
-import org.briarproject.api.transport.OutgoingKeys;
-import org.briarproject.api.transport.TransportKeys;
-import org.briarproject.util.ByteUtils;
-import org.briarproject.util.StringUtils;
+package org.briarproject.bramble.crypto;
+
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.KeyPair;
+import org.briarproject.bramble.api.crypto.KeyParser;
+import org.briarproject.bramble.api.crypto.MessageDigest;
+import org.briarproject.bramble.api.crypto.PrivateKey;
+import org.briarproject.bramble.api.crypto.PseudoRandom;
+import org.briarproject.bramble.api.crypto.PublicKey;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.system.SeedProvider;
+import org.briarproject.bramble.api.transport.IncomingKeys;
+import org.briarproject.bramble.api.transport.OutgoingKeys;
+import org.briarproject.bramble.api.transport.TransportKeys;
+import org.briarproject.bramble.util.ByteUtils;
+import org.briarproject.bramble.util.StringUtils;
 import org.spongycastle.crypto.AsymmetricCipherKeyPair;
 import org.spongycastle.crypto.CipherParameters;
 import org.spongycastle.crypto.CryptoException;
@@ -39,13 +39,13 @@ import java.util.logging.Logger;
 import javax.inject.Inject;
 
 import static java.util.logging.Level.INFO;
-import static org.briarproject.api.invitation.InvitationConstants.CODE_BITS;
-import static org.briarproject.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH;
-import static org.briarproject.crypto.EllipticCurveConstants.PARAMETERS;
-import static org.briarproject.util.ByteUtils.INT_32_BYTES;
-import static org.briarproject.util.ByteUtils.INT_64_BYTES;
-import static org.briarproject.util.ByteUtils.MAX_32_BIT_UNSIGNED;
+import static org.briarproject.bramble.api.invitation.InvitationConstants.CODE_BITS;
+import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
+import static org.briarproject.bramble.crypto.EllipticCurveConstants.PARAMETERS;
+import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES;
+import static org.briarproject.bramble.util.ByteUtils.INT_64_BYTES;
+import static org.briarproject.bramble.util.ByteUtils.MAX_32_BIT_UNSIGNED;
 
 class CryptoComponentImpl implements CryptoComponent {
 
diff --git a/briar-core/src/org/briarproject/crypto/CryptoModule.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/CryptoModule.java
similarity index 81%
rename from briar-core/src/org/briarproject/crypto/CryptoModule.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/CryptoModule.java
index aa9744483778fe0a5a7cefdad78bb9cfb1a6f76e..accfaf52791225bf4623be9125b29cf93aed21f4 100644
--- a/briar-core/src/org/briarproject/crypto/CryptoModule.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/CryptoModule.java
@@ -1,12 +1,12 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.CryptoExecutor;
-import org.briarproject.api.crypto.PasswordStrengthEstimator;
-import org.briarproject.api.crypto.StreamDecrypterFactory;
-import org.briarproject.api.crypto.StreamEncrypterFactory;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.system.SeedProvider;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.CryptoExecutor;
+import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
+import org.briarproject.bramble.api.crypto.StreamDecrypterFactory;
+import org.briarproject.bramble.api.crypto.StreamEncrypterFactory;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.system.SeedProvider;
 
 import java.security.SecureRandom;
 import java.util.concurrent.BlockingQueue;
@@ -30,7 +30,8 @@ public class CryptoModule {
 
 	public static class EagerSingletons {
 		@Inject
-		@CryptoExecutor Executor cryptoExecutor;
+		@CryptoExecutor
+		Executor cryptoExecutor;
 	}
 
 	/**
diff --git a/briar-core/src/org/briarproject/crypto/DigestWrapper.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/DigestWrapper.java
similarity index 80%
rename from briar-core/src/org/briarproject/crypto/DigestWrapper.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/DigestWrapper.java
index 01b7272f72bd4e1243c74285c7372120eff502f0..077a4012ad273a280992454899137bce15382af3 100644
--- a/briar-core/src/org/briarproject/crypto/DigestWrapper.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/DigestWrapper.java
@@ -1,8 +1,13 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
-import org.briarproject.api.crypto.MessageDigest;
+import org.briarproject.bramble.api.crypto.MessageDigest;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.spongycastle.crypto.Digest;
 
+import javax.annotation.concurrent.NotThreadSafe;
+
+@NotThreadSafe
+@NotNullByDefault
 class DigestWrapper implements MessageDigest {
 
 	private final Digest digest;
diff --git a/briar-core/src/org/briarproject/crypto/DoubleDigest.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/DoubleDigest.java
similarity index 81%
rename from briar-core/src/org/briarproject/crypto/DoubleDigest.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/DoubleDigest.java
index 1d1fdd99d1b5f5d040da4b2bdbf29a97cd0eea5f..3740472043e5b0f898136635187241f7786b184a 100644
--- a/briar-core/src/org/briarproject/crypto/DoubleDigest.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/DoubleDigest.java
@@ -1,8 +1,11 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
-import org.briarproject.api.crypto.MessageDigest;
+import org.briarproject.bramble.api.crypto.MessageDigest;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.spongycastle.crypto.Digest;
 
+import javax.annotation.concurrent.NotThreadSafe;
+
 /**
  * A message digest that prevents length extension attacks - see Ferguson and
  * Schneier, <i>Practical Cryptography</i>, chapter 6.
@@ -12,6 +15,8 @@ import org.spongycastle.crypto.Digest;
  * min(k, n/2) where k is the security level of h and n is the size of the hash
  * result."
  */
+@NotThreadSafe
+@NotNullByDefault
 class DoubleDigest implements MessageDigest {
 
 	private final Digest delegate;
@@ -20,6 +25,7 @@ class DoubleDigest implements MessageDigest {
 		this.delegate = delegate;
 	}
 
+	@Override
 	public byte[] digest() {
 		byte[] digest = new byte[delegate.getDigestSize()];
 		delegate.doFinal(digest, 0); // h(m)
@@ -28,11 +34,13 @@ class DoubleDigest implements MessageDigest {
 		return digest;
 	}
 
+	@Override
 	public byte[] digest(byte[] input) {
 		delegate.update(input, 0, input.length);
 		return digest();
 	}
 
+	@Override
 	public int digest(byte[] buf, int offset, int len) {
 		byte[] digest = digest();
 		len = Math.min(len, digest.length);
@@ -40,22 +48,27 @@ class DoubleDigest implements MessageDigest {
 		return len;
 	}
 
+	@Override
 	public int getDigestLength() {
 		return delegate.getDigestSize();
 	}
 
+	@Override
 	public void reset() {
 		delegate.reset();
 	}
 
+	@Override
 	public void update(byte input) {
 		delegate.update(input);
 	}
 
+	@Override
 	public void update(byte[] input) {
 		delegate.update(input, 0, input.length);
 	}
 
+	@Override
 	public void update(byte[] input, int offset, int len) {
 		delegate.update(input, offset, len);
 	}
diff --git a/briar-core/src/org/briarproject/crypto/EllipticCurveConstants.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/EllipticCurveConstants.java
similarity index 91%
rename from briar-core/src/org/briarproject/crypto/EllipticCurveConstants.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/EllipticCurveConstants.java
index 76be53729981a9f87744224d80130808be606d38..e4b4b04e8809ce8a5644c61fd722907d8695ae84 100644
--- a/briar-core/src/org/briarproject/crypto/EllipticCurveConstants.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/EllipticCurveConstants.java
@@ -1,6 +1,4 @@
-package org.briarproject.crypto;
-
-import java.math.BigInteger;
+package org.briarproject.bramble.crypto;
 
 import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves;
 import org.spongycastle.asn1.x9.X9ECParameters;
@@ -10,7 +8,11 @@ import org.spongycastle.math.ec.ECMultiplier;
 import org.spongycastle.math.ec.ECPoint;
 import org.spongycastle.math.ec.MontgomeryLadderMultiplier;
 
-/** Parameters for curve brainpoolp256r1 - see RFC 5639. */
+import java.math.BigInteger;
+
+/**
+ * Parameters for curve brainpoolp256r1 - see RFC 5639.
+ */
 class EllipticCurveConstants {
 
 	static final ECDomainParameters PARAMETERS;
diff --git a/briar-core/src/org/briarproject/crypto/FortunaGenerator.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/FortunaGenerator.java
similarity index 90%
rename from briar-core/src/org/briarproject/crypto/FortunaGenerator.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/FortunaGenerator.java
index 688a03dee42306257e5de2586835e9f1c35dfa47..2c4ef3ef68584aece066a0d245e795523cf7357b 100644
--- a/briar-core/src/org/briarproject/crypto/FortunaGenerator.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/FortunaGenerator.java
@@ -1,18 +1,23 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
-import org.briarproject.api.crypto.MessageDigest;
+import org.briarproject.bramble.api.crypto.MessageDigest;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.spongycastle.crypto.BlockCipher;
 import org.spongycastle.crypto.digests.SHA256Digest;
 import org.spongycastle.crypto.engines.AESLightEngine;
 import org.spongycastle.crypto.params.KeyParameter;
 
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import javax.annotation.concurrent.ThreadSafe;
+
 /**
  * Implements the Fortuna pseudo-random number generator, as described in
  * Ferguson and Schneier, <i>Practical Cryptography</i>, chapter 9.
  */
+@ThreadSafe
+@NotNullByDefault
 class FortunaGenerator {
 
 	private static final int MAX_BYTES_PER_REQUEST = 1024 * 1024;
@@ -86,7 +91,7 @@ class FortunaGenerator {
 			}
 			// Generate a partial block if needed
 			int done = fullBlocks * BLOCK_BYTES, remaining = len - done;
-			assert remaining < BLOCK_BYTES;
+			if (remaining >= BLOCK_BYTES) throw new AssertionError();
 			if (remaining > 0) {
 				cipher.processBlock(counter, 0, buffer, 0);
 				incrementCounter();
diff --git a/briar-core/src/org/briarproject/crypto/FortunaSecureRandom.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/FortunaSecureRandom.java
similarity index 85%
rename from briar-core/src/org/briarproject/crypto/FortunaSecureRandom.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/FortunaSecureRandom.java
index ce3aeeaf86b77dbcb57f8ac94a3d10478cc4fd73..62e609c96b960992b73926879018fea7215858d1 100644
--- a/briar-core/src/org/briarproject/crypto/FortunaSecureRandom.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/FortunaSecureRandom.java
@@ -1,12 +1,12 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
+
+import org.briarproject.bramble.util.StringUtils;
 
 import java.security.Provider;
 import java.security.SecureRandom;
 import java.security.SecureRandomSpi;
 import java.util.Arrays;
 
-import org.briarproject.util.StringUtils;
-
 /**
  * A {@link java.security.SecureRandom SecureRandom} implementation based on a
  * {@link FortunaGenerator}.
@@ -21,7 +21,6 @@ class FortunaSecureRandom extends SecureRandom {
 	static final byte[] SELF_TEST_VECTOR_3 =
 			StringUtils.fromHexString("1E12DA166BD86DCECDE50A8296018DE2");
 
-	private static final long serialVersionUID = -417332227850184134L;
 	private static final Provider PROVIDER = new FortunaProvider();
 
 	FortunaSecureRandom(byte[] seed) {
@@ -42,14 +41,11 @@ class FortunaSecureRandom extends SecureRandom {
 		if (!Arrays.equals(SELF_TEST_VECTOR_2, output)) return false;
 		r.setSeed(seed);
 		r.nextBytes(output);
-		if (!Arrays.equals(SELF_TEST_VECTOR_3, output)) return false;
-		return true;
+		return Arrays.equals(SELF_TEST_VECTOR_3, output);
 	}
 
 	private static class FortunaSecureRandomSpi extends SecureRandomSpi {
 
-		private static final long serialVersionUID = -1677799887497202351L;
-
 		private final FortunaGenerator generator;
 
 		private FortunaSecureRandomSpi(byte[] seed) {
@@ -78,8 +74,6 @@ class FortunaSecureRandom extends SecureRandom {
 
 	private static class FortunaProvider extends Provider {
 
-		private static final long serialVersionUID = -833121797778381769L;
-
 		private FortunaProvider() {
 			super("Fortuna", 1.0, "");
 		}
diff --git a/briar-core/src/org/briarproject/crypto/FrameEncoder.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/FrameEncoder.java
similarity index 72%
rename from briar-core/src/org/briarproject/crypto/FrameEncoder.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/FrameEncoder.java
index 68219c7a66ca941c44871ef0832eb3a9b5e10a5b..b56119b24e8e93353168365a7700cfa2e1573eab 100644
--- a/briar-core/src/org/briarproject/crypto/FrameEncoder.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/FrameEncoder.java
@@ -1,13 +1,15 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
-import org.briarproject.util.ByteUtils;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.util.ByteUtils;
 
-import static org.briarproject.api.transport.TransportConstants.FRAME_HEADER_PLAINTEXT_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.FRAME_NONCE_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
-import static org.briarproject.util.ByteUtils.INT_16_BYTES;
-import static org.briarproject.util.ByteUtils.INT_64_BYTES;
+import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_HEADER_PLAINTEXT_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_NONCE_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
+import static org.briarproject.bramble.util.ByteUtils.INT_16_BYTES;
+import static org.briarproject.bramble.util.ByteUtils.INT_64_BYTES;
 
+@NotNullByDefault
 class FrameEncoder {
 
 	static void encodeNonce(byte[] dest, long frameNumber, boolean header) {
diff --git a/briar-core/src/org/briarproject/crypto/MessageEncrypter.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/MessageEncrypter.java
similarity index 94%
rename from briar-core/src/org/briarproject/crypto/MessageEncrypter.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/MessageEncrypter.java
index c8a8d974f7bb400f463f5aa135b89957671b0ae7..82f3948b65221340990de1e15618e15c88d20869 100644
--- a/briar-core/src/org/briarproject/crypto/MessageEncrypter.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/MessageEncrypter.java
@@ -1,10 +1,11 @@
-package org.briarproject.crypto;
-
-import org.briarproject.api.crypto.KeyPair;
-import org.briarproject.api.crypto.KeyParser;
-import org.briarproject.api.crypto.PrivateKey;
-import org.briarproject.api.crypto.PublicKey;
-import org.briarproject.util.StringUtils;
+package org.briarproject.bramble.crypto;
+
+import org.briarproject.bramble.api.crypto.KeyPair;
+import org.briarproject.bramble.api.crypto.KeyParser;
+import org.briarproject.bramble.api.crypto.PrivateKey;
+import org.briarproject.bramble.api.crypto.PublicKey;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.util.StringUtils;
 import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves;
 import org.spongycastle.asn1.x9.X9ECParameters;
 import org.spongycastle.crypto.AsymmetricCipherKeyPair;
@@ -42,6 +43,10 @@ import java.nio.charset.Charset;
 import java.security.SecureRandom;
 import java.util.Scanner;
 
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 public class MessageEncrypter {
 
 	private static final ECDomainParameters PARAMETERS;
diff --git a/briar-core/src/org/briarproject/crypto/PasswordStrengthEstimatorImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/PasswordStrengthEstimatorImpl.java
similarity index 80%
rename from briar-core/src/org/briarproject/crypto/PasswordStrengthEstimatorImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/PasswordStrengthEstimatorImpl.java
index ca55efa07d2ab31fc45e59303b2b245c34bccbb3..ad1a0148d8b90b06f37238249936e229885b05fc 100644
--- a/briar-core/src/org/briarproject/crypto/PasswordStrengthEstimatorImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/PasswordStrengthEstimatorImpl.java
@@ -1,9 +1,14 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
+
+import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.util.HashSet;
 
-import org.briarproject.api.crypto.PasswordStrengthEstimator;
+import javax.annotation.concurrent.Immutable;
 
+@Immutable
+@NotNullByDefault
 class PasswordStrengthEstimatorImpl implements PasswordStrengthEstimator {
 
 	private static final int LOWER = 26;
@@ -13,6 +18,7 @@ class PasswordStrengthEstimatorImpl implements PasswordStrengthEstimator {
 	private static final double STRONG = Math.log(Math.pow(LOWER + UPPER +
 			DIGIT + OTHER, 10));
 
+	@Override
 	public float estimateStrength(String password) {
 		HashSet<Character> unique = new HashSet<Character>();
 		int length = password.length();
diff --git a/briar-core/src/org/briarproject/crypto/PseudoRandomImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/PseudoRandomImpl.java
similarity index 57%
rename from briar-core/src/org/briarproject/crypto/PseudoRandomImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/PseudoRandomImpl.java
index 2786b2994fc7e8a1e52cb333bf4c12fb620fee31..fb02df047129f013ae928679d25ead63f3540792 100644
--- a/briar-core/src/org/briarproject/crypto/PseudoRandomImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/PseudoRandomImpl.java
@@ -1,10 +1,15 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
-import org.briarproject.api.crypto.PseudoRandom;
-import org.briarproject.util.ByteUtils;
+import org.briarproject.bramble.api.crypto.PseudoRandom;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.util.ByteUtils;
 
-import static org.briarproject.util.ByteUtils.INT_32_BYTES;
+import javax.annotation.concurrent.NotThreadSafe;
 
+import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES;
+
+@NotThreadSafe
+@NotNullByDefault
 class PseudoRandomImpl implements PseudoRandom {
 
 	private final FortunaGenerator generator;
@@ -16,6 +21,7 @@ class PseudoRandomImpl implements PseudoRandom {
 		generator = new FortunaGenerator(seed);
 	}
 
+	@Override
 	public byte[] nextBytes(int length) {
 		byte[] b = new byte[length];
 		int offset = 0;
diff --git a/briar-core/src/org/briarproject/crypto/Sec1KeyParser.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1KeyParser.java
similarity index 91%
rename from briar-core/src/org/briarproject/crypto/Sec1KeyParser.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1KeyParser.java
index a3bc7c71ee3c93b6c6d7cb3fdf54ae0748117b19..edc36c6641fe02c737085994bf9ea05f7a22642c 100644
--- a/briar-core/src/org/briarproject/crypto/Sec1KeyParser.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1KeyParser.java
@@ -1,8 +1,9 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
-import org.briarproject.api.crypto.KeyParser;
-import org.briarproject.api.crypto.PrivateKey;
-import org.briarproject.api.crypto.PublicKey;
+import org.briarproject.bramble.api.crypto.KeyParser;
+import org.briarproject.bramble.api.crypto.PrivateKey;
+import org.briarproject.bramble.api.crypto.PublicKey;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.spongycastle.crypto.params.ECDomainParameters;
 import org.spongycastle.crypto.params.ECPrivateKeyParameters;
 import org.spongycastle.crypto.params.ECPublicKeyParameters;
@@ -13,6 +14,8 @@ import java.math.BigInteger;
 import java.security.GeneralSecurityException;
 import java.util.logging.Logger;
 
+import javax.annotation.concurrent.Immutable;
+
 import static java.util.logging.Level.INFO;
 
 /**
@@ -20,6 +23,8 @@ import static java.util.logging.Level.INFO;
  * Cryptography", section 2.3 (Certicom Corporation, May 2009). Point
  * compression is not used.
  */
+@Immutable
+@NotNullByDefault
 class Sec1KeyParser implements KeyParser {
 
 	private static final Logger LOG =
@@ -38,6 +43,7 @@ class Sec1KeyParser implements KeyParser {
 		privateKeyBytes = bytesPerInt;
 	}
 
+	@Override
 	public PublicKey parsePublicKey(byte[] encodedKey)
 			throws GeneralSecurityException {
 		// The validation procedure comes from SEC 1, section 3.2.2.1. Note
@@ -80,6 +86,7 @@ class Sec1KeyParser implements KeyParser {
 		return p;
 	}
 
+	@Override
 	public PrivateKey parsePrivateKey(byte[] encodedKey)
 			throws GeneralSecurityException {
 		long now = System.currentTimeMillis();
diff --git a/briar-core/src/org/briarproject/crypto/Sec1PrivateKey.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1PrivateKey.java
similarity index 69%
rename from briar-core/src/org/briarproject/crypto/Sec1PrivateKey.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1PrivateKey.java
index ff3877207426e1f7898ca0c83373162be8187836..89e297c4334ff252c8d067f2c1b13a12793576f0 100644
--- a/briar-core/src/org/briarproject/crypto/Sec1PrivateKey.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1PrivateKey.java
@@ -1,8 +1,13 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
-import org.briarproject.api.crypto.PrivateKey;
+import org.briarproject.bramble.api.crypto.PrivateKey;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.spongycastle.crypto.params.ECPrivateKeyParameters;
 
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 class Sec1PrivateKey implements PrivateKey {
 
 	private final ECPrivateKeyParameters key;
@@ -13,6 +18,7 @@ class Sec1PrivateKey implements PrivateKey {
 		bytesPerInt = (keyBits + 7) / 8;
 	}
 
+	@Override
 	public byte[] getEncoded() {
 		byte[] encodedKey = new byte[bytesPerInt];
 		byte[] d = key.getD().toByteArray();
diff --git a/briar-core/src/org/briarproject/crypto/Sec1PublicKey.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1PublicKey.java
similarity index 68%
rename from briar-core/src/org/briarproject/crypto/Sec1PublicKey.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1PublicKey.java
index f85a34b8d7255e7cb31e3a7ce319986e0e52178f..a7fd114e812f0a51f1a16530f90d23828f6e1ec1 100644
--- a/briar-core/src/org/briarproject/crypto/Sec1PublicKey.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1PublicKey.java
@@ -1,13 +1,18 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
-import org.briarproject.api.crypto.PublicKey;
+import org.briarproject.bramble.api.crypto.PublicKey;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.spongycastle.crypto.params.ECPublicKeyParameters;
 
+import javax.annotation.concurrent.Immutable;
+
 /**
  * An elliptic curve public key that uses the encoding defined in "SEC 1:
  * Elliptic Curve Cryptography", section 2.3 (Certicom Corporation, May 2009).
  * Point compression is not used.
  */
+@Immutable
+@NotNullByDefault
 class Sec1PublicKey implements PublicKey {
 
 	private final ECPublicKeyParameters key;
@@ -16,6 +21,7 @@ class Sec1PublicKey implements PublicKey {
 		this.key = key;
 	}
 
+	@Override
 	public byte[] getEncoded() {
 		return key.getQ().getEncoded(false);
 	}
diff --git a/briar-core/src/org/briarproject/crypto/Sec1Utils.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1Utils.java
similarity index 77%
rename from briar-core/src/org/briarproject/crypto/Sec1Utils.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1Utils.java
index 926bcbc69b26221e85c2c897733378be3225a67b..f87d727009fb400cebaa600bc8d4c5a770b3e4bb 100644
--- a/briar-core/src/org/briarproject/crypto/Sec1Utils.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1Utils.java
@@ -1,5 +1,8 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
 class Sec1Utils {
 
 	static void convertToFixedLength(byte[] src, byte[] dest, int destOff,
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/Signature.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/Signature.java
new file mode 100644
index 0000000000000000000000000000000000000000..f5684a7dd75e9942e538518db4b81b3e3ecf8a49
--- /dev/null
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/Signature.java
@@ -0,0 +1,46 @@
+package org.briarproject.bramble.crypto;
+
+import org.briarproject.bramble.api.crypto.PrivateKey;
+import org.briarproject.bramble.api.crypto.PublicKey;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import java.security.GeneralSecurityException;
+
+@NotNullByDefault
+interface Signature {
+
+	/**
+	 * @see {@link java.security.Signature#initSign(java.security.PrivateKey)}
+	 */
+	void initSign(PrivateKey k) throws GeneralSecurityException;
+
+	/**
+	 * @see {@link java.security.Signature#initVerify(java.security.PublicKey)}
+	 */
+	void initVerify(PublicKey k) throws GeneralSecurityException;
+
+	/**
+	 * @see {@link java.security.Signature#update(byte)}
+	 */
+	void update(byte b);
+
+	/**
+	 * @see {@link java.security.Signature#update(byte[])}
+	 */
+	void update(byte[] b);
+
+	/**
+	 * @see {@link java.security.Signature#update(byte[], int, int)}
+	 */
+	void update(byte[] b, int off, int len);
+
+	/**
+	 * @see {@link java.security.Signature#sign()}
+	 */
+	byte[] sign();
+
+	/**
+	 * @see {@link java.security.Signature#verify(byte[])}
+	 */
+	boolean verify(byte[] signature);
+}
diff --git a/briar-core/src/org/briarproject/crypto/SignatureImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/SignatureImpl.java
similarity index 83%
rename from briar-core/src/org/briarproject/crypto/SignatureImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/SignatureImpl.java
index e7c7c6394abc4ae3bb3d08e6055b6c6c54f6d5b2..2a4f8704773e843fb8152a75e96d709160fb0196 100644
--- a/briar-core/src/org/briarproject/crypto/SignatureImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/SignatureImpl.java
@@ -1,7 +1,8 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
-import org.briarproject.api.crypto.PrivateKey;
-import org.briarproject.api.crypto.PublicKey;
+import org.briarproject.bramble.api.crypto.PrivateKey;
+import org.briarproject.bramble.api.crypto.PublicKey;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.spongycastle.crypto.Digest;
 import org.spongycastle.crypto.params.ECPrivateKeyParameters;
 import org.spongycastle.crypto.params.ECPublicKeyParameters;
@@ -15,8 +16,12 @@ import java.security.GeneralSecurityException;
 import java.security.SecureRandom;
 import java.util.logging.Logger;
 
+import javax.annotation.concurrent.NotThreadSafe;
+
 import static java.util.logging.Level.INFO;
 
+@NotThreadSafe
+@NotNullByDefault
 class SignatureImpl implements Signature {
 
 	private static final Logger LOG =
@@ -34,14 +39,16 @@ class SignatureImpl implements Signature {
 
 	@Override
 	public void initSign(PrivateKey k) throws GeneralSecurityException {
-		if (!(k instanceof Sec1PrivateKey)) throw new GeneralSecurityException();
+		if (!(k instanceof Sec1PrivateKey))
+			throw new IllegalArgumentException();
 		ECPrivateKeyParameters priv = ((Sec1PrivateKey) k).getKey();
 		signer.init(true, new ParametersWithRandom(priv, secureRandom));
 	}
 
 	@Override
 	public void initVerify(PublicKey k) throws GeneralSecurityException {
-		if (!(k instanceof Sec1PublicKey)) throw new GeneralSecurityException();
+		if (!(k instanceof Sec1PublicKey))
+			throw new IllegalArgumentException();
 		ECPublicKeyParameters pub = ((Sec1PublicKey) k).getKey();
 		signer.init(false, pub);
 	}
diff --git a/briar-core/src/org/briarproject/crypto/StreamDecrypterFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/StreamDecrypterFactoryImpl.java
similarity index 65%
rename from briar-core/src/org/briarproject/crypto/StreamDecrypterFactoryImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/StreamDecrypterFactoryImpl.java
index c134872b337c70fe53f96c99eb1d976ea4f2fb0c..49fd6ba2eca274a786a6a6d6f816d236d5ac44e5 100644
--- a/briar-core/src/org/briarproject/crypto/StreamDecrypterFactoryImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/StreamDecrypterFactoryImpl.java
@@ -1,15 +1,19 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.crypto.StreamDecrypter;
-import org.briarproject.api.crypto.StreamDecrypterFactory;
-import org.briarproject.api.transport.StreamContext;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.crypto.StreamDecrypter;
+import org.briarproject.bramble.api.crypto.StreamDecrypterFactory;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.transport.StreamContext;
 
 import java.io.InputStream;
 
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 import javax.inject.Provider;
 
+@Immutable
+@NotNullByDefault
 class StreamDecrypterFactoryImpl implements StreamDecrypterFactory {
 
 	private final Provider<AuthenticatedCipher> cipherProvider;
diff --git a/briar-core/src/org/briarproject/crypto/StreamDecrypterImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/StreamDecrypterImpl.java
similarity index 76%
rename from briar-core/src/org/briarproject/crypto/StreamDecrypterImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/StreamDecrypterImpl.java
index bfd961c92bedfcff7b19e1e877decc4077d90fed..22c522d3d5c5cbd4a2525b70d0fdeab6bf207864 100644
--- a/briar-core/src/org/briarproject/crypto/StreamDecrypterImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/StreamDecrypterImpl.java
@@ -1,26 +1,32 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.crypto.StreamDecrypter;
-import org.briarproject.util.ByteUtils;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.crypto.StreamDecrypter;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.util.ByteUtils;
 
 import java.io.EOFException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.security.GeneralSecurityException;
 
-import static org.briarproject.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.FRAME_HEADER_PLAINTEXT_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.FRAME_NONCE_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.MAC_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.MAX_FRAME_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.STREAM_HEADER_IV_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.STREAM_HEADER_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.STREAM_HEADER_NONCE_LENGTH;
-import static org.briarproject.util.ByteUtils.INT_64_BYTES;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.NotThreadSafe;
 
+import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_HEADER_PLAINTEXT_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_NONCE_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAC_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAX_FRAME_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_IV_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_NONCE_LENGTH;
+import static org.briarproject.bramble.util.ByteUtils.INT_64_BYTES;
+
+@NotThreadSafe
+@NotNullByDefault
 class StreamDecrypterImpl implements StreamDecrypter {
 
 	private final InputStream in;
@@ -29,6 +35,7 @@ class StreamDecrypterImpl implements StreamDecrypter {
 	private final SecretKey streamHeaderKey;
 	private final byte[] frameNonce, frameHeader, frameCiphertext;
 
+	@Nullable
 	private SecretKey frameKey;
 	private long frameNumber;
 	private boolean finalFrame;
diff --git a/briar-core/src/org/briarproject/crypto/StreamEncrypterFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/StreamEncrypterFactoryImpl.java
similarity index 68%
rename from briar-core/src/org/briarproject/crypto/StreamEncrypterFactoryImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/StreamEncrypterFactoryImpl.java
index af5606d4407b0011a16903d1679590fc2531f751..4feff3ece868bbeb8fbc98614447b47bde4381fd 100644
--- a/briar-core/src/org/briarproject/crypto/StreamEncrypterFactoryImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/StreamEncrypterFactoryImpl.java
@@ -1,19 +1,23 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.crypto.StreamEncrypter;
-import org.briarproject.api.crypto.StreamEncrypterFactory;
-import org.briarproject.api.transport.StreamContext;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.crypto.StreamEncrypter;
+import org.briarproject.bramble.api.crypto.StreamEncrypterFactory;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.transport.StreamContext;
 
 import java.io.OutputStream;
 
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 import javax.inject.Provider;
 
-import static org.briarproject.api.transport.TransportConstants.STREAM_HEADER_IV_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_IV_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
 
+@Immutable
+@NotNullByDefault
 class StreamEncrypterFactoryImpl implements StreamEncrypterFactory {
 
 	private final CryptoComponent crypto;
diff --git a/briar-core/src/org/briarproject/crypto/StreamEncrypterImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/StreamEncrypterImpl.java
similarity index 76%
rename from briar-core/src/org/briarproject/crypto/StreamEncrypterImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/StreamEncrypterImpl.java
index 955bfc7d38a4135d75576edaa98cbdf212d6f81b..cb708eb4cf54ab2a913248fa891fc49776afbe1f 100644
--- a/briar-core/src/org/briarproject/crypto/StreamEncrypterImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/StreamEncrypterImpl.java
@@ -1,32 +1,39 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.crypto.StreamEncrypter;
-import org.briarproject.util.ByteUtils;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.crypto.StreamEncrypter;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.util.ByteUtils;
 
 import java.io.IOException;
 import java.io.OutputStream;
 import java.security.GeneralSecurityException;
 
-import static org.briarproject.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.FRAME_HEADER_PLAINTEXT_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.FRAME_NONCE_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.MAC_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.MAX_FRAME_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.STREAM_HEADER_IV_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.STREAM_HEADER_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.STREAM_HEADER_NONCE_LENGTH;
-import static org.briarproject.util.ByteUtils.INT_64_BYTES;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.NotThreadSafe;
 
+import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_HEADER_PLAINTEXT_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_NONCE_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAC_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAX_FRAME_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_IV_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_NONCE_LENGTH;
+import static org.briarproject.bramble.util.ByteUtils.INT_64_BYTES;
+
+@NotThreadSafe
+@NotNullByDefault
 class StreamEncrypterImpl implements StreamEncrypter {
 
 	private final OutputStream out;
 	private final AuthenticatedCipher cipher;
 	private final SecretKey streamHeaderKey, frameKey;
 	private final long streamNumber;
-	private final byte[] tag, streamHeaderIv;
+	@Nullable
+	private final byte[] tag;
+	private final byte[] streamHeaderIv;
 	private final byte[] frameNonce, frameHeader;
 	private final byte[] framePlaintext, frameCiphertext;
 
diff --git a/briar-core/src/org/briarproject/crypto/XSalsa20Poly1305AuthenticatedCipher.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/XSalsa20Poly1305AuthenticatedCipher.java
similarity index 83%
rename from briar-core/src/org/briarproject/crypto/XSalsa20Poly1305AuthenticatedCipher.java
rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/XSalsa20Poly1305AuthenticatedCipher.java
index 8143b696ad334c6447c48f34d2eba35eb8f737c1..7bac148f2dca81aefe1bb14eac1aead460a555d6 100644
--- a/briar-core/src/org/briarproject/crypto/XSalsa20Poly1305AuthenticatedCipher.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/XSalsa20Poly1305AuthenticatedCipher.java
@@ -1,6 +1,7 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
-import org.briarproject.api.crypto.SecretKey;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.spongycastle.crypto.DataLengthException;
 import org.spongycastle.crypto.engines.XSalsa20Engine;
 import org.spongycastle.crypto.generators.Poly1305KeyGenerator;
@@ -10,7 +11,9 @@ import org.spongycastle.crypto.params.ParametersWithIV;
 
 import java.security.GeneralSecurityException;
 
-import static org.briarproject.api.transport.TransportConstants.MAC_LENGTH;
+import javax.annotation.concurrent.NotThreadSafe;
+
+import static org.briarproject.bramble.api.transport.TransportConstants.MAC_LENGTH;
 
 /**
  * An authenticated cipher that uses XSalsa20 for encryption and Poly1305 for
@@ -20,14 +23,17 @@ import static org.briarproject.api.transport.TransportConstants.MAC_LENGTH;
  * <p/>
  * References:
  * <ul>
- *     <li>http://nacl.cr.yp.to/secretbox.html</li>
- *     <li>http://cr.yp.to/highspeed/naclcrypto-20090310.pdf</li>
+ * <li>http://nacl.cr.yp.to/secretbox.html</li>
+ * <li>http://cr.yp.to/highspeed/naclcrypto-20090310.pdf</li>
  * </ul>
  */
-public class XSalsa20Poly1305AuthenticatedCipher
-		implements AuthenticatedCipher {
+@NotThreadSafe
+@NotNullByDefault
+class XSalsa20Poly1305AuthenticatedCipher implements AuthenticatedCipher {
 
-	/** Length of the padding to be used to generate the Poly1305 key */
+	/**
+	 * Length of the padding to be used to generate the Poly1305 key
+	 */
 	private static final int SUBKEY_LENGTH = 32;
 
 	private final XSalsa20Engine xSalsa20Engine;
@@ -78,8 +84,10 @@ public class XSalsa20Poly1305AuthenticatedCipher
 			//
 			// To be NaCl-compatible, we reverse the subkey.
 			System.arraycopy(subKey, 0, zero, 0, SUBKEY_LENGTH / 2);
-			System.arraycopy(subKey, SUBKEY_LENGTH / 2, subKey, 0, SUBKEY_LENGTH / 2);
-			System.arraycopy(zero, 0, subKey, SUBKEY_LENGTH / 2, SUBKEY_LENGTH / 2);
+			System.arraycopy(subKey, SUBKEY_LENGTH / 2, subKey, 0,
+					SUBKEY_LENGTH / 2);
+			System.arraycopy(zero, 0, subKey, SUBKEY_LENGTH / 2,
+					SUBKEY_LENGTH / 2);
 			// Now we can clamp the correct part of the subkey
 			Poly1305KeyGenerator.clamp(subKey);
 
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderFactoryImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..959c5582d93a819d9e5a7ee8c0225b8f0e3ef740
--- /dev/null
+++ b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderFactoryImpl.java
@@ -0,0 +1,26 @@
+package org.briarproject.bramble.data;
+
+import org.briarproject.bramble.api.data.BdfReader;
+import org.briarproject.bramble.api.data.BdfReaderFactory;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import java.io.InputStream;
+
+import javax.annotation.concurrent.Immutable;
+
+import static org.briarproject.bramble.api.data.BdfReader.DEFAULT_NESTED_LIMIT;
+
+@Immutable
+@NotNullByDefault
+class BdfReaderFactoryImpl implements BdfReaderFactory {
+
+	@Override
+	public BdfReader createReader(InputStream in) {
+		return new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT);
+	}
+
+	@Override
+	public BdfReader createReader(InputStream in, int nestedLimit) {
+		return new BdfReaderImpl(in, nestedLimit);
+	}
+}
diff --git a/briar-core/src/org/briarproject/data/BdfReaderImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderImpl.java
similarity index 84%
rename from briar-core/src/org/briarproject/data/BdfReaderImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderImpl.java
index d1fe25794f753267dfa12ae97387a07c72c4896f..96f7adea7e9ed2e2c62e6f7bf85f940a0cd09315 100644
--- a/briar-core/src/org/briarproject/data/BdfReaderImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderImpl.java
@@ -1,35 +1,37 @@
-package org.briarproject.data;
+package org.briarproject.bramble.data;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.BdfReader;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.BdfReader;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.IOException;
 import java.io.InputStream;
 
 import javax.annotation.concurrent.NotThreadSafe;
 
-import static org.briarproject.api.data.BdfDictionary.NULL_VALUE;
-import static org.briarproject.data.Types.DICTIONARY;
-import static org.briarproject.data.Types.END;
-import static org.briarproject.data.Types.FALSE;
-import static org.briarproject.data.Types.FLOAT_64;
-import static org.briarproject.data.Types.INT_16;
-import static org.briarproject.data.Types.INT_32;
-import static org.briarproject.data.Types.INT_64;
-import static org.briarproject.data.Types.INT_8;
-import static org.briarproject.data.Types.LIST;
-import static org.briarproject.data.Types.NULL;
-import static org.briarproject.data.Types.RAW_16;
-import static org.briarproject.data.Types.RAW_32;
-import static org.briarproject.data.Types.RAW_8;
-import static org.briarproject.data.Types.STRING_16;
-import static org.briarproject.data.Types.STRING_32;
-import static org.briarproject.data.Types.STRING_8;
-import static org.briarproject.data.Types.TRUE;
+import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
+import static org.briarproject.bramble.data.Types.DICTIONARY;
+import static org.briarproject.bramble.data.Types.END;
+import static org.briarproject.bramble.data.Types.FALSE;
+import static org.briarproject.bramble.data.Types.FLOAT_64;
+import static org.briarproject.bramble.data.Types.INT_16;
+import static org.briarproject.bramble.data.Types.INT_32;
+import static org.briarproject.bramble.data.Types.INT_64;
+import static org.briarproject.bramble.data.Types.INT_8;
+import static org.briarproject.bramble.data.Types.LIST;
+import static org.briarproject.bramble.data.Types.NULL;
+import static org.briarproject.bramble.data.Types.RAW_16;
+import static org.briarproject.bramble.data.Types.RAW_32;
+import static org.briarproject.bramble.data.Types.RAW_8;
+import static org.briarproject.bramble.data.Types.STRING_16;
+import static org.briarproject.bramble.data.Types.STRING_32;
+import static org.briarproject.bramble.data.Types.STRING_8;
+import static org.briarproject.bramble.data.Types.TRUE;
 
 @NotThreadSafe
+@NotNullByDefault
 class BdfReaderImpl implements BdfReader {
 
 	private static final byte[] EMPTY_BUFFER = new byte[0];
@@ -108,37 +110,44 @@ class BdfReaderImpl implements BdfReader {
 		else throw new FormatException();
 	}
 
+	@Override
 	public boolean eof() throws IOException {
 		if (!hasLookahead) readLookahead();
 		return eof;
 	}
 
+	@Override
 	public void close() throws IOException {
 		in.close();
 	}
 
+	@Override
 	public boolean hasNull() throws IOException {
 		if (!hasLookahead) readLookahead();
 		if (eof) return false;
 		return next == NULL;
 	}
 
+	@Override
 	public void readNull() throws IOException {
 		if (!hasNull()) throw new FormatException();
 		hasLookahead = false;
 	}
 
+	@Override
 	public void skipNull() throws IOException {
 		if (!hasNull()) throw new FormatException();
 		hasLookahead = false;
 	}
 
+	@Override
 	public boolean hasBoolean() throws IOException {
 		if (!hasLookahead) readLookahead();
 		if (eof) return false;
 		return next == FALSE || next == TRUE;
 	}
 
+	@Override
 	public boolean readBoolean() throws IOException {
 		if (!hasBoolean()) throw new FormatException();
 		boolean bool = next == TRUE;
@@ -146,11 +155,13 @@ class BdfReaderImpl implements BdfReader {
 		return bool;
 	}
 
+	@Override
 	public void skipBoolean() throws IOException {
 		if (!hasBoolean()) throw new FormatException();
 		hasLookahead = false;
 	}
 
+	@Override
 	public boolean hasLong() throws IOException {
 		if (!hasLookahead) readLookahead();
 		if (eof) return false;
@@ -158,6 +169,7 @@ class BdfReaderImpl implements BdfReader {
 				next == INT_64;
 	}
 
+	@Override
 	public long readLong() throws IOException {
 		if (!hasLong()) throw new FormatException();
 		hasLookahead = false;
@@ -191,6 +203,7 @@ class BdfReaderImpl implements BdfReader {
 		return value;
 	}
 
+	@Override
 	public void skipLong() throws IOException {
 		if (!hasLong()) throw new FormatException();
 		if (next == INT_8) skip(1);
@@ -200,12 +213,14 @@ class BdfReaderImpl implements BdfReader {
 		hasLookahead = false;
 	}
 
+	@Override
 	public boolean hasDouble() throws IOException {
 		if (!hasLookahead) readLookahead();
 		if (eof) return false;
 		return next == FLOAT_64;
 	}
 
+	@Override
 	public double readDouble() throws IOException {
 		if (!hasDouble()) throw new FormatException();
 		hasLookahead = false;
@@ -215,18 +230,21 @@ class BdfReaderImpl implements BdfReader {
 		return Double.longBitsToDouble(value);
 	}
 
+	@Override
 	public void skipDouble() throws IOException {
 		if (!hasDouble()) throw new FormatException();
 		skip(8);
 		hasLookahead = false;
 	}
 
+	@Override
 	public boolean hasString() throws IOException {
 		if (!hasLookahead) readLookahead();
 		if (eof) return false;
 		return next == STRING_8 || next == STRING_16 || next == STRING_32;
 	}
 
+	@Override
 	public String readString(int maxLength) throws IOException {
 		if (!hasString()) throw new FormatException();
 		hasLookahead = false;
@@ -244,6 +262,7 @@ class BdfReaderImpl implements BdfReader {
 		throw new FormatException();
 	}
 
+	@Override
 	public void skipString() throws IOException {
 		if (!hasString()) throw new FormatException();
 		int length = readStringLength();
@@ -252,12 +271,14 @@ class BdfReaderImpl implements BdfReader {
 		hasLookahead = false;
 	}
 
+	@Override
 	public boolean hasRaw() throws IOException {
 		if (!hasLookahead) readLookahead();
 		if (eof) return false;
 		return next == RAW_8 || next == RAW_16 || next == RAW_32;
 	}
 
+	@Override
 	public byte[] readRaw(int maxLength) throws IOException {
 		if (!hasRaw()) throw new FormatException();
 		hasLookahead = false;
@@ -276,6 +297,7 @@ class BdfReaderImpl implements BdfReader {
 		throw new FormatException();
 	}
 
+	@Override
 	public void skipRaw() throws IOException {
 		if (!hasRaw()) throw new FormatException();
 		int length = readRawLength();
@@ -284,12 +306,14 @@ class BdfReaderImpl implements BdfReader {
 		hasLookahead = false;
 	}
 
+	@Override
 	public boolean hasList() throws IOException {
 		if (!hasLookahead) readLookahead();
 		if (eof) return false;
 		return next == LIST;
 	}
 
+	@Override
 	public BdfList readList() throws IOException {
 		return readList(1);
 	}
@@ -304,11 +328,13 @@ class BdfReaderImpl implements BdfReader {
 		return list;
 	}
 
+	@Override
 	public void readListStart() throws IOException {
 		if (!hasList()) throw new FormatException();
 		hasLookahead = false;
 	}
 
+	@Override
 	public boolean hasListEnd() throws IOException {
 		return hasEnd();
 	}
@@ -319,6 +345,7 @@ class BdfReaderImpl implements BdfReader {
 		return next == END;
 	}
 
+	@Override
 	public void readListEnd() throws IOException {
 		readEnd();
 	}
@@ -328,6 +355,7 @@ class BdfReaderImpl implements BdfReader {
 		hasLookahead = false;
 	}
 
+	@Override
 	public void skipList() throws IOException {
 		if (!hasList()) throw new FormatException();
 		hasLookahead = false;
@@ -335,12 +363,14 @@ class BdfReaderImpl implements BdfReader {
 		hasLookahead = false;
 	}
 
+	@Override
 	public boolean hasDictionary() throws IOException {
 		if (!hasLookahead) readLookahead();
 		if (eof) return false;
 		return next == DICTIONARY;
 	}
 
+	@Override
 	public BdfDictionary readDictionary() throws IOException {
 		return readDictionary(1);
 	}
@@ -356,19 +386,23 @@ class BdfReaderImpl implements BdfReader {
 		return dictionary;
 	}
 
+	@Override
 	public void readDictionaryStart() throws IOException {
 		if (!hasDictionary()) throw new FormatException();
 		hasLookahead = false;
 	}
 
+	@Override
 	public boolean hasDictionaryEnd() throws IOException {
 		return hasEnd();
 	}
 
+	@Override
 	public void readDictionaryEnd() throws IOException {
 		readEnd();
 	}
 
+	@Override
 	public void skipDictionary() throws IOException {
 		if (!hasDictionary()) throw new FormatException();
 		hasLookahead = false;
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterFactoryImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..252ed843c02d5b0cf52a7498327d809cec30a4ff
--- /dev/null
+++ b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterFactoryImpl.java
@@ -0,0 +1,19 @@
+package org.briarproject.bramble.data;
+
+import org.briarproject.bramble.api.data.BdfWriter;
+import org.briarproject.bramble.api.data.BdfWriterFactory;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import java.io.OutputStream;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+class BdfWriterFactoryImpl implements BdfWriterFactory {
+
+	@Override
+	public BdfWriter createWriter(OutputStream out) {
+		return new BdfWriterImpl(out);
+	}
+}
diff --git a/briar-core/src/org/briarproject/data/BdfWriterImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterImpl.java
similarity index 70%
rename from briar-core/src/org/briarproject/data/BdfWriterImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterImpl.java
index 2b497dd02f21c802a9498167631acd4769dee65b..e9979e9ffc08082fc3215b458e4b4d3377d11a2f 100644
--- a/briar-core/src/org/briarproject/data/BdfWriterImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterImpl.java
@@ -1,8 +1,9 @@
-package org.briarproject.data;
+package org.briarproject.bramble.data;
 
-import org.briarproject.api.Bytes;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.data.BdfWriter;
+import org.briarproject.bramble.api.Bytes;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfWriter;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.IOException;
 import java.io.OutputStream;
@@ -11,26 +12,30 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
-import static org.briarproject.api.data.BdfDictionary.NULL_VALUE;
-import static org.briarproject.data.Types.DICTIONARY;
-import static org.briarproject.data.Types.END;
-import static org.briarproject.data.Types.FALSE;
-import static org.briarproject.data.Types.FLOAT_64;
-import static org.briarproject.data.Types.INT_16;
-import static org.briarproject.data.Types.INT_32;
-import static org.briarproject.data.Types.INT_64;
-import static org.briarproject.data.Types.INT_8;
-import static org.briarproject.data.Types.LIST;
-import static org.briarproject.data.Types.NULL;
-import static org.briarproject.data.Types.RAW_16;
-import static org.briarproject.data.Types.RAW_32;
-import static org.briarproject.data.Types.RAW_8;
-import static org.briarproject.data.Types.STRING_16;
-import static org.briarproject.data.Types.STRING_32;
-import static org.briarproject.data.Types.STRING_8;
-import static org.briarproject.data.Types.TRUE;
-
-// This class is not thread-safe
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.NotThreadSafe;
+
+import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
+import static org.briarproject.bramble.data.Types.DICTIONARY;
+import static org.briarproject.bramble.data.Types.END;
+import static org.briarproject.bramble.data.Types.FALSE;
+import static org.briarproject.bramble.data.Types.FLOAT_64;
+import static org.briarproject.bramble.data.Types.INT_16;
+import static org.briarproject.bramble.data.Types.INT_32;
+import static org.briarproject.bramble.data.Types.INT_64;
+import static org.briarproject.bramble.data.Types.INT_8;
+import static org.briarproject.bramble.data.Types.LIST;
+import static org.briarproject.bramble.data.Types.NULL;
+import static org.briarproject.bramble.data.Types.RAW_16;
+import static org.briarproject.bramble.data.Types.RAW_32;
+import static org.briarproject.bramble.data.Types.RAW_8;
+import static org.briarproject.bramble.data.Types.STRING_16;
+import static org.briarproject.bramble.data.Types.STRING_32;
+import static org.briarproject.bramble.data.Types.STRING_8;
+import static org.briarproject.bramble.data.Types.TRUE;
+
+@NotThreadSafe
+@NotNullByDefault
 class BdfWriterImpl implements BdfWriter {
 
 	private final OutputStream out;
@@ -39,23 +44,28 @@ class BdfWriterImpl implements BdfWriter {
 		this.out = out;
 	}
 
+	@Override
 	public void flush() throws IOException {
 		out.flush();
 	}
 
+	@Override
 	public void close() throws IOException {
 		out.close();
 	}
 
+	@Override
 	public void writeNull() throws IOException {
 		out.write(NULL);
 	}
 
+	@Override
 	public void writeBoolean(boolean b) throws IOException {
 		if (b) out.write(TRUE);
 		else out.write(FALSE);
 	}
 
+	@Override
 	public void writeLong(long i) throws IOException {
 		if (i >= Byte.MIN_VALUE && i <= Byte.MAX_VALUE) {
 			out.write(INT_8);
@@ -95,11 +105,13 @@ class BdfWriterImpl implements BdfWriter {
 		out.write((byte) ((i << 56) >> 56));
 	}
 
+	@Override
 	public void writeDouble(double d) throws IOException {
 		out.write(FLOAT_64);
 		writeInt64(Double.doubleToRawLongBits(d));
 	}
 
+	@Override
 	public void writeString(String s) throws IOException {
 		byte[] b = s.getBytes("UTF-8");
 		if (b.length <= Byte.MAX_VALUE) {
@@ -115,6 +127,7 @@ class BdfWriterImpl implements BdfWriter {
 		out.write(b);
 	}
 
+	@Override
 	public void writeRaw(byte[] b) throws IOException {
 		if (b.length <= Byte.MAX_VALUE) {
 			out.write(RAW_8);
@@ -129,13 +142,14 @@ class BdfWriterImpl implements BdfWriter {
 		out.write(b);
 	}
 
+	@Override
 	public void writeList(Collection<?> c) throws IOException {
 		out.write(LIST);
 		for (Object o : c) writeObject(o);
 		out.write(END);
 	}
 
-	private void writeObject(Object o) throws IOException {
+	private void writeObject(@Nullable Object o) throws IOException {
 		if (o == null || o == NULL_VALUE) writeNull();
 		else if (o instanceof Boolean) writeBoolean((Boolean) o);
 		else if (o instanceof Byte) writeLong((Byte) o);
@@ -152,14 +166,17 @@ class BdfWriterImpl implements BdfWriter {
 		else throw new FormatException();
 	}
 
+	@Override
 	public void writeListStart() throws IOException {
 		out.write(LIST);
 	}
 
+	@Override
 	public void writeListEnd() throws IOException {
 		out.write(END);
 	}
 
+	@Override
 	public void writeDictionary(Map<?, ?> m) throws IOException {
 		out.write(DICTIONARY);
 		for (Entry<?, ?> e : m.entrySet()) {
@@ -170,10 +187,12 @@ class BdfWriterImpl implements BdfWriter {
 		out.write(END);
 	}
 
+	@Override
 	public void writeDictionaryStart() throws IOException {
 		out.write(DICTIONARY);
 	}
 
+	@Override
 	public void writeDictionaryEnd() throws IOException {
 		out.write(END);
 	}
diff --git a/briar-core/src/org/briarproject/data/DataModule.java b/bramble-core/src/main/java/org/briarproject/bramble/data/DataModule.java
similarity index 67%
rename from briar-core/src/org/briarproject/data/DataModule.java
rename to bramble-core/src/main/java/org/briarproject/bramble/data/DataModule.java
index b83293104ff086fe21f5267e99bab9ba0fd16742..7ddf2be0faa608d9dbfe2df96b6d36b1e33cc6a2 100644
--- a/briar-core/src/org/briarproject/data/DataModule.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/data/DataModule.java
@@ -1,10 +1,9 @@
-package org.briarproject.data;
+package org.briarproject.bramble.data;
 
-
-import org.briarproject.api.data.BdfReaderFactory;
-import org.briarproject.api.data.BdfWriterFactory;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.data.MetadataParser;
+import org.briarproject.bramble.api.data.BdfReaderFactory;
+import org.briarproject.bramble.api.data.BdfWriterFactory;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.data.MetadataParser;
 
 import dagger.Module;
 import dagger.Provides;
diff --git a/briar-core/src/org/briarproject/data/MetadataEncoderImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/data/MetadataEncoderImpl.java
similarity index 73%
rename from briar-core/src/org/briarproject/data/MetadataEncoderImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/data/MetadataEncoderImpl.java
index d6cc64b145a970b68770d86c6ad74b0a63f4de8d..7605b1da74d649a382f573663bf6c93fa2cff92d 100644
--- a/briar-core/src/org/briarproject/data/MetadataEncoderImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/data/MetadataEncoderImpl.java
@@ -1,12 +1,13 @@
-package org.briarproject.data;
+package org.briarproject.bramble.data;
 
-import org.briarproject.api.Bytes;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfWriter;
-import org.briarproject.api.data.BdfWriterFactory;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.db.Metadata;
+import org.briarproject.bramble.api.Bytes;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfWriter;
+import org.briarproject.bramble.api.data.BdfWriterFactory;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -14,11 +15,14 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-import static org.briarproject.api.data.BdfDictionary.NULL_VALUE;
-import static org.briarproject.api.db.Metadata.REMOVE;
+import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
+import static org.briarproject.bramble.api.db.Metadata.REMOVE;
 
+@Immutable
+@NotNullByDefault
 class MetadataEncoderImpl implements MetadataEncoder {
 
 	private final BdfWriterFactory bdfWriterFactory;
diff --git a/briar-core/src/org/briarproject/data/MetadataParserImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/data/MetadataParserImpl.java
similarity index 72%
rename from briar-core/src/org/briarproject/data/MetadataParserImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/data/MetadataParserImpl.java
index f387b2d0c5b244299653354d5b1e2644069cd9dd..6dd44196c1e6e290487fd2f6313e7ff251249693 100644
--- a/briar-core/src/org/briarproject/data/MetadataParserImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/data/MetadataParserImpl.java
@@ -1,21 +1,25 @@
-package org.briarproject.data;
+package org.briarproject.bramble.data;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfReader;
-import org.briarproject.api.data.BdfReaderFactory;
-import org.briarproject.api.data.MetadataParser;
-import org.briarproject.api.db.Metadata;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfReader;
+import org.briarproject.bramble.api.data.BdfReaderFactory;
+import org.briarproject.bramble.api.data.MetadataParser;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.util.Map.Entry;
 
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-import static org.briarproject.api.data.BdfDictionary.NULL_VALUE;
-import static org.briarproject.api.db.Metadata.REMOVE;
+import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
+import static org.briarproject.bramble.api.db.Metadata.REMOVE;
 
+@Immutable
+@NotNullByDefault
 class MetadataParserImpl implements MetadataParser {
 
 	private final BdfReaderFactory bdfReaderFactory;
diff --git a/briar-core/src/org/briarproject/data/Types.java b/bramble-core/src/main/java/org/briarproject/bramble/data/Types.java
similarity index 90%
rename from briar-core/src/org/briarproject/data/Types.java
rename to bramble-core/src/main/java/org/briarproject/bramble/data/Types.java
index 6cc701d28fc13ca78bd99041b127fa5e6bdb957a..e897cc6c367bfd6c82c2033acd4f882957352540 100644
--- a/briar-core/src/org/briarproject/data/Types.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/data/Types.java
@@ -1,4 +1,4 @@
-package org.briarproject.data;
+package org.briarproject.bramble.data;
 
 interface Types {
 
diff --git a/briar-core/src/org/briarproject/db/Database.java b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java
similarity index 93%
rename from briar-core/src/org/briarproject/db/Database.java
rename to bramble-core/src/main/java/org/briarproject/bramble/db/Database.java
index 0d2327200d39888bfe6dbbaf1bbb4755c2ce6022..93e7bf8c685f5bea0fc4fb4127064161c80ee05b 100644
--- a/briar-core/src/org/briarproject/db/Database.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java
@@ -1,28 +1,30 @@
-package org.briarproject.db;
-
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.settings.Settings;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.Group.Visibility;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.sync.MessageStatus;
-import org.briarproject.api.sync.ValidationManager.State;
-import org.briarproject.api.transport.TransportKeys;
-import org.jetbrains.annotations.Nullable;
+package org.briarproject.bramble.db;
+
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.settings.Settings;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.Group.Visibility;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.MessageStatus;
+import org.briarproject.bramble.api.sync.ValidationManager.State;
+import org.briarproject.bramble.api.transport.TransportKeys;
 
 import java.util.Collection;
 import java.util.Map;
 
+import javax.annotation.Nullable;
+
 /**
  * A low-level interface to the database (DatabaseComponent provides a
  * high-level interface). Most operations take a transaction argument, which is
@@ -30,6 +32,7 @@ import java.util.Map;
  * terminated by calling either {@link #abortTransaction(T)} or
  * {@link #commitTransaction(T)}, even if an exception is thrown.
  */
+@NotNullByDefault
 interface Database<T> {
 
 	/**
@@ -288,10 +291,8 @@ interface Database<T> {
 
 	/**
 	 * Returns the IDs and states of all dependencies of the given message.
-	 * Missing dependencies have the state {@link
-	 * org.briarproject.api.sync.ValidationManager.State UNKNOWN}.
-	 * Dependencies in other groups have the state {@link
-	 * org.briarproject.api.sync.ValidationManager.State INVALID}.
+	 * Missing dependencies have the state {@link State UNKNOWN}.
+	 * Dependencies in other groups have the state {@link State INVALID}.
 	 * Note that these states are not set on the dependencies themselves; the
 	 * returned states should only be taken in the context of the given message.
 	 * <p/>
diff --git a/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java
similarity index 87%
rename from briar-core/src/org/briarproject/db/DatabaseComponentImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java
index e09ed8f2c4064481cd37daf7b25d62b03458cb19..8d9be17094b817983cb910967e0593574c876865 100644
--- a/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java
@@ -1,56 +1,56 @@
-package org.briarproject.db;
-
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.ContactExistsException;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.db.NoSuchContactException;
-import org.briarproject.api.db.NoSuchGroupException;
-import org.briarproject.api.db.NoSuchLocalAuthorException;
-import org.briarproject.api.db.NoSuchMessageException;
-import org.briarproject.api.db.NoSuchTransportException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.ContactAddedEvent;
-import org.briarproject.api.event.ContactRemovedEvent;
-import org.briarproject.api.event.ContactStatusChangedEvent;
-import org.briarproject.api.event.ContactVerifiedEvent;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.GroupAddedEvent;
-import org.briarproject.api.event.GroupRemovedEvent;
-import org.briarproject.api.event.GroupVisibilityUpdatedEvent;
-import org.briarproject.api.event.LocalAuthorAddedEvent;
-import org.briarproject.api.event.LocalAuthorRemovedEvent;
-import org.briarproject.api.event.MessageAddedEvent;
-import org.briarproject.api.event.MessageRequestedEvent;
-import org.briarproject.api.event.MessageSharedEvent;
-import org.briarproject.api.event.MessageStateChangedEvent;
-import org.briarproject.api.event.MessageToAckEvent;
-import org.briarproject.api.event.MessageToRequestEvent;
-import org.briarproject.api.event.MessagesAckedEvent;
-import org.briarproject.api.event.MessagesSentEvent;
-import org.briarproject.api.event.SettingsUpdatedEvent;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.lifecycle.ShutdownManager;
-import org.briarproject.api.settings.Settings;
-import org.briarproject.api.sync.Ack;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.Group.Visibility;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.sync.MessageStatus;
-import org.briarproject.api.sync.Offer;
-import org.briarproject.api.sync.Request;
-import org.briarproject.api.sync.ValidationManager.State;
-import org.briarproject.api.transport.TransportKeys;
-import org.jetbrains.annotations.Nullable;
+package org.briarproject.bramble.db;
+
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.event.ContactAddedEvent;
+import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
+import org.briarproject.bramble.api.contact.event.ContactStatusChangedEvent;
+import org.briarproject.bramble.api.contact.event.ContactVerifiedEvent;
+import org.briarproject.bramble.api.db.ContactExistsException;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.db.NoSuchContactException;
+import org.briarproject.bramble.api.db.NoSuchGroupException;
+import org.briarproject.bramble.api.db.NoSuchLocalAuthorException;
+import org.briarproject.bramble.api.db.NoSuchMessageException;
+import org.briarproject.bramble.api.db.NoSuchTransportException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.identity.event.LocalAuthorAddedEvent;
+import org.briarproject.bramble.api.identity.event.LocalAuthorRemovedEvent;
+import org.briarproject.bramble.api.lifecycle.ShutdownManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.settings.Settings;
+import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
+import org.briarproject.bramble.api.sync.Ack;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.Group.Visibility;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.MessageStatus;
+import org.briarproject.bramble.api.sync.Offer;
+import org.briarproject.bramble.api.sync.Request;
+import org.briarproject.bramble.api.sync.ValidationManager.State;
+import org.briarproject.bramble.api.sync.event.GroupAddedEvent;
+import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
+import org.briarproject.bramble.api.sync.event.GroupVisibilityUpdatedEvent;
+import org.briarproject.bramble.api.sync.event.MessageAddedEvent;
+import org.briarproject.bramble.api.sync.event.MessageRequestedEvent;
+import org.briarproject.bramble.api.sync.event.MessageSharedEvent;
+import org.briarproject.bramble.api.sync.event.MessageStateChangedEvent;
+import org.briarproject.bramble.api.sync.event.MessageToAckEvent;
+import org.briarproject.bramble.api.sync.event.MessageToRequestEvent;
+import org.briarproject.bramble.api.sync.event.MessagesAckedEvent;
+import org.briarproject.bramble.api.sync.event.MessagesSentEvent;
+import org.briarproject.bramble.api.transport.TransportKeys;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -63,15 +63,19 @@ import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
 import javax.inject.Inject;
 
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.sync.Group.Visibility.INVISIBLE;
-import static org.briarproject.api.sync.Group.Visibility.SHARED;
-import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
-import static org.briarproject.api.sync.ValidationManager.State.UNKNOWN;
-import static org.briarproject.db.DatabaseConstants.MAX_OFFERED_MESSAGES;
-
+import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
+import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
+import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
+import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
+import static org.briarproject.bramble.db.DatabaseConstants.MAX_OFFERED_MESSAGES;
+
+@ThreadSafe
+@NotNullByDefault
 class DatabaseComponentImpl<T> implements DatabaseComponent {
 
 	private static final Logger LOG =
@@ -228,7 +232,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 		db.addMessage(txn, m, state, shared);
 		for (ContactId c : db.getGroupVisibility(txn, m.getGroupId())) {
 			boolean offered = db.removeOfferedMessage(txn, c, m.getId());
-			boolean seen = offered || c.equals(sender);
+			boolean seen = offered || (sender != null && c.equals(sender));
 			db.addStatus(txn, c, m.getId(), seen, seen);
 		}
 	}
diff --git a/briar-core/src/org/briarproject/db/DatabaseConstants.java b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseConstants.java
similarity index 54%
rename from briar-core/src/org/briarproject/db/DatabaseConstants.java
rename to bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseConstants.java
index 68e3ca1ef393c7c203e040ec7fc1d14d31ed52ca..080a8ce8e28e0a9c8f4d232ed2da3b89c89004d1 100644
--- a/briar-core/src/org/briarproject/db/DatabaseConstants.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseConstants.java
@@ -1,6 +1,6 @@
-package org.briarproject.db;
+package org.briarproject.bramble.db;
 
-import org.briarproject.api.settings.Settings;
+import org.briarproject.bramble.api.settings.Settings;
 
 interface DatabaseConstants {
 
@@ -12,20 +12,20 @@ interface DatabaseConstants {
 	int MAX_OFFERED_MESSAGES = 1000;
 
 	/**
-	 * The namespace of the {@link Settings Settings}
-	 * where the database schema version is stored.
+	 * The namespace of the {@link Settings} where the database schema version
+	 * is stored.
 	 */
 	String DB_SETTINGS_NAMESPACE = "db";
 
 	/**
-	 * The {@link Settings Settings} key under which the
-	 * database schema version is stored.
+	 * The {@link Settings} key under which the database schema version is
+	 * stored.
 	 */
 	String SCHEMA_VERSION_KEY = "schemaVersion";
 
 	/**
-	 * The {@link Settings Settings} key under which the
-	 * minimum supported database schema version is stored.
+	 * The {@link Settings} key under which the minimum supported database
+	 * schema version is stored.
 	 */
 	String MIN_SCHEMA_VERSION_KEY = "minSchemaVersion";
 
diff --git a/briar-core/src/org/briarproject/db/DatabaseExecutorModule.java b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseExecutorModule.java
similarity index 90%
rename from briar-core/src/org/briarproject/db/DatabaseExecutorModule.java
rename to bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseExecutorModule.java
index d0a3bae872f5c76e2627433fa974b546bf817e48..7865faf3645fe00b34024f45e0c0c7134107ecc8 100644
--- a/briar-core/src/org/briarproject/db/DatabaseExecutorModule.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseExecutorModule.java
@@ -1,7 +1,7 @@
-package org.briarproject.db;
+package org.briarproject.bramble.db;
 
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
 
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.Executor;
diff --git a/briar-core/src/org/briarproject/db/DatabaseModule.java b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseModule.java
similarity index 62%
rename from briar-core/src/org/briarproject/db/DatabaseModule.java
rename to bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseModule.java
index 39b1e49dbe9e5f3d0790cb737de857c0983bff0c..a6f3a117487b9ea42c43913b27e8861c46664015 100644
--- a/briar-core/src/org/briarproject/db/DatabaseModule.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseModule.java
@@ -1,10 +1,10 @@
-package org.briarproject.db;
+package org.briarproject.bramble.db;
 
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DatabaseConfig;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.lifecycle.ShutdownManager;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DatabaseConfig;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.lifecycle.ShutdownManager;
+import org.briarproject.bramble.api.system.Clock;
 
 import java.sql.Connection;
 
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/DbStateException.java b/bramble-core/src/main/java/org/briarproject/bramble/db/DbStateException.java
new file mode 100644
index 0000000000000000000000000000000000000000..83ed9a93ff5a3b002f83d48d4bf3c9d7ca61498d
--- /dev/null
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/DbStateException.java
@@ -0,0 +1,9 @@
+package org.briarproject.bramble.db;
+
+import java.sql.SQLException;
+
+/**
+ * Thrown when the database is in an illegal state.
+ */
+class DbStateException extends SQLException {
+}
diff --git a/briar-core/src/org/briarproject/db/ExponentialBackoff.java b/bramble-core/src/main/java/org/briarproject/bramble/db/ExponentialBackoff.java
similarity index 96%
rename from briar-core/src/org/briarproject/db/ExponentialBackoff.java
rename to bramble-core/src/main/java/org/briarproject/bramble/db/ExponentialBackoff.java
index bbb5bc112c5dc06c76b0e73d26e252deabd35ef7..0e2f89bcfa857148d1baa1be9cdedfcf5664e832 100644
--- a/briar-core/src/org/briarproject/db/ExponentialBackoff.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/ExponentialBackoff.java
@@ -1,4 +1,4 @@
-package org.briarproject.db;
+package org.briarproject.bramble.db;
 
 class ExponentialBackoff {
 
diff --git a/briar-core/src/org/briarproject/db/H2Database.java b/bramble-core/src/main/java/org/briarproject/bramble/db/H2Database.java
similarity index 79%
rename from briar-core/src/org/briarproject/db/H2Database.java
rename to bramble-core/src/main/java/org/briarproject/bramble/db/H2Database.java
index 27099f15ba048d6a993cdca4478ebf06bbddc5e2..32596eede3aa70fae92e160b0d4729d5b3029700 100644
--- a/briar-core/src/org/briarproject/db/H2Database.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/H2Database.java
@@ -1,9 +1,11 @@
-package org.briarproject.db;
+package org.briarproject.bramble.db;
 
-import org.briarproject.api.db.DatabaseConfig;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.system.Clock;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.db.DatabaseConfig;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.bramble.util.StringUtils;
 
 import java.io.File;
 import java.sql.Connection;
@@ -13,7 +15,10 @@ import java.util.Properties;
 
 import javax.inject.Inject;
 
-/** Contains all the H2-specific code for the database. */
+/**
+ * Contains all the H2-specific code for the database.
+ */
+@NotNullByDefault
 class H2Database extends JdbcDatabase {
 
 	private static final String HASH_TYPE = "BINARY(32)";
@@ -78,12 +83,13 @@ class H2Database extends JdbcDatabase {
 
 	@Override
 	protected Connection createConnection() throws SQLException {
-		byte[] key = config.getEncryptionKey().getBytes();
+		SecretKey key = config.getEncryptionKey();
 		if (key == null) throw new IllegalStateException();
 		Properties props = new Properties();
 		props.setProperty("user", "user");
 		// Separate the file password from the user password with a space
-		props.put("password", StringUtils.toHexString(key) + " password");
+		String hex = StringUtils.toHexString(key.getBytes());
+		props.put("password", hex + " password");
 		return DriverManager.getConnection(url, props);
 	}
 }
diff --git a/briar-core/src/org/briarproject/db/JdbcDatabase.java b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java
similarity index 96%
rename from briar-core/src/org/briarproject/db/JdbcDatabase.java
rename to bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java
index 4131ec9f4e8564e5fd6d2bc7a27cbebbbea1b596..54238266b28389ad1146758590d6c441607c4046 100644
--- a/briar-core/src/org/briarproject/db/JdbcDatabase.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java
@@ -1,29 +1,29 @@
-package org.briarproject.db;
-
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.db.DbClosedException;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.settings.Settings;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.Group.Visibility;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.sync.MessageStatus;
-import org.briarproject.api.sync.ValidationManager.State;
-import org.briarproject.api.system.Clock;
-import org.briarproject.api.transport.IncomingKeys;
-import org.briarproject.api.transport.OutgoingKeys;
-import org.briarproject.api.transport.TransportKeys;
-import org.jetbrains.annotations.Nullable;
+package org.briarproject.bramble.db;
+
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.db.DbClosedException;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.settings.Settings;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.Group.Visibility;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.MessageStatus;
+import org.briarproject.bramble.api.sync.ValidationManager.State;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.bramble.api.transport.IncomingKeys;
+import org.briarproject.bramble.api.transport.OutgoingKeys;
+import org.briarproject.bramble.api.transport.TransportKeys;
 
 import java.sql.Connection;
 import java.sql.PreparedStatement;
@@ -45,24 +45,27 @@ import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
+
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.db.Metadata.REMOVE;
-import static org.briarproject.api.sync.Group.Visibility.INVISIBLE;
-import static org.briarproject.api.sync.Group.Visibility.SHARED;
-import static org.briarproject.api.sync.Group.Visibility.VISIBLE;
-import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
-import static org.briarproject.api.sync.ValidationManager.State.INVALID;
-import static org.briarproject.api.sync.ValidationManager.State.PENDING;
-import static org.briarproject.api.sync.ValidationManager.State.UNKNOWN;
-import static org.briarproject.db.DatabaseConstants.DB_SETTINGS_NAMESPACE;
-import static org.briarproject.db.DatabaseConstants.MIN_SCHEMA_VERSION_KEY;
-import static org.briarproject.db.DatabaseConstants.SCHEMA_VERSION_KEY;
-import static org.briarproject.db.ExponentialBackoff.calculateExpiry;
+import static org.briarproject.bramble.api.db.Metadata.REMOVE;
+import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
+import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
+import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE;
+import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
+import static org.briarproject.bramble.api.sync.ValidationManager.State.INVALID;
+import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
+import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
+import static org.briarproject.bramble.db.DatabaseConstants.DB_SETTINGS_NAMESPACE;
+import static org.briarproject.bramble.db.DatabaseConstants.MIN_SCHEMA_VERSION_KEY;
+import static org.briarproject.bramble.db.DatabaseConstants.SCHEMA_VERSION_KEY;
+import static org.briarproject.bramble.db.ExponentialBackoff.calculateExpiry;
 
 /**
  * A generic database implementation that can be used with any JDBC-compatible
  * database library.
  */
+@NotNullByDefault
 abstract class JdbcDatabase implements Database<Connection> {
 
 	private static final int SCHEMA_VERSION = 29;
@@ -242,6 +245,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 	private int openConnections = 0; // Locking: connectionsLock
 	private boolean closed = false; // Locking: connectionsLock
 
+	@Nullable
 	protected abstract Connection createConnection() throws SQLException;
 
 	private final Lock connectionsLock = new ReentrantLock();
@@ -295,7 +299,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 		mergeSettings(txn, s, DB_SETTINGS_NAMESPACE);
 	}
 
-	private void tryToClose(ResultSet rs) {
+	private void tryToClose(@Nullable ResultSet rs) {
 		try {
 			if (rs != null) rs.close();
 		} catch (SQLException e) {
@@ -303,7 +307,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 		}
 	}
 
-	private void tryToClose(Statement s) {
+	private void tryToClose(@Nullable Statement s) {
 		try {
 			if (s != null) s.close();
 		} catch (SQLException e) {
@@ -1336,7 +1340,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 			MessageId lastMessageId = null;
 			while (rs.next()) {
 				MessageId messageId = new MessageId(rs.getBytes(1));
-				if (!messageId.equals(lastMessageId)) {
+				if (lastMessageId == null || !messageId.equals(lastMessageId)) {
 					metadata = new Metadata();
 					all.put(messageId, metadata);
 					lastMessageId = messageId;
diff --git a/briar-core/src/org/briarproject/event/EventBusImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/event/EventBusImpl.java
similarity index 55%
rename from briar-core/src/org/briarproject/event/EventBusImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/event/EventBusImpl.java
index ca007e10adb8b59045c7a6146687658c181ac21e..f2b346847510c62b510397068319c33a8947364b 100644
--- a/briar-core/src/org/briarproject/event/EventBusImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/event/EventBusImpl.java
@@ -1,25 +1,33 @@
-package org.briarproject.event;
+package org.briarproject.bramble.event;
+
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.util.Collection;
 import java.util.concurrent.CopyOnWriteArrayList;
 
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
+import javax.annotation.concurrent.ThreadSafe;
 
+@ThreadSafe
+@NotNullByDefault
 class EventBusImpl implements EventBus {
 
 	private final Collection<EventListener> listeners =
 			new CopyOnWriteArrayList<EventListener>();
 
+	@Override
 	public void addListener(EventListener l) {
 		listeners.add(l);
 	}
 
+	@Override
 	public void removeListener(EventListener l) {
 		listeners.remove(l);
 	}
 
+	@Override
 	public void broadcast(Event e) {
 		for (EventListener l : listeners) l.eventOccurred(e);
 	}
diff --git a/briar-core/src/org/briarproject/event/EventModule.java b/bramble-core/src/main/java/org/briarproject/bramble/event/EventModule.java
similarity index 68%
rename from briar-core/src/org/briarproject/event/EventModule.java
rename to bramble-core/src/main/java/org/briarproject/bramble/event/EventModule.java
index e7f92f0379d500ae2d9c06da40d1748a28dcb144..3cd8bcdefbbf0a5a2f6f97aa76d8452e4e4d4ce5 100644
--- a/briar-core/src/org/briarproject/event/EventModule.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/event/EventModule.java
@@ -1,6 +1,6 @@
-package org.briarproject.event;
+package org.briarproject.bramble.event;
 
-import org.briarproject.api.event.EventBus;
+import org.briarproject.bramble.api.event.EventBus;
 
 import javax.inject.Singleton;
 
diff --git a/briar-core/src/org/briarproject/identity/AuthorFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/identity/AuthorFactoryImpl.java
similarity index 65%
rename from briar-core/src/org/briarproject/identity/AuthorFactoryImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/identity/AuthorFactoryImpl.java
index b745f5e003b5f388d8c6de4a12fb04e705579bac..5d4dc0de67808692234067b739459cfa4aae22c7 100644
--- a/briar-core/src/org/briarproject/identity/AuthorFactoryImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/identity/AuthorFactoryImpl.java
@@ -1,19 +1,23 @@
-package org.briarproject.identity;
-
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.data.BdfWriter;
-import org.briarproject.api.data.BdfWriterFactory;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.system.Clock;
+package org.briarproject.bramble.identity;
+
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.data.BdfWriter;
+import org.briarproject.bramble.api.data.BdfWriterFactory;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.system.Clock;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
+@Immutable
+@NotNullByDefault
 class AuthorFactoryImpl implements AuthorFactory {
 
 	private final CryptoComponent crypto;
@@ -28,10 +32,12 @@ class AuthorFactoryImpl implements AuthorFactory {
 		this.clock = clock;
 	}
 
+	@Override
 	public Author createAuthor(String name, byte[] publicKey) {
 		return new Author(getId(name, publicKey), name, publicKey);
 	}
 
+	@Override
 	public LocalAuthor createLocalAuthor(String name, byte[] publicKey,
 			byte[] privateKey) {
 		return new LocalAuthor(getId(name, publicKey), name, publicKey,
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/identity/AuthorReader.java b/bramble-core/src/main/java/org/briarproject/bramble/identity/AuthorReader.java
new file mode 100644
index 0000000000000000000000000000000000000000..fbef7593890ef4d4049fc0c97257ae88b81e4973
--- /dev/null
+++ b/bramble-core/src/main/java/org/briarproject/bramble/identity/AuthorReader.java
@@ -0,0 +1,36 @@
+package org.briarproject.bramble.identity;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfReader;
+import org.briarproject.bramble.api.data.ObjectReader;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import java.io.IOException;
+
+import javax.annotation.concurrent.Immutable;
+
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+
+@Immutable
+@NotNullByDefault
+class AuthorReader implements ObjectReader<Author> {
+
+	private final AuthorFactory authorFactory;
+
+	AuthorReader(AuthorFactory authorFactory) {
+		this.authorFactory = authorFactory;
+	}
+
+	@Override
+	public Author readObject(BdfReader r) throws IOException {
+		r.readListStart();
+		String name = r.readString(MAX_AUTHOR_NAME_LENGTH);
+		if (name.length() == 0) throw new FormatException();
+		byte[] publicKey = r.readRaw(MAX_PUBLIC_KEY_LENGTH);
+		r.readListEnd();
+		return authorFactory.createAuthor(name, publicKey);
+	}
+}
diff --git a/briar-core/src/org/briarproject/identity/IdentityManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/identity/IdentityManagerImpl.java
similarity index 59%
rename from briar-core/src/org/briarproject/identity/IdentityManagerImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/identity/IdentityManagerImpl.java
index e01e13c4d2f3c6cab48720df65ecc9010a8415cc..11e8220c9c5a72206604e24968eaeeaa388807af 100644
--- a/briar-core/src/org/briarproject/identity/IdentityManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/identity/IdentityManagerImpl.java
@@ -1,31 +1,38 @@
-package org.briarproject.identity;
-
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.identity.Author.Status;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
+package org.briarproject.bramble.identity;
+
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.util.Collection;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
 import javax.inject.Inject;
 
-import static org.briarproject.api.identity.Author.Status.OURSELVES;
-import static org.briarproject.api.identity.Author.Status.UNKNOWN;
-import static org.briarproject.api.identity.Author.Status.UNVERIFIED;
-import static org.briarproject.api.identity.Author.Status.VERIFIED;
+import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
+import static org.briarproject.bramble.api.identity.Author.Status.UNKNOWN;
+import static org.briarproject.bramble.api.identity.Author.Status.UNVERIFIED;
+import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED;
 
+@ThreadSafe
+@NotNullByDefault
 class IdentityManagerImpl implements IdentityManager {
-	private final DatabaseComponent db;
 
 	private static final Logger LOG =
 			Logger.getLogger(IdentityManagerImpl.class.getName());
 
+	private final DatabaseComponent db;
+
 	// The local author is immutable so we can cache it
+	@Nullable
 	private volatile LocalAuthor cachedAuthor;
 
 	@Inject
@@ -34,7 +41,8 @@ class IdentityManagerImpl implements IdentityManager {
 	}
 
 	@Override
-	public void registerLocalAuthor(LocalAuthor localAuthor) throws DbException {
+	public void registerLocalAuthor(LocalAuthor localAuthor)
+			throws DbException {
 		Transaction txn = db.startTransaction(false);
 		try {
 			db.addLocalAuthor(txn, localAuthor);
@@ -58,7 +66,9 @@ class IdentityManagerImpl implements IdentityManager {
 				db.endTransaction(txn);
 			}
 		}
-		return cachedAuthor;
+		LocalAuthor cached = cachedAuthor;
+		if (cached == null) throw new AssertionError();
+		return cached;
 	}
 
 
@@ -68,10 +78,12 @@ class IdentityManagerImpl implements IdentityManager {
 			cachedAuthor = loadLocalAuthor(txn);
 			LOG.info("Local author loaded");
 		}
-		return cachedAuthor;
+		LocalAuthor cached = cachedAuthor;
+		if (cached == null) throw new AssertionError();
+		return cached;
 	}
 
-	private LocalAuthor loadLocalAuthor(Transaction txn) throws  DbException{
+	private LocalAuthor loadLocalAuthor(Transaction txn) throws DbException {
 		return db.getLocalAuthors(txn).iterator().next();
 	}
 
diff --git a/briar-core/src/org/briarproject/identity/IdentityModule.java b/bramble-core/src/main/java/org/briarproject/bramble/identity/IdentityModule.java
similarity index 57%
rename from briar-core/src/org/briarproject/identity/IdentityModule.java
rename to bramble-core/src/main/java/org/briarproject/bramble/identity/IdentityModule.java
index 3caa856fccfd644e1fbfde52169b38c089ef3cc1..3fe6b9ab26259f44cf3f4f634ce5ad3405065c5b 100644
--- a/briar-core/src/org/briarproject/identity/IdentityModule.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/identity/IdentityModule.java
@@ -1,13 +1,13 @@
-package org.briarproject.identity;
-
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.data.BdfWriterFactory;
-import org.briarproject.api.data.ObjectReader;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.system.Clock;
+package org.briarproject.bramble.identity;
+
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.data.BdfWriterFactory;
+import org.briarproject.bramble.api.data.ObjectReader;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.system.Clock;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
diff --git a/briar-core/src/org/briarproject/invitation/AliceConnector.java b/bramble-core/src/main/java/org/briarproject/bramble/invitation/AliceConnector.java
similarity index 79%
rename from briar-core/src/org/briarproject/invitation/AliceConnector.java
rename to bramble-core/src/main/java/org/briarproject/bramble/invitation/AliceConnector.java
index 73e49a132e70c9a779bb84a308489e85efac96d8..871db9b4ce9748fb8e6a1705c5cf2a34193d6327 100644
--- a/briar-core/src/org/briarproject/invitation/AliceConnector.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/invitation/AliceConnector.java
@@ -1,16 +1,17 @@
-package org.briarproject.invitation;
+package org.briarproject.bramble.invitation;
 
-import org.briarproject.api.contact.ContactExchangeTask;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.PseudoRandom;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.data.BdfReader;
-import org.briarproject.api.data.BdfReaderFactory;
-import org.briarproject.api.data.BdfWriter;
-import org.briarproject.api.data.BdfWriterFactory;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
-import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
+import org.briarproject.bramble.api.contact.ContactExchangeTask;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.PseudoRandom;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.data.BdfReader;
+import org.briarproject.bramble.api.data.BdfReaderFactory;
+import org.briarproject.bramble.api.data.BdfWriter;
+import org.briarproject.bramble.api.data.BdfWriterFactory;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -24,6 +25,7 @@ import static java.util.logging.Level.WARNING;
 /**
  * A connection thread for the peer being Alice in the invitation protocol.
  */
+@NotNullByDefault
 class AliceConnector extends Connector {
 
 	private static final Logger LOG =
@@ -111,8 +113,7 @@ class AliceConnector extends Connector {
 		// Confirmation succeeded - upgrade to a secure connection
 		if (LOG.isLoggable(INFO))
 			LOG.info(pluginName + " confirmation succeeded");
-		contactExchangeTask
-				.startExchange(group, localAuthor, master, conn, plugin.getId(),
-						true);
+		contactExchangeTask.startExchange(group, localAuthor, master, conn,
+				plugin.getId(), true);
 	}
 }
diff --git a/briar-core/src/org/briarproject/invitation/BobConnector.java b/bramble-core/src/main/java/org/briarproject/bramble/invitation/BobConnector.java
similarity index 79%
rename from briar-core/src/org/briarproject/invitation/BobConnector.java
rename to bramble-core/src/main/java/org/briarproject/bramble/invitation/BobConnector.java
index 80cca62503af1d3174fe77d846a6771b2f690967..d87a9334a01483bdd2916c81ff42e52c790aa6f0 100644
--- a/briar-core/src/org/briarproject/invitation/BobConnector.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/invitation/BobConnector.java
@@ -1,17 +1,17 @@
-package org.briarproject.invitation;
+package org.briarproject.bramble.invitation;
 
-import org.briarproject.api.contact.ContactExchangeTask;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.PseudoRandom;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.data.BdfReader;
-import org.briarproject.api.data.BdfReaderFactory;
-import org.briarproject.api.data.BdfWriter;
-import org.briarproject.api.data.BdfWriterFactory;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
-import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.contact.ContactExchangeTask;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.PseudoRandom;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.data.BdfReader;
+import org.briarproject.bramble.api.data.BdfReaderFactory;
+import org.briarproject.bramble.api.data.BdfWriter;
+import org.briarproject.bramble.api.data.BdfWriterFactory;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -25,6 +25,7 @@ import static java.util.logging.Level.WARNING;
 /**
  * A connection thread for the peer being Bob in the invitation protocol.
  */
+@NotNullByDefault
 class BobConnector extends Connector {
 
 	private static final Logger LOG =
@@ -112,8 +113,7 @@ class BobConnector extends Connector {
 		// Confirmation succeeded - upgrade to a secure connection
 		if (LOG.isLoggable(INFO))
 			LOG.info(pluginName + " confirmation succeeded");
-		contactExchangeTask
-				.startExchange(group, localAuthor, master, conn, plugin.getId(),
-						false);
+		contactExchangeTask.startExchange(group, localAuthor, master, conn,
+				plugin.getId(), false);
 	}
 }
diff --git a/briar-core/src/org/briarproject/invitation/Connector.java b/bramble-core/src/main/java/org/briarproject/bramble/invitation/Connector.java
similarity index 66%
rename from briar-core/src/org/briarproject/invitation/Connector.java
rename to bramble-core/src/main/java/org/briarproject/bramble/invitation/Connector.java
index 6afcedf067407814041f6b36a774a3fb5a9f8619..0fb91aa8a4be140a266cf2bf4fab6b7fc5848525 100644
--- a/briar-core/src/org/briarproject/invitation/Connector.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/invitation/Connector.java
@@ -1,32 +1,36 @@
-package org.briarproject.invitation;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.contact.ContactExchangeTask;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.KeyPair;
-import org.briarproject.api.crypto.KeyParser;
-import org.briarproject.api.crypto.MessageDigest;
-import org.briarproject.api.crypto.PseudoRandom;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.data.BdfReader;
-import org.briarproject.api.data.BdfReaderFactory;
-import org.briarproject.api.data.BdfWriter;
-import org.briarproject.api.data.BdfWriterFactory;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
-import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
+package org.briarproject.bramble.invitation;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.contact.ContactExchangeTask;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.KeyPair;
+import org.briarproject.bramble.api.crypto.KeyParser;
+import org.briarproject.bramble.api.crypto.MessageDigest;
+import org.briarproject.bramble.api.crypto.PseudoRandom;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.data.BdfReader;
+import org.briarproject.bramble.api.data.BdfReaderFactory;
+import org.briarproject.bramble.api.data.BdfWriter;
+import org.briarproject.bramble.api.data.BdfWriterFactory;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
 
 import java.io.IOException;
 import java.security.GeneralSecurityException;
 import java.util.Arrays;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
+
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
-import static org.briarproject.api.invitation.InvitationConstants.CONNECTION_TIMEOUT;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.bramble.api.invitation.InvitationConstants.CONNECTION_TIMEOUT;
 
 // FIXME: This class has way too many dependencies
+@NotNullByDefault
 abstract class Connector extends Thread {
 
 	private static final Logger LOG =
@@ -65,21 +69,21 @@ abstract class Connector extends Thread {
 		messageDigest = crypto.getMessageDigest();
 	}
 
-	protected DuplexTransportConnection createInvitationConnection(
-			boolean alice) {
+	@Nullable
+	DuplexTransportConnection createInvitationConnection(boolean alice) {
 		if (LOG.isLoggable(INFO))
 			LOG.info(pluginName + " creating invitation connection");
 		return plugin.createInvitationConnection(random, CONNECTION_TIMEOUT,
 				alice);
 	}
 
-	protected void sendPublicKeyHash(BdfWriter w) throws IOException {
+	void sendPublicKeyHash(BdfWriter w) throws IOException {
 		w.writeRaw(messageDigest.digest(keyPair.getPublic().getEncoded()));
 		w.flush();
 		if (LOG.isLoggable(INFO)) LOG.info(pluginName + " sent hash");
 	}
 
-	protected byte[] receivePublicKeyHash(BdfReader r) throws IOException {
+	byte[] receivePublicKeyHash(BdfReader r) throws IOException {
 		int hashLength = messageDigest.getDigestLength();
 		byte[] b = r.readRaw(hashLength);
 		if (b.length < hashLength) throw new FormatException();
@@ -87,14 +91,14 @@ abstract class Connector extends Thread {
 		return b;
 	}
 
-	protected void sendPublicKey(BdfWriter w) throws IOException {
+	void sendPublicKey(BdfWriter w) throws IOException {
 		byte[] key = keyPair.getPublic().getEncoded();
 		w.writeRaw(key);
 		w.flush();
 		if (LOG.isLoggable(INFO)) LOG.info(pluginName + " sent key");
 	}
 
-	protected byte[] receivePublicKey(BdfReader r)
+	byte[] receivePublicKey(BdfReader r)
 			throws GeneralSecurityException, IOException {
 		byte[] b = r.readRaw(MAX_PUBLIC_KEY_LENGTH);
 		keyParser.parsePublicKey(b);
@@ -102,8 +106,8 @@ abstract class Connector extends Thread {
 		return b;
 	}
 
-	protected SecretKey deriveMasterSecret(byte[] hash, byte[] key,
-			boolean alice) throws GeneralSecurityException {
+	SecretKey deriveMasterSecret(byte[] hash, byte[] key, boolean alice)
+			throws GeneralSecurityException {
 		// Check that the hash matches the key
 		if (!Arrays.equals(hash, messageDigest.digest(key))) {
 			if (LOG.isLoggable(INFO))
@@ -116,15 +120,14 @@ abstract class Connector extends Thread {
 		return crypto.deriveMasterSecret(key, keyPair, alice);
 	}
 
-	protected void sendConfirmation(BdfWriter w, boolean confirmed)
-			throws IOException {
+	void sendConfirmation(BdfWriter w, boolean confirmed) throws IOException {
 		w.writeBoolean(confirmed);
 		w.flush();
 		if (LOG.isLoggable(INFO))
 			LOG.info(pluginName + " sent confirmation: " + confirmed);
 	}
 
-	protected boolean receiveConfirmation(BdfReader r) throws IOException {
+	boolean receiveConfirmation(BdfReader r) throws IOException {
 		boolean confirmed = r.readBoolean();
 		if (LOG.isLoggable(INFO))
 			LOG.info(pluginName + " received confirmation: " + confirmed);
diff --git a/briar-core/src/org/briarproject/invitation/ConnectorGroup.java b/bramble-core/src/main/java/org/briarproject/bramble/invitation/ConnectorGroup.java
similarity index 83%
rename from briar-core/src/org/briarproject/invitation/ConnectorGroup.java
rename to bramble-core/src/main/java/org/briarproject/bramble/invitation/ConnectorGroup.java
index a88163f52bd3a84335a4a0528b78940c8d61f4a9..103dd03c63e79f5cf57e01ba62130817e6b5c591 100644
--- a/briar-core/src/org/briarproject/invitation/ConnectorGroup.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/invitation/ConnectorGroup.java
@@ -1,20 +1,22 @@
-package org.briarproject.invitation;
+package org.briarproject.bramble.invitation;
 
-import org.briarproject.api.contact.ContactExchangeListener;
-import org.briarproject.api.contact.ContactExchangeTask;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.PseudoRandom;
-import org.briarproject.api.data.BdfReaderFactory;
-import org.briarproject.api.data.BdfWriterFactory;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.invitation.InvitationListener;
-import org.briarproject.api.invitation.InvitationState;
-import org.briarproject.api.invitation.InvitationTask;
-import org.briarproject.api.plugins.PluginManager;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.contact.ContactExchangeListener;
+import org.briarproject.bramble.api.contact.ContactExchangeTask;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.PseudoRandom;
+import org.briarproject.bramble.api.data.BdfReaderFactory;
+import org.briarproject.bramble.api.data.BdfWriterFactory;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.invitation.InvitationListener;
+import org.briarproject.bramble.api.invitation.InvitationState;
+import org.briarproject.bramble.api.invitation.InvitationTask;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.plugin.PluginManager;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -27,11 +29,13 @@ import java.util.logging.Logger;
 
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.invitation.InvitationConstants.CONFIRMATION_TIMEOUT;
+import static org.briarproject.bramble.api.invitation.InvitationConstants.CONFIRMATION_TIMEOUT;
 
 /**
  * A task consisting of one or more parallel connection attempts.
  */
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 class ConnectorGroup extends Thread implements InvitationTask,
 		ContactExchangeListener {
 
@@ -58,7 +62,8 @@ class ConnectorGroup extends Thread implements InvitationTask,
 	private String remoteName = null;
 
 	ConnectorGroup(CryptoComponent crypto, BdfReaderFactory bdfReaderFactory,
-			BdfWriterFactory bdfWriterFactory, ContactExchangeTask contactExchangeTask,
+			BdfWriterFactory bdfWriterFactory,
+			ContactExchangeTask contactExchangeTask,
 			IdentityManager identityManager, PluginManager pluginManager,
 			int localInvitationCode, int remoteInvitationCode) {
 		super("ConnectorGroup");
@@ -75,6 +80,7 @@ class ConnectorGroup extends Thread implements InvitationTask,
 		localConfirmationLatch = new CountDownLatch(1);
 	}
 
+	@Override
 	public InvitationState addListener(InvitationListener l) {
 		lock.lock();
 		try {
@@ -89,10 +95,12 @@ class ConnectorGroup extends Thread implements InvitationTask,
 		}
 	}
 
+	@Override
 	public void removeListener(InvitationListener l) {
 		listeners.remove(l);
 	}
 
+	@Override
 	public void connect() {
 		start();
 	}
@@ -165,6 +173,7 @@ class ConnectorGroup extends Thread implements InvitationTask,
 				contactExchangeTask, this, plugin, localAuthor, random);
 	}
 
+	@Override
 	public void localConfirmationSucceeded() {
 		lock.lock();
 		try {
@@ -176,6 +185,7 @@ class ConnectorGroup extends Thread implements InvitationTask,
 		localConfirmationLatch.countDown();
 	}
 
+	@Override
 	public void localConfirmationFailed() {
 		lock.lock();
 		try {
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/invitation/InvitationModule.java b/bramble-core/src/main/java/org/briarproject/bramble/invitation/InvitationModule.java
new file mode 100644
index 0000000000000000000000000000000000000000..0c6dbcfac53a6e864bf8ea40d8b6338e8f437597
--- /dev/null
+++ b/bramble-core/src/main/java/org/briarproject/bramble/invitation/InvitationModule.java
@@ -0,0 +1,16 @@
+package org.briarproject.bramble.invitation;
+
+import org.briarproject.bramble.api.invitation.InvitationTaskFactory;
+
+import dagger.Module;
+import dagger.Provides;
+
+@Module
+public class InvitationModule {
+
+	@Provides
+	InvitationTaskFactory provideInvitationTaskFactory(
+			InvitationTaskFactoryImpl invitationTaskFactory) {
+		return invitationTaskFactory;
+	}
+}
diff --git a/briar-core/src/org/briarproject/invitation/InvitationTaskFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/invitation/InvitationTaskFactoryImpl.java
similarity index 61%
rename from briar-core/src/org/briarproject/invitation/InvitationTaskFactoryImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/invitation/InvitationTaskFactoryImpl.java
index 5c18deddc0c4332ed98e5a2c75fb8632228ccc57..19bd8c6b9da1ad22dc18c81b5ee0d0e462b90b24 100644
--- a/briar-core/src/org/briarproject/invitation/InvitationTaskFactoryImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/invitation/InvitationTaskFactoryImpl.java
@@ -1,16 +1,20 @@
-package org.briarproject.invitation;
+package org.briarproject.bramble.invitation;
 
-import org.briarproject.api.contact.ContactExchangeTask;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.data.BdfReaderFactory;
-import org.briarproject.api.data.BdfWriterFactory;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.invitation.InvitationTask;
-import org.briarproject.api.invitation.InvitationTaskFactory;
-import org.briarproject.api.plugins.PluginManager;
+import org.briarproject.bramble.api.contact.ContactExchangeTask;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.data.BdfReaderFactory;
+import org.briarproject.bramble.api.data.BdfWriterFactory;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.invitation.InvitationTask;
+import org.briarproject.bramble.api.invitation.InvitationTaskFactory;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.PluginManager;
 
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
+@Immutable
+@NotNullByDefault
 class InvitationTaskFactoryImpl implements InvitationTaskFactory {
 
 	private final CryptoComponent crypto;
@@ -34,6 +38,7 @@ class InvitationTaskFactoryImpl implements InvitationTaskFactory {
 		this.pluginManager = pluginManager;
 	}
 
+	@Override
 	public InvitationTask createTask(int localCode, int remoteCode) {
 		return new ConnectorGroup(crypto, bdfReaderFactory, bdfWriterFactory,
 				contactExchangeTask, identityManager, pluginManager,
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/AbortException.java b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/AbortException.java
new file mode 100644
index 0000000000000000000000000000000000000000..5cae0d7466c69e73c0ee66599b7a854c5da1f757
--- /dev/null
+++ b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/AbortException.java
@@ -0,0 +1,24 @@
+package org.briarproject.bramble.keyagreement;
+
+class AbortException extends Exception {
+
+	boolean receivedAbort;
+
+	AbortException() {
+		this(false);
+	}
+
+	AbortException(boolean receivedAbort) {
+		super();
+		this.receivedAbort = receivedAbort;
+	}
+
+	AbortException(Exception e) {
+		this(e, false);
+	}
+
+	private AbortException(Exception e, boolean receivedAbort) {
+		super(e);
+		this.receivedAbort = receivedAbort;
+	}
+}
diff --git a/briar-core/src/org/briarproject/keyagreement/KeyAgreementConnector.java b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementConnector.java
similarity index 85%
rename from briar-core/src/org/briarproject/keyagreement/KeyAgreementConnector.java
rename to bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementConnector.java
index ee5c0e10dd279baac285535c27ff3d769e147150..ad3015bb4d846a591646806ab2f30cafa3c69a60 100644
--- a/briar-core/src/org/briarproject/keyagreement/KeyAgreementConnector.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementConnector.java
@@ -1,18 +1,19 @@
-package org.briarproject.keyagreement;
-
-import org.briarproject.api.TransportId;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.KeyPair;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.keyagreement.KeyAgreementConnection;
-import org.briarproject.api.keyagreement.KeyAgreementListener;
-import org.briarproject.api.keyagreement.Payload;
-import org.briarproject.api.keyagreement.TransportDescriptor;
-import org.briarproject.api.plugins.Plugin;
-import org.briarproject.api.plugins.PluginManager;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
-import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
-import org.briarproject.api.system.Clock;
+package org.briarproject.bramble.keyagreement;
+
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.KeyPair;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
+import org.briarproject.bramble.api.keyagreement.Payload;
+import org.briarproject.bramble.api.keyagreement.TransportDescriptor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.Plugin;
+import org.briarproject.bramble.api.plugin.PluginManager;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
+import org.briarproject.bramble.api.system.Clock;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -26,11 +27,14 @@ import java.util.concurrent.ExecutorCompletionService;
 import java.util.concurrent.Future;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
+
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.keyagreement.KeyAgreementConstants.CONNECTION_TIMEOUT;
+import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.CONNECTION_TIMEOUT;
 
+@NotNullByDefault
 class KeyAgreementConnector {
 
 	interface Callbacks {
@@ -94,6 +98,7 @@ class KeyAgreementConnector {
 		listeners.clear();
 	}
 
+	@Nullable
 	public KeyAgreementTransport connect(Payload remotePayload,
 			boolean alice) {
 		// Let the listeners know if we are Alice
@@ -140,7 +145,7 @@ class KeyAgreementConnector {
 		}
 	}
 
-	private void closePending(KeyAgreementConnection chosen) {
+	private void closePending(@Nullable KeyAgreementConnection chosen) {
 		for (Future<KeyAgreementConnection> f : pending) {
 			try {
 				if (f.cancel(true))
diff --git a/briar-core/src/org/briarproject/keyagreement/KeyAgreementModule.java b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementModule.java
similarity index 55%
rename from briar-core/src/org/briarproject/keyagreement/KeyAgreementModule.java
rename to bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementModule.java
index 9f6a529028a668fc4cbde1231a3a61201730f847..9875387db916d282d9bc382077b25d37a8d40286 100644
--- a/briar-core/src/org/briarproject/keyagreement/KeyAgreementModule.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementModule.java
@@ -1,15 +1,15 @@
-package org.briarproject.keyagreement;
-
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.data.BdfReaderFactory;
-import org.briarproject.api.data.BdfWriterFactory;
-import org.briarproject.api.event.EventBus;
-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.plugins.PluginManager;
-import org.briarproject.api.system.Clock;
+package org.briarproject.bramble.keyagreement;
+
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.data.BdfReaderFactory;
+import org.briarproject.bramble.api.data.BdfWriterFactory;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementTaskFactory;
+import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
+import org.briarproject.bramble.api.keyagreement.PayloadParser;
+import org.briarproject.bramble.api.lifecycle.IoExecutor;
+import org.briarproject.bramble.api.plugin.PluginManager;
+import org.briarproject.bramble.api.system.Clock;
 
 import java.util.concurrent.Executor;
 
diff --git a/briar-core/src/org/briarproject/keyagreement/KeyAgreementProtocol.java b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementProtocol.java
similarity index 89%
rename from briar-core/src/org/briarproject/keyagreement/KeyAgreementProtocol.java
rename to bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementProtocol.java
index f67a85ecd655657544b50d430eb1e445d9bf4cd1..1c56c2d1493a68a1d2d49d48c1d4869002aea88e 100644
--- a/briar-core/src/org/briarproject/keyagreement/KeyAgreementProtocol.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementProtocol.java
@@ -1,10 +1,11 @@
-package org.briarproject.keyagreement;
+package org.briarproject.bramble.keyagreement;
 
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.KeyPair;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.keyagreement.Payload;
-import org.briarproject.api.keyagreement.PayloadEncoder;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.KeyPair;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.keyagreement.Payload;
+import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.IOException;
 import java.security.GeneralSecurityException;
@@ -44,6 +45,7 @@ import java.util.Arrays;
  * <li>Derive master</li>
  * </ul>
  */
+@NotNullByDefault
 class KeyAgreementProtocol {
 
 	interface Callbacks {
@@ -80,7 +82,7 @@ class KeyAgreementProtocol {
 	 *
 	 * @return the negotiated master secret.
 	 * @throws AbortException when the protocol may have been tampered with.
-	 * @throws IOException    for all other other connection errors.
+	 * @throws IOException for all other other connection errors.
 	 */
 	SecretKey perform() throws AbortException, IOException {
 		try {
diff --git a/briar-core/src/org/briarproject/keyagreement/KeyAgreementTaskFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementTaskFactoryImpl.java
similarity index 53%
rename from briar-core/src/org/briarproject/keyagreement/KeyAgreementTaskFactoryImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementTaskFactoryImpl.java
index aafde49b3b1acb32aa01c995b9402a96cf615e41..4d9dc00cf684cb5d2cf4d2454719768d218015f0 100644
--- a/briar-core/src/org/briarproject/keyagreement/KeyAgreementTaskFactoryImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementTaskFactoryImpl.java
@@ -1,23 +1,22 @@
-package org.briarproject.keyagreement;
+package org.briarproject.bramble.keyagreement;
 
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.KeyAgreementAbortedEvent;
-import org.briarproject.api.event.KeyAgreementFailedEvent;
-import org.briarproject.api.event.KeyAgreementFinishedEvent;
-import org.briarproject.api.keyagreement.KeyAgreementTask;
-import org.briarproject.api.keyagreement.KeyAgreementTaskFactory;
-import org.briarproject.api.keyagreement.PayloadEncoder;
-import org.briarproject.api.lifecycle.IoExecutor;
-import org.briarproject.api.plugins.PluginManager;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementTask;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementTaskFactory;
+import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
+import org.briarproject.bramble.api.lifecycle.IoExecutor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.PluginManager;
+import org.briarproject.bramble.api.system.Clock;
 
 import java.util.concurrent.Executor;
 
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
+@Immutable
+@NotNullByDefault
 class KeyAgreementTaskFactoryImpl implements KeyAgreementTaskFactory {
 
 	private final Clock clock;
@@ -39,7 +38,8 @@ class KeyAgreementTaskFactoryImpl implements KeyAgreementTaskFactory {
 		this.pluginManager = pluginManager;
 	}
 
-	public KeyAgreementTask getTask() {
+	@Override
+	public KeyAgreementTask createTask() {
 		return new KeyAgreementTaskImpl(clock, crypto, eventBus, payloadEncoder,
 				pluginManager, ioExecutor);
 	}
diff --git a/briar-core/src/org/briarproject/keyagreement/KeyAgreementTaskImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementTaskImpl.java
similarity index 73%
rename from briar-core/src/org/briarproject/keyagreement/KeyAgreementTaskImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementTaskImpl.java
index e50267698764a701a893cd8c00af402494ff710f..af180b89e29ff628b7fbd401d5fe42cf90e79766 100644
--- a/briar-core/src/org/briarproject/keyagreement/KeyAgreementTaskImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementTaskImpl.java
@@ -1,21 +1,23 @@
-package org.briarproject.keyagreement;
-
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.KeyPair;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.KeyAgreementAbortedEvent;
-import org.briarproject.api.event.KeyAgreementFailedEvent;
-import org.briarproject.api.event.KeyAgreementFinishedEvent;
-import org.briarproject.api.event.KeyAgreementListeningEvent;
-import org.briarproject.api.event.KeyAgreementStartedEvent;
-import org.briarproject.api.event.KeyAgreementWaitingEvent;
-import org.briarproject.api.keyagreement.KeyAgreementResult;
-import org.briarproject.api.keyagreement.KeyAgreementTask;
-import org.briarproject.api.keyagreement.Payload;
-import org.briarproject.api.keyagreement.PayloadEncoder;
-import org.briarproject.api.plugins.PluginManager;
-import org.briarproject.api.system.Clock;
+package org.briarproject.bramble.keyagreement;
+
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.KeyPair;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementResult;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementTask;
+import org.briarproject.bramble.api.keyagreement.Payload;
+import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
+import org.briarproject.bramble.api.keyagreement.event.KeyAgreementAbortedEvent;
+import org.briarproject.bramble.api.keyagreement.event.KeyAgreementFailedEvent;
+import org.briarproject.bramble.api.keyagreement.event.KeyAgreementFinishedEvent;
+import org.briarproject.bramble.api.keyagreement.event.KeyAgreementListeningEvent;
+import org.briarproject.bramble.api.keyagreement.event.KeyAgreementStartedEvent;
+import org.briarproject.bramble.api.keyagreement.event.KeyAgreementWaitingEvent;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.plugin.PluginManager;
+import org.briarproject.bramble.api.system.Clock;
 
 import java.io.IOException;
 import java.util.concurrent.Executor;
@@ -23,6 +25,8 @@ import java.util.logging.Logger;
 
 import static java.util.logging.Level.WARNING;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 class KeyAgreementTaskImpl extends Thread implements
 		KeyAgreementTask, KeyAgreementConnector.Callbacks,
 		KeyAgreementProtocol.Callbacks {
diff --git a/briar-core/src/org/briarproject/keyagreement/KeyAgreementTransport.java b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementTransport.java
similarity index 69%
rename from briar-core/src/org/briarproject/keyagreement/KeyAgreementTransport.java
rename to bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementTransport.java
index 25a18962bad176a7d58535d2fd5009d6977b1a51..2044f2b65df2bc70ce138b959d56818a26334152 100644
--- a/briar-core/src/org/briarproject/keyagreement/KeyAgreementTransport.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementTransport.java
@@ -1,9 +1,10 @@
-package org.briarproject.keyagreement;
+package org.briarproject.bramble.keyagreement;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.keyagreement.KeyAgreementConnection;
-import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
-import org.briarproject.util.ByteUtils;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
+import org.briarproject.bramble.util.ByteUtils;
 
 import java.io.EOFException;
 import java.io.IOException;
@@ -12,16 +13,17 @@ import java.io.OutputStream;
 import java.util.logging.Logger;
 
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.keyagreement.KeyAgreementConstants.PROTOCOL_VERSION;
-import static org.briarproject.api.keyagreement.KeyAgreementConstants.RECORD_HEADER_LENGTH;
-import static org.briarproject.api.keyagreement.KeyAgreementConstants.RECORD_HEADER_PAYLOAD_LENGTH_OFFSET;
-import static org.briarproject.api.keyagreement.RecordTypes.ABORT;
-import static org.briarproject.api.keyagreement.RecordTypes.CONFIRM;
-import static org.briarproject.api.keyagreement.RecordTypes.KEY;
+import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.PROTOCOL_VERSION;
+import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.RECORD_HEADER_LENGTH;
+import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.RECORD_HEADER_PAYLOAD_LENGTH_OFFSET;
+import static org.briarproject.bramble.api.keyagreement.RecordTypes.ABORT;
+import static org.briarproject.bramble.api.keyagreement.RecordTypes.CONFIRM;
+import static org.briarproject.bramble.api.keyagreement.RecordTypes.KEY;
 
 /**
  * Handles the sending and receiving of BQP records.
  */
+@NotNullByDefault
 class KeyAgreementTransport {
 
 	private static final Logger LOG =
@@ -31,7 +33,7 @@ class KeyAgreementTransport {
 	private final InputStream in;
 	private final OutputStream out;
 
-	public KeyAgreementTransport(KeyAgreementConnection kac)
+	KeyAgreementTransport(KeyAgreementConnection kac)
 			throws IOException {
 		this.kac = kac;
 		in = kac.getConnection().getReader().getInputStream();
@@ -46,23 +48,23 @@ class KeyAgreementTransport {
 		return kac.getTransportId();
 	}
 
-	public void sendKey(byte[] key) throws IOException {
+	void sendKey(byte[] key) throws IOException {
 		writeRecord(KEY, key);
 	}
 
-	public byte[] receiveKey() throws AbortException {
+	byte[] receiveKey() throws AbortException {
 		return readRecord(KEY);
 	}
 
-	public void sendConfirm(byte[] confirm) throws IOException {
+	void sendConfirm(byte[] confirm) throws IOException {
 		writeRecord(CONFIRM, confirm);
 	}
 
-	public byte[] receiveConfirm() throws AbortException {
+	byte[] receiveConfirm() throws AbortException {
 		return readRecord(CONFIRM);
 	}
 
-	public void sendAbort(boolean exception) {
+	void sendAbort(boolean exception) {
 		try {
 			writeRecord(ABORT, new byte[0]);
 		} catch (IOException e) {
diff --git a/briar-core/src/org/briarproject/keyagreement/PayloadEncoderImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/PayloadEncoderImpl.java
similarity index 64%
rename from briar-core/src/org/briarproject/keyagreement/PayloadEncoderImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/keyagreement/PayloadEncoderImpl.java
index ac1a647d13c2e13ceadfb5faf37286a792950b91..b6c3481eeda1e81f7f665b1d9720bbdb2879e71f 100644
--- a/briar-core/src/org/briarproject/keyagreement/PayloadEncoderImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/PayloadEncoderImpl.java
@@ -1,11 +1,11 @@
-package org.briarproject.keyagreement;
+package org.briarproject.bramble.keyagreement;
 
-import org.briarproject.api.data.BdfWriter;
-import org.briarproject.api.data.BdfWriterFactory;
-import org.briarproject.api.keyagreement.Payload;
-import org.briarproject.api.keyagreement.PayloadEncoder;
-import org.briarproject.api.keyagreement.TransportDescriptor;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.data.BdfWriter;
+import org.briarproject.bramble.api.data.BdfWriterFactory;
+import org.briarproject.bramble.api.keyagreement.Payload;
+import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
+import org.briarproject.bramble.api.keyagreement.TransportDescriptor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -13,7 +13,7 @@ import java.io.IOException;
 import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-import static org.briarproject.api.keyagreement.KeyAgreementConstants.PROTOCOL_VERSION;
+import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.PROTOCOL_VERSION;
 
 @Immutable
 @NotNullByDefault
diff --git a/briar-core/src/org/briarproject/keyagreement/PayloadParserImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/PayloadParserImpl.java
similarity index 61%
rename from briar-core/src/org/briarproject/keyagreement/PayloadParserImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/keyagreement/PayloadParserImpl.java
index c0ee0064fea1b3e9b20133771d3e7d91a39d7fbc..5b4df07c4846592d3effe6a831a5b0cd955cc137 100644
--- a/briar-core/src/org/briarproject/keyagreement/PayloadParserImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/PayloadParserImpl.java
@@ -1,16 +1,16 @@
-package org.briarproject.keyagreement;
+package org.briarproject.bramble.keyagreement;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.BdfReader;
-import org.briarproject.api.data.BdfReaderFactory;
-import org.briarproject.api.keyagreement.Payload;
-import org.briarproject.api.keyagreement.PayloadParser;
-import org.briarproject.api.keyagreement.TransportDescriptor;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.plugins.BluetoothConstants;
-import org.briarproject.api.plugins.LanTcpConstants;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.BdfReader;
+import org.briarproject.bramble.api.data.BdfReaderFactory;
+import org.briarproject.bramble.api.keyagreement.Payload;
+import org.briarproject.bramble.api.keyagreement.PayloadParser;
+import org.briarproject.bramble.api.keyagreement.TransportDescriptor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.BluetoothConstants;
+import org.briarproject.bramble.api.plugin.LanTcpConstants;
+import org.briarproject.bramble.api.plugin.TransportId;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
@@ -20,10 +20,10 @@ import java.util.List;
 import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-import static org.briarproject.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
-import static org.briarproject.api.keyagreement.KeyAgreementConstants.PROTOCOL_VERSION;
-import static org.briarproject.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_BLUETOOTH;
-import static org.briarproject.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_LAN;
+import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
+import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.PROTOCOL_VERSION;
+import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_BLUETOOTH;
+import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_LAN;
 
 @Immutable
 @NotNullByDefault
diff --git a/briar-core/src/org/briarproject/lifecycle/LifecycleManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/lifecycle/LifecycleManagerImpl.java
similarity index 82%
rename from briar-core/src/org/briarproject/lifecycle/LifecycleManagerImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/lifecycle/LifecycleManagerImpl.java
index fa66b14fde740b7b267b472c767a3cde68601aaa..da3536bebd9f47a09567098c2ab371dcb0f77372 100644
--- a/briar-core/src/org/briarproject/lifecycle/LifecycleManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/lifecycle/LifecycleManagerImpl.java
@@ -1,19 +1,20 @@
-package org.briarproject.lifecycle;
-
-import org.briarproject.api.clients.Client;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.KeyPair;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.ShutdownEvent;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.lifecycle.Service;
-import org.briarproject.api.lifecycle.ServiceException;
+package org.briarproject.bramble.lifecycle;
+
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.KeyPair;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.lifecycle.Service;
+import org.briarproject.bramble.api.lifecycle.ServiceException;
+import org.briarproject.bramble.api.lifecycle.event.ShutdownEvent;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Client;
 
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
@@ -23,15 +24,18 @@ import java.util.concurrent.Semaphore;
 import java.util.logging.Logger;
 
 import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
 import javax.inject.Inject;
 
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.lifecycle.LifecycleManager.StartResult.ALREADY_RUNNING;
-import static org.briarproject.api.lifecycle.LifecycleManager.StartResult.DB_ERROR;
-import static org.briarproject.api.lifecycle.LifecycleManager.StartResult.SERVICE_ERROR;
-import static org.briarproject.api.lifecycle.LifecycleManager.StartResult.SUCCESS;
+import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.ALREADY_RUNNING;
+import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.DB_ERROR;
+import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SERVICE_ERROR;
+import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SUCCESS;
 
+@ThreadSafe
+@NotNullByDefault
 class LifecycleManagerImpl implements LifecycleManager {
 
 	private static final Logger LOG =
diff --git a/briar-core/src/org/briarproject/lifecycle/LifecycleModule.java b/bramble-core/src/main/java/org/briarproject/bramble/lifecycle/LifecycleModule.java
similarity index 73%
rename from briar-core/src/org/briarproject/lifecycle/LifecycleModule.java
rename to bramble-core/src/main/java/org/briarproject/bramble/lifecycle/LifecycleModule.java
index 67c94c1a841ac59e59e6a0944ee638bedf6d36b3..2db43072355f8c4f7d367b2162d7069dada031c8 100644
--- a/briar-core/src/org/briarproject/lifecycle/LifecycleModule.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/lifecycle/LifecycleModule.java
@@ -1,13 +1,13 @@
-package org.briarproject.lifecycle;
+package org.briarproject.bramble.lifecycle;
 
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.lifecycle.IoExecutor;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.lifecycle.ShutdownManager;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.lifecycle.IoExecutor;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.lifecycle.ShutdownManager;
 
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.Executor;
@@ -64,7 +64,7 @@ public class LifecycleModule {
 	@Provides
 	@Singleton
 	@IoExecutor
-	Executor getIoExecutor(LifecycleManager lifecycleManager) {
+	Executor provideIoExecutor(LifecycleManager lifecycleManager) {
 		lifecycleManager.registerForShutdown(ioExecutor);
 		return ioExecutor;
 	}
diff --git a/briar-core/src/org/briarproject/lifecycle/ShutdownManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/lifecycle/ShutdownManagerImpl.java
similarity index 75%
rename from briar-core/src/org/briarproject/lifecycle/ShutdownManagerImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/lifecycle/ShutdownManagerImpl.java
index 3779db25832890fdc8c608024ffc6efec3cf3ba8..1b5e4ad6aa24e90da2bde02f5bf95ada8da6604e 100644
--- a/briar-core/src/org/briarproject/lifecycle/ShutdownManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/lifecycle/ShutdownManagerImpl.java
@@ -1,15 +1,20 @@
-package org.briarproject.lifecycle;
+package org.briarproject.bramble.lifecycle;
+
+import org.briarproject.bramble.api.lifecycle.ShutdownManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
-import org.briarproject.api.lifecycle.ShutdownManager;
+import javax.annotation.concurrent.ThreadSafe;
 
+@ThreadSafe
+@NotNullByDefault
 class ShutdownManagerImpl implements ShutdownManager {
 
-	private final Lock lock = new ReentrantLock();
+	protected final Lock lock = new ReentrantLock();
 
 	// The following are locking: lock
 	protected final Map<Integer, Thread> hooks;
@@ -19,6 +24,7 @@ class ShutdownManagerImpl implements ShutdownManager {
 		hooks = new HashMap<Integer, Thread>();
 	}
 
+	@Override
 	public int addShutdownHook(Runnable r) {
 		lock.lock();
 		try {
@@ -37,6 +43,7 @@ class ShutdownManagerImpl implements ShutdownManager {
 		return new Thread(r, "ShutdownManager");
 	}
 
+	@Override
 	public boolean removeShutdownHook(int handle) {
 		lock.lock();
 		try {
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/BackoffFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/BackoffFactoryImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..7640a957151a32e974843bc71c2832837f6934df
--- /dev/null
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/BackoffFactoryImpl.java
@@ -0,0 +1,18 @@
+package org.briarproject.bramble.plugin;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.Backoff;
+import org.briarproject.bramble.api.plugin.BackoffFactory;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+class BackoffFactoryImpl implements BackoffFactory {
+
+	@Override
+	public Backoff createBackoff(int minInterval, int maxInterval,
+			double base) {
+		return new BackoffImpl(minInterval, maxInterval, base);
+	}
+}
diff --git a/briar-core/src/org/briarproject/plugins/BackoffImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/BackoffImpl.java
similarity index 76%
rename from briar-core/src/org/briarproject/plugins/BackoffImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/plugin/BackoffImpl.java
index 175c0d35ffa209ba846b9649fef1c5754385f735..a4522cbb4cf701b44e3301a98fb5f48ddcc22791 100644
--- a/briar-core/src/org/briarproject/plugins/BackoffImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/BackoffImpl.java
@@ -1,9 +1,14 @@
-package org.briarproject.plugins;
+package org.briarproject.bramble.plugin;
 
-import org.briarproject.api.plugins.Backoff;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.Backoff;
 
 import java.util.concurrent.atomic.AtomicInteger;
 
+import javax.annotation.concurrent.ThreadSafe;
+
+@ThreadSafe
+@NotNullByDefault
 class BackoffImpl implements Backoff {
 
 	private final int minInterval, maxInterval;
diff --git a/briar-core/src/org/briarproject/plugins/ConnectionManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/ConnectionManagerImpl.java
similarity index 91%
rename from briar-core/src/org/briarproject/plugins/ConnectionManagerImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/plugin/ConnectionManagerImpl.java
index c85c5f016d64c3af085454ca856d240943f0b93f..3714e420ff54b984772a1d69a14f651a573c4cab 100644
--- a/briar-core/src/org/briarproject/plugins/ConnectionManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/ConnectionManagerImpl.java
@@ -1,20 +1,20 @@
-package org.briarproject.plugins;
-
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.lifecycle.IoExecutor;
-import org.briarproject.api.plugins.ConnectionManager;
-import org.briarproject.api.plugins.ConnectionRegistry;
-import org.briarproject.api.plugins.TransportConnectionReader;
-import org.briarproject.api.plugins.TransportConnectionWriter;
-import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
-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;
+package org.briarproject.bramble.plugin;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.lifecycle.IoExecutor;
+import org.briarproject.bramble.api.plugin.ConnectionManager;
+import org.briarproject.bramble.api.plugin.ConnectionRegistry;
+import org.briarproject.bramble.api.plugin.TransportConnectionReader;
+import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
+import org.briarproject.bramble.api.sync.SyncSession;
+import org.briarproject.bramble.api.sync.SyncSessionFactory;
+import org.briarproject.bramble.api.transport.KeyManager;
+import org.briarproject.bramble.api.transport.StreamContext;
+import org.briarproject.bramble.api.transport.StreamReaderFactory;
+import org.briarproject.bramble.api.transport.StreamWriterFactory;
 
 import java.io.EOFException;
 import java.io.IOException;
@@ -26,7 +26,7 @@ import java.util.logging.Logger;
 import javax.inject.Inject;
 
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
 
 class ConnectionManagerImpl implements ConnectionManager {
 
@@ -54,21 +54,25 @@ class ConnectionManagerImpl implements ConnectionManager {
 		this.connectionRegistry = connectionRegistry;
 	}
 
+	@Override
 	public void manageIncomingConnection(TransportId t,
 			TransportConnectionReader r) {
 		ioExecutor.execute(new ManageIncomingSimplexConnection(t, r));
 	}
 
+	@Override
 	public void manageIncomingConnection(TransportId t,
 			DuplexTransportConnection d) {
 		ioExecutor.execute(new ManageIncomingDuplexConnection(t, d));
 	}
 
+	@Override
 	public void manageOutgoingConnection(ContactId c, TransportId t,
 			TransportConnectionWriter w) {
 		ioExecutor.execute(new ManageOutgoingSimplexConnection(c, t, w));
 	}
 
+	@Override
 	public void manageOutgoingConnection(ContactId c, TransportId t,
 			DuplexTransportConnection d) {
 		ioExecutor.execute(new ManageOutgoingDuplexConnection(c, t, d));
@@ -123,6 +127,7 @@ class ConnectionManagerImpl implements ConnectionManager {
 			this.reader = reader;
 		}
 
+		@Override
 		public void run() {
 			// Read and recognise the tag
 			StreamContext ctx;
@@ -180,6 +185,7 @@ class ConnectionManagerImpl implements ConnectionManager {
 			this.writer = writer;
 		}
 
+		@Override
 		public void run() {
 			// Allocate a stream context
 			StreamContext ctx;
@@ -236,6 +242,7 @@ class ConnectionManagerImpl implements ConnectionManager {
 			writer = transport.getWriter();
 		}
 
+		@Override
 		public void run() {
 			// Read and recognise the tag
 			StreamContext ctx;
@@ -260,6 +267,7 @@ class ConnectionManagerImpl implements ConnectionManager {
 			connectionRegistry.registerConnection(contactId, transportId, true);
 			// Start the outgoing session on another thread
 			ioExecutor.execute(new Runnable() {
+				@Override
 				public void run() {
 					runOutgoingSession();
 				}
@@ -343,6 +351,7 @@ class ConnectionManagerImpl implements ConnectionManager {
 			writer = transport.getWriter();
 		}
 
+		@Override
 		public void run() {
 			// Allocate a stream context
 			StreamContext ctx;
@@ -360,6 +369,7 @@ class ConnectionManagerImpl implements ConnectionManager {
 			}
 			// Start the incoming session on another thread
 			ioExecutor.execute(new Runnable() {
+				@Override
 				public void run() {
 					runIncomingSession();
 				}
diff --git a/briar-core/src/org/briarproject/plugins/ConnectionRegistryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/ConnectionRegistryImpl.java
similarity index 84%
rename from briar-core/src/org/briarproject/plugins/ConnectionRegistryImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/plugin/ConnectionRegistryImpl.java
index 7b687f9355b1115893f53a5e252b659ff6fbc9be..5c4b5d4221fd6c2b0bad082f753a09620f64709a 100644
--- a/briar-core/src/org/briarproject/plugins/ConnectionRegistryImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/ConnectionRegistryImpl.java
@@ -1,13 +1,14 @@
-package org.briarproject.plugins;
+package org.briarproject.bramble.plugin;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.event.ConnectionClosedEvent;
-import org.briarproject.api.event.ConnectionOpenedEvent;
-import org.briarproject.api.event.ContactConnectedEvent;
-import org.briarproject.api.event.ContactDisconnectedEvent;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.plugins.ConnectionRegistry;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.ConnectionRegistry;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.event.ConnectionClosedEvent;
+import org.briarproject.bramble.api.plugin.event.ConnectionOpenedEvent;
+import org.briarproject.bramble.api.plugin.event.ContactConnectedEvent;
+import org.briarproject.bramble.api.plugin.event.ContactDisconnectedEvent;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -19,10 +20,13 @@ import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.logging.Logger;
 
+import javax.annotation.concurrent.ThreadSafe;
 import javax.inject.Inject;
 
 import static java.util.logging.Level.INFO;
 
+@ThreadSafe
+@NotNullByDefault
 class ConnectionRegistryImpl implements ConnectionRegistry {
 
 	private static final Logger LOG =
diff --git a/briar-core/src/org/briarproject/plugins/PluginManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/PluginManagerImpl.java
similarity index 83%
rename from briar-core/src/org/briarproject/plugins/PluginManagerImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/plugin/PluginManagerImpl.java
index 010e75da58a4ce255be62582839d619b25b3f4a4..45eeb2d44c956b54769bb09daec6164a2cea6b19 100644
--- a/briar-core/src/org/briarproject/plugins/PluginManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/PluginManagerImpl.java
@@ -1,34 +1,34 @@
-package org.briarproject.plugins;
-
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.TransportDisabledEvent;
-import org.briarproject.api.event.TransportEnabledEvent;
-import org.briarproject.api.lifecycle.IoExecutor;
-import org.briarproject.api.lifecycle.Service;
-import org.briarproject.api.lifecycle.ServiceException;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.plugins.ConnectionManager;
-import org.briarproject.api.plugins.Plugin;
-import org.briarproject.api.plugins.PluginCallback;
-import org.briarproject.api.plugins.PluginConfig;
-import org.briarproject.api.plugins.PluginManager;
-import org.briarproject.api.plugins.TransportConnectionReader;
-import org.briarproject.api.plugins.TransportConnectionWriter;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
-import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
-import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
-import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
-import org.briarproject.api.plugins.simplex.SimplexPlugin;
-import org.briarproject.api.plugins.simplex.SimplexPluginCallback;
-import org.briarproject.api.plugins.simplex.SimplexPluginFactory;
-import org.briarproject.api.properties.TransportProperties;
-import org.briarproject.api.properties.TransportPropertyManager;
-import org.briarproject.api.settings.Settings;
-import org.briarproject.api.settings.SettingsManager;
-import org.briarproject.api.ui.UiCallback;
+package org.briarproject.bramble.plugin;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.lifecycle.IoExecutor;
+import org.briarproject.bramble.api.lifecycle.Service;
+import org.briarproject.bramble.api.lifecycle.ServiceException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.ConnectionManager;
+import org.briarproject.bramble.api.plugin.Plugin;
+import org.briarproject.bramble.api.plugin.PluginCallback;
+import org.briarproject.bramble.api.plugin.PluginConfig;
+import org.briarproject.bramble.api.plugin.PluginManager;
+import org.briarproject.bramble.api.plugin.TransportConnectionReader;
+import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
+import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
+import org.briarproject.bramble.api.plugin.event.TransportDisabledEvent;
+import org.briarproject.bramble.api.plugin.event.TransportEnabledEvent;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPluginCallback;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
+import org.briarproject.bramble.api.properties.TransportProperties;
+import org.briarproject.bramble.api.properties.TransportPropertyManager;
+import org.briarproject.bramble.api.settings.Settings;
+import org.briarproject.bramble.api.settings.SettingsManager;
+import org.briarproject.bramble.api.ui.UiCallback;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -256,11 +256,12 @@ class PluginManagerImpl implements PluginManager, Service {
 		}
 	}
 
+	@NotNullByDefault
 	private abstract class PluginCallbackImpl implements PluginCallback {
 
 		protected final TransportId id;
 
-		protected PluginCallbackImpl(TransportId id) {
+		PluginCallbackImpl(TransportId id) {
 			this.id = id;
 		}
 
@@ -277,9 +278,7 @@ class PluginManagerImpl implements PluginManager, Service {
 		@Override
 		public TransportProperties getLocalProperties() {
 			try {
-				TransportProperties p =
-						transportPropertyManager.getLocalProperties(id);
-				return p == null ? new TransportProperties() : p;
+				return transportPropertyManager.getLocalProperties(id);
 			} catch (DbException e) {
 				if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
 				return new TransportProperties();
@@ -340,6 +339,7 @@ class PluginManagerImpl implements PluginManager, Service {
 		}
 	}
 
+	@NotNullByDefault
 	private class SimplexCallback extends PluginCallbackImpl
 			implements SimplexPluginCallback {
 
@@ -358,6 +358,7 @@ class PluginManagerImpl implements PluginManager, Service {
 		}
 	}
 
+	@NotNullByDefault
 	private class DuplexCallback extends PluginCallbackImpl
 			implements DuplexPluginCallback {
 
diff --git a/briar-core/src/org/briarproject/plugins/PluginsModule.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/PluginModule.java
similarity index 70%
rename from briar-core/src/org/briarproject/plugins/PluginsModule.java
rename to bramble-core/src/main/java/org/briarproject/bramble/plugin/PluginModule.java
index d7e6925e557fd6152b10d42824abae45fe4b5f7a..43ed215557969a2aefbfef6f78de067adb81e2dd 100644
--- a/briar-core/src/org/briarproject/plugins/PluginsModule.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/PluginModule.java
@@ -1,14 +1,14 @@
-package org.briarproject.plugins;
+package org.briarproject.bramble.plugin;
 
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.lifecycle.IoExecutor;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.plugins.BackoffFactory;
-import org.briarproject.api.plugins.ConnectionManager;
-import org.briarproject.api.plugins.ConnectionRegistry;
-import org.briarproject.api.plugins.PluginManager;
-import org.briarproject.api.system.Clock;
-import org.briarproject.api.system.Scheduler;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.lifecycle.IoExecutor;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.plugin.BackoffFactory;
+import org.briarproject.bramble.api.plugin.ConnectionManager;
+import org.briarproject.bramble.api.plugin.ConnectionRegistry;
+import org.briarproject.bramble.api.plugin.PluginManager;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.bramble.api.system.Scheduler;
 
 import java.security.SecureRandom;
 import java.util.concurrent.Executor;
@@ -21,7 +21,7 @@ import dagger.Module;
 import dagger.Provides;
 
 @Module
-public class PluginsModule {
+public class PluginModule {
 
 	public static class EagerSingletons {
 		@Inject
diff --git a/briar-core/src/org/briarproject/plugins/Poller.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/Poller.java
similarity index 80%
rename from briar-core/src/org/briarproject/plugins/Poller.java
rename to bramble-core/src/main/java/org/briarproject/bramble/plugin/Poller.java
index a904bbfe6d14c9b60135b7305a5eea7441e8c24b..f315bda9e8631bfd112d0a45ce54261b956bdcbc 100644
--- a/briar-core/src/org/briarproject/plugins/Poller.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/Poller.java
@@ -1,24 +1,25 @@
-package org.briarproject.plugins;
-
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.event.ConnectionClosedEvent;
-import org.briarproject.api.event.ConnectionOpenedEvent;
-import org.briarproject.api.event.ContactStatusChangedEvent;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.TransportEnabledEvent;
-import org.briarproject.api.lifecycle.IoExecutor;
-import org.briarproject.api.plugins.ConnectionManager;
-import org.briarproject.api.plugins.ConnectionRegistry;
-import org.briarproject.api.plugins.Plugin;
-import org.briarproject.api.plugins.PluginManager;
-import org.briarproject.api.plugins.TransportConnectionWriter;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
-import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
-import org.briarproject.api.plugins.simplex.SimplexPlugin;
-import org.briarproject.api.system.Clock;
-import org.briarproject.api.system.Scheduler;
+package org.briarproject.bramble.plugin;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.event.ContactStatusChangedEvent;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.lifecycle.IoExecutor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.ConnectionManager;
+import org.briarproject.bramble.api.plugin.ConnectionRegistry;
+import org.briarproject.bramble.api.plugin.Plugin;
+import org.briarproject.bramble.api.plugin.PluginManager;
+import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
+import org.briarproject.bramble.api.plugin.event.ConnectionClosedEvent;
+import org.briarproject.bramble.api.plugin.event.ConnectionOpenedEvent;
+import org.briarproject.bramble.api.plugin.event.TransportEnabledEvent;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.bramble.api.system.Scheduler;
 
 import java.security.SecureRandom;
 import java.util.HashMap;
@@ -29,11 +30,14 @@ import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.logging.Logger;
 
+import javax.annotation.concurrent.ThreadSafe;
 import javax.inject.Inject;
 
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.logging.Level.INFO;
 
+@ThreadSafe
+@NotNullByDefault
 class Poller implements EventListener {
 
 	private static final Logger LOG = Logger.getLogger(Poller.class.getName());
diff --git a/briar-core/src/org/briarproject/plugins/file/FilePlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/file/FilePlugin.java
similarity index 85%
rename from briar-core/src/org/briarproject/plugins/file/FilePlugin.java
rename to bramble-core/src/main/java/org/briarproject/bramble/plugin/file/FilePlugin.java
index 108db3c7b25ef17715d87ab4357701e275cc1c73..17b61358d20bd4b0d1cdbb9bf39244e882923ced 100644
--- a/briar-core/src/org/briarproject/plugins/file/FilePlugin.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/file/FilePlugin.java
@@ -1,11 +1,11 @@
-package org.briarproject.plugins.file;
+package org.briarproject.bramble.plugin.file;
 
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.plugins.TransportConnectionReader;
-import org.briarproject.api.plugins.TransportConnectionWriter;
-import org.briarproject.api.plugins.simplex.SimplexPlugin;
-import org.briarproject.api.plugins.simplex.SimplexPluginCallback;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportConnectionReader;
+import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPluginCallback;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -21,7 +21,7 @@ import java.util.logging.Logger;
 import javax.annotation.Nullable;
 
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.transport.TransportConstants.MIN_STREAM_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MIN_STREAM_LENGTH;
 
 @NotNullByDefault
 abstract class FilePlugin implements SimplexPlugin {
@@ -38,8 +38,11 @@ abstract class FilePlugin implements SimplexPlugin {
 
 	@Nullable
 	protected abstract File chooseOutputDirectory();
+
 	protected abstract Collection<File> findFilesByName(String filename);
+
 	protected abstract void writerFinished(File f);
+
 	protected abstract void readerFinished(File f);
 
 	protected FilePlugin(Executor ioExecutor, SimplexPluginCallback callback,
diff --git a/briar-core/src/org/briarproject/plugins/file/FileTransportReader.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/file/FileTransportReader.java
similarity index 79%
rename from briar-core/src/org/briarproject/plugins/file/FileTransportReader.java
rename to bramble-core/src/main/java/org/briarproject/bramble/plugin/file/FileTransportReader.java
index ed6219797c7dd5d33629eee3bb25f79955a708bd..df5d5b9086d4c61ad5bdb26823fc9974d4e52867 100644
--- a/briar-core/src/org/briarproject/plugins/file/FileTransportReader.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/file/FileTransportReader.java
@@ -1,6 +1,7 @@
-package org.briarproject.plugins.file;
+package org.briarproject.bramble.plugin.file;
 
-import org.briarproject.api.plugins.TransportConnectionReader;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportConnectionReader;
 
 import java.io.File;
 import java.io.IOException;
@@ -9,6 +10,7 @@ import java.util.logging.Logger;
 
 import static java.util.logging.Level.WARNING;
 
+@NotNullByDefault
 class FileTransportReader implements TransportConnectionReader {
 
 	private static final Logger LOG =
@@ -24,10 +26,12 @@ class FileTransportReader implements TransportConnectionReader {
 		this.plugin = plugin;
 	}
 
+	@Override
 	public InputStream getInputStream() {
 		return in;
 	}
 
+	@Override
 	public void dispose(boolean exception, boolean recognised) {
 		try {
 			in.close();
diff --git a/briar-core/src/org/briarproject/plugins/file/FileTransportWriter.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/file/FileTransportWriter.java
similarity index 81%
rename from briar-core/src/org/briarproject/plugins/file/FileTransportWriter.java
rename to bramble-core/src/main/java/org/briarproject/bramble/plugin/file/FileTransportWriter.java
index 94e83fe5b86b0c4bb5bbb3804aed431e5f9b9281..2752f7c8be82ad0ebc9f1323c8884fc6aa067e72 100644
--- a/briar-core/src/org/briarproject/plugins/file/FileTransportWriter.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/file/FileTransportWriter.java
@@ -1,14 +1,16 @@
-package org.briarproject.plugins.file;
+package org.briarproject.bramble.plugin.file;
 
-import static java.util.logging.Level.WARNING;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
 
 import java.io.File;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.util.logging.Logger;
 
-import org.briarproject.api.plugins.TransportConnectionWriter;
+import static java.util.logging.Level.WARNING;
 
+@NotNullByDefault
 class FileTransportWriter implements TransportConnectionWriter {
 
 	private static final Logger LOG =
@@ -27,22 +29,27 @@ class FileTransportWriter implements TransportConnectionWriter {
 		this.plugin = plugin;
 	}
 
+	@Override
 	public int getMaxLatency() {
 		return plugin.getMaxLatency();
 	}
 
+	@Override
 	public int getMaxIdleTime() {
 		return plugin.getMaxIdleTime();
 	}
 
+	@Override
 	public long getCapacity() {
 		return capacity;
 	}
 
+	@Override
 	public OutputStream getOutputStream() {
 		return out;
 	}
 
+	@Override
 	public void dispose(boolean exception) {
 		try {
 			out.close();
diff --git a/briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java
similarity index 88%
rename from briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java
rename to bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java
index f60a0a743c8f922809bb6ffc7e4b31712eae5018..36c06d48533fd9a5ae5723de59657247cc32962f 100644
--- a/briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java
@@ -1,18 +1,18 @@
-package org.briarproject.plugins.tcp;
+package org.briarproject.bramble.plugin.tcp;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.keyagreement.KeyAgreementConnection;
-import org.briarproject.api.keyagreement.KeyAgreementListener;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.plugins.Backoff;
-import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
-import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
-import org.briarproject.api.properties.TransportProperties;
-import org.briarproject.api.settings.Settings;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.Backoff;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
+import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
+import org.briarproject.bramble.api.properties.TransportProperties;
+import org.briarproject.bramble.api.settings.Settings;
+import org.briarproject.bramble.util.StringUtils;
 
 import java.io.IOException;
 import java.net.Inet4Address;
@@ -32,10 +32,10 @@ import java.util.logging.Logger;
 
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_LAN;
-import static org.briarproject.api.plugins.LanTcpConstants.ID;
-import static org.briarproject.util.ByteUtils.MAX_16_BIT_UNSIGNED;
-import static org.briarproject.util.PrivacyUtils.scrubSocketAddress;
+import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_LAN;
+import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
+import static org.briarproject.bramble.util.ByteUtils.MAX_16_BIT_UNSIGNED;
+import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress;
 
 @NotNullByDefault
 class LanTcpPlugin extends TcpPlugin {
diff --git a/briar-core/src/org/briarproject/plugins/tcp/LanTcpPluginFactory.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginFactory.java
similarity index 63%
rename from briar-core/src/org/briarproject/plugins/tcp/LanTcpPluginFactory.java
rename to bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginFactory.java
index 2818666b0be276848ce7f14c32d83597eefd0ca7..a15277c22309b13426785dbfe8fd59bb80f42211 100644
--- a/briar-core/src/org/briarproject/plugins/tcp/LanTcpPluginFactory.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginFactory.java
@@ -1,16 +1,21 @@
-package org.briarproject.plugins.tcp;
+package org.briarproject.bramble.plugin.tcp;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.plugins.Backoff;
-import org.briarproject.api.plugins.BackoffFactory;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
-import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
-import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.Backoff;
+import org.briarproject.bramble.api.plugin.BackoffFactory;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
 
 import java.util.concurrent.Executor;
 
-import static org.briarproject.api.plugins.LanTcpConstants.ID;
+import javax.annotation.concurrent.Immutable;
 
+import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
+
+@Immutable
+@NotNullByDefault
 public class LanTcpPluginFactory implements DuplexPluginFactory {
 
 	private static final int MAX_LATENCY = 30 * 1000; // 30 seconds
diff --git a/briar-core/src/org/briarproject/plugins/tcp/MappingResult.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/MappingResult.java
similarity index 50%
rename from briar-core/src/org/briarproject/plugins/tcp/MappingResult.java
rename to bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/MappingResult.java
index 3e86a9668a9a388c6e4ef290407c6089baacb678..aa9c271f55aaab33c7b7a11132646227b9da96aa 100644
--- a/briar-core/src/org/briarproject/plugins/tcp/MappingResult.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/MappingResult.java
@@ -1,31 +1,42 @@
-package org.briarproject.plugins.tcp;
+package org.briarproject.bramble.plugin.tcp;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 class MappingResult {
 
-	private final InetAddress internal, external;
+	private final InetAddress internal;
+	@Nullable
+	private final InetAddress external;
 	private final int port;
 	private final boolean succeeded;
 
-	MappingResult(InetAddress internal, InetAddress external, int port,
-			boolean succeeded) {
+	MappingResult(InetAddress internal, @Nullable InetAddress external,
+			int port, boolean succeeded) {
 		this.internal = internal;
 		this.external = external;
 		this.port = port;
 		this.succeeded = succeeded;
 	}
 
+	@Nullable
 	InetSocketAddress getInternal() {
 		return isUsable() ? new InetSocketAddress(internal, port) : null;
 	}
 
+	@Nullable
 	InetSocketAddress getExternal() {
 		return isUsable() ? new InetSocketAddress(external, port) : null;
 	}
 
 	boolean isUsable() {
-		return internal != null && external != null && port != 0 && succeeded;
+		return external != null && port != 0 && succeeded;
 	}
 }
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/PortMapper.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/PortMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..3d12a84b81006cfc39a6975a787b76b030a31bb8
--- /dev/null
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/PortMapper.java
@@ -0,0 +1,9 @@
+package org.briarproject.bramble.plugin.tcp;
+
+import javax.annotation.Nullable;
+
+interface PortMapper {
+
+	@Nullable
+	MappingResult map(int port);
+}
diff --git a/briar-core/src/org/briarproject/plugins/tcp/PortMapperImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/PortMapperImpl.java
similarity index 84%
rename from briar-core/src/org/briarproject/plugins/tcp/PortMapperImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/PortMapperImpl.java
index 5e135419bffc799a24049f6cd0102222430fb0e0..2156bd10d12ee90445e96f0e220b2b9a1f05fce8 100644
--- a/briar-core/src/org/briarproject/plugins/tcp/PortMapperImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/PortMapperImpl.java
@@ -1,8 +1,10 @@
-package org.briarproject.plugins.tcp;
+package org.briarproject.bramble.plugin.tcp;
 
 import org.bitlet.weupnp.GatewayDevice;
 import org.bitlet.weupnp.GatewayDiscover;
-import org.briarproject.api.lifecycle.ShutdownManager;
+import org.briarproject.bramble.api.lifecycle.ShutdownManager;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
 import org.xml.sax.SAXException;
 
 import java.io.IOException;
@@ -10,12 +12,16 @@ import java.net.InetAddress;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.logging.Logger;
 
+import javax.annotation.concurrent.ThreadSafe;
 import javax.xml.parsers.ParserConfigurationException;
 
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.util.PrivacyUtils.scrubInetAddress;
+import static org.briarproject.bramble.util.PrivacyUtils.scrubInetAddress;
 
+@ThreadSafe
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 class PortMapperImpl implements PortMapper {
 
 	private static final Logger LOG =
@@ -30,6 +36,7 @@ class PortMapperImpl implements PortMapper {
 		this.shutdownManager = shutdownManager;
 	}
 
+	@Override
 	public MappingResult map(final int port) {
 		if (!started.getAndSet(true)) start();
 		if (gateway == null) return null;
@@ -44,6 +51,7 @@ class PortMapperImpl implements PortMapper {
 					getHostAddress(internal), "TCP", "TCP");
 			if (succeeded) {
 				shutdownManager.addShutdownHook(new Runnable() {
+					@Override
 					public void run() {
 						deleteMapping(port);
 					}
@@ -88,7 +96,7 @@ class PortMapperImpl implements PortMapper {
 		try {
 			gateway.deletePortMapping(port, "TCP");
 			if (LOG.isLoggable(INFO))
-				LOG.info("Deleted mapping for port " + port); 
+				LOG.info("Deleted mapping for port " + port);
 		} catch (IOException e) {
 			if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
 		} catch (SAXException e) {
diff --git a/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java
similarity index 89%
rename from briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java
rename to bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java
index 76da5bf7dd8899d0fdf0da01cf8ae35180c49939..1708e918fec6ef8f9b0841dc7169b05983944fd4 100644
--- a/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java
@@ -1,16 +1,16 @@
-package org.briarproject.plugins.tcp;
-
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.crypto.PseudoRandom;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.keyagreement.KeyAgreementListener;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.plugins.Backoff;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
-import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
-import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
-import org.briarproject.util.StringUtils;
+package org.briarproject.bramble.plugin.tcp;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.crypto.PseudoRandom;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.plugin.Backoff;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
+import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
+import org.briarproject.bramble.util.StringUtils;
 
 import java.io.IOException;
 import java.net.InetAddress;
@@ -34,7 +34,7 @@ import javax.annotation.Nullable;
 
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.util.PrivacyUtils.scrubSocketAddress;
+import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress;
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
@@ -78,7 +78,7 @@ abstract class TcpPlugin implements DuplexPlugin {
 	 */
 	protected abstract boolean isConnectable(InetSocketAddress remote);
 
-	protected TcpPlugin(Executor ioExecutor, Backoff backoff,
+	TcpPlugin(Executor ioExecutor, Backoff backoff,
 			DuplexPluginCallback callback, int maxLatency, int maxIdleTime) {
 		this.ioExecutor = ioExecutor;
 		this.backoff = backoff;
@@ -157,7 +157,7 @@ abstract class TcpPlugin implements DuplexPlugin {
 		}
 	}
 
-	protected String getIpPortString(InetSocketAddress a) {
+	String getIpPortString(InetSocketAddress a) {
 		String addr = a.getAddress().getHostAddress();
 		int percent = addr.indexOf('%');
 		if (percent != -1) addr = addr.substring(0, percent);
@@ -259,7 +259,7 @@ abstract class TcpPlugin implements DuplexPlugin {
 	}
 
 	@Nullable
-	protected InetSocketAddress parseSocketAddress(String ipPort) {
+	InetSocketAddress parseSocketAddress(String ipPort) {
 		if (StringUtils.isNullOrEmpty(ipPort)) return null;
 		String[] split = ipPort.split(":");
 		if (split.length != 2) return null;
@@ -309,7 +309,7 @@ abstract class TcpPlugin implements DuplexPlugin {
 		throw new UnsupportedOperationException();
 	}
 
-	protected Collection<InetAddress> getLocalIpAddresses() {
+	Collection<InetAddress> getLocalIpAddresses() {
 		List<NetworkInterface> ifaces;
 		try {
 			ifaces = Collections.list(NetworkInterface.getNetworkInterfaces());
diff --git a/briar-core/src/org/briarproject/plugins/tcp/TcpTransportConnection.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpTransportConnection.java
similarity index 66%
rename from briar-core/src/org/briarproject/plugins/tcp/TcpTransportConnection.java
rename to bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpTransportConnection.java
index 7d8d33a9ae84c62873b8b581c4bc8c2ac64bd376..97afa37434acf4db2c3f00592d76ef163851325c 100644
--- a/briar-core/src/org/briarproject/plugins/tcp/TcpTransportConnection.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpTransportConnection.java
@@ -1,13 +1,18 @@
-package org.briarproject.plugins.tcp;
+package org.briarproject.bramble.plugin.tcp;
 
-import org.briarproject.api.plugins.Plugin;
-import org.briarproject.api.plugins.duplex.AbstractDuplexTransportConnection;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.Plugin;
+import org.briarproject.bramble.api.plugin.duplex.AbstractDuplexTransportConnection;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.Socket;
 
+import javax.annotation.concurrent.ThreadSafe;
+
+@ThreadSafe
+@NotNullByDefault
 class TcpTransportConnection extends AbstractDuplexTransportConnection {
 
 	private final Socket socket;
diff --git a/briar-core/src/org/briarproject/plugins/tcp/WanTcpPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/WanTcpPlugin.java
similarity index 78%
rename from briar-core/src/org/briarproject/plugins/tcp/WanTcpPlugin.java
rename to bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/WanTcpPlugin.java
index f51767af60a472dbc78e175857ba9bf888d35df6..fe3045728528599aa6f1dd6f06284c55e6564fdb 100644
--- a/briar-core/src/org/briarproject/plugins/tcp/WanTcpPlugin.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/WanTcpPlugin.java
@@ -1,12 +1,12 @@
-package org.briarproject.plugins.tcp;
+package org.briarproject.bramble.plugin.tcp;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.plugins.Backoff;
-import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
-import org.briarproject.api.properties.TransportProperties;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.plugin.Backoff;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
+import org.briarproject.bramble.api.properties.TransportProperties;
 
 import java.net.Inet4Address;
 import java.net.InetAddress;
@@ -16,7 +16,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.Executor;
 
-import static org.briarproject.api.plugins.WanTcpConstants.ID;
+import static org.briarproject.bramble.api.plugin.WanTcpConstants.ID;
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
@@ -58,7 +58,8 @@ class WanTcpPlugin extends TcpPlugin {
 		mappingResult = portMapper.map(port);
 		if (mappingResult != null && mappingResult.isUsable()) {
 			InetSocketAddress a = mappingResult.getInternal();
-			if (a.getAddress() instanceof Inet4Address) addrs.add(a);
+			if (a != null && a.getAddress() instanceof Inet4Address)
+				addrs.add(a);
 		}
 		return addrs;
 	}
@@ -95,8 +96,10 @@ class WanTcpPlugin extends TcpPlugin {
 	protected void setLocalSocketAddress(InetSocketAddress a) {
 		if (mappingResult != null && mappingResult.isUsable()) {
 			// Advertise the external address to contacts
-			if (a.equals(mappingResult.getInternal()))
-				a = mappingResult.getExternal();
+			if (a.equals(mappingResult.getInternal())) {
+				InetSocketAddress external = mappingResult.getExternal();
+				if (external != null) a = external;
+			}
 		}
 		TransportProperties p = new TransportProperties();
 		p.put(PROP_IP_PORT, getIpPortString(a));
diff --git a/briar-core/src/org/briarproject/plugins/tcp/WanTcpPluginFactory.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/WanTcpPluginFactory.java
similarity index 64%
rename from briar-core/src/org/briarproject/plugins/tcp/WanTcpPluginFactory.java
rename to bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/WanTcpPluginFactory.java
index f1fd78bcf5127d375811ef95a4293b86c4f3ece4..42deaaffc455ec6b230f9b6291a4bf395f564686 100644
--- a/briar-core/src/org/briarproject/plugins/tcp/WanTcpPluginFactory.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/WanTcpPluginFactory.java
@@ -1,17 +1,22 @@
-package org.briarproject.plugins.tcp;
+package org.briarproject.bramble.plugin.tcp;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.lifecycle.ShutdownManager;
-import org.briarproject.api.plugins.Backoff;
-import org.briarproject.api.plugins.BackoffFactory;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
-import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
-import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
+import org.briarproject.bramble.api.lifecycle.ShutdownManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.Backoff;
+import org.briarproject.bramble.api.plugin.BackoffFactory;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
 
 import java.util.concurrent.Executor;
 
-import static org.briarproject.api.plugins.WanTcpConstants.ID;
+import javax.annotation.concurrent.Immutable;
 
+import static org.briarproject.bramble.api.plugin.WanTcpConstants.ID;
+
+@Immutable
+@NotNullByDefault
 public class WanTcpPluginFactory implements DuplexPluginFactory {
 
 	private static final int MAX_LATENCY = 30 * 1000; // 30 seconds
diff --git a/briar-core/src/org/briarproject/properties/PropertiesModule.java b/bramble-core/src/main/java/org/briarproject/bramble/properties/PropertiesModule.java
similarity index 54%
rename from briar-core/src/org/briarproject/properties/PropertiesModule.java
rename to bramble-core/src/main/java/org/briarproject/bramble/properties/PropertiesModule.java
index cea2c7504e7a563856d6c7257da8e0c329e3dd29..0078beba5b229396f896a993b15582c17227498e 100644
--- a/briar-core/src/org/briarproject/properties/PropertiesModule.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/properties/PropertiesModule.java
@@ -1,12 +1,12 @@
-package org.briarproject.properties;
+package org.briarproject.bramble.properties;
 
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.properties.TransportPropertyManager;
-import org.briarproject.api.sync.ValidationManager;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.properties.TransportPropertyManager;
+import org.briarproject.bramble.api.sync.ValidationManager;
+import org.briarproject.bramble.api.system.Clock;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -14,14 +14,16 @@ import javax.inject.Singleton;
 import dagger.Module;
 import dagger.Provides;
 
-import static org.briarproject.properties.TransportPropertyManagerImpl.CLIENT_ID;
+import static org.briarproject.bramble.api.properties.TransportPropertyManager.CLIENT_ID;
 
 @Module
 public class PropertiesModule {
 
 	public static class EagerSingletons {
-		@Inject TransportPropertyValidator transportPropertyValidator;
-		@Inject TransportPropertyManager transportPropertyManager;
+		@Inject
+		TransportPropertyValidator transportPropertyValidator;
+		@Inject
+		TransportPropertyManager transportPropertyManager;
 	}
 
 	@Provides
@@ -35,10 +37,10 @@ public class PropertiesModule {
 		return validator;
 	}
 
-	@Provides @Singleton
+	@Provides
+	@Singleton
 	TransportPropertyManager getTransportPropertyManager(
-			LifecycleManager lifecycleManager,
-			ContactManager contactManager,
+			LifecycleManager lifecycleManager, ContactManager contactManager,
 			TransportPropertyManagerImpl transportPropertyManager) {
 		lifecycleManager.registerClient(transportPropertyManager);
 		contactManager.registerAddContactHook(transportPropertyManager);
diff --git a/briar-core/src/org/briarproject/properties/TransportPropertyManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/properties/TransportPropertyManagerImpl.java
similarity index 83%
rename from briar-core/src/org/briarproject/properties/TransportPropertyManagerImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/properties/TransportPropertyManagerImpl.java
index 62b4be0c03b7f2626db5f4612df5e938d85d03ed..1fe72cdfc10655baf714e07b66fece664aa161f5 100644
--- a/briar-core/src/org/briarproject/properties/TransportPropertyManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/properties/TransportPropertyManagerImpl.java
@@ -1,35 +1,40 @@
-package org.briarproject.properties;
+package org.briarproject.bramble.properties;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.clients.Client;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.ContactGroupFactory;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.contact.ContactManager.AddContactHook;
-import org.briarproject.api.contact.ContactManager.RemoveContactHook;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.properties.TransportProperties;
-import org.briarproject.api.properties.TransportPropertyManager;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.client.ContactGroupFactory;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager.AddContactHook;
+import org.briarproject.bramble.api.contact.ContactManager.RemoveContactHook;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.properties.TransportProperties;
+import org.briarproject.bramble.api.properties.TransportPropertyManager;
+import org.briarproject.bramble.api.sync.Client;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.system.Clock;
 
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
 
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-import static org.briarproject.api.sync.Group.Visibility.SHARED;
+import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
 
+@Immutable
+@NotNullByDefault
 class TransportPropertyManagerImpl implements TransportPropertyManager,
 		Client, AddContactHook, RemoveContactHook {
 
@@ -116,6 +121,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
 			for (Entry<TransportId, LatestUpdate> e : latest.entrySet()) {
 				BdfList message = clientHelper.getMessageAsList(txn,
 						e.getValue().messageId);
+				if (message == null) throw new DbException();
 				local.put(e.getKey(), parseProperties(message));
 			}
 			return local;
@@ -138,13 +144,14 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
 					// Retrieve and parse the latest local properties
 					BdfList message = clientHelper.getMessageAsList(txn,
 							latest.messageId);
+					if (message == null) throw new DbException();
 					p = parseProperties(message);
 				}
 				db.commitTransaction(txn);
 			} finally {
 				db.endTransaction(txn);
 			}
-			return p;
+			return p == null ? new TransportProperties() : p;
 		} catch (FormatException e) {
 			throw new DbException(e);
 		}
@@ -168,6 +175,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
 						// Retrieve and parse the latest remote properties
 						BdfList message = clientHelper.getMessageAsList(txn,
 								latest.messageId);
+						if (message == null) throw new DbException();
 						remote.put(c.getId(), parseProperties(message));
 					}
 				}
@@ -198,6 +206,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
 				} else {
 					BdfList message = clientHelper.getMessageAsList(txn,
 							latest.messageId);
+					if (message == null) throw new DbException();
 					TransportProperties old = parseProperties(message);
 					merged = new TransportProperties(old);
 					merged.putAll(p);
@@ -271,6 +280,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
 		return latestUpdates;
 	}
 
+	@Nullable
 	private LatestUpdate findLatest(Transaction txn, GroupId g, TransportId t,
 			boolean local) throws DbException, FormatException {
 		LatestUpdate latest = null;
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/properties/TransportPropertyValidator.java b/bramble-core/src/main/java/org/briarproject/bramble/properties/TransportPropertyValidator.java
new file mode 100644
index 0000000000000000000000000000000000000000..f0431254b9796f06672513202e6a8f6455d738fb
--- /dev/null
+++ b/bramble-core/src/main/java/org/briarproject/bramble/properties/TransportPropertyValidator.java
@@ -0,0 +1,58 @@
+package org.briarproject.bramble.properties;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.BdfMessageContext;
+import org.briarproject.bramble.api.client.BdfMessageValidator;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.system.Clock;
+
+import javax.annotation.concurrent.Immutable;
+
+import static org.briarproject.bramble.api.plugin.TransportId.MAX_TRANSPORT_ID_LENGTH;
+import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MAX_PROPERTIES_PER_TRANSPORT;
+import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
+import static org.briarproject.bramble.util.ValidationUtils.checkLength;
+import static org.briarproject.bramble.util.ValidationUtils.checkSize;
+
+@Immutable
+@NotNullByDefault
+class TransportPropertyValidator extends BdfMessageValidator {
+
+	TransportPropertyValidator(ClientHelper clientHelper,
+			MetadataEncoder metadataEncoder, Clock clock) {
+		super(clientHelper, metadataEncoder, clock);
+	}
+
+	@Override
+	protected BdfMessageContext validateMessage(Message m, Group g,
+			BdfList body) throws FormatException {
+		// Transport ID, version, properties
+		checkSize(body, 3);
+		// Transport ID
+		String transportId = body.getString(0);
+		checkLength(transportId, 1, MAX_TRANSPORT_ID_LENGTH);
+		// Version
+		long version = body.getLong(1);
+		if (version < 0) throw new FormatException();
+		// Properties
+		BdfDictionary dictionary = body.getDictionary(2);
+		checkSize(dictionary, 0, MAX_PROPERTIES_PER_TRANSPORT);
+		for (String key : dictionary.keySet()) {
+			checkLength(key, 0, MAX_PROPERTY_LENGTH);
+			String value = dictionary.getString(key);
+			checkLength(value, 0, MAX_PROPERTY_LENGTH);
+		}
+		// Return the metadata
+		BdfDictionary meta = new BdfDictionary();
+		meta.put("transportId", transportId);
+		meta.put("version", version);
+		meta.put("local", false);
+		return new BdfMessageContext(meta);
+	}
+}
diff --git a/briar-core/src/org/briarproject/reliability/Ack.java b/bramble-core/src/main/java/org/briarproject/bramble/reliability/Ack.java
similarity index 54%
rename from briar-core/src/org/briarproject/reliability/Ack.java
rename to bramble-core/src/main/java/org/briarproject/bramble/reliability/Ack.java
index 1f5352c62926019ad8024de8c952be25a3c0332c..737e32fd53a57714646f07b4f96a96feccbcc614 100644
--- a/briar-core/src/org/briarproject/reliability/Ack.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/reliability/Ack.java
@@ -1,20 +1,25 @@
-package org.briarproject.reliability;
+package org.briarproject.bramble.reliability;
 
-import org.briarproject.util.ByteUtils;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.util.ByteUtils;
 
+import javax.annotation.concurrent.NotThreadSafe;
+
+@NotThreadSafe
+@NotNullByDefault
 class Ack extends Frame {
 
 	static final int LENGTH = 11;
 
 	Ack() {
 		super(new byte[LENGTH]);
-		buf[0] = (byte) Frame.ACK_FLAG;
+		buf[0] = Frame.ACK_FLAG;
 	}
 
 	Ack(byte[] buf) {
 		super(buf);
 		if (buf.length != LENGTH) throw new IllegalArgumentException();
-		buf[0] = (byte) Frame.ACK_FLAG;
+		buf[0] = Frame.ACK_FLAG;
 	}
 
 	int getWindowSize() {
diff --git a/briar-core/src/org/briarproject/reliability/Crc32.java b/bramble-core/src/main/java/org/briarproject/bramble/reliability/Crc32.java
similarity index 80%
rename from briar-core/src/org/briarproject/reliability/Crc32.java
rename to bramble-core/src/main/java/org/briarproject/bramble/reliability/Crc32.java
index 1b456fb77786516b8e7727397cb3f2085b11b22a..b4cf7bc25d726e9766eb81248df55682b671509e 100644
--- a/briar-core/src/org/briarproject/reliability/Crc32.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/reliability/Crc32.java
@@ -1,5 +1,8 @@
-package org.briarproject.reliability;
+package org.briarproject.bramble.reliability;
 
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
 class Crc32 {
 
 	private static final long[] TABLE = new long[256];
diff --git a/briar-core/src/org/briarproject/reliability/Data.java b/bramble-core/src/main/java/org/briarproject/bramble/reliability/Data.java
similarity index 70%
rename from briar-core/src/org/briarproject/reliability/Data.java
rename to bramble-core/src/main/java/org/briarproject/bramble/reliability/Data.java
index 09edb4e61972f930f0bdee12b2d8ad36fa5485c2..ab33b67cd444fb759a4cd486882e65a19c769663 100644
--- a/briar-core/src/org/briarproject/reliability/Data.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/reliability/Data.java
@@ -1,5 +1,11 @@
-package org.briarproject.reliability;
+package org.briarproject.bramble.reliability;
 
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.NotThreadSafe;
+
+@NotThreadSafe
+@NotNullByDefault
 class Data extends Frame {
 
 	static final int HEADER_LENGTH = 5, FOOTER_LENGTH = 4;
@@ -18,7 +24,7 @@ class Data extends Frame {
 	}
 
 	void setLastFrame(boolean lastFrame) {
-		if (lastFrame) buf[0] = (byte) Frame.FIN_FLAG;
+		if (lastFrame) buf[0] = Frame.FIN_FLAG;
 	}
 
 	int getPayloadLength() {
diff --git a/briar-core/src/org/briarproject/reliability/Frame.java b/bramble-core/src/main/java/org/briarproject/bramble/reliability/Frame.java
similarity index 79%
rename from briar-core/src/org/briarproject/reliability/Frame.java
rename to bramble-core/src/main/java/org/briarproject/bramble/reliability/Frame.java
index 65d9a4c81a78300d99330153456de1bb7ecef11d..6e5d1969c5ff2a50c7e5b2372510c0605ae9a3e6 100644
--- a/briar-core/src/org/briarproject/reliability/Frame.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/reliability/Frame.java
@@ -1,14 +1,19 @@
-package org.briarproject.reliability;
+package org.briarproject.bramble.reliability;
 
-import org.briarproject.util.ByteUtils;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.util.ByteUtils;
 
+import javax.annotation.concurrent.NotThreadSafe;
+
+@NotThreadSafe
+@NotNullByDefault
 abstract class Frame {
 
 	static final byte ACK_FLAG = (byte) 128, FIN_FLAG = 64;
 
 	protected final byte[] buf;
 
-	protected Frame(byte[] buf) {
+	Frame(byte[] buf) {
 		this.buf = buf;
 	}
 
diff --git a/briar-core/src/org/briarproject/reliability/Receiver.java b/bramble-core/src/main/java/org/briarproject/bramble/reliability/Receiver.java
similarity index 86%
rename from briar-core/src/org/briarproject/reliability/Receiver.java
rename to bramble-core/src/main/java/org/briarproject/bramble/reliability/Receiver.java
index b45dcfafe77e97818a3562600e79fadef2cb7411..c5c5de2e28de374e68f1d1205d68ffefc4822bba 100644
--- a/briar-core/src/org/briarproject/reliability/Receiver.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/reliability/Receiver.java
@@ -1,6 +1,8 @@
-package org.briarproject.reliability;
+package org.briarproject.bramble.reliability;
 
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.reliability.ReadHandler;
+import org.briarproject.bramble.api.system.Clock;
 
 import java.io.IOException;
 import java.util.Comparator;
@@ -11,9 +13,12 @@ import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
-import org.briarproject.api.reliability.ReadHandler;
-import org.briarproject.api.system.Clock;
+import javax.annotation.concurrent.ThreadSafe;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
 
+@ThreadSafe
+@NotNullByDefault
 class Receiver implements ReadHandler {
 
 	private static final int READ_TIMEOUT = 5 * 60 * 1000; // Milliseconds
@@ -80,19 +85,19 @@ class Receiver implements ReadHandler {
 		}
 	}
 
+	@Override
 	public void handleRead(byte[] b) throws IOException {
 		if (!valid) throw new IOException("Connection closed");
-		switch(b[0]) {
-		case 0:
-		case Frame.FIN_FLAG:
-			handleData(b);
-			break;
-		case Frame.ACK_FLAG:
-			sender.handleAck(b);
-			break;
-		default:
-			// Ignore unknown frame type
-			return;
+		switch (b[0]) {
+			case 0:
+			case Frame.FIN_FLAG:
+				handleData(b);
+				break;
+			case Frame.ACK_FLAG:
+				sender.handleAck(b);
+				break;
+			default:
+				// Ignore unknown frame type
 		}
 	}
 
@@ -121,7 +126,8 @@ class Receiver implements ReadHandler {
 				Iterator<Data> it = dataFrames.iterator();
 				while (it.hasNext()) {
 					Data d1 = it.next();
-					if (d1.getSequenceNumber() >= finalSequenceNumber) it.remove();
+					if (d1.getSequenceNumber() >= finalSequenceNumber)
+						it.remove();
 				}
 				if (dataFrames.add(d)) {
 					windowSize -= payloadLength;
@@ -142,6 +148,7 @@ class Receiver implements ReadHandler {
 
 	private static class SequenceNumberComparator implements Comparator<Data> {
 
+		@Override
 		public int compare(Data d1, Data d2) {
 			long s1 = d1.getSequenceNumber(), s2 = d2.getSequenceNumber();
 			if (s1 < s2) return -1;
diff --git a/briar-core/src/org/briarproject/reliability/ReceiverInputStream.java b/bramble-core/src/main/java/org/briarproject/bramble/reliability/ReceiverInputStream.java
similarity index 76%
rename from briar-core/src/org/briarproject/reliability/ReceiverInputStream.java
rename to bramble-core/src/main/java/org/briarproject/bramble/reliability/ReceiverInputStream.java
index ac520f1912776a8a2028a85de0951b41dddf3035..6c0b838b973c922255d58b171603e6ff80792ee5 100644
--- a/briar-core/src/org/briarproject/reliability/ReceiverInputStream.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/reliability/ReceiverInputStream.java
@@ -1,12 +1,20 @@
-package org.briarproject.reliability;
+package org.briarproject.bramble.reliability;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.IOException;
 import java.io.InputStream;
 
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.NotThreadSafe;
+
+@NotThreadSafe
+@NotNullByDefault
 class ReceiverInputStream extends InputStream {
 
 	private final Receiver receiver;
 
+	@Nullable
 	private Data data = null;
 	private int offset = 0, length = 0;
 
@@ -18,6 +26,7 @@ class ReceiverInputStream extends InputStream {
 	public int read() throws IOException {
 		if (length == -1) return -1;
 		while (length == 0) if (!receive()) return -1;
+		if (data == null) throw new AssertionError();
 		int b = data.getBuffer()[offset] & 0xff;
 		offset++;
 		length--;
@@ -33,6 +42,7 @@ class ReceiverInputStream extends InputStream {
 	public int read(byte[] b, int off, int len) throws IOException {
 		if (length == -1) return -1;
 		while (length == 0) if (!receive()) return -1;
+		if (data == null) throw new AssertionError();
 		len = Math.min(len, length);
 		System.arraycopy(data.getBuffer(), offset, b, off, len);
 		offset += len;
@@ -41,7 +51,7 @@ class ReceiverInputStream extends InputStream {
 	}
 
 	private boolean receive() throws IOException {
-		assert length == 0;
+		if (length != 0) throw new AssertionError();
 		if (data != null && data.isLastFrame()) {
 			length = -1;
 			return false;
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/reliability/ReliabilityLayerFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/reliability/ReliabilityLayerFactoryImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..fbe4b18233efba77eaf63931b954bfdcbc303285
--- /dev/null
+++ b/bramble-core/src/main/java/org/briarproject/bramble/reliability/ReliabilityLayerFactoryImpl.java
@@ -0,0 +1,33 @@
+package org.briarproject.bramble.reliability;
+
+import org.briarproject.bramble.api.lifecycle.IoExecutor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.reliability.ReliabilityLayer;
+import org.briarproject.bramble.api.reliability.ReliabilityLayerFactory;
+import org.briarproject.bramble.api.reliability.WriteHandler;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.bramble.system.SystemClock;
+
+import java.util.concurrent.Executor;
+
+import javax.annotation.concurrent.Immutable;
+import javax.inject.Inject;
+
+@Immutable
+@NotNullByDefault
+class ReliabilityLayerFactoryImpl implements ReliabilityLayerFactory {
+
+	private final Executor ioExecutor;
+	private final Clock clock;
+
+	@Inject
+	ReliabilityLayerFactoryImpl(@IoExecutor Executor ioExecutor) {
+		this.ioExecutor = ioExecutor;
+		clock = new SystemClock();
+	}
+
+	@Override
+	public ReliabilityLayer createReliabilityLayer(WriteHandler writeHandler) {
+		return new ReliabilityLayerImpl(ioExecutor, clock, writeHandler);
+	}
+}
diff --git a/briar-core/src/org/briarproject/reliability/ReliabilityLayerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/reliability/ReliabilityLayerImpl.java
similarity index 85%
rename from briar-core/src/org/briarproject/reliability/ReliabilityLayerImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/reliability/ReliabilityLayerImpl.java
index 5058984731326e4ebed7a0ed44a1f102e397f852..b6b60ef9d659c757cbd7cd8d6de8a85b38037012 100644
--- a/briar-core/src/org/briarproject/reliability/ReliabilityLayerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/reliability/ReliabilityLayerImpl.java
@@ -1,7 +1,10 @@
-package org.briarproject.reliability;
+package org.briarproject.bramble.reliability;
 
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.logging.Level.WARNING;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.reliability.ReliabilityLayer;
+import org.briarproject.bramble.api.reliability.WriteHandler;
+import org.briarproject.bramble.api.system.Clock;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -11,10 +14,11 @@ import java.util.concurrent.Executor;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.logging.Logger;
 
-import org.briarproject.api.reliability.ReliabilityLayer;
-import org.briarproject.api.reliability.WriteHandler;
-import org.briarproject.api.system.Clock;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.logging.Level.WARNING;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 class ReliabilityLayerImpl implements ReliabilityLayer, WriteHandler {
 
 	private static final int TICK_INTERVAL = 500; // Milliseconds
@@ -41,6 +45,7 @@ class ReliabilityLayerImpl implements ReliabilityLayer, WriteHandler {
 		writes = new LinkedBlockingQueue<byte[]>();
 	}
 
+	@Override
 	public void start() {
 		SlipEncoder encoder = new SlipEncoder(this);
 		final Sender sender = new Sender(clock, encoder);
@@ -50,6 +55,7 @@ class ReliabilityLayerImpl implements ReliabilityLayer, WriteHandler {
 		outputStream = new SenderOutputStream(sender);
 		running = true;
 		executor.execute(new Runnable() {
+			@Override
 			public void run() {
 				long now = clock.currentTimeMillis();
 				long next = now + TICK_INTERVAL;
@@ -82,26 +88,31 @@ class ReliabilityLayerImpl implements ReliabilityLayer, WriteHandler {
 		});
 	}
 
+	@Override
 	public void stop() {
 		running = false;
 		receiver.invalidate();
 		writes.add(new byte[0]); // Poison pill
 	}
 
+	@Override
 	public InputStream getInputStream() {
 		return inputStream;
 	}
 
+	@Override
 	public OutputStream getOutputStream() {
 		return outputStream;
 	}
 
 	// The lower layer calls this method to pass data up to the SLIP decoder
+	@Override
 	public void handleRead(byte[] b) throws IOException {
 		if (running) decoder.handleRead(b);
 	}
 
 	// The SLIP encoder calls this method to pass data down to the lower layer
+	@Override
 	public void handleWrite(byte[] b) {
 		if (running && b.length > 0) writes.add(b);
 	}
diff --git a/briar-core/src/org/briarproject/reliability/ReliabilityModule.java b/bramble-core/src/main/java/org/briarproject/bramble/reliability/ReliabilityModule.java
similarity index 56%
rename from briar-core/src/org/briarproject/reliability/ReliabilityModule.java
rename to bramble-core/src/main/java/org/briarproject/bramble/reliability/ReliabilityModule.java
index 092f218b34a13d71972a5a742b3e23b0c17c29be..a4431a42254a740229306644fba522b7185d6730 100644
--- a/briar-core/src/org/briarproject/reliability/ReliabilityModule.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/reliability/ReliabilityModule.java
@@ -1,12 +1,10 @@
-package org.briarproject.reliability;
+package org.briarproject.bramble.reliability;
 
-import org.briarproject.api.lifecycle.IoExecutor;
-import org.briarproject.api.reliability.ReliabilityLayerFactory;
+import org.briarproject.bramble.api.lifecycle.IoExecutor;
+import org.briarproject.bramble.api.reliability.ReliabilityLayerFactory;
 
 import java.util.concurrent.Executor;
 
-import javax.inject.Named;
-
 import dagger.Module;
 import dagger.Provides;
 
@@ -14,8 +12,8 @@ import dagger.Provides;
 public class ReliabilityModule {
 
 	@Provides
-	ReliabilityLayerFactory provideReliabilityFactoryByExector(@IoExecutor
-	Executor ioExecutor) {
+	ReliabilityLayerFactory provideReliabilityFactoryByExector(
+			@IoExecutor Executor ioExecutor) {
 		return new ReliabilityLayerFactoryImpl(ioExecutor);
 	}
 
diff --git a/briar-core/src/org/briarproject/reliability/Sender.java b/bramble-core/src/main/java/org/briarproject/bramble/reliability/Sender.java
similarity index 94%
rename from briar-core/src/org/briarproject/reliability/Sender.java
rename to bramble-core/src/main/java/org/briarproject/bramble/reliability/Sender.java
index 06d5e3efc8371ff2a57705a2ca0a9539644c7325..3062780994376cfcb633856f6820fe174ecae5a5 100644
--- a/briar-core/src/org/briarproject/reliability/Sender.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/reliability/Sender.java
@@ -1,6 +1,8 @@
-package org.briarproject.reliability;
+package org.briarproject.bramble.reliability;
 
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.reliability.WriteHandler;
+import org.briarproject.bramble.api.system.Clock;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -11,9 +13,12 @@ import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
-import org.briarproject.api.reliability.WriteHandler;
-import org.briarproject.api.system.Clock;
+import javax.annotation.concurrent.ThreadSafe;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
 
+@ThreadSafe
+@NotNullByDefault
 class Sender {
 
 	// All times are in milliseconds
@@ -169,7 +174,8 @@ class Sender {
 		try {
 			// Wait for space in the window
 			long now = clock.currentTimeMillis(), end = now + WRITE_TIMEOUT;
-			while (now < end && outstandingBytes + payloadLength >= windowSize) {
+			while (now < end &&
+					outstandingBytes + payloadLength >= windowSize) {
 				dataWaiting = true;
 				sendWindowAvailable.await(end - now, MILLISECONDS);
 				now = clock.currentTimeMillis();
diff --git a/briar-core/src/org/briarproject/reliability/SenderOutputStream.java b/bramble-core/src/main/java/org/briarproject/bramble/reliability/SenderOutputStream.java
similarity index 91%
rename from briar-core/src/org/briarproject/reliability/SenderOutputStream.java
rename to bramble-core/src/main/java/org/briarproject/bramble/reliability/SenderOutputStream.java
index 715fadaff291714146031518f31b3aaba510bbad..b90494b529f35816e06565209f127d2a83467755 100644
--- a/briar-core/src/org/briarproject/reliability/SenderOutputStream.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/reliability/SenderOutputStream.java
@@ -1,8 +1,14 @@
-package org.briarproject.reliability;
+package org.briarproject.bramble.reliability;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.IOException;
 import java.io.OutputStream;
 
+import javax.annotation.concurrent.NotThreadSafe;
+
+@NotThreadSafe
+@NotNullByDefault
 class SenderOutputStream extends OutputStream {
 
 	private final Sender sender;
diff --git a/briar-core/src/org/briarproject/reliability/SlipDecoder.java b/bramble-core/src/main/java/org/briarproject/bramble/reliability/SlipDecoder.java
similarity index 86%
rename from briar-core/src/org/briarproject/reliability/SlipDecoder.java
rename to bramble-core/src/main/java/org/briarproject/bramble/reliability/SlipDecoder.java
index 3ad966a79bd528a8cd1d99e08795e163847e534b..b4ca04c94d5ddaa40fa61f1b0b590b9aed308e9f 100644
--- a/briar-core/src/org/briarproject/reliability/SlipDecoder.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/reliability/SlipDecoder.java
@@ -1,9 +1,14 @@
-package org.briarproject.reliability;
+package org.briarproject.bramble.reliability;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.reliability.ReadHandler;
 
 import java.io.IOException;
 
-import org.briarproject.api.reliability.ReadHandler;
+import javax.annotation.concurrent.Immutable;
 
+@Immutable
+@NotNullByDefault
 class SlipDecoder implements ReadHandler {
 
 	// https://tools.ietf.org/html/rfc1055
@@ -21,6 +26,7 @@ class SlipDecoder implements ReadHandler {
 		buf = new byte[maxDecodedLength];
 	}
 
+	@Override
 	public void handleRead(byte[] b) throws IOException {
 		for (int i = 0; i < b.length; i++) {
 			switch(b[i]) {
diff --git a/briar-core/src/org/briarproject/reliability/SlipEncoder.java b/bramble-core/src/main/java/org/briarproject/bramble/reliability/SlipEncoder.java
similarity index 78%
rename from briar-core/src/org/briarproject/reliability/SlipEncoder.java
rename to bramble-core/src/main/java/org/briarproject/bramble/reliability/SlipEncoder.java
index 2051f63049ba59ad35f6226f4b09b5cd279ef1e6..1d7710845371425805c2dc24ce01713699a5315d 100644
--- a/briar-core/src/org/briarproject/reliability/SlipEncoder.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/reliability/SlipEncoder.java
@@ -1,9 +1,14 @@
-package org.briarproject.reliability;
+package org.briarproject.bramble.reliability;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.reliability.WriteHandler;
 
 import java.io.IOException;
 
-import org.briarproject.api.reliability.WriteHandler;
+import javax.annotation.concurrent.Immutable;
 
+@Immutable
+@NotNullByDefault
 class SlipEncoder implements WriteHandler {
 
 	// https://tools.ietf.org/html/rfc1055
@@ -16,6 +21,7 @@ class SlipEncoder implements WriteHandler {
 		this.writeHandler = writeHandler;
 	}
 
+	@Override
 	public void handleWrite(byte[] b) throws IOException {
 		int encodedLength = b.length + 2;
 		for (int i = 0; i < b.length; i++)
diff --git a/briar-core/src/org/briarproject/reporting/DevReportServer.java b/bramble-core/src/main/java/org/briarproject/bramble/reporting/DevReportServer.java
similarity index 87%
rename from briar-core/src/org/briarproject/reporting/DevReportServer.java
rename to bramble-core/src/main/java/org/briarproject/bramble/reporting/DevReportServer.java
index e8e0ffa97f0786b729918c9e6d2364e9269efb54..5490c7ee099b192e413950d7d30092e21a0efa9d 100644
--- a/briar-core/src/org/briarproject/reporting/DevReportServer.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/reporting/DevReportServer.java
@@ -1,4 +1,6 @@
-package org.briarproject.reporting;
+package org.briarproject.bramble.reporting;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.Closeable;
 import java.io.File;
@@ -11,6 +13,11 @@ import java.net.ServerSocket;
 import java.net.Socket;
 import java.util.concurrent.Semaphore;
 
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 public class DevReportServer {
 
 	private static final String FILE_PREFIX = "report-";
@@ -43,7 +50,23 @@ public class DevReportServer {
 		} catch (InterruptedException e) {
 			System.err.println("Interrupted while listening");
 		} finally {
-			ss.close();
+			tryToClose(ss);
+		}
+	}
+
+	private void tryToClose(@Nullable ServerSocket ss) {
+		try {
+			if (ss != null) ss.close();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+
+	private void tryToClose(@Nullable Closeable c) {
+		try {
+			if (c != null) c.close();
+		} catch (IOException e) {
+			e.printStackTrace();
 		}
 	}
 
@@ -133,13 +156,5 @@ public class DevReportServer {
 				tryToClose(out);
 			}
 		}
-
-		private void tryToClose(Closeable c) {
-			try {
-				if (c != null) c.close();
-			} catch (IOException e) {
-				e.printStackTrace();
-			}
-		}
 	}
 }
diff --git a/briar-core/src/org/briarproject/reporting/DevReporterImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/reporting/DevReporterImpl.java
similarity index 82%
rename from briar-core/src/org/briarproject/reporting/DevReporterImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/reporting/DevReporterImpl.java
index e9df7058280cb951a5f1e429a55a3b0b3d195408..919b6f240c54c8e1da69b2cc7dfaf6c1d9d730ad 100644
--- a/briar-core/src/org/briarproject/reporting/DevReporterImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/reporting/DevReporterImpl.java
@@ -1,10 +1,11 @@
-package org.briarproject.reporting;
+package org.briarproject.bramble.reporting;
 
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.reporting.DevConfig;
-import org.briarproject.api.reporting.DevReporter;
-import org.briarproject.util.IoUtils;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.reporting.DevConfig;
+import org.briarproject.bramble.api.reporting.DevReporter;
+import org.briarproject.bramble.util.IoUtils;
+import org.briarproject.bramble.util.StringUtils;
 
 import java.io.Closeable;
 import java.io.File;
@@ -19,10 +20,14 @@ import java.io.PrintWriter;
 import java.net.Socket;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
 import javax.net.SocketFactory;
 
 import static java.util.logging.Level.WARNING;
 
+@Immutable
+@NotNullByDefault
 class DevReporterImpl implements DevReporter {
 
 	private static final Logger LOG =
@@ -102,7 +107,7 @@ class DevReporterImpl implements DevReporter {
 		LOG.info("Reports sent");
 	}
 
-	private void tryToClose(Closeable c) {
+	private void tryToClose(@Nullable Closeable c) {
 		try {
 			if (c != null) c.close();
 		} catch (IOException e) {
@@ -110,7 +115,7 @@ class DevReporterImpl implements DevReporter {
 		}
 	}
 
-	private void tryToClose(Socket s) {
+	private void tryToClose(@Nullable Socket s) {
 		try {
 			if (s != null) s.close();
 		} catch (IOException e) {
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/reporting/ReportingModule.java b/bramble-core/src/main/java/org/briarproject/bramble/reporting/ReportingModule.java
new file mode 100644
index 0000000000000000000000000000000000000000..1996ea86b7371cead85901be4f2d215ec35fd296
--- /dev/null
+++ b/bramble-core/src/main/java/org/briarproject/bramble/reporting/ReportingModule.java
@@ -0,0 +1,20 @@
+package org.briarproject.bramble.reporting;
+
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.reporting.DevConfig;
+import org.briarproject.bramble.api.reporting.DevReporter;
+
+import javax.net.SocketFactory;
+
+import dagger.Module;
+import dagger.Provides;
+
+@Module
+public class ReportingModule {
+
+	@Provides
+	DevReporter provideDevReporter(CryptoComponent crypto,
+			DevConfig devConfig, SocketFactory torSocketFactory) {
+		return new DevReporterImpl(crypto, devConfig, torSocketFactory);
+	}
+}
diff --git a/briar-core/src/org/briarproject/settings/SettingsManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/settings/SettingsManagerImpl.java
similarity index 61%
rename from briar-core/src/org/briarproject/settings/SettingsManagerImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/settings/SettingsManagerImpl.java
index cfd20daf2314e3115d6ff3ddcd980e42b6c4a3ca..5663f8e8b10c2e4cff2ccd85acf2bd23e9f85664 100644
--- a/briar-core/src/org/briarproject/settings/SettingsManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/settings/SettingsManagerImpl.java
@@ -1,14 +1,17 @@
-package org.briarproject.settings;
+package org.briarproject.bramble.settings;
 
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.settings.Settings;
+import org.briarproject.bramble.api.settings.SettingsManager;
 
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.settings.Settings;
-import org.briarproject.api.settings.SettingsManager;
-
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
+@Immutable
+@NotNullByDefault
 class SettingsManagerImpl implements SettingsManager {
 
 	private final DatabaseComponent db;
diff --git a/briar-core/src/org/briarproject/settings/SettingsModule.java b/bramble-core/src/main/java/org/briarproject/bramble/settings/SettingsModule.java
similarity index 53%
rename from briar-core/src/org/briarproject/settings/SettingsModule.java
rename to bramble-core/src/main/java/org/briarproject/bramble/settings/SettingsModule.java
index b9edc99515f8f727f86351fec1c64b6305c64850..3c0900d73efab89398f995b76c177301bd2cd2c2 100644
--- a/briar-core/src/org/briarproject/settings/SettingsModule.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/settings/SettingsModule.java
@@ -1,8 +1,7 @@
-package org.briarproject.settings;
+package org.briarproject.bramble.settings;
 
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.settings.SettingsManager;
-import org.briarproject.db.DatabaseModule;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.settings.SettingsManager;
 
 import dagger.Module;
 import dagger.Provides;
diff --git a/briar-core/src/org/briarproject/socks/SocksModule.java b/bramble-core/src/main/java/org/briarproject/bramble/socks/SocksModule.java
similarity index 63%
rename from briar-core/src/org/briarproject/socks/SocksModule.java
rename to bramble-core/src/main/java/org/briarproject/bramble/socks/SocksModule.java
index eaaa3c4d6231cb52b47949e07d31ca52151bec15..1fe9f31c6fb7c3623e7ce4dcc4081a0dd86614e5 100644
--- a/briar-core/src/org/briarproject/socks/SocksModule.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/socks/SocksModule.java
@@ -1,4 +1,4 @@
-package org.briarproject.socks;
+package org.briarproject.bramble.socks;
 
 import java.net.InetSocketAddress;
 
@@ -7,8 +7,8 @@ import javax.net.SocketFactory;
 import dagger.Module;
 import dagger.Provides;
 
-import static org.briarproject.api.plugins.TorConstants.CONNECT_TO_PROXY_TIMEOUT;
-import static org.briarproject.api.plugins.TorConstants.SOCKS_PORT;
+import static org.briarproject.bramble.api.plugin.TorConstants.CONNECT_TO_PROXY_TIMEOUT;
+import static org.briarproject.bramble.api.plugin.TorConstants.SOCKS_PORT;
 
 @Module
 public class SocksModule {
diff --git a/briar-core/src/org/briarproject/socks/SocksSocket.java b/bramble-core/src/main/java/org/briarproject/bramble/socks/SocksSocket.java
similarity index 96%
rename from briar-core/src/org/briarproject/socks/SocksSocket.java
rename to bramble-core/src/main/java/org/briarproject/bramble/socks/SocksSocket.java
index 7c627daef947e0bd3207c3046a3e9b888ca146ad..2265966265cdccfdaad8f60726c8a193cb1162fe 100644
--- a/briar-core/src/org/briarproject/socks/SocksSocket.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/socks/SocksSocket.java
@@ -1,7 +1,7 @@
-package org.briarproject.socks;
+package org.briarproject.bramble.socks;
 
-import org.briarproject.util.ByteUtils;
-import org.briarproject.util.IoUtils;
+import org.briarproject.bramble.util.ByteUtils;
+import org.briarproject.bramble.util.IoUtils;
 
 import java.io.IOException;
 import java.io.InputStream;
diff --git a/briar-core/src/org/briarproject/socks/SocksSocketFactory.java b/bramble-core/src/main/java/org/briarproject/bramble/socks/SocksSocketFactory.java
similarity index 96%
rename from briar-core/src/org/briarproject/socks/SocksSocketFactory.java
rename to bramble-core/src/main/java/org/briarproject/bramble/socks/SocksSocketFactory.java
index dfcd973597429e955de2b21cfa50bbbbe22ad42c..adc5265fb989256aca09cfbfb8a7e408d55730d0 100644
--- a/briar-core/src/org/briarproject/socks/SocksSocketFactory.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/socks/SocksSocketFactory.java
@@ -1,4 +1,4 @@
-package org.briarproject.socks;
+package org.briarproject.bramble.socks;
 
 import java.io.IOException;
 import java.net.InetAddress;
diff --git a/briar-core/src/org/briarproject/sync/DuplexOutgoingSession.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/DuplexOutgoingSession.java
similarity index 79%
rename from briar-core/src/org/briarproject/sync/DuplexOutgoingSession.java
rename to bramble-core/src/main/java/org/briarproject/bramble/sync/DuplexOutgoingSession.java
index a4c8f499f26bd2c47f0064a7bee8ca0e133b5b12..c8b306fdaae6680ebc12bb0b3662ca4a21868f08 100644
--- a/briar-core/src/org/briarproject/sync/DuplexOutgoingSession.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/DuplexOutgoingSession.java
@@ -1,25 +1,28 @@
-package org.briarproject.sync;
-
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.ContactRemovedEvent;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.GroupVisibilityUpdatedEvent;
-import org.briarproject.api.event.MessageRequestedEvent;
-import org.briarproject.api.event.MessageSharedEvent;
-import org.briarproject.api.event.MessageToAckEvent;
-import org.briarproject.api.event.MessageToRequestEvent;
-import org.briarproject.api.event.ShutdownEvent;
-import org.briarproject.api.sync.Ack;
-import org.briarproject.api.sync.Offer;
-import org.briarproject.api.sync.PacketWriter;
-import org.briarproject.api.sync.Request;
-import org.briarproject.api.sync.SyncSession;
-import org.briarproject.api.system.Clock;
+package org.briarproject.bramble.sync;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.lifecycle.IoExecutor;
+import org.briarproject.bramble.api.lifecycle.event.ShutdownEvent;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Ack;
+import org.briarproject.bramble.api.sync.Offer;
+import org.briarproject.bramble.api.sync.PacketWriter;
+import org.briarproject.bramble.api.sync.Request;
+import org.briarproject.bramble.api.sync.SyncSession;
+import org.briarproject.bramble.api.sync.event.GroupVisibilityUpdatedEvent;
+import org.briarproject.bramble.api.sync.event.MessageRequestedEvent;
+import org.briarproject.bramble.api.sync.event.MessageSharedEvent;
+import org.briarproject.bramble.api.sync.event.MessageToAckEvent;
+import org.briarproject.bramble.api.sync.event.MessageToRequestEvent;
+import org.briarproject.bramble.api.system.Clock;
 
 import java.io.IOException;
 import java.util.Collection;
@@ -28,18 +31,22 @@ import java.util.concurrent.Executor;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.logging.Logger;
 
+import javax.annotation.concurrent.ThreadSafe;
+
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_IDS;
-import static org.briarproject.api.sync.SyncConstants.MAX_PACKET_PAYLOAD_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_IDS;
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_PACKET_PAYLOAD_LENGTH;
 
 /**
- * An outgoing {@link org.briarproject.api.sync.SyncSession SyncSession}
- * suitable for duplex transports. The session offers messages before sending
- * them, keeps its output stream open when there are no packets to send, and
- * reacts to events that make packets available to send.
+ * An outgoing {@link SyncSession} suitable for duplex transports. The session
+ * offers messages before sending them, keeps its output stream open when there
+ * are no packets to send, and reacts to events that make packets available to
+ * send.
  */
+@ThreadSafe
+@NotNullByDefault
 class DuplexOutgoingSession implements SyncSession, EventListener {
 
 	// Check for retransmittable packets once every 60 seconds
@@ -49,7 +56,9 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
 
 	private static final ThrowingRunnable<IOException> CLOSE =
 			new ThrowingRunnable<IOException>() {
-				public void run() {}
+				@Override
+				public void run() {
+				}
 			};
 
 	private final DatabaseComponent db;
@@ -77,6 +86,8 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
 		writerTasks = new LinkedBlockingQueue<ThrowingRunnable<IOException>>();
 	}
 
+	@IoExecutor
+	@Override
 	public void run() throws IOException {
 		eventBus.addListener(this);
 		try {
@@ -136,11 +147,13 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
 		}
 	}
 
+	@Override
 	public void interrupt() {
 		interrupted = true;
 		writerTasks.add(CLOSE);
 	}
 
+	@Override
 	public void eventOccurred(Event e) {
 		if (e instanceof ContactRemovedEvent) {
 			ContactRemovedEvent c = (ContactRemovedEvent) e;
@@ -165,9 +178,10 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
 		}
 	}
 
-	// This task runs on the database thread
 	private class GenerateAck implements Runnable {
 
+		@DatabaseExecutor
+		@Override
 		public void run() {
 			if (interrupted) return;
 			try {
@@ -189,7 +203,6 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
 		}
 	}
 
-	// This task runs on the writer thread
 	private class WriteAck implements ThrowingRunnable<IOException> {
 
 		private final Ack ack;
@@ -198,6 +211,8 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
 			this.ack = ack;
 		}
 
+		@IoExecutor
+		@Override
 		public void run() throws IOException {
 			if (interrupted) return;
 			packetWriter.writeAck(ack);
@@ -206,9 +221,10 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
 		}
 	}
 
-	// This task runs on the database thread
 	private class GenerateBatch implements Runnable {
 
+		@DatabaseExecutor
+		@Override
 		public void run() {
 			if (interrupted) return;
 			try {
@@ -231,7 +247,6 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
 		}
 	}
 
-	// This task runs on the writer thread
 	private class WriteBatch implements ThrowingRunnable<IOException> {
 
 		private final Collection<byte[]> batch;
@@ -240,6 +255,8 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
 			this.batch = batch;
 		}
 
+		@IoExecutor
+		@Override
 		public void run() throws IOException {
 			if (interrupted) return;
 			for (byte[] raw : batch) packetWriter.writeMessage(raw);
@@ -248,9 +265,10 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
 		}
 	}
 
-	// This task runs on the database thread
 	private class GenerateOffer implements Runnable {
 
+		@DatabaseExecutor
+		@Override
 		public void run() {
 			if (interrupted) return;
 			try {
@@ -273,7 +291,6 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
 		}
 	}
 
-	// This task runs on the writer thread
 	private class WriteOffer implements ThrowingRunnable<IOException> {
 
 		private final Offer offer;
@@ -282,6 +299,8 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
 			this.offer = offer;
 		}
 
+		@IoExecutor
+		@Override
 		public void run() throws IOException {
 			if (interrupted) return;
 			packetWriter.writeOffer(offer);
@@ -290,9 +309,10 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
 		}
 	}
 
-	// This task runs on the database thread
 	private class GenerateRequest implements Runnable {
 
+		@DatabaseExecutor
+		@Override
 		public void run() {
 			if (interrupted) return;
 			try {
@@ -314,7 +334,6 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
 		}
 	}
 
-	// This task runs on the writer thread
 	private class WriteRequest implements ThrowingRunnable<IOException> {
 
 		private final Request request;
@@ -323,6 +342,8 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
 			this.request = request;
 		}
 
+		@IoExecutor
+		@Override
 		public void run() throws IOException {
 			if (interrupted) return;
 			packetWriter.writeRequest(request);
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/GroupFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/GroupFactoryImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..18065fc104976d888cbfdc1bf82b04ad92bb7d60
--- /dev/null
+++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/GroupFactoryImpl.java
@@ -0,0 +1,31 @@
+package org.briarproject.bramble.sync;
+
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupFactory;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.util.StringUtils;
+
+import javax.annotation.concurrent.Immutable;
+import javax.inject.Inject;
+
+@Immutable
+@NotNullByDefault
+class GroupFactoryImpl implements GroupFactory {
+
+	private final CryptoComponent crypto;
+
+	@Inject
+	GroupFactoryImpl(CryptoComponent crypto) {
+		this.crypto = crypto;
+	}
+
+	@Override
+	public Group createGroup(ClientId c, byte[] descriptor) {
+		byte[] hash = crypto.hash(GroupId.LABEL,
+				StringUtils.toUtf8(c.getString()), descriptor);
+		return new Group(new GroupId(hash), c, descriptor);
+	}
+}
diff --git a/briar-core/src/org/briarproject/sync/IncomingSession.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/IncomingSession.java
similarity index 74%
rename from briar-core/src/org/briarproject/sync/IncomingSession.java
rename to bramble-core/src/main/java/org/briarproject/bramble/sync/IncomingSession.java
index b434bb6430dece9c9f37cb14a1b3ff8a48a44f3d..4c64a17f50f702741058ec4e695b070d212cb9a5 100644
--- a/briar-core/src/org/briarproject/sync/IncomingSession.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/IncomingSession.java
@@ -1,31 +1,38 @@
-package org.briarproject.sync;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.ContactRemovedEvent;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.ShutdownEvent;
-import org.briarproject.api.sync.Ack;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.Offer;
-import org.briarproject.api.sync.PacketReader;
-import org.briarproject.api.sync.Request;
-import org.briarproject.api.sync.SyncSession;
+package org.briarproject.bramble.sync;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.lifecycle.IoExecutor;
+import org.briarproject.bramble.api.lifecycle.event.ShutdownEvent;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Ack;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.Offer;
+import org.briarproject.bramble.api.sync.PacketReader;
+import org.briarproject.bramble.api.sync.Request;
+import org.briarproject.bramble.api.sync.SyncSession;
 
 import java.io.IOException;
 import java.util.concurrent.Executor;
 import java.util.logging.Logger;
 
+import javax.annotation.concurrent.ThreadSafe;
+
 import static java.util.logging.Level.WARNING;
 
 /**
- * An incoming {@link org.briarproject.api.sync.SyncSession SyncSession}.
+ * An incoming {@link SyncSession}.
  */
+@ThreadSafe
+@NotNullByDefault
 class IncomingSession implements SyncSession, EventListener {
 
 	private static final Logger LOG =
@@ -49,6 +56,8 @@ class IncomingSession implements SyncSession, EventListener {
 		this.packetReader = packetReader;
 	}
 
+	@IoExecutor
+	@Override
 	public void run() throws IOException {
 		eventBus.addListener(this);
 		try {
@@ -75,11 +84,13 @@ class IncomingSession implements SyncSession, EventListener {
 		}
 	}
 
+	@Override
 	public void interrupt() {
 		// FIXME: This won't interrupt a blocking read
 		interrupted = true;
 	}
 
+	@Override
 	public void eventOccurred(Event e) {
 		if (e instanceof ContactRemovedEvent) {
 			ContactRemovedEvent c = (ContactRemovedEvent) e;
@@ -97,6 +108,8 @@ class IncomingSession implements SyncSession, EventListener {
 			this.ack = ack;
 		}
 
+		@DatabaseExecutor
+		@Override
 		public void run() {
 			try {
 				Transaction txn = db.startTransaction(false);
@@ -121,6 +134,8 @@ class IncomingSession implements SyncSession, EventListener {
 			this.message = message;
 		}
 
+		@DatabaseExecutor
+		@Override
 		public void run() {
 			try {
 				Transaction txn = db.startTransaction(false);
@@ -145,6 +160,8 @@ class IncomingSession implements SyncSession, EventListener {
 			this.offer = offer;
 		}
 
+		@DatabaseExecutor
+		@Override
 		public void run() {
 			try {
 				Transaction txn = db.startTransaction(false);
@@ -169,6 +186,8 @@ class IncomingSession implements SyncSession, EventListener {
 			this.request = request;
 		}
 
+		@DatabaseExecutor
+		@Override
 		public void run() {
 			try {
 				Transaction txn = db.startTransaction(false);
diff --git a/briar-core/src/org/briarproject/sync/MessageFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/MessageFactoryImpl.java
similarity index 65%
rename from briar-core/src/org/briarproject/sync/MessageFactoryImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/sync/MessageFactoryImpl.java
index c245ea53b83b9a89417285b9f4cdb3f9ff4d9255..d94eb7c4bec09ef08aaf6ae3f04701c5b1551121 100644
--- a/briar-core/src/org/briarproject/sync/MessageFactoryImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/MessageFactoryImpl.java
@@ -1,19 +1,19 @@
-package org.briarproject.sync;
+package org.briarproject.bramble.sync;
 
-import org.briarproject.api.UniqueId;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageFactory;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.util.ByteUtils;
+import org.briarproject.bramble.api.UniqueId;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageFactory;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.util.ByteUtils;
 
 import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
-import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
 
 @Immutable
 @NotNullByDefault
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/PacketReaderFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/PacketReaderFactoryImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..914bbf1f51e7e3882def186f99d14604b43c3a7d
--- /dev/null
+++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/PacketReaderFactoryImpl.java
@@ -0,0 +1,28 @@
+package org.briarproject.bramble.sync;
+
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.PacketReader;
+import org.briarproject.bramble.api.sync.PacketReaderFactory;
+
+import java.io.InputStream;
+
+import javax.annotation.concurrent.Immutable;
+import javax.inject.Inject;
+
+@Immutable
+@NotNullByDefault
+class PacketReaderFactoryImpl implements PacketReaderFactory {
+
+	private final CryptoComponent crypto;
+
+	@Inject
+	PacketReaderFactoryImpl(CryptoComponent crypto) {
+		this.crypto = crypto;
+	}
+
+	@Override
+	public PacketReader createPacketReader(InputStream in) {
+		return new PacketReaderImpl(crypto, in);
+	}
+}
diff --git a/briar-core/src/org/briarproject/sync/PacketReaderImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/PacketReaderImpl.java
similarity index 73%
rename from briar-core/src/org/briarproject/sync/PacketReaderImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/sync/PacketReaderImpl.java
index abe24fa6b4551a34ebc6486442bb7ebaf7c30707..414f7e812038c5d2e8278f4533a25cc47482aa48 100644
--- a/briar-core/src/org/briarproject/sync/PacketReaderImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/PacketReaderImpl.java
@@ -1,32 +1,36 @@
-package org.briarproject.sync;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.UniqueId;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.sync.Ack;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.sync.Offer;
-import org.briarproject.api.sync.PacketReader;
-import org.briarproject.api.sync.Request;
-import org.briarproject.util.ByteUtils;
+package org.briarproject.bramble.sync;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.UniqueId;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Ack;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.Offer;
+import org.briarproject.bramble.api.sync.PacketReader;
+import org.briarproject.bramble.api.sync.Request;
+import org.briarproject.bramble.util.ByteUtils;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.List;
 
-import static org.briarproject.api.sync.PacketTypes.ACK;
-import static org.briarproject.api.sync.PacketTypes.MESSAGE;
-import static org.briarproject.api.sync.PacketTypes.OFFER;
-import static org.briarproject.api.sync.PacketTypes.REQUEST;
-import static org.briarproject.api.sync.SyncConstants.MAX_PACKET_PAYLOAD_LENGTH;
-import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
-import static org.briarproject.api.sync.SyncConstants.PACKET_HEADER_LENGTH;
-import static org.briarproject.api.sync.SyncConstants.PROTOCOL_VERSION;
+import javax.annotation.concurrent.NotThreadSafe;
 
-// This class is not thread-safe
+import static org.briarproject.bramble.api.sync.PacketTypes.ACK;
+import static org.briarproject.bramble.api.sync.PacketTypes.MESSAGE;
+import static org.briarproject.bramble.api.sync.PacketTypes.OFFER;
+import static org.briarproject.bramble.api.sync.PacketTypes.REQUEST;
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_PACKET_PAYLOAD_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.PACKET_HEADER_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.PROTOCOL_VERSION;
+
+@NotThreadSafe
+@NotNullByDefault
 class PacketReaderImpl implements PacketReader {
 
 	private enum State { BUFFER_EMPTY, BUFFER_FULL, EOF }
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/PacketWriterFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/PacketWriterFactoryImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..343819390fd190b6cef20cb7f7ca65a75a2ed498
--- /dev/null
+++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/PacketWriterFactoryImpl.java
@@ -0,0 +1,16 @@
+package org.briarproject.bramble.sync;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.PacketWriter;
+import org.briarproject.bramble.api.sync.PacketWriterFactory;
+
+import java.io.OutputStream;
+
+@NotNullByDefault
+class PacketWriterFactoryImpl implements PacketWriterFactory {
+
+	@Override
+	public PacketWriter createPacketWriter(OutputStream out) {
+		return new PacketWriterImpl(out);
+	}
+}
diff --git a/briar-core/src/org/briarproject/sync/PacketWriterImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/PacketWriterImpl.java
similarity index 59%
rename from briar-core/src/org/briarproject/sync/PacketWriterImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/sync/PacketWriterImpl.java
index 9bcbe570f360b5b03f8c76cc1631ffe614b5dd10..62e702e4157a61cc8b664ae364ed0384b60dbfb8 100644
--- a/briar-core/src/org/briarproject/sync/PacketWriterImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/PacketWriterImpl.java
@@ -1,25 +1,29 @@
-package org.briarproject.sync;
+package org.briarproject.bramble.sync;
 
-import org.briarproject.api.sync.Ack;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.sync.Offer;
-import org.briarproject.api.sync.PacketTypes;
-import org.briarproject.api.sync.PacketWriter;
-import org.briarproject.api.sync.Request;
-import org.briarproject.util.ByteUtils;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Ack;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.Offer;
+import org.briarproject.bramble.api.sync.PacketTypes;
+import org.briarproject.bramble.api.sync.PacketWriter;
+import org.briarproject.bramble.api.sync.Request;
+import org.briarproject.bramble.util.ByteUtils;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 
-import static org.briarproject.api.sync.PacketTypes.ACK;
-import static org.briarproject.api.sync.PacketTypes.OFFER;
-import static org.briarproject.api.sync.PacketTypes.REQUEST;
-import static org.briarproject.api.sync.SyncConstants.MAX_PACKET_PAYLOAD_LENGTH;
-import static org.briarproject.api.sync.SyncConstants.PACKET_HEADER_LENGTH;
-import static org.briarproject.api.sync.SyncConstants.PROTOCOL_VERSION;
+import javax.annotation.concurrent.NotThreadSafe;
 
-// This class is not thread-safe
+import static org.briarproject.bramble.api.sync.PacketTypes.ACK;
+import static org.briarproject.bramble.api.sync.PacketTypes.OFFER;
+import static org.briarproject.bramble.api.sync.PacketTypes.REQUEST;
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_PACKET_PAYLOAD_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.PACKET_HEADER_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.PROTOCOL_VERSION;
+
+@NotThreadSafe
+@NotNullByDefault
 class PacketWriterImpl implements PacketWriter {
 
 	private final OutputStream out;
@@ -41,12 +45,14 @@ class PacketWriterImpl implements PacketWriter {
 		payload.reset();
 	}
 
+	@Override
 	public void writeAck(Ack a) throws IOException {
 		if (payload.size() != 0) throw new IllegalStateException();
 		for (MessageId m : a.getMessageIds()) payload.write(m.getBytes());
 		writePacket(ACK);
 	}
 
+	@Override
 	public void writeMessage(byte[] raw) throws IOException {
 		header[1] = PacketTypes.MESSAGE;
 		ByteUtils.writeUint16(raw.length, header, 2);
@@ -54,18 +60,21 @@ class PacketWriterImpl implements PacketWriter {
 		out.write(raw);
 	}
 
+	@Override
 	public void writeOffer(Offer o) throws IOException {
 		if (payload.size() != 0) throw new IllegalStateException();
 		for (MessageId m : o.getMessageIds()) payload.write(m.getBytes());
 		writePacket(OFFER);
 	}
 
+	@Override
 	public void writeRequest(Request r) throws IOException {
 		if (payload.size() != 0) throw new IllegalStateException();
 		for (MessageId m : r.getMessageIds()) payload.write(m.getBytes());
 		writePacket(REQUEST);
 	}
 
+	@Override
 	public void flush() throws IOException {
 		out.flush();
 	}
diff --git a/briar-core/src/org/briarproject/sync/SimplexOutgoingSession.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/SimplexOutgoingSession.java
similarity index 75%
rename from briar-core/src/org/briarproject/sync/SimplexOutgoingSession.java
rename to bramble-core/src/main/java/org/briarproject/bramble/sync/SimplexOutgoingSession.java
index a2caf77c5ebb3f53b6a0c7aeb525a58e36c9a79e..c2a1bc64e4707b9a8836699687bac46141906ece 100644
--- a/briar-core/src/org/briarproject/sync/SimplexOutgoingSession.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/SimplexOutgoingSession.java
@@ -1,17 +1,20 @@
-package org.briarproject.sync;
-
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.ContactRemovedEvent;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.ShutdownEvent;
-import org.briarproject.api.sync.Ack;
-import org.briarproject.api.sync.PacketWriter;
-import org.briarproject.api.sync.SyncSession;
+package org.briarproject.bramble.sync;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.lifecycle.IoExecutor;
+import org.briarproject.bramble.api.lifecycle.event.ShutdownEvent;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Ack;
+import org.briarproject.bramble.api.sync.PacketWriter;
+import org.briarproject.bramble.api.sync.SyncSession;
 
 import java.io.IOException;
 import java.util.Collection;
@@ -21,17 +24,20 @@ import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.logging.Logger;
 
+import javax.annotation.concurrent.ThreadSafe;
+
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_IDS;
-import static org.briarproject.api.sync.SyncConstants.MAX_PACKET_PAYLOAD_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_IDS;
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_PACKET_PAYLOAD_LENGTH;
 
 /**
- * An outgoing {@link org.briarproject.api.sync.SyncSession SyncSession}
- * suitable for simplex transports. The session sends messages without offering
- * them first, and closes its output stream when there are no more packets to
- * send.
+ * An outgoing {@link SyncSession} suitable for simplex transports. The session
+ * sends messages without offering them first, and closes its output stream
+ * when there are no more packets to send.
  */
+@ThreadSafe
+@NotNullByDefault
 class SimplexOutgoingSession implements SyncSession, EventListener {
 
 	private static final Logger LOG =
@@ -39,7 +45,9 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
 
 	private static final ThrowingRunnable<IOException> CLOSE =
 			new ThrowingRunnable<IOException>() {
-				public void run() {}
+				@Override
+				public void run() {
+				}
 			};
 
 	private final DatabaseComponent db;
@@ -66,6 +74,8 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
 		writerTasks = new LinkedBlockingQueue<ThrowingRunnable<IOException>>();
 	}
 
+	@IoExecutor
+	@Override
 	public void run() throws IOException {
 		eventBus.addListener(this);
 		try {
@@ -89,6 +99,7 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
 		}
 	}
 
+	@Override
 	public void interrupt() {
 		interrupted = true;
 		writerTasks.add(CLOSE);
@@ -98,6 +109,7 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
 		if (outstandingQueries.decrementAndGet() == 0) writerTasks.add(CLOSE);
 	}
 
+	@Override
 	public void eventOccurred(Event e) {
 		if (e instanceof ContactRemovedEvent) {
 			ContactRemovedEvent c = (ContactRemovedEvent) e;
@@ -107,9 +119,10 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
 		}
 	}
 
-	// This task runs on the database thread
 	private class GenerateAck implements Runnable {
 
+		@DatabaseExecutor
+		@Override
 		public void run() {
 			if (interrupted) return;
 			try {
@@ -132,7 +145,6 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
 		}
 	}
 
-	// This task runs on the writer thread
 	private class WriteAck implements ThrowingRunnable<IOException> {
 
 		private final Ack ack;
@@ -141,6 +153,8 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
 			this.ack = ack;
 		}
 
+		@IoExecutor
+		@Override
 		public void run() throws IOException {
 			if (interrupted) return;
 			packetWriter.writeAck(ack);
@@ -149,9 +163,10 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
 		}
 	}
 
-	// This task runs on the database thread
 	private class GenerateBatch implements Runnable {
 
+		@DatabaseExecutor
+		@Override
 		public void run() {
 			if (interrupted) return;
 			try {
@@ -175,7 +190,6 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
 		}
 	}
 
-	// This task runs on the writer thread
 	private class WriteBatch implements ThrowingRunnable<IOException> {
 
 		private final Collection<byte[]> batch;
@@ -184,6 +198,8 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
 			this.batch = batch;
 		}
 
+		@IoExecutor
+		@Override
 		public void run() throws IOException {
 			if (interrupted) return;
 			for (byte[] raw : batch) packetWriter.writeMessage(raw);
diff --git a/briar-core/src/org/briarproject/sync/SyncModule.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/SyncModule.java
similarity index 63%
rename from briar-core/src/org/briarproject/sync/SyncModule.java
rename to bramble-core/src/main/java/org/briarproject/bramble/sync/SyncModule.java
index 2cbbac5d796c17d288ee0cb7c82f4391d75a3f0b..44703c8b39fd4645e40aa3b06f857eeffd507c35 100644
--- a/briar-core/src/org/briarproject/sync/SyncModule.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/SyncModule.java
@@ -1,17 +1,17 @@
-package org.briarproject.sync;
+package org.briarproject.bramble.sync;
 
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.sync.GroupFactory;
-import org.briarproject.api.sync.MessageFactory;
-import org.briarproject.api.sync.PacketReaderFactory;
-import org.briarproject.api.sync.PacketWriterFactory;
-import org.briarproject.api.sync.SyncSessionFactory;
-import org.briarproject.api.sync.ValidationManager;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.sync.GroupFactory;
+import org.briarproject.bramble.api.sync.MessageFactory;
+import org.briarproject.bramble.api.sync.PacketReaderFactory;
+import org.briarproject.bramble.api.sync.PacketWriterFactory;
+import org.briarproject.bramble.api.sync.SyncSessionFactory;
+import org.briarproject.bramble.api.sync.ValidationManager;
+import org.briarproject.bramble.api.system.Clock;
 
 import java.util.concurrent.Executor;
 
@@ -25,7 +25,8 @@ import dagger.Provides;
 public class SyncModule {
 
 	public static class EagerSingletons {
-		@Inject ValidationManager validationManager;
+		@Inject
+		ValidationManager validationManager;
 	}
 
 	@Provides
diff --git a/briar-core/src/org/briarproject/sync/SyncSessionFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/SyncSessionFactoryImpl.java
similarity index 66%
rename from briar-core/src/org/briarproject/sync/SyncSessionFactoryImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/sync/SyncSessionFactoryImpl.java
index 6fac0012f6acfcad59e8790844d9a6fa06523d4c..c337bf94ac3638355545a24b67a366b0d93fb127 100644
--- a/briar-core/src/org/briarproject/sync/SyncSessionFactoryImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/SyncSessionFactoryImpl.java
@@ -1,23 +1,27 @@
-package org.briarproject.sync;
-
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.event.EventBus;
-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.SyncSession;
-import org.briarproject.api.sync.SyncSessionFactory;
-import org.briarproject.api.system.Clock;
+package org.briarproject.bramble.sync;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.PacketReader;
+import org.briarproject.bramble.api.sync.PacketReaderFactory;
+import org.briarproject.bramble.api.sync.PacketWriter;
+import org.briarproject.bramble.api.sync.PacketWriterFactory;
+import org.briarproject.bramble.api.sync.SyncSession;
+import org.briarproject.bramble.api.sync.SyncSessionFactory;
+import org.briarproject.bramble.api.system.Clock;
 
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.concurrent.Executor;
 
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
+@Immutable
+@NotNullByDefault
 class SyncSessionFactoryImpl implements SyncSessionFactory {
 
 	private final DatabaseComponent db;
@@ -40,11 +44,13 @@ class SyncSessionFactoryImpl implements SyncSessionFactory {
 		this.packetWriterFactory = packetWriterFactory;
 	}
 
+	@Override
 	public SyncSession createIncomingSession(ContactId c, InputStream in) {
 		PacketReader packetReader = packetReaderFactory.createPacketReader(in);
 		return new IncomingSession(db, dbExecutor, eventBus, c, packetReader);
 	}
 
+	@Override
 	public SyncSession createSimplexOutgoingSession(ContactId c,
 			int maxLatency, OutputStream out) {
 		PacketWriter packetWriter = packetWriterFactory.createPacketWriter(out);
@@ -52,6 +58,7 @@ class SyncSessionFactoryImpl implements SyncSessionFactory {
 				maxLatency, packetWriter);
 	}
 
+	@Override
 	public SyncSession createDuplexOutgoingSession(ContactId c, int maxLatency,
 			int maxIdleTime, OutputStream out) {
 		PacketWriter packetWriter = packetWriterFactory.createPacketWriter(out);
diff --git a/briar-core/src/org/briarproject/sync/ThrowingRunnable.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/ThrowingRunnable.java
similarity index 66%
rename from briar-core/src/org/briarproject/sync/ThrowingRunnable.java
rename to bramble-core/src/main/java/org/briarproject/bramble/sync/ThrowingRunnable.java
index 5532a8fc0facbdf393b240f2920087b8a8f46fbc..55d966d31cf866db7954578113b36598f442d370 100644
--- a/briar-core/src/org/briarproject/sync/ThrowingRunnable.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/ThrowingRunnable.java
@@ -1,4 +1,4 @@
-package org.briarproject.sync;
+package org.briarproject.bramble.sync;
 
 interface ThrowingRunnable<T extends Throwable> {
 
diff --git a/briar-core/src/org/briarproject/sync/ValidationManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/ValidationManagerImpl.java
similarity index 91%
rename from briar-core/src/org/briarproject/sync/ValidationManagerImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/sync/ValidationManagerImpl.java
index c4be29aa40011a39d389927f2321690c9081eaf0..7e7aa865fbeb781b9fc356a3a10bf5ede40d64e1 100644
--- a/briar-core/src/org/briarproject/sync/ValidationManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/ValidationManagerImpl.java
@@ -1,26 +1,26 @@
-package org.briarproject.sync;
-
-import org.briarproject.api.crypto.CryptoExecutor;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.db.NoSuchGroupException;
-import org.briarproject.api.db.NoSuchMessageException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.MessageAddedEvent;
-import org.briarproject.api.lifecycle.Service;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.InvalidMessageException;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageContext;
-import org.briarproject.api.sync.MessageFactory;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.sync.ValidationManager;
+package org.briarproject.bramble.sync;
+
+import org.briarproject.bramble.api.crypto.CryptoExecutor;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.db.NoSuchGroupException;
+import org.briarproject.bramble.api.db.NoSuchMessageException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.lifecycle.Service;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.InvalidMessageException;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageContext;
+import org.briarproject.bramble.api.sync.MessageFactory;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.ValidationManager;
+import org.briarproject.bramble.api.sync.event.MessageAddedEvent;
 
 import java.util.Collection;
 import java.util.LinkedList;
@@ -37,9 +37,9 @@ import javax.inject.Inject;
 
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
-import static org.briarproject.api.sync.ValidationManager.State.INVALID;
-import static org.briarproject.api.sync.ValidationManager.State.PENDING;
+import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
+import static org.briarproject.bramble.api.sync.ValidationManager.State.INVALID;
+import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
 
 @ThreadSafe
 @NotNullByDefault
diff --git a/briar-core/src/org/briarproject/system/LinuxSeedProvider.java b/bramble-core/src/main/java/org/briarproject/bramble/system/LinuxSeedProvider.java
similarity index 86%
rename from briar-core/src/org/briarproject/system/LinuxSeedProvider.java
rename to bramble-core/src/main/java/org/briarproject/bramble/system/LinuxSeedProvider.java
index 6481b4a5f2f3d8eec0d2e8357898eeab7dc45713..e4141a4179acd94861cf0f6354b4b91430895db2 100644
--- a/briar-core/src/org/briarproject/system/LinuxSeedProvider.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/system/LinuxSeedProvider.java
@@ -1,6 +1,7 @@
-package org.briarproject.system;
+package org.briarproject.bramble.system;
 
-import org.briarproject.api.system.SeedProvider;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.system.SeedProvider;
 
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
@@ -13,8 +14,12 @@ import java.util.Collections;
 import java.util.List;
 import java.util.logging.Logger;
 
+import javax.annotation.concurrent.Immutable;
+
 import static java.util.logging.Level.WARNING;
 
+@Immutable
+@NotNullByDefault
 class LinuxSeedProvider implements SeedProvider {
 
 	private static final Logger LOG =
@@ -31,6 +36,7 @@ class LinuxSeedProvider implements SeedProvider {
 		this.inputFile = inputFile;
 	}
 
+	@Override
 	public byte[] getSeed() {
 		byte[] seed = new byte[SEED_BYTES];
 		// Contribute whatever slightly unpredictable info we have to the pool
@@ -46,7 +52,7 @@ class LinuxSeedProvider implements SeedProvider {
 		}
 		// Read the seed from the pool
 		try {
-			DataInputStream in =  new DataInputStream(
+			DataInputStream in = new DataInputStream(
 					new FileInputStream(inputFile));
 			in.readFully(seed);
 			in.close();
diff --git a/briar-core/src/org/briarproject/system/SystemClock.java b/bramble-core/src/main/java/org/briarproject/bramble/system/SystemClock.java
similarity index 59%
rename from briar-core/src/org/briarproject/system/SystemClock.java
rename to bramble-core/src/main/java/org/briarproject/bramble/system/SystemClock.java
index 3117b0a5035bbf779af77280d57bec0732fcc569..b1737ad8052dfb4cda3fd542752e4745be51492c 100644
--- a/briar-core/src/org/briarproject/system/SystemClock.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/system/SystemClock.java
@@ -1,14 +1,18 @@
-package org.briarproject.system;
+package org.briarproject.bramble.system;
 
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.system.Clock;
 
-/** Default clock implementation. */
+/**
+ * Default clock implementation.
+ */
 public class SystemClock implements Clock {
 
+	@Override
 	public long currentTimeMillis() {
 		return System.currentTimeMillis();
 	}
 
+	@Override
 	public void sleep(long milliseconds) throws InterruptedException {
 		Thread.sleep(milliseconds);
 	}
diff --git a/briar-core/src/org/briarproject/system/SystemModule.java b/bramble-core/src/main/java/org/briarproject/bramble/system/SystemModule.java
similarity index 78%
rename from briar-core/src/org/briarproject/system/SystemModule.java
rename to bramble-core/src/main/java/org/briarproject/bramble/system/SystemModule.java
index 40ca8037c906e65030c92c30125e7e9cbf45c7d4..a052b4d54cf5ef8d2955850598928d1d856a156d 100644
--- a/briar-core/src/org/briarproject/system/SystemModule.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/system/SystemModule.java
@@ -1,8 +1,8 @@
-package org.briarproject.system;
+package org.briarproject.bramble.system;
 
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.system.Clock;
-import org.briarproject.api.system.Scheduler;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.bramble.api.system.Scheduler;
 
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
diff --git a/briar-core/src/org/briarproject/transport/KeyManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/KeyManagerImpl.java
similarity index 77%
rename from briar-core/src/org/briarproject/transport/KeyManagerImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/transport/KeyManagerImpl.java
index a6c8f1be1271a857591c46e27185c477d50a7a7c..11e459eaf93861ffc2b8a1a55f9bafc6fccfe25a 100644
--- a/briar-core/src/org/briarproject/transport/KeyManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/KeyManagerImpl.java
@@ -1,24 +1,25 @@
-package org.briarproject.transport;
+package org.briarproject.bramble.transport;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.ContactRemovedEvent;
-import org.briarproject.api.event.ContactStatusChangedEvent;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.lifecycle.Service;
-import org.briarproject.api.lifecycle.ServiceException;
-import org.briarproject.api.plugins.PluginConfig;
-import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
-import org.briarproject.api.plugins.simplex.SimplexPluginFactory;
-import org.briarproject.api.transport.KeyManager;
-import org.briarproject.api.transport.StreamContext;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
+import org.briarproject.bramble.api.contact.event.ContactStatusChangedEvent;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.lifecycle.Service;
+import org.briarproject.bramble.api.lifecycle.ServiceException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.PluginConfig;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
+import org.briarproject.bramble.api.transport.KeyManager;
+import org.briarproject.bramble.api.transport.StreamContext;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -28,10 +29,13 @@ import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.logging.Logger;
 
+import javax.annotation.concurrent.ThreadSafe;
 import javax.inject.Inject;
 
 import static java.util.logging.Level.INFO;
 
+@ThreadSafe
+@NotNullByDefault
 class KeyManagerImpl implements KeyManager, Service, EventListener {
 
 	private static final Logger LOG =
diff --git a/briar-core/src/org/briarproject/transport/MutableIncomingKeys.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/MutableIncomingKeys.java
similarity index 70%
rename from briar-core/src/org/briarproject/transport/MutableIncomingKeys.java
rename to bramble-core/src/main/java/org/briarproject/bramble/transport/MutableIncomingKeys.java
index 6be3d1823d210416539696516922a19e9ba651c5..3f2f94a5caa70762b50ee7187aa58b0eb2eb8100 100644
--- a/briar-core/src/org/briarproject/transport/MutableIncomingKeys.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/MutableIncomingKeys.java
@@ -1,9 +1,13 @@
-package org.briarproject.transport;
+package org.briarproject.bramble.transport;
 
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.transport.IncomingKeys;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.transport.IncomingKeys;
 
-// This class is not thread-safe
+import javax.annotation.concurrent.NotThreadSafe;
+
+@NotThreadSafe
+@NotNullByDefault
 class MutableIncomingKeys {
 
 	private final SecretKey tagKey, headerKey;
diff --git a/briar-core/src/org/briarproject/transport/MutableOutgoingKeys.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/MutableOutgoingKeys.java
similarity index 69%
rename from briar-core/src/org/briarproject/transport/MutableOutgoingKeys.java
rename to bramble-core/src/main/java/org/briarproject/bramble/transport/MutableOutgoingKeys.java
index d8163e4f2b045ee8436110ede340075efffcdea6..aaafec13bd192a0600b1d73170039432b102732b 100644
--- a/briar-core/src/org/briarproject/transport/MutableOutgoingKeys.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/MutableOutgoingKeys.java
@@ -1,9 +1,13 @@
-package org.briarproject.transport;
+package org.briarproject.bramble.transport;
 
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.transport.OutgoingKeys;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.transport.OutgoingKeys;
 
-// This class is not thread-safe
+import javax.annotation.concurrent.NotThreadSafe;
+
+@NotThreadSafe
+@NotNullByDefault
 class MutableOutgoingKeys {
 
 	private final SecretKey tagKey, headerKey;
diff --git a/briar-core/src/org/briarproject/transport/MutableTransportKeys.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/MutableTransportKeys.java
similarity index 76%
rename from briar-core/src/org/briarproject/transport/MutableTransportKeys.java
rename to bramble-core/src/main/java/org/briarproject/bramble/transport/MutableTransportKeys.java
index 65861974e75e97c61fcff529e40b706b12da22a9..ebaef9973a148b5ad246f8603dd28de955387035 100644
--- a/briar-core/src/org/briarproject/transport/MutableTransportKeys.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/MutableTransportKeys.java
@@ -1,8 +1,13 @@
-package org.briarproject.transport;
+package org.briarproject.bramble.transport;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.transport.TransportKeys;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.transport.TransportKeys;
 
+import javax.annotation.concurrent.NotThreadSafe;
+
+@NotThreadSafe
+@NotNullByDefault
 class MutableTransportKeys {
 
 	private final TransportId transportId;
diff --git a/briar-core/src/org/briarproject/transport/ReorderingWindow.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/ReorderingWindow.java
similarity index 90%
rename from briar-core/src/org/briarproject/transport/ReorderingWindow.java
rename to bramble-core/src/main/java/org/briarproject/bramble/transport/ReorderingWindow.java
index c1baca01b709293ce7b7a076d4efaff664c9954a..f81d57fa6dc7be6e69baab6e2efbf0c6328f2030 100644
--- a/briar-core/src/org/briarproject/transport/ReorderingWindow.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/ReorderingWindow.java
@@ -1,12 +1,17 @@
-package org.briarproject.transport;
+package org.briarproject.bramble.transport;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
-import static org.briarproject.util.ByteUtils.MAX_32_BIT_UNSIGNED;
+import javax.annotation.concurrent.NotThreadSafe;
+
+import static org.briarproject.bramble.util.ByteUtils.MAX_32_BIT_UNSIGNED;
 
-// This class is not thread-safe
+@NotThreadSafe
+@NotNullByDefault
 class ReorderingWindow {
 
 	private long base;
diff --git a/briar-core/src/org/briarproject/transport/StreamReaderFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/StreamReaderFactoryImpl.java
similarity index 60%
rename from briar-core/src/org/briarproject/transport/StreamReaderFactoryImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/transport/StreamReaderFactoryImpl.java
index 48179153f57898276f03b52a5eceb5acbbfe3380..0d2e9cfb73011e73a9263d3e0026d5b4dc90c8fa 100644
--- a/briar-core/src/org/briarproject/transport/StreamReaderFactoryImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/StreamReaderFactoryImpl.java
@@ -1,14 +1,18 @@
-package org.briarproject.transport;
+package org.briarproject.bramble.transport;
+
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.crypto.StreamDecrypterFactory;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.transport.StreamContext;
+import org.briarproject.bramble.api.transport.StreamReaderFactory;
 
 import java.io.InputStream;
 
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.crypto.StreamDecrypterFactory;
-import org.briarproject.api.transport.StreamContext;
-import org.briarproject.api.transport.StreamReaderFactory;
-
+@Immutable
+@NotNullByDefault
 class StreamReaderFactoryImpl implements StreamReaderFactory {
 
 	private final StreamDecrypterFactory streamDecrypterFactory;
@@ -18,11 +22,13 @@ class StreamReaderFactoryImpl implements StreamReaderFactory {
 		this.streamDecrypterFactory = streamDecrypterFactory;
 	}
 
+	@Override
 	public InputStream createStreamReader(InputStream in, StreamContext ctx) {
 		return new StreamReaderImpl(
 				streamDecrypterFactory.createStreamDecrypter(in, ctx));
 	}
 
+	@Override
 	public InputStream createInvitationStreamReader(InputStream in,
 			SecretKey headerKey) {
 		return new StreamReaderImpl(
diff --git a/briar-core/src/org/briarproject/transport/StreamReaderImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/StreamReaderImpl.java
similarity index 72%
rename from briar-core/src/org/briarproject/transport/StreamReaderImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/transport/StreamReaderImpl.java
index 87a90eb796163c5448c3665f3fbe29030d6c333b..770592c739a313233566d2c01e08d83c49f48ede 100644
--- a/briar-core/src/org/briarproject/transport/StreamReaderImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/StreamReaderImpl.java
@@ -1,18 +1,20 @@
-package org.briarproject.transport;
+package org.briarproject.bramble.transport;
 
-import static org.briarproject.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
+import org.briarproject.bramble.api.crypto.StreamDecrypter;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.IOException;
 import java.io.InputStream;
 
-import org.briarproject.api.crypto.StreamDecrypter;
+import javax.annotation.concurrent.NotThreadSafe;
+
+import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
 
 /**
- * An {@link java.io.InputStream InputStream} that unpacks payload data from
- * transport frames.
- * <p>
- * This class is not thread-safe.
+ * An {@link InputStream} that unpacks payload data from transport frames.
  */
+@NotThreadSafe
+@NotNullByDefault
 class StreamReaderImpl extends InputStream {
 
 	private final StreamDecrypter decrypter;
diff --git a/briar-core/src/org/briarproject/transport/StreamWriterFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/StreamWriterFactoryImpl.java
similarity index 61%
rename from briar-core/src/org/briarproject/transport/StreamWriterFactoryImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/transport/StreamWriterFactoryImpl.java
index 4335273db3d067df4385e7b402939ba566c2735c..77dc7657d77153f912ce6b6860b9a81da399b93f 100644
--- a/briar-core/src/org/briarproject/transport/StreamWriterFactoryImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/StreamWriterFactoryImpl.java
@@ -1,14 +1,18 @@
-package org.briarproject.transport;
+package org.briarproject.bramble.transport;
+
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.crypto.StreamEncrypterFactory;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.transport.StreamContext;
+import org.briarproject.bramble.api.transport.StreamWriterFactory;
 
 import java.io.OutputStream;
 
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.crypto.StreamEncrypterFactory;
-import org.briarproject.api.transport.StreamContext;
-import org.briarproject.api.transport.StreamWriterFactory;
-
+@Immutable
+@NotNullByDefault
 class StreamWriterFactoryImpl implements StreamWriterFactory {
 
 	private final StreamEncrypterFactory streamEncrypterFactory;
@@ -18,12 +22,14 @@ class StreamWriterFactoryImpl implements StreamWriterFactory {
 		this.streamEncrypterFactory = streamEncrypterFactory;
 	}
 
+	@Override
 	public OutputStream createStreamWriter(OutputStream out,
 			StreamContext ctx) {
 		return new StreamWriterImpl(
 				streamEncrypterFactory.createStreamEncrypter(out, ctx));
 	}
 
+	@Override
 	public OutputStream createInvitationStreamWriter(OutputStream out,
 			SecretKey headerKey) {
 		return new StreamWriterImpl(
diff --git a/briar-core/src/org/briarproject/transport/StreamWriterImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/StreamWriterImpl.java
similarity index 72%
rename from briar-core/src/org/briarproject/transport/StreamWriterImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/transport/StreamWriterImpl.java
index 2fad041439270224c6d0fdd3163173537b8c5b68..142ca19ff798ec7e5c4fe0c46eba5d55e7f152ff 100644
--- a/briar-core/src/org/briarproject/transport/StreamWriterImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/StreamWriterImpl.java
@@ -1,19 +1,22 @@
-package org.briarproject.transport;
+package org.briarproject.bramble.transport;
 
-import static org.briarproject.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
+import org.briarproject.bramble.api.crypto.StreamEncrypter;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.IOException;
 import java.io.OutputStream;
 
-import org.briarproject.api.crypto.StreamEncrypter;
+import javax.annotation.concurrent.NotThreadSafe;
+
+import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
 
 /**
- * An {@link java.io.OutputStream OutputStream} that packs data into transport
- * frames, writing a frame whenever there is a full frame to write or the
- * {@link #flush()} method is called.
- * <p>
- * This class is not thread-safe.
+ * An {@link OutputStream} that packs data into transport frames, writing a
+ * frame whenever there is a full frame to write or the {@link #flush()} method
+ * is called.
  */
+@NotThreadSafe
+@NotNullByDefault
 class StreamWriterImpl extends OutputStream {
 
 	private final StreamEncrypter encrypter;
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManager.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..6aa6d360fe2b24af7a643167347c955f75e90bdb
--- /dev/null
+++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManager.java
@@ -0,0 +1,30 @@
+package org.briarproject.bramble.transport;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.transport.StreamContext;
+
+import javax.annotation.Nullable;
+
+@NotNullByDefault
+interface TransportKeyManager {
+
+	void start(Transaction txn) throws DbException;
+
+	void addContact(Transaction txn, ContactId c, SecretKey master,
+			long timestamp, boolean alice) throws DbException;
+
+	void removeContact(ContactId c);
+
+	@Nullable
+	StreamContext getStreamContext(Transaction txn, ContactId c)
+			throws DbException;
+
+	@Nullable
+	StreamContext getStreamContext(Transaction txn, byte[] tag)
+			throws DbException;
+
+}
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerFactory.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..64907dc4124261d62689ea7f8a44853b1ec7ae2a
--- /dev/null
+++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerFactory.java
@@ -0,0 +1,12 @@
+package org.briarproject.bramble.transport;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+
+@NotNullByDefault
+interface TransportKeyManagerFactory {
+
+	TransportKeyManager createTransportKeyManager(TransportId transportId,
+			long maxLatency);
+
+}
diff --git a/briar-core/src/org/briarproject/transport/TransportKeyManagerFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerFactoryImpl.java
similarity index 64%
rename from briar-core/src/org/briarproject/transport/TransportKeyManagerFactoryImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerFactoryImpl.java
index 55818bfdccfa33a8fe28813f95835ab22bec2c2e..d212a027b98f78304f31e6e2e3b6d9b544fca8b0 100644
--- a/briar-core/src/org/briarproject/transport/TransportKeyManagerFactoryImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerFactoryImpl.java
@@ -1,17 +1,21 @@
-package org.briarproject.transport;
+package org.briarproject.bramble.transport;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.system.Clock;
-import org.briarproject.api.system.Scheduler;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.bramble.api.system.Scheduler;
 
 import java.util.concurrent.Executor;
 import java.util.concurrent.ScheduledExecutorService;
 
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
+@Immutable
+@NotNullByDefault
 class TransportKeyManagerFactoryImpl implements
 		TransportKeyManagerFactory {
 
diff --git a/briar-core/src/org/briarproject/transport/TransportKeyManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerImpl.java
similarity index 88%
rename from briar-core/src/org/briarproject/transport/TransportKeyManagerImpl.java
rename to bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerImpl.java
index 72d0e444dbb7d67a715a5380a53cb0806dc50092..9c1582425c8bf89b2d0cc5171322578ecc4133f4 100644
--- a/briar-core/src/org/briarproject/transport/TransportKeyManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerImpl.java
@@ -1,18 +1,19 @@
-package org.briarproject.transport;
+package org.briarproject.bramble.transport;
 
-import org.briarproject.api.Bytes;
-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.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.system.Clock;
-import org.briarproject.api.system.Scheduler;
-import org.briarproject.api.transport.StreamContext;
-import org.briarproject.api.transport.TransportKeys;
-import org.briarproject.transport.ReorderingWindow.Change;
+import org.briarproject.bramble.api.Bytes;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.bramble.api.system.Scheduler;
+import org.briarproject.bramble.api.transport.StreamContext;
+import org.briarproject.bramble.api.transport.TransportKeys;
+import org.briarproject.bramble.transport.ReorderingWindow.Change;
 
 import java.util.HashMap;
 import java.util.Iterator;
@@ -23,12 +24,16 @@ import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.logging.Logger;
 
+import javax.annotation.concurrent.ThreadSafe;
+
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
-import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH;
-import static org.briarproject.util.ByteUtils.MAX_32_BIT_UNSIGNED;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
+import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
+import static org.briarproject.bramble.util.ByteUtils.MAX_32_BIT_UNSIGNED;
 
+@ThreadSafe
+@NotNullByDefault
 class TransportKeyManagerImpl implements TransportKeyManager {
 
 	private static final Logger LOG =
diff --git a/briar-core/src/org/briarproject/transport/TransportModule.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportModule.java
similarity index 67%
rename from briar-core/src/org/briarproject/transport/TransportModule.java
rename to bramble-core/src/main/java/org/briarproject/bramble/transport/TransportModule.java
index 461e1d8dcb91fd883d01d6e8eabf8da1312d4aef..5b33073147018a573babf53cd4ac9ec04b2f9148 100644
--- a/briar-core/src/org/briarproject/transport/TransportModule.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportModule.java
@@ -1,12 +1,12 @@
-package org.briarproject.transport;
-
-import org.briarproject.api.crypto.StreamDecrypterFactory;
-import org.briarproject.api.crypto.StreamEncrypterFactory;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.transport.KeyManager;
-import org.briarproject.api.transport.StreamReaderFactory;
-import org.briarproject.api.transport.StreamWriterFactory;
+package org.briarproject.bramble.transport;
+
+import org.briarproject.bramble.api.crypto.StreamDecrypterFactory;
+import org.briarproject.bramble.api.crypto.StreamEncrypterFactory;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.transport.KeyManager;
+import org.briarproject.bramble.api.transport.StreamReaderFactory;
+import org.briarproject.bramble.api.transport.StreamWriterFactory;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
diff --git a/bramble-j2se/.gitignore b/bramble-j2se/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..eeb02632a0a71dc53ad5bbb4f04aff39855b50e6
--- /dev/null
+++ b/bramble-j2se/.gitignore
@@ -0,0 +1,3 @@
+bin
+build
+.settings
diff --git a/bramble-j2se/build.gradle b/bramble-j2se/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..d61f5dcdcdae51e34d8e282aa8969d248ea99fd1
--- /dev/null
+++ b/bramble-j2se/build.gradle
@@ -0,0 +1,10 @@
+apply plugin: 'java'
+sourceCompatibility = 1.7
+targetCompatibility = 1.7
+
+apply plugin: 'witness'
+
+dependencies {
+	compile project(':bramble-core')
+	compile fileTree(dir: 'libs', include: '*.jar')
+}
diff --git a/briar-desktop/libs/bluecove-2.1.1-SNAPSHOT-briar.jar b/bramble-j2se/libs/bluecove-2.1.1-SNAPSHOT-briar.jar
similarity index 100%
rename from briar-desktop/libs/bluecove-2.1.1-SNAPSHOT-briar.jar
rename to bramble-j2se/libs/bluecove-2.1.1-SNAPSHOT-briar.jar
diff --git a/briar-desktop/libs/bluecove-gpl-2.1.1-SNAPSHOT.jar b/bramble-j2se/libs/bluecove-gpl-2.1.1-SNAPSHOT.jar
similarity index 100%
rename from briar-desktop/libs/bluecove-gpl-2.1.1-SNAPSHOT.jar
rename to bramble-j2se/libs/bluecove-gpl-2.1.1-SNAPSHOT.jar
diff --git a/briar-desktop/libs/jna-4.1.0.jar b/bramble-j2se/libs/jna-4.1.0.jar
similarity index 100%
rename from briar-desktop/libs/jna-4.1.0.jar
rename to bramble-j2se/libs/jna-4.1.0.jar
diff --git a/briar-desktop/libs/jna-platform-4.1.0.jar b/bramble-j2se/libs/jna-platform-4.1.0.jar
similarity index 100%
rename from briar-desktop/libs/jna-platform-4.1.0.jar
rename to bramble-j2se/libs/jna-platform-4.1.0.jar
diff --git a/briar-desktop/libs/jnotify-0.94.jar b/bramble-j2se/libs/jnotify-0.94.jar
similarity index 100%
rename from briar-desktop/libs/jnotify-0.94.jar
rename to bramble-j2se/libs/jnotify-0.94.jar
diff --git a/briar-desktop/libs/jnotify-x86.dll b/bramble-j2se/libs/jnotify-x86.dll
similarity index 100%
rename from briar-desktop/libs/jnotify-x86.dll
rename to bramble-j2se/libs/jnotify-x86.dll
diff --git a/briar-desktop/libs/jnotify-x86_64.dll b/bramble-j2se/libs/jnotify-x86_64.dll
similarity index 100%
rename from briar-desktop/libs/jnotify-x86_64.dll
rename to bramble-j2se/libs/jnotify-x86_64.dll
diff --git a/briar-desktop/libs/jssc-0.9-briar.jar b/bramble-j2se/libs/jssc-0.9-briar.jar
similarity index 100%
rename from briar-desktop/libs/jssc-0.9-briar.jar
rename to bramble-j2se/libs/jssc-0.9-briar.jar
diff --git a/briar-desktop/libs/libjnotify-amd64.so b/bramble-j2se/libs/libjnotify-amd64.so
similarity index 100%
rename from briar-desktop/libs/libjnotify-amd64.so
rename to bramble-j2se/libs/libjnotify-amd64.so
diff --git a/briar-desktop/libs/libjnotify-i386.so b/bramble-j2se/libs/libjnotify-i386.so
similarity index 100%
rename from briar-desktop/libs/libjnotify-i386.so
rename to bramble-j2se/libs/libjnotify-i386.so
diff --git a/briar-desktop/libs/libjnotify.dylib b/bramble-j2se/libs/libjnotify.dylib
similarity index 100%
rename from briar-desktop/libs/libjnotify.dylib
rename to bramble-j2se/libs/libjnotify.dylib
diff --git a/briar-desktop/libs/source/jssc-0.9-briar-source.jar b/bramble-j2se/libs/source/jssc-0.9-briar-source.jar
similarity index 100%
rename from briar-desktop/libs/source/jssc-0.9-briar-source.jar
rename to bramble-j2se/libs/source/jssc-0.9-briar-source.jar
diff --git a/briar-desktop/src/org/briarproject/lifecycle/DesktopLifecycleModule.java b/bramble-j2se/src/main/java/org/briarproject/bramble/lifecycle/DesktopLifecycleModule.java
similarity index 68%
rename from briar-desktop/src/org/briarproject/lifecycle/DesktopLifecycleModule.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/lifecycle/DesktopLifecycleModule.java
index 79525935a0123371418ae744006f41563c3b2394..de9ca4bdb61fd6edc7ada54430434bd0a729d06c 100644
--- a/briar-desktop/src/org/briarproject/lifecycle/DesktopLifecycleModule.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/lifecycle/DesktopLifecycleModule.java
@@ -1,7 +1,7 @@
-package org.briarproject.lifecycle;
+package org.briarproject.bramble.lifecycle;
 
-import org.briarproject.api.lifecycle.ShutdownManager;
-import org.briarproject.util.OsUtils;
+import org.briarproject.bramble.api.lifecycle.ShutdownManager;
+import org.briarproject.bramble.util.OsUtils;
 
 import javax.inject.Singleton;
 
diff --git a/briar-desktop/src/org/briarproject/lifecycle/WindowsShutdownManagerImpl.java b/bramble-j2se/src/main/java/org/briarproject/bramble/lifecycle/WindowsShutdownManagerImpl.java
similarity index 95%
rename from briar-desktop/src/org/briarproject/lifecycle/WindowsShutdownManagerImpl.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/lifecycle/WindowsShutdownManagerImpl.java
index 764f25f6005e59fc0f38ce768aa75b9156ddaab7..aac6a02199ac434434d9a4d131ce64a39ebae8c4 100644
--- a/briar-desktop/src/org/briarproject/lifecycle/WindowsShutdownManagerImpl.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/lifecycle/WindowsShutdownManagerImpl.java
@@ -1,4 +1,4 @@
-package org.briarproject.lifecycle;
+package org.briarproject.bramble.lifecycle;
 
 import com.sun.jna.Native;
 import com.sun.jna.Pointer;
@@ -14,20 +14,23 @@ import com.sun.jna.win32.StdCallLibrary.StdCallCallback;
 import com.sun.jna.win32.W32APIFunctionMapper;
 import com.sun.jna.win32.W32APITypeMapper;
 
-import org.briarproject.util.OsUtils;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.util.OsUtils;
 
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
 import java.util.logging.Logger;
 
+import javax.annotation.concurrent.ThreadSafe;
+
 import static com.sun.jna.Library.OPTION_FUNCTION_MAPPER;
 import static com.sun.jna.Library.OPTION_TYPE_MAPPER;
 import static java.util.logging.Level.WARNING;
 
+@ThreadSafe
+@NotNullByDefault
 class WindowsShutdownManagerImpl extends ShutdownManagerImpl {
 
 	private static final Logger LOG =
@@ -38,7 +41,6 @@ class WindowsShutdownManagerImpl extends ShutdownManagerImpl {
 	private static final int WS_MINIMIZE = 0x20000000;
 
 	private final Map<String, Object> options;
-	private final Lock lock = new ReentrantLock();
 
 	private boolean initialised = false; // Locking: lock
 
@@ -170,11 +172,15 @@ class WindowsShutdownManagerImpl extends ShutdownManagerImpl {
 				HMENU menu, HINSTANCE instance, Pointer param);
 
 		LRESULT DefWindowProc(HWND hwnd, int msg, WPARAM wp, LPARAM lp);
+
 		LRESULT SetWindowLong(HWND hwnd, int index, WindowProc newProc);
+
 		LRESULT SetWindowLongPtr(HWND hwnd, int index, WindowProc newProc);
 
 		int GetMessage(MSG msg, HWND hwnd, int filterMin, int filterMax);
+
 		boolean TranslateMessage(MSG msg);
+
 		LRESULT DispatchMessage(MSG msg);
 	}
 
diff --git a/briar-desktop/src/org/briarproject/plugins/DesktopPluginsModule.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/DesktopPluginModule.java
similarity index 55%
rename from briar-desktop/src/org/briarproject/plugins/DesktopPluginsModule.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/DesktopPluginModule.java
index 912a0a7d7a1d4950f972acef29779b5e4b6f7258..616f9661109541df235f5eab8f2a571d02843ce1 100644
--- a/briar-desktop/src/org/briarproject/plugins/DesktopPluginsModule.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/DesktopPluginModule.java
@@ -1,17 +1,18 @@
-package org.briarproject.plugins;
+package org.briarproject.bramble.plugin;
 
-import org.briarproject.api.lifecycle.IoExecutor;
-import org.briarproject.api.lifecycle.ShutdownManager;
-import org.briarproject.api.plugins.BackoffFactory;
-import org.briarproject.api.plugins.PluginConfig;
-import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
-import org.briarproject.api.plugins.simplex.SimplexPluginFactory;
-import org.briarproject.api.reliability.ReliabilityLayerFactory;
-import org.briarproject.plugins.bluetooth.BluetoothPluginFactory;
-import org.briarproject.plugins.file.RemovableDrivePluginFactory;
-import org.briarproject.plugins.modem.ModemPluginFactory;
-import org.briarproject.plugins.tcp.LanTcpPluginFactory;
-import org.briarproject.plugins.tcp.WanTcpPluginFactory;
+import org.briarproject.bramble.api.lifecycle.IoExecutor;
+import org.briarproject.bramble.api.lifecycle.ShutdownManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.BackoffFactory;
+import org.briarproject.bramble.api.plugin.PluginConfig;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
+import org.briarproject.bramble.api.reliability.ReliabilityLayerFactory;
+import org.briarproject.bramble.plugin.bluetooth.BluetoothPluginFactory;
+import org.briarproject.bramble.plugin.file.RemovableDrivePluginFactory;
+import org.briarproject.bramble.plugin.modem.ModemPluginFactory;
+import org.briarproject.bramble.plugin.tcp.LanTcpPluginFactory;
+import org.briarproject.bramble.plugin.tcp.WanTcpPluginFactory;
 
 import java.security.SecureRandom;
 import java.util.Arrays;
@@ -23,7 +24,7 @@ import dagger.Module;
 import dagger.Provides;
 
 @Module
-public class DesktopPluginsModule extends PluginsModule {
+public class DesktopPluginModule extends PluginModule {
 
 	@Provides
 	PluginConfig getPluginConfig(@IoExecutor Executor ioExecutor,
@@ -44,7 +45,8 @@ public class DesktopPluginsModule extends PluginsModule {
 				Collections.singletonList(removable);
 		final Collection<DuplexPluginFactory> duplex =
 				Arrays.asList(bluetooth, modem, lan, wan);
-		return new PluginConfig() {
+		@NotNullByDefault
+		PluginConfig pluginConfig = new PluginConfig() {
 
 			@Override
 			public Collection<DuplexPluginFactory> getDuplexFactories() {
@@ -56,5 +58,6 @@ public class DesktopPluginsModule extends PluginsModule {
 				return simplex;
 			}
 		};
+		return pluginConfig;
 	}
 }
diff --git a/briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothPlugin.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java
similarity index 90%
rename from briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothPlugin.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java
index 81d5588abee5aed47caa12c812936cc6453774b2..091aa9425b09e96315427c481ff35f3ad6406afa 100644
--- a/briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothPlugin.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java
@@ -1,21 +1,21 @@
-package org.briarproject.plugins.bluetooth;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.crypto.PseudoRandom;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.keyagreement.KeyAgreementConnection;
-import org.briarproject.api.keyagreement.KeyAgreementListener;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.plugins.Backoff;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
-import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
-import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
-import org.briarproject.api.properties.TransportProperties;
-import org.briarproject.util.OsUtils;
-import org.briarproject.util.StringUtils;
+package org.briarproject.bramble.plugin.bluetooth;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.crypto.PseudoRandom;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.plugin.Backoff;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
+import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
+import org.briarproject.bramble.api.properties.TransportProperties;
+import org.briarproject.bramble.util.OsUtils;
+import org.briarproject.bramble.util.StringUtils;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -48,11 +48,11 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
 import static javax.bluetooth.DiscoveryAgent.GIAC;
-import static org.briarproject.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_BLUETOOTH;
-import static org.briarproject.api.plugins.BluetoothConstants.ID;
-import static org.briarproject.api.plugins.BluetoothConstants.PROP_ADDRESS;
-import static org.briarproject.api.plugins.BluetoothConstants.PROP_UUID;
-import static org.briarproject.api.plugins.BluetoothConstants.UUID_BYTES;
+import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_BLUETOOTH;
+import static org.briarproject.bramble.api.plugin.BluetoothConstants.ID;
+import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_ADDRESS;
+import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_UUID;
+import static org.briarproject.bramble.api.plugin.BluetoothConstants.UUID_BYTES;
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
@@ -472,7 +472,7 @@ class BluetoothPlugin implements DuplexPlugin {
 		}
 
 		@Override
-		public StreamConnection call() throws Exception  {
+		public StreamConnection call() throws Exception {
 			StreamConnection s = serverSocket.acceptAndOpen();
 			LOG.info("Incoming connection");
 			return s;
diff --git a/briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothPluginFactory.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPluginFactory.java
similarity index 64%
rename from briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothPluginFactory.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPluginFactory.java
index fbe51e342fcedbdc92340fad78b5e1d8f6522419..e8dc0a754a90b914e015afcf7f08795a614914fc 100644
--- a/briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothPluginFactory.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPluginFactory.java
@@ -1,17 +1,22 @@
-package org.briarproject.plugins.bluetooth;
+package org.briarproject.bramble.plugin.bluetooth;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.plugins.Backoff;
-import org.briarproject.api.plugins.BackoffFactory;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
-import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
-import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.Backoff;
+import org.briarproject.bramble.api.plugin.BackoffFactory;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
 
 import java.security.SecureRandom;
 import java.util.concurrent.Executor;
 
-import static org.briarproject.api.plugins.BluetoothConstants.ID;
+import javax.annotation.concurrent.Immutable;
 
+import static org.briarproject.bramble.api.plugin.BluetoothConstants.ID;
+
+@Immutable
+@NotNullByDefault
 public class BluetoothPluginFactory implements DuplexPluginFactory {
 
 	private static final int MAX_LATENCY = 30 * 1000; // 30 seconds
diff --git a/briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothTransportConnection.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothTransportConnection.java
similarity index 72%
rename from briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothTransportConnection.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothTransportConnection.java
index a68dd001f22bbaef564478b86869e096171a0e25..4a8849c7b0561478f4699c2f757afeacb5dc48ef 100644
--- a/briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothTransportConnection.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothTransportConnection.java
@@ -1,7 +1,8 @@
-package org.briarproject.plugins.bluetooth;
+package org.briarproject.bramble.plugin.bluetooth;
 
-import org.briarproject.api.plugins.Plugin;
-import org.briarproject.api.plugins.duplex.AbstractDuplexTransportConnection;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.Plugin;
+import org.briarproject.bramble.api.plugin.duplex.AbstractDuplexTransportConnection;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -9,6 +10,7 @@ import java.io.OutputStream;
 
 import javax.microedition.io.StreamConnection;
 
+@NotNullByDefault
 class BluetoothTransportConnection extends AbstractDuplexTransportConnection {
 
 	private final StreamConnection stream;
diff --git a/briar-desktop/src/org/briarproject/plugins/bluetooth/InvitationListener.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/bluetooth/InvitationListener.java
similarity index 93%
rename from briar-desktop/src/org/briarproject/plugins/bluetooth/InvitationListener.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/bluetooth/InvitationListener.java
index 38d9ce3c61942d1ec3e171d493eb86e6cef7335e..0a389134b3452582a422ec37f53d62eda3c04b8e 100644
--- a/briar-desktop/src/org/briarproject/plugins/bluetooth/InvitationListener.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/bluetooth/InvitationListener.java
@@ -1,6 +1,4 @@
-package org.briarproject.plugins.bluetooth;
-
-import static java.util.logging.Level.WARNING;
+package org.briarproject.bramble.plugin.bluetooth;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -19,6 +17,8 @@ import javax.bluetooth.RemoteDevice;
 import javax.bluetooth.ServiceRecord;
 import javax.bluetooth.UUID;
 
+import static java.util.logging.Level.WARNING;
+
 class InvitationListener implements DiscoveryListener {
 
 	private static final Logger LOG =
@@ -41,8 +41,9 @@ class InvitationListener implements DiscoveryListener {
 		return url;
 	}
 
+	@Override
 	public void deviceDiscovered(RemoteDevice device, DeviceClass deviceClass) {
-		UUID[] uuids = new UUID[] { new UUID(uuid, false) };
+		UUID[] uuids = new UUID[] {new UUID(uuid, false)};
 		// Try to discover the services associated with the UUID
 		try {
 			discoveryAgent.searchServices(null, uuids, device, this);
@@ -52,6 +53,7 @@ class InvitationListener implements DiscoveryListener {
 		}
 	}
 
+	@Override
 	public void servicesDiscovered(int transaction, ServiceRecord[] services) {
 		for (ServiceRecord record : services) {
 			// Does this service have a URL?
@@ -59,7 +61,7 @@ class InvitationListener implements DiscoveryListener {
 					ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);
 			if (serviceUrl == null) continue;
 			// Does this service have the UUID we're looking for?
-			Collection<String> uuids = new TreeSet<String>();
+			Collection<String> uuids = new TreeSet<>();
 			findNestedClassIds(record.getAttributeValue(0x1), uuids);
 			for (String u : uuids) {
 				if (uuid.equalsIgnoreCase(u)) {
@@ -72,10 +74,12 @@ class InvitationListener implements DiscoveryListener {
 		}
 	}
 
+	@Override
 	public void inquiryCompleted(int discoveryType) {
 		if (searches.decrementAndGet() == 0) finished.countDown();
 	}
 
+	@Override
 	public void serviceSearchCompleted(int transaction, int response) {
 		if (searches.decrementAndGet() == 0) finished.countDown();
 	}
diff --git a/briar-desktop/src/org/briarproject/plugins/file/LinuxRemovableDriveFinder.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/LinuxRemovableDriveFinder.java
similarity index 76%
rename from briar-desktop/src/org/briarproject/plugins/file/LinuxRemovableDriveFinder.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/LinuxRemovableDriveFinder.java
index 124e0819fa119411fa7b764bd3163f4f1d00fa8b..df922489ffa3f5053a13c751a22b0e3297ed9e3f 100644
--- a/briar-desktop/src/org/briarproject/plugins/file/LinuxRemovableDriveFinder.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/LinuxRemovableDriveFinder.java
@@ -1,5 +1,10 @@
-package org.briarproject.plugins.file;
+package org.briarproject.bramble.plugin.file;
 
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.Nullable;
+
+@NotNullByDefault
 class LinuxRemovableDriveFinder extends UnixRemovableDriveFinder {
 
 	@Override
@@ -8,6 +13,7 @@ class LinuxRemovableDriveFinder extends UnixRemovableDriveFinder {
 	}
 
 	@Override
+	@Nullable
 	protected String parseMountPoint(String line) {
 		// The format is "/dev/foo on /bar/baz type bam (opt1,opt2)"
 		String pattern = "^/dev/[^ ]+ on (.*) type [^ ]+ \\([^)]+\\)$";
diff --git a/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/LinuxRemovableDriveMonitor.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/LinuxRemovableDriveMonitor.java
new file mode 100644
index 0000000000000000000000000000000000000000..6807f606f6c5e05902c8c6805038142abbe7b007
--- /dev/null
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/LinuxRemovableDriveMonitor.java
@@ -0,0 +1,12 @@
+package org.briarproject.bramble.plugin.file;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+class LinuxRemovableDriveMonitor extends UnixRemovableDriveMonitor {
+
+	@Override
+	protected String[] getPathsToWatch() {
+		return new String[] {"/mnt", "/media"};
+	}
+}
diff --git a/briar-desktop/src/org/briarproject/plugins/file/MacRemovableDriveFinder.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/MacRemovableDriveFinder.java
similarity index 74%
rename from briar-desktop/src/org/briarproject/plugins/file/MacRemovableDriveFinder.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/MacRemovableDriveFinder.java
index a35c7af9a2ef70a6d5e35c7e202c23d0c5ab8af7..8bd9b92d16b87172d1fb5c80de7bf81336d3858a 100644
--- a/briar-desktop/src/org/briarproject/plugins/file/MacRemovableDriveFinder.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/MacRemovableDriveFinder.java
@@ -1,5 +1,10 @@
-package org.briarproject.plugins.file;
+package org.briarproject.bramble.plugin.file;
 
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.Nullable;
+
+@NotNullByDefault
 class MacRemovableDriveFinder extends UnixRemovableDriveFinder {
 
 	@Override
@@ -8,6 +13,7 @@ class MacRemovableDriveFinder extends UnixRemovableDriveFinder {
 	}
 
 	@Override
+	@Nullable
 	protected String parseMountPoint(String line) {
 		// The format is "/dev/foo on /bar/baz (opt1, opt2)"
 		String pattern = "^/dev/[^ ]+ on (.*) \\([^)]+\\)$";
diff --git a/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/MacRemovableDriveMonitor.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/MacRemovableDriveMonitor.java
new file mode 100644
index 0000000000000000000000000000000000000000..fb3b1acd492c3b125d551f1e60f44238ec9c9cf2
--- /dev/null
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/MacRemovableDriveMonitor.java
@@ -0,0 +1,12 @@
+package org.briarproject.bramble.plugin.file;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+class MacRemovableDriveMonitor extends UnixRemovableDriveMonitor {
+
+	@Override
+	protected String[] getPathsToWatch() {
+		return new String[] {"/Volumes"};
+	}
+}
diff --git a/briar-desktop/src/org/briarproject/plugins/file/PollingRemovableDriveMonitor.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/PollingRemovableDriveMonitor.java
similarity index 85%
rename from briar-desktop/src/org/briarproject/plugins/file/PollingRemovableDriveMonitor.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/PollingRemovableDriveMonitor.java
index a09508582f859e4d0bf810b125a470703cd5ab78..335051a8216e3d8d08a011404bf5be90be6cb032 100644
--- a/briar-desktop/src/org/briarproject/plugins/file/PollingRemovableDriveMonitor.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/PollingRemovableDriveMonitor.java
@@ -1,6 +1,7 @@
-package org.briarproject.plugins.file;
+package org.briarproject.bramble.plugin.file;
 
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
 
 import java.io.File;
 import java.io.IOException;
@@ -11,6 +12,10 @@ import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.logging.Logger;
 
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable {
 
 	private static final Logger LOG =
@@ -26,30 +31,32 @@ class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable {
 	private volatile boolean running = false;
 	private volatile Callback callback = null;
 
-	public PollingRemovableDriveMonitor(Executor ioExecutor,
+	PollingRemovableDriveMonitor(Executor ioExecutor,
 			RemovableDriveFinder finder, int pollingInterval) {
 		this.ioExecutor = ioExecutor;
 		this.finder = finder;
 		this.pollingInterval = pollingInterval;
 	}
 
+	@Override
 	public void start(Callback callback) throws IOException {
 		this.callback = callback;
 		running = true;
 		ioExecutor.execute(this);
 	}
 
+	@Override
 	public void stop() throws IOException {
 		running = false;
 		pollingLock.lock();
 		try {
 			stopPolling.signalAll();
-		}
-		finally {
+		} finally {
 			pollingLock.unlock();
 		}
 	}
 
+	@Override
 	public void run() {
 		try {
 			Collection<File> drives = finder.findRemovableDrives();
diff --git a/briar-desktop/src/org/briarproject/plugins/file/RemovableDriveFinder.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/RemovableDriveFinder.java
similarity index 57%
rename from briar-desktop/src/org/briarproject/plugins/file/RemovableDriveFinder.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/RemovableDriveFinder.java
index efac80007024bd3d3f3bdd0a8d4419bc67c7d919..bae6193569c497710e5847efb0d5106dd94202ec 100644
--- a/briar-desktop/src/org/briarproject/plugins/file/RemovableDriveFinder.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/RemovableDriveFinder.java
@@ -1,9 +1,12 @@
-package org.briarproject.plugins.file;
+package org.briarproject.bramble.plugin.file;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.File;
 import java.io.IOException;
 import java.util.Collection;
 
+@NotNullByDefault
 interface RemovableDriveFinder {
 
 	Collection<File> findRemovableDrives() throws IOException;
diff --git a/briar-desktop/src/org/briarproject/plugins/file/RemovableDriveMonitor.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/RemovableDriveMonitor.java
similarity index 67%
rename from briar-desktop/src/org/briarproject/plugins/file/RemovableDriveMonitor.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/RemovableDriveMonitor.java
index 169dbc140800d289d8f8014dc590887b5ce28a30..1145c5687f0a0b4a22e3a8dde482914c38ffac53 100644
--- a/briar-desktop/src/org/briarproject/plugins/file/RemovableDriveMonitor.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/RemovableDriveMonitor.java
@@ -1,8 +1,11 @@
-package org.briarproject.plugins.file;
+package org.briarproject.bramble.plugin.file;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.File;
 import java.io.IOException;
 
+@NotNullByDefault
 interface RemovableDriveMonitor {
 
 	void start(Callback c) throws IOException;
diff --git a/briar-desktop/src/org/briarproject/plugins/file/RemovableDrivePlugin.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/RemovableDrivePlugin.java
similarity index 89%
rename from briar-desktop/src/org/briarproject/plugins/file/RemovableDrivePlugin.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/RemovableDrivePlugin.java
index a5dba602e096843a62d70ac3c6886055290b2053..5a5e99a2bfbede62063aaf03cee7e1f3d98ca682 100644
--- a/briar-desktop/src/org/briarproject/plugins/file/RemovableDrivePlugin.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/RemovableDrivePlugin.java
@@ -1,9 +1,9 @@
-package org.briarproject.plugins.file;
+package org.briarproject.bramble.plugin.file;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.plugins.simplex.SimplexPluginCallback;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPluginCallback;
 
 import java.io.File;
 import java.io.IOException;
@@ -17,7 +17,7 @@ import static java.util.logging.Level.WARNING;
 
 @NotNullByDefault
 class RemovableDrivePlugin extends FilePlugin
-implements RemovableDriveMonitor.Callback {
+		implements RemovableDriveMonitor.Callback {
 
 	static final TransportId ID =
 			new TransportId("org.briarproject.bramble.file");
diff --git a/briar-desktop/src/org/briarproject/plugins/file/RemovableDrivePluginFactory.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/RemovableDrivePluginFactory.java
similarity index 73%
rename from briar-desktop/src/org/briarproject/plugins/file/RemovableDrivePluginFactory.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/RemovableDrivePluginFactory.java
index e2db0717d77aafdeade20519f45dbe55e8afb840..1b53e250e5f0e6384b4fdf94e8a48aef76e6f4c6 100644
--- a/briar-desktop/src/org/briarproject/plugins/file/RemovableDrivePluginFactory.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/RemovableDrivePluginFactory.java
@@ -1,13 +1,18 @@
-package org.briarproject.plugins.file;
+package org.briarproject.bramble.plugin.file;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.plugins.simplex.SimplexPlugin;
-import org.briarproject.api.plugins.simplex.SimplexPluginCallback;
-import org.briarproject.api.plugins.simplex.SimplexPluginFactory;
-import org.briarproject.util.OsUtils;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPluginCallback;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
+import org.briarproject.bramble.util.OsUtils;
 
 import java.util.concurrent.Executor;
 
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 public class RemovableDrivePluginFactory implements SimplexPluginFactory {
 
 	// Maximum latency 14 days (Royal Mail or lackadaisical carrier pigeon)
@@ -20,14 +25,17 @@ public class RemovableDrivePluginFactory implements SimplexPluginFactory {
 		this.ioExecutor = ioExecutor;
 	}
 
+	@Override
 	public TransportId getId() {
 		return RemovableDrivePlugin.ID;
 	}
 
+	@Override
 	public int getMaxLatency() {
 		return MAX_LATENCY;
 	}
 
+	@Override
 	public SimplexPlugin createPlugin(SimplexPluginCallback callback) {
 		RemovableDriveFinder finder;
 		RemovableDriveMonitor monitor;
diff --git a/briar-desktop/src/org/briarproject/plugins/file/UnixRemovableDriveFinder.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/UnixRemovableDriveFinder.java
similarity index 82%
rename from briar-desktop/src/org/briarproject/plugins/file/UnixRemovableDriveFinder.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/UnixRemovableDriveFinder.java
index 0931f6f4434ceafaa47cf066d7876c3b813ff406..c5626fdb94bc7ae14ea4c8707c8c4ef45abc12f0 100644
--- a/briar-desktop/src/org/briarproject/plugins/file/UnixRemovableDriveFinder.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/UnixRemovableDriveFinder.java
@@ -1,4 +1,6 @@
-package org.briarproject.plugins.file;
+package org.briarproject.bramble.plugin.file;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.File;
 import java.io.IOException;
@@ -6,10 +8,16 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Scanner;
 
+import javax.annotation.Nullable;
+
+@NotNullByDefault
 abstract class UnixRemovableDriveFinder implements RemovableDriveFinder {
 
 	protected abstract String getMountCommand();
+
+	@Nullable
 	protected abstract String parseMountPoint(String line);
+
 	protected abstract boolean isRemovableDriveMountPoint(String path);
 
 	@Override
@@ -26,7 +34,7 @@ abstract class UnixRemovableDriveFinder implements RemovableDriveFinder {
 				if (tokens[0].startsWith("/dev/") && tokens[1].equals("on")) {
 					// The path may contain spaces so we can't use tokens[2]
 					String path = parseMountPoint(line);
-					if (isRemovableDriveMountPoint(path)) {
+					if (path != null && isRemovableDriveMountPoint(path)) {
 						File f = new File(path);
 						if (f.exists() && f.isDirectory()) drives.add(f);
 					}
diff --git a/briar-desktop/src/org/briarproject/plugins/file/UnixRemovableDriveMonitor.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/UnixRemovableDriveMonitor.java
similarity index 78%
rename from briar-desktop/src/org/briarproject/plugins/file/UnixRemovableDriveMonitor.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/UnixRemovableDriveMonitor.java
index bfe731d87ce6dff916e21fda26ef4ff89359c5c0..8fcc0a539ad96516cccb042522a69158df5869be 100644
--- a/briar-desktop/src/org/briarproject/plugins/file/UnixRemovableDriveMonitor.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/UnixRemovableDriveMonitor.java
@@ -1,4 +1,10 @@
-package org.briarproject.plugins.file;
+package org.briarproject.bramble.plugin.file;
+
+import net.contentobjects.jnotify.JNotify;
+import net.contentobjects.jnotify.JNotifyListener;
+
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
 
 import java.io.File;
 import java.io.IOException;
@@ -7,9 +13,8 @@ import java.util.List;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
-import net.contentobjects.jnotify.JNotify;
-import net.contentobjects.jnotify.JNotifyListener;
-
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 abstract class UnixRemovableDriveMonitor implements RemovableDriveMonitor,
 JNotifyListener {
 
@@ -23,7 +28,7 @@ JNotifyListener {
 	private final Lock lock = new ReentrantLock();
 
 	// The following are locking: lock
-	private final List<Integer> watches = new ArrayList<Integer>();
+	private final List<Integer> watches = new ArrayList<>();
 	private boolean started = false;
 	private Callback callback = null;
 
@@ -40,7 +45,7 @@ JNotifyListener {
 		}
 	}
 
-	public static void checkEnabled() throws IOException {
+	private static void checkEnabled() throws IOException {
 		staticLock.lock();
 		try {
 			if (!triedLoad) {
@@ -53,9 +58,10 @@ JNotifyListener {
 		}
 	}
 
+	@Override
 	public void start(Callback callback) throws IOException {
 		checkEnabled();
-		List<Integer> watches = new ArrayList<Integer>();
+		List<Integer> watches = new ArrayList<>();
 		int mask = JNotify.FILE_CREATED;
 		for (String path : getPathsToWatch()) {
 			if (new File(path).exists())
@@ -63,8 +69,8 @@ JNotifyListener {
 		}
 		lock.lock();
 		try {
-			assert !started;
-			assert this.callback == null;
+			if (started) throw new AssertionError();
+			if (this.callback != null) throw new AssertionError();
 			started = true;
 			this.callback = callback;
 			this.watches.addAll(watches);
@@ -73,16 +79,17 @@ JNotifyListener {
 		}
 	}
 
+	@Override
 	public void stop() throws IOException {
 		checkEnabled();
 		List<Integer> watches;
 		lock.lock();
 		try {
-			assert started;
-			assert callback != null;
+			if (!started) throw new AssertionError();
+			if (callback == null) throw new AssertionError();
 			started = false;
 			callback = null;
-			watches = new ArrayList<Integer>(this.watches);
+			watches = new ArrayList<>(this.watches);
 			this.watches.clear();
 		} finally {
 			lock.unlock();
@@ -90,6 +97,7 @@ JNotifyListener {
 		for (Integer w : watches) JNotify.removeWatch(w);
 	}
 
+	@Override
 	public void fileCreated(int wd, String rootPath, String name) {
 		Callback callback;
 		lock.lock();
@@ -102,14 +110,17 @@ JNotifyListener {
 			callback.driveInserted(new File(rootPath + "/" + name));
 	}
 
+	@Override
 	public void fileDeleted(int wd, String rootPath, String name) {
 		throw new UnsupportedOperationException();
 	}
 
+	@Override
 	public void fileModified(int wd, String rootPath, String name) {
 		throw new UnsupportedOperationException();
 	}
 
+	@Override
 	public void fileRenamed(int wd, String rootPath, String oldName,
 			String newName) {
 		throw new UnsupportedOperationException();
diff --git a/briar-desktop/src/org/briarproject/plugins/file/WindowsRemovableDriveFinder.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/WindowsRemovableDriveFinder.java
similarity index 86%
rename from briar-desktop/src/org/briarproject/plugins/file/WindowsRemovableDriveFinder.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/WindowsRemovableDriveFinder.java
index c67783ca8d50c2521ea83273377048a3e559768d..abdbbf0bf95641c56b2d74d128a2453f26424802 100644
--- a/briar-desktop/src/org/briarproject/plugins/file/WindowsRemovableDriveFinder.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/WindowsRemovableDriveFinder.java
@@ -1,13 +1,16 @@
-package org.briarproject.plugins.file;
+package org.briarproject.bramble.plugin.file;
 
 import com.sun.jna.platform.win32.Kernel32;
 
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
+@NotNullByDefault
 class WindowsRemovableDriveFinder implements RemovableDriveFinder {
 
 	// http://msdn.microsoft.com/en-us/library/windows/desktop/aa364939.aspx
diff --git a/briar-desktop/src/org/briarproject/plugins/modem/CountryCodes.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/CountryCodes.java
similarity index 99%
rename from briar-desktop/src/org/briarproject/plugins/modem/CountryCodes.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/CountryCodes.java
index 0ffb166c8324b1608b0815678dc898e1fcb9720c..674d9f6b23fd2e71d755f4daabebd847f85db288 100644
--- a/briar-desktop/src/org/briarproject/plugins/modem/CountryCodes.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/CountryCodes.java
@@ -1,4 +1,4 @@
-package org.briarproject.plugins.modem;
+package org.briarproject.bramble.plugin.modem;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -247,8 +247,7 @@ class CountryCodes {
 		new Country("ZW", "Zimbabwe", "263", "110", "0")
 	};
 
-	private static final Map<String, Country> COUNTRY_MAP =
-			new HashMap<String, Country>();
+	private static final Map<String, Country> COUNTRY_MAP = new HashMap<>();
 
 	static {
 		for (Country c : COUNTRIES) COUNTRY_MAP.put(c.iso3166, c);
diff --git a/briar-desktop/src/org/briarproject/plugins/modem/Modem.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/Modem.java
similarity index 90%
rename from briar-desktop/src/org/briarproject/plugins/modem/Modem.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/Modem.java
index 72c3a85d640ebb54426b5acc222f2ae9f46bfa1a..a25acbad5f1277f19154555bdcd4e908f68a362b 100644
--- a/briar-desktop/src/org/briarproject/plugins/modem/Modem.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/Modem.java
@@ -1,4 +1,6 @@
-package org.briarproject.plugins.modem;
+package org.briarproject.bramble.plugin.modem;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -8,6 +10,7 @@ import java.io.OutputStream;
  * A modem that can be used for multiple sequential incoming and outgoing
  * calls. If an exception is thrown, a new modem instance must be created.
  */
+@NotNullByDefault
 interface Modem {
 
 	/**
diff --git a/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/ModemFactory.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/ModemFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..81866a9ac89dd0bf27c7d91b2a86390b016ac6f2
--- /dev/null
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/ModemFactory.java
@@ -0,0 +1,9 @@
+package org.briarproject.bramble.plugin.modem;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+interface ModemFactory {
+
+	Modem createModem(Modem.Callback callback, String portName);
+}
diff --git a/briar-desktop/src/org/briarproject/plugins/modem/ModemFactoryImpl.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/ModemFactoryImpl.java
similarity index 61%
rename from briar-desktop/src/org/briarproject/plugins/modem/ModemFactoryImpl.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/ModemFactoryImpl.java
index ee2aef1e0986a61c5604e197ed17cfbe637eec4f..78b8eff8b473f0091dbd3f59b343e6d87b0aa572 100644
--- a/briar-desktop/src/org/briarproject/plugins/modem/ModemFactoryImpl.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/ModemFactoryImpl.java
@@ -1,11 +1,16 @@
-package org.briarproject.plugins.modem;
+package org.briarproject.bramble.plugin.modem;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.reliability.ReliabilityLayerFactory;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.bramble.system.SystemClock;
 
 import java.util.concurrent.Executor;
 
-import org.briarproject.api.reliability.ReliabilityLayerFactory;
-import org.briarproject.api.system.Clock;
-import org.briarproject.system.SystemClock;
+import javax.annotation.concurrent.Immutable;
 
+@Immutable
+@NotNullByDefault
 class ModemFactoryImpl implements ModemFactory {
 
 	private final Executor ioExecutor;
@@ -19,6 +24,7 @@ class ModemFactoryImpl implements ModemFactory {
 		clock = new SystemClock();
 	}
 
+	@Override
 	public Modem createModem(Modem.Callback callback, String portName) {
 		return new ModemImpl(ioExecutor, reliabilityFactory, clock, callback,
 				new SerialPortImpl(portName));
diff --git a/briar-desktop/src/org/briarproject/plugins/modem/ModemImpl.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/ModemImpl.java
similarity index 94%
rename from briar-desktop/src/org/briarproject/plugins/modem/ModemImpl.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/ModemImpl.java
index 59fc18930b88f9dc32c91f8ef72e2860e4cf6cb1..4aff1d94c16537bf5541977c1cf42268cc6c7808 100644
--- a/briar-desktop/src/org/briarproject/plugins/modem/ModemImpl.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/ModemImpl.java
@@ -1,10 +1,11 @@
-package org.briarproject.plugins.modem;
+package org.briarproject.bramble.plugin.modem;
 
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.logging.Level.INFO;
-import static java.util.logging.Level.WARNING;
-import static jssc.SerialPort.PURGE_RXCLEAR;
-import static jssc.SerialPort.PURGE_TXCLEAR;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.reliability.ReliabilityLayer;
+import org.briarproject.bramble.api.reliability.ReliabilityLayerFactory;
+import org.briarproject.bramble.api.reliability.WriteHandler;
+import org.briarproject.bramble.api.system.Clock;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -16,14 +17,19 @@ import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
+
 import jssc.SerialPortEvent;
 import jssc.SerialPortEventListener;
 
-import org.briarproject.api.reliability.ReliabilityLayer;
-import org.briarproject.api.reliability.ReliabilityLayerFactory;
-import org.briarproject.api.reliability.WriteHandler;
-import org.briarproject.api.system.Clock;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.logging.Level.INFO;
+import static java.util.logging.Level.WARNING;
+import static jssc.SerialPort.PURGE_RXCLEAR;
+import static jssc.SerialPort.PURGE_TXCLEAR;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
 
 	private static final Logger LOG =
@@ -65,6 +71,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
 		line = new byte[MAX_LINE_LENGTH];
 	}
 
+	@Override
 	public boolean start() throws IOException {
 		LOG.info("Starting");
 		try {
@@ -125,7 +132,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
 		}
 	}
 
-	private void tryToClose(SerialPort port) {
+	private void tryToClose(@Nullable SerialPort port) {
 		try {
 			if (port != null) port.closePort();
 		} catch (IOException e) {
@@ -133,6 +140,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
 		}
 	}
 
+	@Override
 	public void stop() throws IOException {
 		LOG.info("Stopping");
 		lock.lock();
@@ -193,6 +201,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
 		}
 	}
 
+	@Override
 	public boolean dial(String number) throws IOException {
 		if (!stateChange.tryAcquire()) {
 			LOG.info("Not dialling - state change in progress");
@@ -250,6 +259,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
 		}
 	}
 
+	@Override
 	public InputStream getInputStream() throws IOException {
 		ReliabilityLayer reliability;
 		lock.lock();
@@ -262,6 +272,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
 		return reliability.getInputStream();
 	}
 
+	@Override
 	public OutputStream getOutputStream() throws IOException {
 		ReliabilityLayer reliability;
 		lock.lock();
@@ -274,6 +285,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
 		return reliability.getOutputStream();
 	}
 
+	@Override
 	public void hangUp() throws IOException {
 		try {
 			stateChange.acquire();
@@ -289,6 +301,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
 		}
 	}
 
+	@Override
 	public void handleWrite(byte[] b) throws IOException {
 		try {
 			port.writeBytes(b);
@@ -298,6 +311,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
 		}
 	}
 
+	@Override
 	public void serialEvent(SerialPortEvent ev) {
 		try {
 			if (ev.isRXCHAR()) {
@@ -377,6 +391,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
 					}
 				} else if (s.equals("RING")) {
 					ioExecutor.execute(new Runnable() {
+						@Override
 						public void run() {
 							try {
 								answer();
diff --git a/briar-desktop/src/org/briarproject/plugins/modem/ModemPlugin.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/ModemPlugin.java
similarity index 84%
rename from briar-desktop/src/org/briarproject/plugins/modem/ModemPlugin.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/ModemPlugin.java
index ae08ea3973793018a258302a3c972d9bce8a52ed..5169e5d5dc61b8348a9db27aa04f5a6d29117723 100644
--- a/briar-desktop/src/org/briarproject/plugins/modem/ModemPlugin.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/ModemPlugin.java
@@ -1,231 +1,231 @@
-package org.briarproject.plugins.modem;
-
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.crypto.PseudoRandom;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.keyagreement.KeyAgreementListener;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.plugins.duplex.AbstractDuplexTransportConnection;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
-import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
-import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
-import org.briarproject.api.properties.TransportProperties;
-import org.briarproject.util.StringUtils;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Collection;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.logging.Logger;
-
-import static java.util.logging.Level.INFO;
-import static java.util.logging.Level.WARNING;
-
-@MethodsNotNullByDefault
-@ParametersNotNullByDefault
-class ModemPlugin implements DuplexPlugin, Modem.Callback {
-
-	static final TransportId ID =
-			new TransportId("org.briarproject.bramble.modem");
-
-	private static final Logger LOG =
-			Logger.getLogger(ModemPlugin.class.getName());
-
-	private final ModemFactory modemFactory;
-	private final SerialPortList serialPortList;
-	private final DuplexPluginCallback callback;
-	private final int maxLatency;
-	private final AtomicBoolean used = new AtomicBoolean(false);
-
-	private volatile boolean running = false;
-	private volatile Modem modem = null;
-
-	ModemPlugin(ModemFactory modemFactory, SerialPortList serialPortList,
-			DuplexPluginCallback callback, int maxLatency) {
-		this.modemFactory = modemFactory;
-		this.serialPortList = serialPortList;
-		this.callback = callback;
-		this.maxLatency = maxLatency;
-	}
-
-	@Override
-	public TransportId getId() {
-		return ID;
-	}
-
-	@Override
-	public int getMaxLatency() {
-		return maxLatency;
-	}
-
-	@Override
-	public int getMaxIdleTime() {
-		// FIXME: Do we need keepalives for this transport?
-		return Integer.MAX_VALUE;
-	}
-
-	@Override
-	public boolean start() {
-		if (used.getAndSet(true)) throw new IllegalStateException();
-		for (String portName : serialPortList.getPortNames()) {
-			if (LOG.isLoggable(INFO))
-				LOG.info("Trying to initialise modem on " + portName);
-			modem = modemFactory.createModem(this, portName);
-			try {
-				if (!modem.start()) continue;
-				if (LOG.isLoggable(INFO))
-					LOG.info("Initialised modem on " + portName);
-				running = true;
-				return true;
-			} catch (IOException e) {
-				if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
-			}
-		}
-		return false;
-	}
-
-	@Override
-	public void stop() {
-		running = false;
-		if (modem != null) {
-			try {
-				modem.stop();
-			} catch (IOException e) {
-				if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
-			}
-		}
-	}
-
-	@Override
-	public boolean isRunning() {
-		return running;
-	}
-
-	@Override
-	public boolean shouldPoll() {
-		return false;
-	}
-
-	@Override
-	public int getPollingInterval() {
-		throw new UnsupportedOperationException();
-	}
-
-	@Override
-	public void poll(Collection<ContactId> connected) {
-		throw new UnsupportedOperationException();
-	}
-
-	private boolean resetModem() {
-		if (!running) return false;
-		for (String portName : serialPortList.getPortNames()) {
-			if (LOG.isLoggable(INFO))
-				LOG.info("Trying to initialise modem on " + portName);
-			modem = modemFactory.createModem(this, portName);
-			try {
-				if (!modem.start()) continue;
-				if (LOG.isLoggable(INFO))
-					LOG.info("Initialised modem on " + portName);
-				return true;
-			} catch (IOException e) {
-				if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
-			}
-		}
-		running = false;
-		return false;
-	}
-
-	@Override
-	public DuplexTransportConnection createConnection(ContactId c) {
-		if (!running) return null;
-		// Get the ISO 3166 code for the caller's country
-		String fromIso = callback.getLocalProperties().get("iso3166");
-		if (StringUtils.isNullOrEmpty(fromIso)) return null;
-		// Get the ISO 3166 code for the callee's country
-		TransportProperties properties = callback.getRemoteProperties().get(c);
-		if (properties == null) return null;
-		String toIso = properties.get("iso3166");
-		if (StringUtils.isNullOrEmpty(toIso)) return null;
-		// Get the callee's phone number
-		String number = properties.get("number");
-		if (StringUtils.isNullOrEmpty(number)) return null;
-		// Convert the number into direct dialling form
-		number = CountryCodes.translate(number, fromIso, toIso);
-		if (number == null) return null;
-		// Dial the number
-		try {
-			if (!modem.dial(number)) return null;
-		} catch (IOException e) {
-			if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
-			resetModem();
-			return null;
-		}
-		return new ModemTransportConnection();
-	}
-
-	@Override
-	public boolean supportsInvitations() {
-		return false;
-	}
-
-	@Override
-	public DuplexTransportConnection createInvitationConnection(PseudoRandom r,
-			long timeout, boolean alice) {
-		throw new UnsupportedOperationException();
-	}
-
-	@Override
-	public boolean supportsKeyAgreement() {
-		return false;
-	}
-
-	@Override
-	public KeyAgreementListener createKeyAgreementListener(byte[] commitment) {
-		throw new UnsupportedOperationException();
-	}
-
-	@Override
-	public DuplexTransportConnection createKeyAgreementConnection(
-			byte[] commitment, BdfList descriptor, long timeout) {
-		throw new UnsupportedOperationException();
-	}
-
-	@Override
-	public void incomingCallConnected() {
-		LOG.info("Incoming call connected");
-		callback.incomingConnectionCreated(new ModemTransportConnection());
-	}
-
-	private class ModemTransportConnection
-			extends AbstractDuplexTransportConnection {
-
-		private ModemTransportConnection() {
-			super(ModemPlugin.this);
-		}
-
-		@Override
-		protected InputStream getInputStream() throws IOException {
-			return modem.getInputStream();
-		}
-
-		@Override
-		protected OutputStream getOutputStream() throws IOException {
-			return modem.getOutputStream();
-		}
-
-		@Override
-		protected void closeConnection(boolean exception) {
-			LOG.info("Call disconnected");
-			try {
-				modem.hangUp();
-			} catch (IOException e) {
-				if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
-				exception = true;
-			}
-			if (exception) resetModem();
-		}
-	}
-}
+package org.briarproject.bramble.plugin.modem;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.crypto.PseudoRandom;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.AbstractDuplexTransportConnection;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
+import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
+import org.briarproject.bramble.api.properties.TransportProperties;
+import org.briarproject.bramble.util.StringUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collection;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.logging.Logger;
+
+import static java.util.logging.Level.INFO;
+import static java.util.logging.Level.WARNING;
+
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
+class ModemPlugin implements DuplexPlugin, Modem.Callback {
+
+	static final TransportId ID =
+			new TransportId("org.briarproject.bramble.modem");
+
+	private static final Logger LOG =
+			Logger.getLogger(ModemPlugin.class.getName());
+
+	private final ModemFactory modemFactory;
+	private final SerialPortList serialPortList;
+	private final DuplexPluginCallback callback;
+	private final int maxLatency;
+	private final AtomicBoolean used = new AtomicBoolean(false);
+
+	private volatile boolean running = false;
+	private volatile Modem modem = null;
+
+	ModemPlugin(ModemFactory modemFactory, SerialPortList serialPortList,
+			DuplexPluginCallback callback, int maxLatency) {
+		this.modemFactory = modemFactory;
+		this.serialPortList = serialPortList;
+		this.callback = callback;
+		this.maxLatency = maxLatency;
+	}
+
+	@Override
+	public TransportId getId() {
+		return ID;
+	}
+
+	@Override
+	public int getMaxLatency() {
+		return maxLatency;
+	}
+
+	@Override
+	public int getMaxIdleTime() {
+		// FIXME: Do we need keepalives for this transport?
+		return Integer.MAX_VALUE;
+	}
+
+	@Override
+	public boolean start() {
+		if (used.getAndSet(true)) throw new IllegalStateException();
+		for (String portName : serialPortList.getPortNames()) {
+			if (LOG.isLoggable(INFO))
+				LOG.info("Trying to initialise modem on " + portName);
+			modem = modemFactory.createModem(this, portName);
+			try {
+				if (!modem.start()) continue;
+				if (LOG.isLoggable(INFO))
+					LOG.info("Initialised modem on " + portName);
+				running = true;
+				return true;
+			} catch (IOException e) {
+				if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
+			}
+		}
+		return false;
+	}
+
+	@Override
+	public void stop() {
+		running = false;
+		if (modem != null) {
+			try {
+				modem.stop();
+			} catch (IOException e) {
+				if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
+			}
+		}
+	}
+
+	@Override
+	public boolean isRunning() {
+		return running;
+	}
+
+	@Override
+	public boolean shouldPoll() {
+		return false;
+	}
+
+	@Override
+	public int getPollingInterval() {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void poll(Collection<ContactId> connected) {
+		throw new UnsupportedOperationException();
+	}
+
+	private boolean resetModem() {
+		if (!running) return false;
+		for (String portName : serialPortList.getPortNames()) {
+			if (LOG.isLoggable(INFO))
+				LOG.info("Trying to initialise modem on " + portName);
+			modem = modemFactory.createModem(this, portName);
+			try {
+				if (!modem.start()) continue;
+				if (LOG.isLoggable(INFO))
+					LOG.info("Initialised modem on " + portName);
+				return true;
+			} catch (IOException e) {
+				if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
+			}
+		}
+		running = false;
+		return false;
+	}
+
+	@Override
+	public DuplexTransportConnection createConnection(ContactId c) {
+		if (!running) return null;
+		// Get the ISO 3166 code for the caller's country
+		String fromIso = callback.getLocalProperties().get("iso3166");
+		if (StringUtils.isNullOrEmpty(fromIso)) return null;
+		// Get the ISO 3166 code for the callee's country
+		TransportProperties properties = callback.getRemoteProperties().get(c);
+		if (properties == null) return null;
+		String toIso = properties.get("iso3166");
+		if (StringUtils.isNullOrEmpty(toIso)) return null;
+		// Get the callee's phone number
+		String number = properties.get("number");
+		if (StringUtils.isNullOrEmpty(number)) return null;
+		// Convert the number into direct dialling form
+		number = CountryCodes.translate(number, fromIso, toIso);
+		if (number == null) return null;
+		// Dial the number
+		try {
+			if (!modem.dial(number)) return null;
+		} catch (IOException e) {
+			if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
+			resetModem();
+			return null;
+		}
+		return new ModemTransportConnection();
+	}
+
+	@Override
+	public boolean supportsInvitations() {
+		return false;
+	}
+
+	@Override
+	public DuplexTransportConnection createInvitationConnection(PseudoRandom r,
+			long timeout, boolean alice) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public boolean supportsKeyAgreement() {
+		return false;
+	}
+
+	@Override
+	public KeyAgreementListener createKeyAgreementListener(byte[] commitment) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public DuplexTransportConnection createKeyAgreementConnection(
+			byte[] commitment, BdfList descriptor, long timeout) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void incomingCallConnected() {
+		LOG.info("Incoming call connected");
+		callback.incomingConnectionCreated(new ModemTransportConnection());
+	}
+
+	private class ModemTransportConnection
+			extends AbstractDuplexTransportConnection {
+
+		private ModemTransportConnection() {
+			super(ModemPlugin.this);
+		}
+
+		@Override
+		protected InputStream getInputStream() throws IOException {
+			return modem.getInputStream();
+		}
+
+		@Override
+		protected OutputStream getOutputStream() throws IOException {
+			return modem.getOutputStream();
+		}
+
+		@Override
+		protected void closeConnection(boolean exception) {
+			LOG.info("Call disconnected");
+			try {
+				modem.hangUp();
+			} catch (IOException e) {
+				if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
+				exception = true;
+			}
+			if (exception) resetModem();
+		}
+	}
+}
diff --git a/briar-desktop/src/org/briarproject/plugins/modem/ModemPluginFactory.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/ModemPluginFactory.java
similarity index 59%
rename from briar-desktop/src/org/briarproject/plugins/modem/ModemPluginFactory.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/ModemPluginFactory.java
index 690b3c7d78f6f603a400bd690a1c92464b263215..1a3a1f24af857f93bd3ae9682f44a47d5641b316 100644
--- a/briar-desktop/src/org/briarproject/plugins/modem/ModemPluginFactory.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/ModemPluginFactory.java
@@ -1,40 +1,48 @@
-package org.briarproject.plugins.modem;
-
-import org.briarproject.api.TransportId;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
-import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
-import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
-import org.briarproject.api.reliability.ReliabilityLayerFactory;
-import org.briarproject.util.StringUtils;
-
-import java.util.concurrent.Executor;
-
-public class ModemPluginFactory implements DuplexPluginFactory {
-
-	private static final int MAX_LATENCY = 30 * 1000; // 30 seconds
-
-	private final ModemFactory modemFactory;
-	private final SerialPortList serialPortList;
-
-	public ModemPluginFactory(Executor ioExecutor,
-			ReliabilityLayerFactory reliabilityFactory) {
-		modemFactory = new ModemFactoryImpl(ioExecutor, reliabilityFactory);
-		serialPortList = new SerialPortListImpl();
-	}
-
-	public TransportId getId() {
-		return ModemPlugin.ID;
-	}
-
-	public int getMaxLatency() {
-		return MAX_LATENCY;
-	}
-
-	public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
-		// This plugin is not enabled by default
-		String enabled = callback.getSettings().get("enabled");
-		if (StringUtils.isNullOrEmpty(enabled)) return null;
-		return new ModemPlugin(modemFactory, serialPortList, callback,
-				MAX_LATENCY);
-	}
-}
+package org.briarproject.bramble.plugin.modem;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
+import org.briarproject.bramble.api.reliability.ReliabilityLayerFactory;
+import org.briarproject.bramble.util.StringUtils;
+
+import java.util.concurrent.Executor;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public class ModemPluginFactory implements DuplexPluginFactory {
+
+	private static final int MAX_LATENCY = 30 * 1000; // 30 seconds
+
+	private final ModemFactory modemFactory;
+	private final SerialPortList serialPortList;
+
+	public ModemPluginFactory(Executor ioExecutor,
+			ReliabilityLayerFactory reliabilityFactory) {
+		modemFactory = new ModemFactoryImpl(ioExecutor, reliabilityFactory);
+		serialPortList = new SerialPortListImpl();
+	}
+
+	@Override
+	public TransportId getId() {
+		return ModemPlugin.ID;
+	}
+
+	@Override
+	public int getMaxLatency() {
+		return MAX_LATENCY;
+	}
+
+	@Override
+	public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
+		// This plugin is not enabled by default
+		String enabled = callback.getSettings().get("enabled");
+		if (StringUtils.isNullOrEmpty(enabled)) return null;
+		return new ModemPlugin(modemFactory, serialPortList, callback,
+				MAX_LATENCY);
+	}
+}
diff --git a/briar-desktop/src/org/briarproject/plugins/modem/SerialPort.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/SerialPort.java
similarity index 78%
rename from briar-desktop/src/org/briarproject/plugins/modem/SerialPort.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/SerialPort.java
index 6d9f602313d20be68a1c9243179589fcb33579bc..b21100c7d7582ab67b34373f37ac9b1c5d62dda7 100644
--- a/briar-desktop/src/org/briarproject/plugins/modem/SerialPort.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/SerialPort.java
@@ -1,9 +1,12 @@
-package org.briarproject.plugins.modem;
+package org.briarproject.bramble.plugin.modem;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.IOException;
 
 import jssc.SerialPortEventListener;
 
+@NotNullByDefault
 interface SerialPort {
 
 	void openPort() throws IOException;
diff --git a/briar-desktop/src/org/briarproject/plugins/modem/SerialPortImpl.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/SerialPortImpl.java
similarity index 89%
rename from briar-desktop/src/org/briarproject/plugins/modem/SerialPortImpl.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/SerialPortImpl.java
index 3722e23182ff333bdbf99be9223d56e6b72aa827..f3e1aff06e87033e931071b0f27d8f9e8e2587fe 100644
--- a/briar-desktop/src/org/briarproject/plugins/modem/SerialPortImpl.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/SerialPortImpl.java
@@ -1,10 +1,13 @@
-package org.briarproject.plugins.modem;
+package org.briarproject.bramble.plugin.modem;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.IOException;
 
 import jssc.SerialPortEventListener;
 import jssc.SerialPortException;
 
+@NotNullByDefault
 class SerialPortImpl implements SerialPort {
 
 	private final jssc.SerialPort port;
@@ -13,6 +16,7 @@ class SerialPortImpl implements SerialPort {
 		port = new jssc.SerialPort(portName);
 	}
 
+	@Override
 	public void openPort() throws IOException {
 		try {
 			if (!port.openPort()) throw new IOException("Failed to open port");
@@ -21,6 +25,7 @@ class SerialPortImpl implements SerialPort {
 		}
 	}
 
+	@Override
 	public void closePort() throws IOException {
 		try {
 			if (!port.closePort()) throw new IOException("Failed to close port");
@@ -29,6 +34,7 @@ class SerialPortImpl implements SerialPort {
 		}
 	}
 
+	@Override
 	public boolean setParams(int baudRate, int dataBits, int stopBits,
 			int parityBits) throws IOException {
 		try {
@@ -38,6 +44,7 @@ class SerialPortImpl implements SerialPort {
 		}
 	}
 
+	@Override
 	public void purgePort(int flags) throws IOException {
 		try {
 			if (!port.purgePort(flags))
@@ -47,6 +54,7 @@ class SerialPortImpl implements SerialPort {
 		}
 	}
 
+	@Override
 	public void addEventListener(SerialPortEventListener l) throws IOException {
 		try {
 			port.addEventListener(l);
@@ -55,6 +63,7 @@ class SerialPortImpl implements SerialPort {
 		}
 	}
 
+	@Override
 	public byte[] readBytes() throws IOException {
 		try {
 			return port.readBytes();
@@ -63,6 +72,7 @@ class SerialPortImpl implements SerialPort {
 		}
 	}
 
+	@Override
 	public void writeBytes(byte[] b) throws IOException {
 		try {
 			if (!port.writeBytes(b)) throw new IOException("Failed to write");
diff --git a/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/SerialPortList.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/SerialPortList.java
new file mode 100644
index 0000000000000000000000000000000000000000..918bcd6f3b0a49fb1d151a56a68b486e84e5ef1f
--- /dev/null
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/SerialPortList.java
@@ -0,0 +1,9 @@
+package org.briarproject.bramble.plugin.modem;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+interface SerialPortList {
+
+	String[] getPortNames();
+}
diff --git a/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/SerialPortListImpl.java b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/SerialPortListImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..b2375d0d4d5cb42987ac9b0ef919feb58e30db08
--- /dev/null
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/SerialPortListImpl.java
@@ -0,0 +1,12 @@
+package org.briarproject.bramble.plugin.modem;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+class SerialPortListImpl implements SerialPortList {
+
+	@Override
+	public String[] getPortNames() {
+		return jssc.SerialPortList.getPortNames();
+	}
+}
diff --git a/briar-desktop/src/org/briarproject/system/DesktopSeedProviderModule.java b/bramble-j2se/src/main/java/org/briarproject/bramble/system/DesktopSeedProviderModule.java
similarity index 64%
rename from briar-desktop/src/org/briarproject/system/DesktopSeedProviderModule.java
rename to bramble-j2se/src/main/java/org/briarproject/bramble/system/DesktopSeedProviderModule.java
index 8ed175a8b2c9656a479e2476587c945258def262..d603f7a1344243edb2e5089bffbcee4619bf0f53 100644
--- a/briar-desktop/src/org/briarproject/system/DesktopSeedProviderModule.java
+++ b/bramble-j2se/src/main/java/org/briarproject/bramble/system/DesktopSeedProviderModule.java
@@ -1,7 +1,7 @@
-package org.briarproject.system;
+package org.briarproject.bramble.system;
 
-import org.briarproject.api.system.SeedProvider;
-import org.briarproject.util.OsUtils;
+import org.briarproject.bramble.api.system.SeedProvider;
+import org.briarproject.bramble.util.OsUtils;
 
 import javax.inject.Singleton;
 
diff --git a/briar-android-tests/build.gradle b/briar-android-tests/build.gradle
index 914bb06ff9c0d7a423db94b91fbea9ba39cea3e4..82a778db6421c690912f5720bf5d4f45b3f939c1 100644
--- a/briar-android-tests/build.gradle
+++ b/briar-android-tests/build.gradle
@@ -18,12 +18,10 @@ android {
 }
 
 dependencies {
-    testCompile project(':briar-api')
-    testCompile project(':briar-core')
+    testCompile project(':briar-tests')
     testCompile 'junit:junit:4.12'
     testCompile 'net.jodah:concurrentunit:0.4.2'
     testCompile 'com.android.support:appcompat-v7:23.2.1'
     testApt 'com.google.dagger:dagger-compiler:2.0.2'
     provided 'javax.annotation:jsr250-api:1.0'
-    testCompile project(':briar-tests')
 }
diff --git a/briar-android-tests/src/test/java/org/briarproject/BlogManagerTest.java b/briar-android-tests/src/test/java/org/briarproject/BlogManagerTest.java
index 85803e837e3f0dbd7df0aa0c98fda57954bc0fda..8226a135b15c0fe9b6c4f588e4449f2a4ab76bed 100644
--- a/briar-android-tests/src/test/java/org/briarproject/BlogManagerTest.java
+++ b/briar-android-tests/src/test/java/org/briarproject/BlogManagerTest.java
@@ -1,11 +1,12 @@
 package org.briarproject;
 
-import org.briarproject.api.blogs.Blog;
-import org.briarproject.api.blogs.BlogCommentHeader;
-import org.briarproject.api.blogs.BlogManager;
-import org.briarproject.api.blogs.BlogPost;
-import org.briarproject.api.blogs.BlogPostHeader;
-import org.briarproject.api.db.DbException;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.blog.Blog;
+import org.briarproject.briar.api.blog.BlogCommentHeader;
+import org.briarproject.briar.api.blog.BlogManager;
+import org.briarproject.briar.api.blog.BlogPost;
+import org.briarproject.briar.api.blog.BlogPostHeader;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -15,14 +16,16 @@ import java.util.Collection;
 import java.util.Iterator;
 
 import static junit.framework.Assert.assertFalse;
-import static org.briarproject.api.blogs.MessageType.COMMENT;
-import static org.briarproject.api.blogs.MessageType.POST;
-import static org.briarproject.api.blogs.MessageType.WRAPPED_COMMENT;
-import static org.briarproject.api.blogs.MessageType.WRAPPED_POST;
+import static junit.framework.Assert.assertNotNull;
+import static org.briarproject.briar.api.blog.MessageType.COMMENT;
+import static org.briarproject.briar.api.blog.MessageType.POST;
+import static org.briarproject.briar.api.blog.MessageType.WRAPPED_COMMENT;
+import static org.briarproject.briar.api.blog.MessageType.WRAPPED_POST;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
-public class BlogManagerTest extends BriarIntegrationTest {
+public class BlogManagerTest
+		extends BriarIntegrationTest<BriarIntegrationTestComponent> {
 
 	private BlogManager blogManager0, blogManager1;
 	private Blog blog0, blog1;
@@ -45,6 +48,25 @@ public class BlogManagerTest extends BriarIntegrationTest {
 		blog1 = blogFactory.createBlog(author1);
 	}
 
+	@Override
+	protected void createComponents() {
+		BriarIntegrationTestComponent component =
+				DaggerBriarIntegrationTestComponent.builder().build();
+		component.inject(this);
+
+		c0 = DaggerBriarIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t0Dir)).build();
+		injectEagerSingletons(c0);
+
+		c1 = DaggerBriarIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t1Dir)).build();
+		injectEagerSingletons(c1);
+
+		c2 = DaggerBriarIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t2Dir)).build();
+		injectEagerSingletons(c2);
+	}
+
 	@Test
 	public void testPersonalBlogInitialisation() throws Exception {
 		Collection<Blog> blogs0 = blogManager0.getBlogs();
@@ -189,7 +211,9 @@ public class BlogManagerTest extends BriarIntegrationTest {
 		assertEquals(author0, h.getParent().getAuthor());
 
 		// ensure that body can be retrieved from wrapped post
-		assertEquals(body, blogManager0.getPostBody(h.getParentId()));
+		MessageId parentId = h.getParentId();
+		assertNotNull(parentId);
+		assertEquals(body, blogManager0.getPostBody(parentId));
 
 		// 1 has only their own comment in their blog
 		headers1 = blogManager1.getPostHeaders(blog1.getId());
@@ -227,7 +251,7 @@ public class BlogManagerTest extends BriarIntegrationTest {
 			if (h.getType() == POST) {
 				assertEquals(body, blogManager1.getPostBody(h.getId()));
 			} else {
-				assertEquals(comment, ((BlogCommentHeader)h).getComment());
+				assertEquals(comment, ((BlogCommentHeader) h).getComment());
 			}
 		}
 	}
diff --git a/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTest.java
index 2ceea6e9f2a9e28464e91db1f579c0009d98c924..538cf3ccf9b761735469526657603d06bbb62244 100644
--- a/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTest.java
+++ b/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTest.java
@@ -2,19 +2,20 @@ package org.briarproject;
 
 import net.jodah.concurrentunit.Waiter;
 
-import org.briarproject.api.blogs.Blog;
-import org.briarproject.api.blogs.BlogInvitationRequest;
-import org.briarproject.api.blogs.BlogInvitationResponse;
-import org.briarproject.api.blogs.BlogManager;
-import org.briarproject.api.blogs.BlogSharingManager;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.event.BlogInvitationReceivedEvent;
-import org.briarproject.api.event.BlogInvitationResponseReceivedEvent;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.sharing.InvitationMessage;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.api.blog.Blog;
+import org.briarproject.briar.api.blog.BlogInvitationRequest;
+import org.briarproject.briar.api.blog.BlogInvitationResponse;
+import org.briarproject.briar.api.blog.BlogManager;
+import org.briarproject.briar.api.blog.BlogSharingManager;
+import org.briarproject.briar.api.blog.event.BlogInvitationRequestReceivedEvent;
+import org.briarproject.briar.api.blog.event.BlogInvitationResponseReceivedEvent;
+import org.briarproject.briar.api.sharing.InvitationMessage;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -25,12 +26,13 @@ import java.util.Collection;
 import java.util.List;
 
 import static org.briarproject.TestUtils.assertGroupCount;
-import static org.briarproject.api.blogs.BlogSharingManager.CLIENT_ID;
+import static org.briarproject.briar.api.blog.BlogSharingManager.CLIENT_ID;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-public class BlogSharingIntegrationTest extends BriarIntegrationTest {
+public class BlogSharingIntegrationTest
+		extends BriarIntegrationTest<BriarIntegrationTestComponent> {
 
 	private BlogManager blogManager1;
 	private Blog blog0, blog1, blog2;
@@ -65,6 +67,25 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest {
 		eventWaiter = new Waiter();
 	}
 
+	@Override
+	protected void createComponents() {
+		BriarIntegrationTestComponent component =
+				DaggerBriarIntegrationTestComponent.builder().build();
+		component.inject(this);
+
+		c0 = DaggerBriarIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t0Dir)).build();
+		injectEagerSingletons(c0);
+
+		c1 = DaggerBriarIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t1Dir)).build();
+		injectEagerSingletons(c1);
+
+		c2 = DaggerBriarIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t2Dir)).build();
+		injectEagerSingletons(c2);
+	}
+
 	@Test
 	public void testPersonalBlogCannotBeSharedWithOwner() throws Exception {
 		listenToEvents(true);
@@ -213,7 +234,8 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest {
 				blogSharingManager0.getInvitationMessages(contactId1From0)
 						.size());
 		// blog can be shared again
-		assertTrue(blogSharingManager0.canBeShared(blog2.getId(), contact1From0));
+		assertTrue(
+				blogSharingManager0.canBeShared(blog2.getId(), contact1From0));
 	}
 
 	@Test
@@ -264,8 +286,10 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest {
 		assertFalse(blogSharingManager1.getSharedBy(blog2.getId())
 				.contains(contact0From1));
 		// blog can be shared again
-		assertTrue(blogSharingManager0.canBeShared(blog2.getId(), contact1From0));
-		assertTrue(blogSharingManager1.canBeShared(blog2.getId(), contact0From1));
+		assertTrue(
+				blogSharingManager0.canBeShared(blog2.getId(), contact1From0));
+		assertTrue(
+				blogSharingManager1.canBeShared(blog2.getId(), contact0From1));
 	}
 
 	@Test
@@ -393,6 +417,7 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest {
 		assertFalse(blogManager1.canBeRemoved(blog2.getId()));
 	}
 
+	@NotNullByDefault
 	private class SharerListener implements EventListener {
 
 		private volatile boolean responseReceived = false;
@@ -407,9 +432,9 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest {
 				eventWaiter.resume();
 			}
 			// this is only needed for tests where a blog is re-shared
-			else if (e instanceof BlogInvitationReceivedEvent) {
-				BlogInvitationReceivedEvent event =
-						(BlogInvitationReceivedEvent) e;
+			else if (e instanceof BlogInvitationRequestReceivedEvent) {
+				BlogInvitationRequestReceivedEvent event =
+						(BlogInvitationRequestReceivedEvent) e;
 				eventWaiter.assertEquals(contactId1From0, event.getContactId());
 				Blog b = event.getShareable();
 				try {
@@ -424,6 +449,7 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest {
 		}
 	}
 
+	@NotNullByDefault
 	private class InviteeListener implements EventListener {
 
 		private volatile boolean requestReceived = false;
@@ -441,9 +467,9 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest {
 
 		@Override
 		public void eventOccurred(Event e) {
-			if (e instanceof BlogInvitationReceivedEvent) {
-				BlogInvitationReceivedEvent event =
-						(BlogInvitationReceivedEvent) e;
+			if (e instanceof BlogInvitationRequestReceivedEvent) {
+				BlogInvitationRequestReceivedEvent event =
+						(BlogInvitationRequestReceivedEvent) e;
 				requestReceived = true;
 				if (!answer) return;
 				Blog b = event.getShareable();
diff --git a/briar-android-tests/src/test/java/org/briarproject/BriarIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/BriarIntegrationTest.java
index fcd3205e73a759c6f3d652c21df7eb9a7aeb5cd5..73efbf9ba19703a8d91953e11c583e661981cecf 100644
--- a/briar-android-tests/src/test/java/org/briarproject/BriarIntegrationTest.java
+++ b/briar-android-tests/src/test/java/org/briarproject/BriarIntegrationTest.java
@@ -4,47 +4,48 @@ import android.support.annotation.CallSuper;
 
 import net.jodah.concurrentunit.Waiter;
 
-import org.briarproject.api.blogs.BlogFactory;
-import org.briarproject.api.blogs.BlogPostFactory;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.ContactGroupFactory;
-import org.briarproject.api.clients.MessageTracker;
-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.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.MessageStateChangedEvent;
-import org.briarproject.api.forum.ForumPostFactory;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.privategroup.GroupMessageFactory;
-import org.briarproject.api.privategroup.PrivateGroupFactory;
-import org.briarproject.api.privategroup.invitation.GroupInvitationFactory;
-import org.briarproject.api.sync.SyncSession;
-import org.briarproject.api.sync.SyncSessionFactory;
-import org.briarproject.api.system.Clock;
-import org.briarproject.blogs.BlogsModule;
-import org.briarproject.contact.ContactModule;
-import org.briarproject.crypto.CryptoModule;
-import org.briarproject.forum.ForumModule;
-import org.briarproject.introduction.IntroductionGroupFactory;
-import org.briarproject.introduction.IntroductionModule;
-import org.briarproject.lifecycle.LifecycleModule;
-import org.briarproject.privategroup.PrivateGroupModule;
-import org.briarproject.privategroup.invitation.GroupInvitationModule;
-import org.briarproject.properties.PropertiesModule;
-import org.briarproject.sharing.SharingModule;
-import org.briarproject.sync.SyncModule;
-import org.briarproject.transport.TransportModule;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.client.ContactGroupFactory;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.SyncSession;
+import org.briarproject.bramble.api.sync.SyncSessionFactory;
+import org.briarproject.bramble.api.sync.event.MessageStateChangedEvent;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.bramble.contact.ContactModule;
+import org.briarproject.bramble.crypto.CryptoModule;
+import org.briarproject.bramble.identity.IdentityModule;
+import org.briarproject.bramble.lifecycle.LifecycleModule;
+import org.briarproject.bramble.properties.PropertiesModule;
+import org.briarproject.bramble.sync.SyncModule;
+import org.briarproject.bramble.system.SystemModule;
+import org.briarproject.bramble.transport.TransportModule;
+import org.briarproject.briar.api.blog.BlogFactory;
+import org.briarproject.briar.api.blog.BlogPostFactory;
+import org.briarproject.briar.api.client.MessageTracker;
+import org.briarproject.briar.api.forum.ForumPostFactory;
+import org.briarproject.briar.api.privategroup.GroupMessageFactory;
+import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory;
+import org.briarproject.briar.blog.BlogModule;
+import org.briarproject.briar.forum.ForumModule;
+import org.briarproject.briar.introduction.IntroductionModule;
+import org.briarproject.briar.messaging.MessagingModule;
+import org.briarproject.briar.privategroup.PrivateGroupModule;
+import org.briarproject.briar.privategroup.invitation.GroupInvitationModule;
+import org.briarproject.briar.sharing.SharingModule;
 import org.junit.After;
 import org.junit.Before;
 
@@ -55,19 +56,21 @@ import java.io.IOException;
 import java.util.concurrent.TimeoutException;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import static junit.framework.Assert.assertNotNull;
-import static org.briarproject.TestPluginsModule.MAX_LATENCY;
+import static org.briarproject.TestPluginConfigModule.MAX_LATENCY;
 import static org.briarproject.TestUtils.getSecretKey;
-import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
-import static org.briarproject.api.sync.ValidationManager.State.INVALID;
-import static org.briarproject.api.sync.ValidationManager.State.PENDING;
+import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
+import static org.briarproject.bramble.api.sync.ValidationManager.State.INVALID;
+import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
 import static org.junit.Assert.assertTrue;
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
-public abstract class BriarIntegrationTest extends BriarTestCase {
+public abstract class BriarIntegrationTest<C extends BriarIntegrationTestComponent>
+		extends BriarTestCase {
 
 	private static final Logger LOG =
 			Logger.getLogger(BriarIntegrationTest.class.getName());
@@ -98,8 +101,6 @@ public abstract class BriarIntegrationTest extends BriarTestCase {
 	@Inject
 	protected AuthorFactory authorFactory;
 	@Inject
-	protected IntroductionGroupFactory introductionGroupFactory;
-	@Inject
 	ContactGroupFactory contactGroupFactory;
 	@Inject
 	PrivateGroupFactory privateGroupFactory;
@@ -119,33 +120,22 @@ public abstract class BriarIntegrationTest extends BriarTestCase {
 	private volatile Waiter deliveryWaiter;
 
 	protected final static int TIMEOUT = 15000;
-	protected BriarIntegrationTestComponent c0, c1, c2;
+	protected C c0, c1, c2;
 
 	private final File testDir = TestUtils.getTestDirectory();
 	private final String AUTHOR0 = "Author 0";
 	private final String AUTHOR1 = "Author 1";
 	private final String AUTHOR2 = "Author 2";
 
+	protected File t0Dir = new File(testDir, AUTHOR0);
+	protected File t1Dir = new File(testDir, AUTHOR1);
+	protected File t2Dir = new File(testDir, AUTHOR2);
+
 	@Before
 	@CallSuper
 	public void setUp() throws Exception {
-		BriarIntegrationTestComponent component =
-				DaggerBriarIntegrationTestComponent.builder().build();
-		component.inject(this);
-
 		assertTrue(testDir.mkdirs());
-		File t0Dir = new File(testDir, AUTHOR0);
-		c0 = DaggerBriarIntegrationTestComponent.builder()
-				.testDatabaseModule(new TestDatabaseModule(t0Dir)).build();
-		injectEagerSingletons(c0);
-		File t1Dir = new File(testDir, AUTHOR1);
-		c1 = DaggerBriarIntegrationTestComponent.builder()
-				.testDatabaseModule(new TestDatabaseModule(t1Dir)).build();
-		injectEagerSingletons(c1);
-		File t2Dir = new File(testDir, AUTHOR2);
-		c2 = DaggerBriarIntegrationTestComponent.builder()
-				.testDatabaseModule(new TestDatabaseModule(t2Dir)).build();
-		injectEagerSingletons(c2);
+		createComponents();
 
 		identityManager0 = c0.getIdentityManager();
 		identityManager1 = c1.getIdentityManager();
@@ -174,19 +164,24 @@ public abstract class BriarIntegrationTest extends BriarTestCase {
 		listenToEvents();
 	}
 
-	private void injectEagerSingletons(
+	abstract protected void createComponents();
+
+	protected void injectEagerSingletons(
 			BriarIntegrationTestComponent component) {
-		component.inject(new LifecycleModule.EagerSingletons());
-		component.inject(new BlogsModule.EagerSingletons());
-		component.inject(new CryptoModule.EagerSingletons());
+		component.inject(new BlogModule.EagerSingletons());
 		component.inject(new ContactModule.EagerSingletons());
+		component.inject(new CryptoModule.EagerSingletons());
 		component.inject(new ForumModule.EagerSingletons());
 		component.inject(new GroupInvitationModule.EagerSingletons());
+		component.inject(new IdentityModule.EagerSingletons());
 		component.inject(new IntroductionModule.EagerSingletons());
-		component.inject(new PropertiesModule.EagerSingletons());
+		component.inject(new LifecycleModule.EagerSingletons());
+		component.inject(new MessagingModule.EagerSingletons());
 		component.inject(new PrivateGroupModule.EagerSingletons());
-		component.inject(new SyncModule.EagerSingletons());
+		component.inject(new PropertiesModule.EagerSingletons());
 		component.inject(new SharingModule.EagerSingletons());
+		component.inject(new SyncModule.EagerSingletons());
+		component.inject(new SystemModule.EagerSingletons());
 		component.inject(new TransportModule.EagerSingletons());
 	}
 
@@ -355,8 +350,10 @@ public abstract class BriarIntegrationTest extends BriarTestCase {
 		contactManager0.removeContact(contactId1From0);
 		contactManager0.removeContact(contactId2From0);
 		contactManager1.removeContact(contactId0From1);
-		contactManager1.removeContact(contactId2From1);
 		contactManager2.removeContact(contactId0From2);
+		assertNotNull(contactId2From1);
+		contactManager1.removeContact(contactId2From1);
+		assertNotNull(contactId1From2);
 		contactManager2.removeContact(contactId1From2);
 	}
 }
diff --git a/briar-android-tests/src/test/java/org/briarproject/BriarIntegrationTestComponent.java b/briar-android-tests/src/test/java/org/briarproject/BriarIntegrationTestComponent.java
index 7d4cdf2a8a8197f63954c8d58676d9d8fd019edd..ddca97605e5eff615ce1986673c08228315fa327 100644
--- a/briar-android-tests/src/test/java/org/briarproject/BriarIntegrationTestComponent.java
+++ b/briar-android-tests/src/test/java/org/briarproject/BriarIntegrationTestComponent.java
@@ -1,42 +1,42 @@
 package org.briarproject;
 
-import org.briarproject.api.blogs.BlogManager;
-import org.briarproject.api.blogs.BlogSharingManager;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageQueueManager;
-import org.briarproject.api.clients.MessageTracker;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.forum.ForumSharingManager;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.introduction.IntroductionManager;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.privategroup.PrivateGroupManager;
-import org.briarproject.api.privategroup.invitation.GroupInvitationManager;
-import org.briarproject.api.properties.TransportPropertyManager;
-import org.briarproject.api.sync.SyncSessionFactory;
-import org.briarproject.blogs.BlogsModule;
-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.forum.ForumModule;
-import org.briarproject.identity.IdentityModule;
-import org.briarproject.introduction.IntroductionModule;
-import org.briarproject.introduction.MessageSender;
-import org.briarproject.lifecycle.LifecycleModule;
-import org.briarproject.messaging.MessagingModule;
-import org.briarproject.privategroup.PrivateGroupModule;
-import org.briarproject.privategroup.invitation.GroupInvitationModule;
-import org.briarproject.properties.PropertiesModule;
-import org.briarproject.sharing.SharingModule;
-import org.briarproject.sync.SyncModule;
-import org.briarproject.system.SystemModule;
-import org.briarproject.transport.TransportModule;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.properties.TransportPropertyManager;
+import org.briarproject.bramble.api.sync.SyncSessionFactory;
+import org.briarproject.bramble.client.ClientModule;
+import org.briarproject.bramble.contact.ContactModule;
+import org.briarproject.bramble.crypto.CryptoModule;
+import org.briarproject.bramble.data.DataModule;
+import org.briarproject.bramble.db.DatabaseModule;
+import org.briarproject.bramble.event.EventModule;
+import org.briarproject.bramble.identity.IdentityModule;
+import org.briarproject.bramble.lifecycle.LifecycleModule;
+import org.briarproject.bramble.properties.PropertiesModule;
+import org.briarproject.bramble.sync.SyncModule;
+import org.briarproject.bramble.system.SystemModule;
+import org.briarproject.bramble.transport.TransportModule;
+import org.briarproject.briar.api.blog.BlogManager;
+import org.briarproject.briar.api.blog.BlogSharingManager;
+import org.briarproject.briar.api.client.MessageQueueManager;
+import org.briarproject.briar.api.client.MessageTracker;
+import org.briarproject.briar.api.forum.ForumManager;
+import org.briarproject.briar.api.forum.ForumSharingManager;
+import org.briarproject.briar.api.introduction.IntroductionManager;
+import org.briarproject.briar.api.privategroup.PrivateGroupManager;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager;
+import org.briarproject.briar.blog.BlogModule;
+import org.briarproject.briar.client.BriarClientModule;
+import org.briarproject.briar.forum.ForumModule;
+import org.briarproject.briar.introduction.IntroductionModule;
+import org.briarproject.briar.messaging.MessagingModule;
+import org.briarproject.briar.privategroup.PrivateGroupModule;
+import org.briarproject.briar.privategroup.invitation.GroupInvitationModule;
+import org.briarproject.briar.sharing.SharingModule;
 
 import javax.inject.Singleton;
 
@@ -45,21 +45,22 @@ import dagger.Component;
 @Singleton
 @Component(modules = {
 		TestDatabaseModule.class,
-		TestPluginsModule.class,
+		TestPluginConfigModule.class,
 		TestSeedProviderModule.class,
-		ClientsModule.class,
+		BlogModule.class,
+		BriarClientModule.class,
+		ClientModule.class,
 		ContactModule.class,
 		CryptoModule.class,
-		BlogsModule.class,
 		DataModule.class,
 		DatabaseModule.class,
 		EventModule.class,
 		ForumModule.class,
 		GroupInvitationModule.class,
-		MessagingModule.class,
 		IdentityModule.class,
 		IntroductionModule.class,
 		LifecycleModule.class,
+		MessagingModule.class,
 		PrivateGroupModule.class,
 		PropertiesModule.class,
 		SharingModule.class,
@@ -69,9 +70,9 @@ import dagger.Component;
 })
 public interface BriarIntegrationTestComponent {
 
-	void inject(BriarIntegrationTest init);
+	void inject(BriarIntegrationTest<BriarIntegrationTestComponent> init);
 
-	void inject(BlogsModule.EagerSingletons init);
+	void inject(BlogModule.EagerSingletons init);
 
 	void inject(ContactModule.EagerSingletons init);
 
@@ -81,10 +82,14 @@ public interface BriarIntegrationTestComponent {
 
 	void inject(GroupInvitationModule.EagerSingletons init);
 
+	void inject(IdentityModule.EagerSingletons init);
+
 	void inject(IntroductionModule.EagerSingletons init);
 
 	void inject(LifecycleModule.EagerSingletons init);
 
+	void inject(MessagingModule.EagerSingletons init);
+
 	void inject(PrivateGroupModule.EagerSingletons init);
 
 	void inject(PropertiesModule.EagerSingletons init);
@@ -93,6 +98,8 @@ public interface BriarIntegrationTestComponent {
 
 	void inject(SyncModule.EagerSingletons init);
 
+	void inject(SystemModule.EagerSingletons init);
+
 	void inject(TransportModule.EagerSingletons init);
 
 	LifecycleManager getLifecycleManager();
@@ -123,8 +130,6 @@ public interface BriarIntegrationTestComponent {
 
 	MessageTracker getMessageTracker();
 
-	MessageSender getMessageSender();
-
 	MessageQueueManager getMessageQueueManager();
 
 	PrivateGroupManager getPrivateGroupManager();
diff --git a/briar-android-tests/src/test/java/org/briarproject/ForumManagerTest.java b/briar-android-tests/src/test/java/org/briarproject/ForumManagerTest.java
index 3d5c827d0fe946ce23fd546b9b91f28a7a105b88..72c8fc0e43861513265213fda76b6c98ae942aee 100644
--- a/briar-android-tests/src/test/java/org/briarproject/ForumManagerTest.java
+++ b/briar-android-tests/src/test/java/org/briarproject/ForumManagerTest.java
@@ -2,25 +2,27 @@ package org.briarproject;
 
 import junit.framework.Assert;
 
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.forum.ForumPost;
-import org.briarproject.api.forum.ForumPostHeader;
-import org.briarproject.api.forum.ForumSharingManager;
-import org.briarproject.api.sync.GroupId;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.api.forum.Forum;
+import org.briarproject.briar.api.forum.ForumManager;
+import org.briarproject.briar.api.forum.ForumPost;
+import org.briarproject.briar.api.forum.ForumPostHeader;
+import org.briarproject.briar.api.forum.ForumSharingManager;
 import org.junit.Before;
 import org.junit.Test;
 
 import java.util.Collection;
 
+import javax.annotation.Nullable;
+
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertNull;
 import static junit.framework.TestCase.assertFalse;
 import static org.briarproject.TestUtils.assertGroupCount;
 import static org.junit.Assert.assertTrue;
 
-public class ForumManagerTest extends BriarIntegrationTest {
+public class ForumManagerTest
+		extends BriarIntegrationTest<BriarIntegrationTestComponent> {
 
 	private ForumManager forumManager0, forumManager1;
 	private ForumSharingManager forumSharingManager0, forumSharingManager1;
@@ -47,6 +49,25 @@ public class ForumManagerTest extends BriarIntegrationTest {
 		sync1To0(1, true);
 	}
 
+	@Override
+	protected void createComponents() {
+		BriarIntegrationTestComponent component =
+				DaggerBriarIntegrationTestComponent.builder().build();
+		component.inject(this);
+
+		c0 = DaggerBriarIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t0Dir)).build();
+		injectEagerSingletons(c0);
+
+		c1 = DaggerBriarIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t1Dir)).build();
+		injectEagerSingletons(c1);
+
+		c2 = DaggerBriarIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t2Dir)).build();
+		injectEagerSingletons(c2);
+	}
+
 	private ForumPost createForumPost(GroupId groupId,
 			@Nullable ForumPost parent, String body, long ms) throws Exception {
 		return forumPostFactory.createPost(groupId, ms,
diff --git a/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java
index 249354bd2116147efba70b1a05a6be6af6981935..40e3f0103f00f63da54b8cb5716a8f0c8eeebbb2 100644
--- a/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java
+++ b/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java
@@ -2,28 +2,29 @@ package org.briarproject;
 
 import net.jodah.concurrentunit.Waiter;
 
-import org.briarproject.api.Bytes;
-import org.briarproject.api.clients.MessageQueueManager;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.ForumInvitationReceivedEvent;
-import org.briarproject.api.event.ForumInvitationResponseReceivedEvent;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumInvitationRequest;
-import org.briarproject.api.forum.ForumInvitationResponse;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.forum.ForumPost;
-import org.briarproject.api.forum.ForumPostHeader;
-import org.briarproject.api.forum.ForumSharingManager;
-import org.briarproject.api.sharing.InvitationMessage;
-import org.briarproject.api.sharing.SharingInvitationItem;
-import org.briarproject.api.sync.Group;
+import org.briarproject.bramble.api.Bytes;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.briar.api.client.MessageQueueManager;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.forum.Forum;
+import org.briarproject.briar.api.forum.ForumInvitationRequest;
+import org.briarproject.briar.api.forum.ForumInvitationResponse;
+import org.briarproject.briar.api.forum.ForumManager;
+import org.briarproject.briar.api.forum.ForumPost;
+import org.briarproject.briar.api.forum.ForumPostHeader;
+import org.briarproject.briar.api.forum.ForumSharingManager;
+import org.briarproject.briar.api.forum.event.ForumInvitationRequestReceivedEvent;
+import org.briarproject.briar.api.forum.event.ForumInvitationResponseReceivedEvent;
+import org.briarproject.briar.api.sharing.InvitationMessage;
+import org.briarproject.briar.api.sharing.SharingInvitationItem;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -33,14 +34,16 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
-import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH;
-import static org.briarproject.api.forum.ForumSharingManager.CLIENT_ID;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION;
+import static junit.framework.Assert.assertNotNull;
+import static org.briarproject.briar.api.forum.ForumConstants.FORUM_SALT_LENGTH;
+import static org.briarproject.briar.api.forum.ForumSharingManager.CLIENT_ID;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-public class ForumSharingIntegrationTest extends BriarIntegrationTest {
+public class ForumSharingIntegrationTest
+		extends BriarIntegrationTest<BriarIntegrationTestComponent> {
 
 	private ForumManager forumManager0, forumManager1;
 	private SharerListener listener0, listener2;
@@ -76,6 +79,25 @@ public class ForumSharingIntegrationTest extends BriarIntegrationTest {
 		addForumForSharer();
 	}
 
+	@Override
+	protected void createComponents() {
+		BriarIntegrationTestComponent component =
+				DaggerBriarIntegrationTestComponent.builder().build();
+		component.inject(this);
+
+		c0 = DaggerBriarIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t0Dir)).build();
+		injectEagerSingletons(c0);
+
+		c1 = DaggerBriarIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t1Dir)).build();
+		injectEagerSingletons(c1);
+
+		c2 = DaggerBriarIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t2Dir)).build();
+		injectEagerSingletons(c2);
+	}
+
 	private void addForumForSharer() throws DbException {
 		forum0 = forumManager0.addForum("Test Forum");
 	}
@@ -633,6 +655,7 @@ public class ForumSharingIntegrationTest extends BriarIntegrationTest {
 		assertEquals(2, contacts.size());
 
 		// answer second request
+		assertNotNull(contactId2From1);
 		Contact contact2From1 = contactManager1.getContact(contactId2From1);
 		forumSharingManager1.respondToInvitation(forum0, contact2From1, true);
 		// sync response
@@ -752,6 +775,7 @@ public class ForumSharingIntegrationTest extends BriarIntegrationTest {
 		assertTrue(found);
 	}
 
+	@NotNullByDefault
 	private class SharerListener implements EventListener {
 
 		private volatile boolean requestReceived = false;
@@ -764,9 +788,9 @@ public class ForumSharingIntegrationTest extends BriarIntegrationTest {
 				eventWaiter.resume();
 			}
 			// this is only needed for tests where a forum is re-shared
-			else if (e instanceof ForumInvitationReceivedEvent) {
-				ForumInvitationReceivedEvent event =
-						(ForumInvitationReceivedEvent) e;
+			else if (e instanceof ForumInvitationRequestReceivedEvent) {
+				ForumInvitationRequestReceivedEvent event =
+						(ForumInvitationRequestReceivedEvent) e;
 				eventWaiter.assertEquals(contactId1From0, event.getContactId());
 				requestReceived = true;
 				Forum f = event.getShareable();
@@ -782,6 +806,7 @@ public class ForumSharingIntegrationTest extends BriarIntegrationTest {
 		}
 	}
 
+	@NotNullByDefault
 	private class InviteeListener implements EventListener {
 
 		private volatile boolean requestReceived = false;
@@ -800,9 +825,9 @@ public class ForumSharingIntegrationTest extends BriarIntegrationTest {
 
 		@Override
 		public void eventOccurred(Event e) {
-			if (e instanceof ForumInvitationReceivedEvent) {
-				ForumInvitationReceivedEvent event =
-						(ForumInvitationReceivedEvent) e;
+			if (e instanceof ForumInvitationRequestReceivedEvent) {
+				ForumInvitationRequestReceivedEvent event =
+						(ForumInvitationRequestReceivedEvent) e;
 				requestReceived = true;
 				if (!answer) return;
 				Forum f = event.getShareable();
diff --git a/briar-android-tests/src/test/java/org/briarproject/GroupInvitationIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/GroupInvitationIntegrationTest.java
index 198a3039d65b155f54d23429b1bd2048a9f34253..7c350c630129e836fb1aeeb765e608b1890901bd 100644
--- a/briar-android-tests/src/test/java/org/briarproject/GroupInvitationIntegrationTest.java
+++ b/briar-android-tests/src/test/java/org/briarproject/GroupInvitationIntegrationTest.java
@@ -1,29 +1,31 @@
 package org.briarproject;
 
-import org.briarproject.api.clients.ProtocolStateException;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.privategroup.GroupMessage;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.privategroup.PrivateGroupManager;
-import org.briarproject.api.privategroup.invitation.GroupInvitationItem;
-import org.briarproject.api.privategroup.invitation.GroupInvitationManager;
-import org.briarproject.api.privategroup.invitation.GroupInvitationRequest;
-import org.briarproject.api.privategroup.invitation.GroupInvitationResponse;
-import org.briarproject.api.sharing.InvitationMessage;
-import org.briarproject.api.sync.Group;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.briar.api.client.ProtocolStateException;
+import org.briarproject.briar.api.privategroup.GroupMessage;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.privategroup.PrivateGroupManager;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationItem;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse;
+import org.briarproject.briar.api.sharing.InvitationMessage;
 import org.junit.Before;
 import org.junit.Test;
 
 import java.util.Collection;
 
+import javax.annotation.Nullable;
+
 import static junit.framework.TestCase.fail;
 import static org.briarproject.TestUtils.assertGroupCount;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-public class GroupInvitationIntegrationTest extends BriarIntegrationTest {
+public class GroupInvitationIntegrationTest
+		extends BriarIntegrationTest<BriarIntegrationTestComponent> {
 
 	private PrivateGroup privateGroup0;
 	private PrivateGroupManager groupManager0, groupManager1;
@@ -48,6 +50,25 @@ public class GroupInvitationIntegrationTest extends BriarIntegrationTest {
 		groupManager0.addPrivateGroup(privateGroup0, joinMsg0, true);
 	}
 
+	@Override
+	protected void createComponents() {
+		BriarIntegrationTestComponent component =
+				DaggerBriarIntegrationTestComponent.builder().build();
+		component.inject(this);
+
+		c0 = DaggerBriarIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t0Dir)).build();
+		injectEagerSingletons(c0);
+
+		c1 = DaggerBriarIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t1Dir)).build();
+		injectEagerSingletons(c1);
+
+		c2 = DaggerBriarIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t2Dir)).build();
+		injectEagerSingletons(c2);
+	}
+
 	@Test
 	public void testSendInvitation() throws Exception {
 		long timestamp = clock.currentTimeMillis();
diff --git a/briar-android-tests/src/test/java/org/briarproject/MessageSizeIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/MessageSizeIntegrationTest.java
index b63c070dc883b0ae8783e0e87f7346965856e1d7..78a57af54c32f049243163faa915f43dd201dd5d 100644
--- a/briar-android-tests/src/test/java/org/briarproject/MessageSizeIntegrationTest.java
+++ b/briar-android-tests/src/test/java/org/briarproject/MessageSizeIntegrationTest.java
@@ -1,28 +1,28 @@
 package org.briarproject;
 
-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.AuthorFactory;
-import org.briarproject.api.identity.LocalAuthor;
-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.briarproject.system.SystemModule;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.UniqueId;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.PrivateKey;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.system.SystemModule;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.api.forum.ForumConstants;
+import org.briarproject.briar.api.forum.ForumPost;
+import org.briarproject.briar.api.forum.ForumPostFactory;
+import org.briarproject.briar.api.messaging.PrivateMessage;
+import org.briarproject.briar.api.messaging.PrivateMessageFactory;
 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.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_PACKET_PAYLOAD_LENGTH;
+import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
+import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
 import static org.junit.Assert.assertTrue;
 
 public class MessageSizeIntegrationTest extends BriarTestCase {
@@ -40,7 +40,7 @@ public class MessageSizeIntegrationTest extends BriarTestCase {
 		MessageSizeIntegrationTestComponent component =
 				DaggerMessageSizeIntegrationTestComponent.builder().build();
 		component.inject(this);
-		component.inject(new SystemModule.EagerSingletons());
+		injectEagerSingletons(component);
 	}
 
 	@Test
@@ -84,4 +84,9 @@ public class MessageSizeIntegrationTest extends BriarTestCase {
 				+ MAX_FORUM_POST_BODY_LENGTH);
 		assertTrue(length <= MAX_PACKET_PAYLOAD_LENGTH);
 	}
+
+	private static void injectEagerSingletons(
+			MessageSizeIntegrationTestComponent component) {
+		component.inject(new SystemModule.EagerSingletons());
+	}
 }
diff --git a/briar-android-tests/src/test/java/org/briarproject/MessageSizeIntegrationTestComponent.java b/briar-android-tests/src/test/java/org/briarproject/MessageSizeIntegrationTestComponent.java
index fe530464065456a4d633f83621d6a2bacf40eb87..5921a61410deeaf7d22d47a2eb7d7258185daf8b 100644
--- a/briar-android-tests/src/test/java/org/briarproject/MessageSizeIntegrationTestComponent.java
+++ b/briar-android-tests/src/test/java/org/briarproject/MessageSizeIntegrationTestComponent.java
@@ -1,15 +1,16 @@
 package org.briarproject;
 
-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 org.briarproject.system.SystemModule;
+import org.briarproject.bramble.client.ClientModule;
+import org.briarproject.bramble.crypto.CryptoModule;
+import org.briarproject.bramble.data.DataModule;
+import org.briarproject.bramble.db.DatabaseModule;
+import org.briarproject.bramble.event.EventModule;
+import org.briarproject.bramble.identity.IdentityModule;
+import org.briarproject.bramble.sync.SyncModule;
+import org.briarproject.bramble.system.SystemModule;
+import org.briarproject.briar.client.BriarClientModule;
+import org.briarproject.briar.forum.ForumModule;
+import org.briarproject.briar.messaging.MessagingModule;
 
 import javax.inject.Singleton;
 
@@ -20,7 +21,8 @@ import dagger.Component;
 		TestDatabaseModule.class,
 		TestLifecycleModule.class,
 		TestSeedProviderModule.class,
-		ClientsModule.class,
+		BriarClientModule.class,
+		ClientModule.class,
 		CryptoModule.class,
 		DataModule.class,
 		DatabaseModule.class,
@@ -31,7 +33,7 @@ import dagger.Component;
 		SyncModule.class,
 		SystemModule.class
 })
-public interface MessageSizeIntegrationTestComponent {
+interface MessageSizeIntegrationTestComponent {
 
 	void inject(MessageSizeIntegrationTest testCase);
 
diff --git a/briar-android-tests/src/test/java/org/briarproject/PrivateGroupIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/PrivateGroupIntegrationTest.java
index f1b96df29fb5011dc98d50b08948a0a5d8c7036a..7e435710e65b95ca05bba9292e2f579c3fa66e17 100644
--- a/briar-android-tests/src/test/java/org/briarproject/PrivateGroupIntegrationTest.java
+++ b/briar-android-tests/src/test/java/org/briarproject/PrivateGroupIntegrationTest.java
@@ -1,28 +1,29 @@
 package org.briarproject;
 
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.privategroup.GroupMember;
-import org.briarproject.api.privategroup.GroupMessage;
-import org.briarproject.api.privategroup.GroupMessageHeader;
-import org.briarproject.api.privategroup.JoinMessageHeader;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.privategroup.PrivateGroupManager;
-import org.briarproject.api.privategroup.invitation.GroupInvitationManager;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.privategroup.GroupMember;
+import org.briarproject.briar.api.privategroup.GroupMessage;
+import org.briarproject.briar.api.privategroup.GroupMessageHeader;
+import org.briarproject.briar.api.privategroup.JoinMessageHeader;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.privategroup.PrivateGroupManager;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager;
 import org.junit.Before;
 import org.junit.Test;
 
 import java.util.Collection;
 
-import static org.briarproject.api.identity.Author.Status.OURSELVES;
-import static org.briarproject.api.privategroup.Visibility.INVISIBLE;
-import static org.briarproject.api.privategroup.Visibility.REVEALED_BY_CONTACT;
-import static org.briarproject.api.privategroup.Visibility.REVEALED_BY_US;
+import javax.annotation.Nullable;
+
+import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
+import static org.briarproject.briar.api.privategroup.Visibility.INVISIBLE;
+import static org.briarproject.briar.api.privategroup.Visibility.REVEALED_BY_CONTACT;
+import static org.briarproject.briar.api.privategroup.Visibility.REVEALED_BY_US;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -30,7 +31,8 @@ import static org.junit.Assert.assertTrue;
  * This class tests how PrivateGroupManager and GroupInvitationManager
  * play together.
  */
-public class PrivateGroupIntegrationTest extends BriarIntegrationTest {
+public class PrivateGroupIntegrationTest
+		extends BriarIntegrationTest<BriarIntegrationTestComponent> {
 
 	private GroupId groupId0;
 	private PrivateGroup privateGroup0;
@@ -59,6 +61,25 @@ public class PrivateGroupIntegrationTest extends BriarIntegrationTest {
 		groupManager0.addPrivateGroup(privateGroup0, joinMsg0, true);
 	}
 
+	@Override
+	protected void createComponents() {
+		BriarIntegrationTestComponent component =
+				DaggerBriarIntegrationTestComponent.builder().build();
+		component.inject(this);
+
+		c0 = DaggerBriarIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t0Dir)).build();
+		injectEagerSingletons(c0);
+
+		c1 = DaggerBriarIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t1Dir)).build();
+		injectEagerSingletons(c1);
+
+		c2 = DaggerBriarIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t2Dir)).build();
+		injectEagerSingletons(c2);
+	}
+
 	@Test
 	public void testMembership() throws Exception {
 		sendInvitation(contactId1From0, clock.currentTimeMillis(), "Hi!");
diff --git a/briar-android-tests/src/test/java/org/briarproject/PrivateGroupManagerTest.java b/briar-android-tests/src/test/java/org/briarproject/PrivateGroupManagerTest.java
index 4e1dbc0cd25b1296f1951b2480657f10add853ed..8b00a35f529572bedcd7fd4c99bbd254d5a08e22 100644
--- a/briar-android-tests/src/test/java/org/briarproject/PrivateGroupManagerTest.java
+++ b/briar-android-tests/src/test/java/org/briarproject/PrivateGroupManagerTest.java
@@ -1,35 +1,36 @@
 package org.briarproject;
 
-import org.briarproject.api.clients.MessageTracker.GroupCount;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.privategroup.GroupMember;
-import org.briarproject.api.privategroup.GroupMessage;
-import org.briarproject.api.privategroup.GroupMessageHeader;
-import org.briarproject.api.privategroup.JoinMessageHeader;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.privategroup.PrivateGroupManager;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.MessageTracker.GroupCount;
+import org.briarproject.briar.api.privategroup.GroupMember;
+import org.briarproject.briar.api.privategroup.GroupMessage;
+import org.briarproject.briar.api.privategroup.GroupMessageHeader;
+import org.briarproject.briar.api.privategroup.JoinMessageHeader;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.privategroup.PrivateGroupManager;
 import org.junit.Before;
 import org.junit.Test;
 
 import java.util.Collection;
 
 import static org.briarproject.TestUtils.getRandomBytes;
-import static org.briarproject.api.identity.Author.Status.VERIFIED;
-import static org.briarproject.api.privategroup.Visibility.INVISIBLE;
-import static org.briarproject.api.privategroup.Visibility.REVEALED_BY_CONTACT;
-import static org.briarproject.api.privategroup.Visibility.REVEALED_BY_US;
-import static org.briarproject.api.privategroup.Visibility.VISIBLE;
-import static org.briarproject.api.privategroup.invitation.GroupInvitationFactory.SIGNING_LABEL_INVITE;
-import static org.briarproject.api.sync.Group.Visibility.SHARED;
+import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED;
+import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
+import static org.briarproject.briar.api.privategroup.Visibility.INVISIBLE;
+import static org.briarproject.briar.api.privategroup.Visibility.REVEALED_BY_CONTACT;
+import static org.briarproject.briar.api.privategroup.Visibility.REVEALED_BY_US;
+import static org.briarproject.briar.api.privategroup.Visibility.VISIBLE;
+import static org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory.SIGNING_LABEL_INVITE;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-public class PrivateGroupManagerTest extends BriarIntegrationTest {
+public class PrivateGroupManagerTest
+		extends BriarIntegrationTest<BriarIntegrationTestComponent> {
 
 	private PrivateGroup privateGroup0;
 	private GroupId groupId0;
@@ -48,6 +49,25 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
 		groupId0 = privateGroup0.getId();
 	}
 
+	@Override
+	protected void createComponents() {
+		BriarIntegrationTestComponent component =
+				DaggerBriarIntegrationTestComponent.builder().build();
+		component.inject(this);
+
+		c0 = DaggerBriarIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t0Dir)).build();
+		injectEagerSingletons(c0);
+
+		c1 = DaggerBriarIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t1Dir)).build();
+		injectEagerSingletons(c1);
+
+		c2 = DaggerBriarIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t2Dir)).build();
+		injectEagerSingletons(c2);
+	}
+
 	@Test
 	public void testSendingMessage() throws Exception {
 		addGroup();
@@ -220,7 +240,8 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
 
 		// share the group with 1
 		Transaction txn0 = db0.startTransaction(false);
-		db0.setGroupVisibility(txn0, contactId1From0, privateGroup0.getId(), SHARED);
+		db0.setGroupVisibility(txn0, contactId1From0, privateGroup0.getId(),
+				SHARED);
 		db0.commitTransaction(txn0);
 		db0.endTransaction(txn0);
 
@@ -277,7 +298,8 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
 
 		// share the group with 1
 		Transaction txn0 = db0.startTransaction(false);
-		db0.setGroupVisibility(txn0, contactId1From0, privateGroup0.getId(), SHARED);
+		db0.setGroupVisibility(txn0, contactId1From0, privateGroup0.getId(),
+				SHARED);
 		db0.commitTransaction(txn0);
 		db0.endTransaction(txn0);
 
@@ -298,7 +320,8 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
 
 		// share the group with 0
 		Transaction txn1 = db1.startTransaction(false);
-		db1.setGroupVisibility(txn1, contactId0From1, privateGroup0.getId(), SHARED);
+		db1.setGroupVisibility(txn1, contactId0From1, privateGroup0.getId(),
+				SHARED);
 		db1.commitTransaction(txn1);
 		db1.endTransaction(txn1);
 
@@ -376,7 +399,8 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
 
 		// share the group with 2
 		Transaction txn0 = db0.startTransaction(false);
-		db0.setGroupVisibility(txn0, contactId2From0, privateGroup0.getId(), SHARED);
+		db0.setGroupVisibility(txn0, contactId2From0, privateGroup0.getId(),
+				SHARED);
 		db0.commitTransaction(txn0);
 		db0.endTransaction(txn0);
 
@@ -507,7 +531,8 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest {
 
 		// share the group with 1
 		Transaction txn0 = db0.startTransaction(false);
-		db0.setGroupVisibility(txn0, contactId1From0, privateGroup0.getId(), SHARED);
+		db0.setGroupVisibility(txn0, contactId1From0, privateGroup0.getId(),
+				SHARED);
 		db0.commitTransaction(txn0);
 		db0.endTransaction(txn0);
 
diff --git a/briar-android-tests/src/test/java/org/briarproject/SimplexMessagingIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/SimplexMessagingIntegrationTest.java
index cc98b42c0347af7622f2954ef26d2e672b0babc8..68515bd0fd7304f874638895a158c7e63d16c92c 100644
--- a/briar-android-tests/src/test/java/org/briarproject/SimplexMessagingIntegrationTest.java
+++ b/briar-android-tests/src/test/java/org/briarproject/SimplexMessagingIntegrationTest.java
@@ -1,27 +1,29 @@
 package org.briarproject;
 
-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.briarproject.system.SystemModule;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.SyncSession;
+import org.briarproject.bramble.api.sync.SyncSessionFactory;
+import org.briarproject.bramble.api.sync.event.MessageAddedEvent;
+import org.briarproject.bramble.api.transport.KeyManager;
+import org.briarproject.bramble.api.transport.StreamContext;
+import org.briarproject.bramble.api.transport.StreamReaderFactory;
+import org.briarproject.bramble.api.transport.StreamWriterFactory;
+import org.briarproject.bramble.system.SystemModule;
+import org.briarproject.briar.api.messaging.MessagingManager;
+import org.briarproject.briar.api.messaging.PrivateMessage;
+import org.briarproject.briar.api.messaging.PrivateMessageFactory;
+import org.briarproject.briar.messaging.MessagingModule;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -32,10 +34,10 @@ 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.briarproject.TestPluginConfigModule.MAX_LATENCY;
+import static org.briarproject.TestPluginConfigModule.TRANSPORT_ID;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -61,10 +63,11 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
 		assertTrue(testDir.mkdirs());
 		alice = DaggerSimplexMessagingIntegrationTestComponent.builder()
 				.testDatabaseModule(new TestDatabaseModule(aliceDir)).build();
+		injectEagerSingletons(alice);
 		alice.inject(new SystemModule.EagerSingletons());
 		bob = DaggerSimplexMessagingIntegrationTestComponent.builder()
 				.testDatabaseModule(new TestDatabaseModule(bobDir)).build();
-		bob.inject(new SystemModule.EagerSingletons());
+		injectEagerSingletons(bob);
 	}
 
 	@Test
@@ -136,8 +139,6 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
 		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(null);
@@ -185,6 +186,13 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
 		TestUtils.deleteTestDirectory(testDir);
 	}
 
+	private static void injectEagerSingletons(
+			SimplexMessagingIntegrationTestComponent component) {
+		component.inject(new MessagingModule.EagerSingletons());
+		component.inject(new SystemModule.EagerSingletons());
+	}
+
+	@NotNullByDefault
 	private static class MessageListener implements EventListener {
 
 		private volatile boolean messageAdded = false;
diff --git a/briar-android-tests/src/test/java/org/briarproject/SimplexMessagingIntegrationTestComponent.java b/briar-android-tests/src/test/java/org/briarproject/SimplexMessagingIntegrationTestComponent.java
index 9de8e9c5ea755fac01073114a5281c0d6a2470b5..91536eccad5ce5ddf2424028baec5f55628040eb 100644
--- a/briar-android-tests/src/test/java/org/briarproject/SimplexMessagingIntegrationTestComponent.java
+++ b/briar-android-tests/src/test/java/org/briarproject/SimplexMessagingIntegrationTestComponent.java
@@ -1,28 +1,28 @@
 package org.briarproject;
 
-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.system.SystemModule;
-import org.briarproject.transport.TransportModule;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.sync.SyncSessionFactory;
+import org.briarproject.bramble.api.transport.KeyManager;
+import org.briarproject.bramble.api.transport.StreamReaderFactory;
+import org.briarproject.bramble.api.transport.StreamWriterFactory;
+import org.briarproject.bramble.client.ClientModule;
+import org.briarproject.bramble.contact.ContactModule;
+import org.briarproject.bramble.crypto.CryptoModule;
+import org.briarproject.bramble.data.DataModule;
+import org.briarproject.bramble.db.DatabaseModule;
+import org.briarproject.bramble.event.EventModule;
+import org.briarproject.bramble.identity.IdentityModule;
+import org.briarproject.bramble.lifecycle.LifecycleModule;
+import org.briarproject.bramble.sync.SyncModule;
+import org.briarproject.bramble.system.SystemModule;
+import org.briarproject.bramble.transport.TransportModule;
+import org.briarproject.briar.api.messaging.MessagingManager;
+import org.briarproject.briar.api.messaging.PrivateMessageFactory;
+import org.briarproject.briar.client.BriarClientModule;
+import org.briarproject.briar.messaging.MessagingModule;
 
 import javax.inject.Singleton;
 
@@ -31,9 +31,10 @@ import dagger.Component;
 @Singleton
 @Component(modules = {
 		TestDatabaseModule.class,
-		TestPluginsModule.class,
+		TestPluginConfigModule.class,
 		TestSeedProviderModule.class,
-		ClientsModule.class,
+		BriarClientModule.class,
+		ClientModule.class,
 		ContactModule.class,
 		CryptoModule.class,
 		DataModule.class,
@@ -42,12 +43,13 @@ import dagger.Component;
 		IdentityModule.class,
 		LifecycleModule.class,
 		MessagingModule.class,
-		PluginsModule.class,
 		SyncModule.class,
 		SystemModule.class,
 		TransportModule.class
 })
-public interface SimplexMessagingIntegrationTestComponent {
+interface SimplexMessagingIntegrationTestComponent {
+
+	void inject(MessagingModule.EagerSingletons init);
 
 	void inject(SystemModule.EagerSingletons init);
 
diff --git a/briar-android-tests/src/test/java/org/briarproject/SyncIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/SyncIntegrationTest.java
index 07a671747d7c65c17169ae9829da9327e03060b8..ef6ed72abba8020c85908d49296e81ba7b8195d7 100644
--- a/briar-android-tests/src/test/java/org/briarproject/SyncIntegrationTest.java
+++ b/briar-android-tests/src/test/java/org/briarproject/SyncIntegrationTest.java
@@ -1,25 +1,25 @@
 package org.briarproject;
 
-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.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.sync.Ack;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupFactory;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageFactory;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.Offer;
+import org.briarproject.bramble.api.sync.PacketReader;
+import org.briarproject.bramble.api.sync.PacketReaderFactory;
+import org.briarproject.bramble.api.sync.PacketWriter;
+import org.briarproject.bramble.api.sync.PacketWriterFactory;
+import org.briarproject.bramble.api.sync.Request;
+import org.briarproject.bramble.api.transport.StreamContext;
+import org.briarproject.bramble.api.transport.StreamReaderFactory;
+import org.briarproject.bramble.api.transport.StreamWriterFactory;
 import org.junit.Test;
 
 import java.io.ByteArrayInputStream;
@@ -31,7 +31,7 @@ import java.util.Collection;
 
 import javax.inject.Inject;
 
-import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
diff --git a/briar-android-tests/src/test/java/org/briarproject/SyncIntegrationTestComponent.java b/briar-android-tests/src/test/java/org/briarproject/SyncIntegrationTestComponent.java
index 69710bd5a6b710e1cc94981cee256944fb845bc3..f20e66c8ee6b6f504b013505c9cefc24777e62df 100644
--- a/briar-android-tests/src/test/java/org/briarproject/SyncIntegrationTestComponent.java
+++ b/briar-android-tests/src/test/java/org/briarproject/SyncIntegrationTestComponent.java
@@ -1,8 +1,8 @@
 package org.briarproject;
 
-import org.briarproject.crypto.CryptoModule;
-import org.briarproject.sync.SyncModule;
-import org.briarproject.transport.TransportModule;
+import org.briarproject.bramble.crypto.CryptoModule;
+import org.briarproject.bramble.sync.SyncModule;
+import org.briarproject.bramble.transport.TransportModule;
 
 import javax.inject.Singleton;
 
@@ -15,6 +15,7 @@ import dagger.Component;
 		SyncModule.class,
 		TransportModule.class
 })
-public interface SyncIntegrationTestComponent {
+interface SyncIntegrationTestComponent {
+
 	void inject(SyncIntegrationTest testCase);
 }
diff --git a/briar-tests/src/org/briarproject/TestDatabaseModule.java b/briar-android-tests/src/test/java/org/briarproject/TestDatabaseModule.java
similarity index 74%
rename from briar-tests/src/org/briarproject/TestDatabaseModule.java
rename to briar-android-tests/src/test/java/org/briarproject/TestDatabaseModule.java
index be401e4e28a1e3efe1c6e1a62d6f1947c1f7c9e6..b978c8deaeeb3bd1c98ee2863ec57d19d6730833 100644
--- a/briar-tests/src/org/briarproject/TestDatabaseModule.java
+++ b/briar-android-tests/src/test/java/org/briarproject/TestDatabaseModule.java
@@ -1,8 +1,7 @@
 package org.briarproject;
 
-import org.briarproject.api.db.DatabaseConfig;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.db.DatabaseModule;
+import org.briarproject.bramble.api.db.DatabaseConfig;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
 
 import java.io.File;
 import java.util.concurrent.Executor;
@@ -13,7 +12,7 @@ import dagger.Module;
 import dagger.Provides;
 
 @Module
-public class TestDatabaseModule extends DatabaseModule {
+public class TestDatabaseModule {
 
 	private final DatabaseConfig config;
 
diff --git a/briar-tests/src/org/briarproject/TestLifecycleModule.java b/briar-android-tests/src/test/java/org/briarproject/TestLifecycleModule.java
similarity index 63%
rename from briar-tests/src/org/briarproject/TestLifecycleModule.java
rename to briar-android-tests/src/test/java/org/briarproject/TestLifecycleModule.java
index b97bb8251d2d4f4bfbd9609f534dfb4323c6b093..16407ea418686e780cc32993494d5e2fe6f99ea7 100644
--- a/briar-tests/src/org/briarproject/TestLifecycleModule.java
+++ b/briar-android-tests/src/test/java/org/briarproject/TestLifecycleModule.java
@@ -1,72 +1,70 @@
 package org.briarproject;
 
-import org.briarproject.api.clients.Client;
-import org.briarproject.api.lifecycle.IoExecutor;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.lifecycle.Service;
-import org.briarproject.api.lifecycle.ShutdownManager;
+import org.briarproject.bramble.api.lifecycle.IoExecutor;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.lifecycle.Service;
+import org.briarproject.bramble.api.lifecycle.ShutdownManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Client;
 
 import java.util.concurrent.Executor;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
+import javax.annotation.Nullable;
 import javax.inject.Singleton;
 
 import dagger.Module;
 import dagger.Provides;
 
 @Module
-public class TestLifecycleModule {
+class TestLifecycleModule {
 
 	@Provides
 	LifecycleManager provideLifecycleManager() {
-		return new LifecycleManager() {
+		@NotNullByDefault
+		LifecycleManager lifecycleManager = new LifecycleManager() {
 
 			@Override
 			public void registerService(Service s) {
-
 			}
 
 			@Override
 			public void registerClient(Client c) {
-
 			}
 
 			@Override
 			public void registerForShutdown(ExecutorService e) {
-
 			}
 
 			@Override
-			public StartResult startServices(String nickname) {
+			public StartResult startServices(@Nullable String nickname) {
 				return StartResult.SUCCESS;
 			}
 
 			@Override
 			public void stopServices() {
-
 			}
 
 			@Override
 			public void waitForDatabase() throws InterruptedException {
-
 			}
 
 			@Override
 			public void waitForStartup() throws InterruptedException {
-
 			}
 
 			@Override
 			public void waitForShutdown() throws InterruptedException {
-
 			}
 		};
+		return lifecycleManager;
 	}
 
 	@Provides
 	ShutdownManager provideShutdownManager() {
-		return new ShutdownManager() {
+		@NotNullByDefault
+		ShutdownManager shutdownManager = new ShutdownManager() {
 
 			@Override
 			public int addShutdownHook(Runnable hook) {
@@ -78,6 +76,7 @@ public class TestLifecycleModule {
 				return true;
 			}
 		};
+		return shutdownManager;
 	}
 
 	@Provides
diff --git a/briar-tests/src/org/briarproject/TestPluginsModule.java b/briar-android-tests/src/test/java/org/briarproject/TestPluginConfigModule.java
similarity index 58%
rename from briar-tests/src/org/briarproject/TestPluginsModule.java
rename to briar-android-tests/src/test/java/org/briarproject/TestPluginConfigModule.java
index b7cf4209ee34199b051b1bc2e61c95d308291c43..416d5f1085b8c3d2f70e86c9fda610cd7ee137a8 100644
--- a/briar-tests/src/org/briarproject/TestPluginsModule.java
+++ b/briar-android-tests/src/test/java/org/briarproject/TestPluginConfigModule.java
@@ -1,24 +1,28 @@
 package org.briarproject;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.plugins.PluginConfig;
-import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
-import org.briarproject.api.plugins.simplex.SimplexPlugin;
-import org.briarproject.api.plugins.simplex.SimplexPluginCallback;
-import org.briarproject.api.plugins.simplex.SimplexPluginFactory;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.PluginConfig;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPluginCallback;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
 
 import java.util.Collection;
 import java.util.Collections;
 
+import javax.annotation.Nullable;
+
 import dagger.Module;
 import dagger.Provides;
 
 @Module
-public class TestPluginsModule {
+public class TestPluginConfigModule {
 
 	public static final TransportId TRANSPORT_ID = new TransportId("id");
 	public static final int MAX_LATENCY = 2 * 60 * 1000; // 2 minutes
 
+	@NotNullByDefault
 	private final SimplexPluginFactory simplex = new SimplexPluginFactory() {
 
 		@Override
@@ -32,6 +36,7 @@ public class TestPluginsModule {
 		}
 
 		@Override
+		@Nullable
 		public SimplexPlugin createPlugin(SimplexPluginCallback callback) {
 			return null;
 		}
@@ -39,7 +44,8 @@ public class TestPluginsModule {
 
 	@Provides
 	PluginConfig providePluginConfig() {
-		return new PluginConfig() {
+		@NotNullByDefault
+		PluginConfig pluginConfig = new PluginConfig() {
 
 			@Override
 			public Collection<DuplexPluginFactory> getDuplexFactories() {
@@ -51,5 +57,6 @@ public class TestPluginsModule {
 				return Collections.singletonList(simplex);
 			}
 		};
+		return pluginConfig;
 	}
 }
diff --git a/briar-tests/src/org/briarproject/TestSeedProviderModule.java b/briar-android-tests/src/test/java/org/briarproject/TestSeedProviderModule.java
similarity index 81%
rename from briar-tests/src/org/briarproject/TestSeedProviderModule.java
rename to briar-android-tests/src/test/java/org/briarproject/TestSeedProviderModule.java
index a239ba7d8dc0954a2446d8c033403f348f549416..1d449284fa7c3a2c078f297cdb1f238479fb2361 100644
--- a/briar-tests/src/org/briarproject/TestSeedProviderModule.java
+++ b/briar-android-tests/src/test/java/org/briarproject/TestSeedProviderModule.java
@@ -1,6 +1,6 @@
 package org.briarproject;
 
-import org.briarproject.api.system.SeedProvider;
+import org.briarproject.bramble.api.system.SeedProvider;
 
 import javax.inject.Singleton;
 
diff --git a/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java
similarity index 85%
rename from briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTest.java
rename to briar-android-tests/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java
index 1fb7ef67380ba64f59e5aaf4f3f49d69a34ced94..099a51041819db7adf53791d4d03633fd05faa8c 100644
--- a/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTest.java
+++ b/briar-android-tests/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java
@@ -1,36 +1,40 @@
-package org.briarproject.introduction;
+package org.briarproject.briar.introduction;
 
 import net.jodah.concurrentunit.Waiter;
 
 import org.briarproject.BriarIntegrationTest;
+import org.briarproject.TestDatabaseModule;
 import org.briarproject.TestUtils;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.crypto.KeyPair;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.db.Transaction;
-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.introduction.IntroductionManager;
-import org.briarproject.api.introduction.IntroductionMessage;
-import org.briarproject.api.introduction.IntroductionRequest;
-import org.briarproject.api.properties.TransportProperties;
-import org.briarproject.api.properties.TransportPropertyManager;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.crypto.KeyPair;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.properties.TransportProperties;
+import org.briarproject.bramble.api.properties.TransportPropertyManager;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.introduction.IntroductionManager;
+import org.briarproject.briar.api.introduction.IntroductionMessage;
+import org.briarproject.briar.api.introduction.IntroductionRequest;
+import org.briarproject.briar.api.introduction.event.IntroductionAbortedEvent;
+import org.briarproject.briar.api.introduction.event.IntroductionRequestReceivedEvent;
+import org.briarproject.briar.api.introduction.event.IntroductionResponseReceivedEvent;
+import org.briarproject.briar.api.introduction.event.IntroductionSucceededEvent;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -45,31 +49,37 @@ import java.util.Map.Entry;
 import java.util.concurrent.TimeoutException;
 import java.util.logging.Logger;
 
-import static org.briarproject.TestPluginsModule.TRANSPORT_ID;
+import javax.inject.Inject;
+
+import static org.briarproject.TestPluginConfigModule.TRANSPORT_ID;
 import static org.briarproject.TestUtils.assertGroupCount;
-import static org.briarproject.api.clients.MessageQueueManager.QUEUE_STATE_KEY;
-import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
-import static org.briarproject.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
-import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.MAC;
-import static org.briarproject.api.introduction.IntroductionConstants.MAC_KEY;
-import static org.briarproject.api.introduction.IntroductionConstants.NAME;
-import static org.briarproject.api.introduction.IntroductionConstants.NONCE;
-import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY;
-import static org.briarproject.api.introduction.IntroductionConstants.SESSION_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.SIGNATURE;
-import static org.briarproject.api.introduction.IntroductionConstants.TIME;
-import static org.briarproject.api.introduction.IntroductionConstants.TRANSPORT;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
-import static org.briarproject.introduction.IntroduceeManager.SIGNING_LABEL_RESPONSE;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.briar.api.client.MessageQueueManager.QUEUE_STATE_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MAC;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MAC_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.NAME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.NONCE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.PUBLIC_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.SESSION_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.SIGNATURE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TIME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TRANSPORT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_REQUEST;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_RESPONSE;
+import static org.briarproject.briar.introduction.IntroduceeManager.SIGNING_LABEL_RESPONSE;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-public class IntroductionIntegrationTest extends BriarIntegrationTest {
+public class IntroductionIntegrationTest
+		extends BriarIntegrationTest<IntroductionIntegrationTestComponent> {
+
+	@Inject
+	IntroductionGroupFactory introductionGroupFactory;
 
 	// objects accessed from background threads need to be volatile
 	private volatile IntroductionManager introductionManager0;
@@ -103,6 +113,25 @@ public class IntroductionIntegrationTest extends BriarIntegrationTest {
 		addTransportProperties();
 	}
 
+	@Override
+	protected void createComponents() {
+		IntroductionIntegrationTestComponent component =
+				DaggerIntroductionIntegrationTestComponent.builder().build();
+		component.inject(this);
+
+		c0 = DaggerIntroductionIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t0Dir)).build();
+		injectEagerSingletons(c0);
+
+		c1 = DaggerIntroductionIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t1Dir)).build();
+		injectEagerSingletons(c1);
+
+		c2 = DaggerIntroductionIntegrationTestComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(t2Dir)).build();
+		injectEagerSingletons(c2);
+	}
+
 	@Test
 	public void testIntroductionSession() throws Exception {
 		addListeners(true, true);
@@ -827,6 +856,8 @@ public class IntroductionIntegrationTest extends BriarIntegrationTest {
 		c2.getEventBus().addListener(listener2);
 	}
 
+	@MethodsNotNullByDefault
+	@ParametersNotNullByDefault
 	private class IntroduceeListener implements EventListener {
 
 		private volatile boolean requestReceived = false;
@@ -894,6 +925,7 @@ public class IntroductionIntegrationTest extends BriarIntegrationTest {
 		}
 	}
 
+	@NotNullByDefault
 	private class IntroducerListener implements EventListener {
 
 		private volatile boolean response1Received = false;
diff --git a/briar-android-tests/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTestComponent.java b/briar-android-tests/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTestComponent.java
new file mode 100644
index 0000000000000000000000000000000000000000..1f6dcb7fd803717486aeeaa8522014a3b4019cd9
--- /dev/null
+++ b/briar-android-tests/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTestComponent.java
@@ -0,0 +1,64 @@
+package org.briarproject.briar.introduction;
+
+import org.briarproject.BriarIntegrationTestComponent;
+import org.briarproject.TestDatabaseModule;
+import org.briarproject.TestPluginConfigModule;
+import org.briarproject.TestSeedProviderModule;
+import org.briarproject.bramble.client.ClientModule;
+import org.briarproject.bramble.contact.ContactModule;
+import org.briarproject.bramble.crypto.CryptoModule;
+import org.briarproject.bramble.data.DataModule;
+import org.briarproject.bramble.db.DatabaseModule;
+import org.briarproject.bramble.event.EventModule;
+import org.briarproject.bramble.identity.IdentityModule;
+import org.briarproject.bramble.lifecycle.LifecycleModule;
+import org.briarproject.bramble.properties.PropertiesModule;
+import org.briarproject.bramble.sync.SyncModule;
+import org.briarproject.bramble.system.SystemModule;
+import org.briarproject.bramble.transport.TransportModule;
+import org.briarproject.briar.blog.BlogModule;
+import org.briarproject.briar.client.BriarClientModule;
+import org.briarproject.briar.forum.ForumModule;
+import org.briarproject.briar.messaging.MessagingModule;
+import org.briarproject.briar.privategroup.PrivateGroupModule;
+import org.briarproject.briar.privategroup.invitation.GroupInvitationModule;
+import org.briarproject.briar.sharing.SharingModule;
+
+import javax.inject.Singleton;
+
+import dagger.Component;
+
+@Singleton
+@Component(modules = {
+		TestDatabaseModule.class,
+		TestPluginConfigModule.class,
+		TestSeedProviderModule.class,
+		BlogModule.class,
+		BriarClientModule.class,
+		ClientModule.class,
+		ContactModule.class,
+		CryptoModule.class,
+		DataModule.class,
+		DatabaseModule.class,
+		EventModule.class,
+		ForumModule.class,
+		GroupInvitationModule.class,
+		IdentityModule.class,
+		IntroductionModule.class,
+		LifecycleModule.class,
+		MessagingModule.class,
+		PrivateGroupModule.class,
+		PropertiesModule.class,
+		SharingModule.class,
+		SyncModule.class,
+		SystemModule.class,
+		TransportModule.class
+})
+interface IntroductionIntegrationTestComponent
+		extends BriarIntegrationTestComponent {
+
+	void inject(IntroductionIntegrationTest init);
+
+	MessageSender getMessageSender();
+
+}
diff --git a/briar-android/.gitignore b/briar-android/.gitignore
index f30761ae8846712f8c769c1ed6f4ba998768745f..2efc20c3651be2ac308b8fe13c0f3e6f56cb5554 100644
--- a/briar-android/.gitignore
+++ b/briar-android/.gitignore
@@ -3,5 +3,4 @@ gen
 build
 local.properties
 .settings
-assets/geoip.zip
-assets/tor-*.zip
+src/main/assets/*.zip
diff --git a/briar-android/.tx/config b/briar-android/.tx/config
index 893ff42a841961d4f4fd00e3cf2b8104231276b6..df6373eaa2ae42b361a6ba5512d9c2bd6eed1dcc 100644
--- a/briar-android/.tx/config
+++ b/briar-android/.tx/config
@@ -3,8 +3,8 @@ host = https://www.transifex.com
 lang_map = pt_BR: pt-rBR, fr_FR: fr
 
 [briar.stringsxml-5]
-file_filter = res/values-<lang>/strings.xml
-source_file = res/values/strings.xml
+file_filter = src/main/res/values-<lang>/strings.xml
+source_file = src/main/res/values/strings.xml
 source_lang = en
 type = ANDROID
 minimum_perc = 25
diff --git a/briar-android/build.gradle b/briar-android/build.gradle
index 113bb63dfbc0564fca20eeb344c8211e9e4095d4..48ee85bf19b16b450624d57f2a665ce8c8aac3fa 100644
--- a/briar-android/build.gradle
+++ b/briar-android/build.gradle
@@ -1,15 +1,11 @@
-import de.undercouch.gradle.tasks.download.Download
-import de.undercouch.gradle.tasks.download.Verify
-
 apply plugin: 'com.android.application'
 apply plugin: 'witness'
 apply plugin: 'com.neenbedankt.android-apt'
-apply plugin: 'de.undercouch.download'
 
 dependencies {
 	def supportVersion = '23.2.1'
-	compile project(':briar-api')
 	compile project(':briar-core')
+	compile project(':bramble-android')
 	compile fileTree(dir: 'libs', include: '*.jar')
 
 	compile "com.android.support:support-v4:$supportVersion"
@@ -63,6 +59,7 @@ dependencyVerification {
 			'com.android.support:animated-vector-drawable:06d1963b85aa917099d7757e6a7b3e4dc06889413dc747f625ae8683606db3a1',
 			'com.android.support:support-vector-drawable:799bafe4c3de812386f0b291f744d5d6876452722dd40189b9ab87dbbf594ea1',
 			'com.android.support:recyclerview-v7:44040a888e23e0c93162a3377cfe06751080e3c22d369ab0d4301ef60d63b0fe',
+			'com.android.support:preference-v7:775101bd07bd052e455761c5c5d9523d7ad59f2f320e3e8cbde241fd6b1d6025',
 			'com.android.support:cardview-v7:4595f1c4a28cfa083b6c0920ad4d49e1c2ca4b8302a955e548f68eb63b74931b',
 			'com.jpardogo.materialtabstrip:library:24d19232b319f8c73e25793432357919a7ed972186f57a3b2c9093ea74ad8311',
 			'com.github.bumptech.glide:glide:76ef123957b5fbaebb05fcbe6606dd58c3bc3fcdadb257f99811d0ac9ea9b88b',
@@ -75,32 +72,9 @@ android {
 	buildToolsVersion "23.0.3"
 
 	defaultConfig {
-		resValue "string", "app_package", "org.briarproject"
-	}
-
-	sourceSets {
-		main {
-			manifest.srcFile 'AndroidManifest.xml'
-			java.srcDirs = ['src']
-			resources.srcDirs = ['src']
-			aidl.srcDirs = ['src']
-			renderscript.srcDirs = ['src']
-			res.srcDirs = ['res']
-			assets.srcDirs = ['assets']
-		}
-
-		androidTest.setRoot('androidTest')
-		androidTest {
-			java.srcDirs = ['androidTest/java']
-		}
-
-		test.setRoot('test')
-		test {
-			java.srcDirs = ['test/java']
-			testOptions {
-				unitTests.returnDefaultValues = true
-			}
-		}
+		minSdkVersion 14
+		targetSdkVersion 22
+		resValue "string", "app_package", "org.briarproject.briar"
 	}
 
 	buildTypes {
@@ -126,75 +100,3 @@ android {
 		warning 'ImpliedQuantity'
 	}
 }
-
-task downloadTorGeoIp(type: Download) {
-    src 'https://briarproject.org/build/geoip-2015-12-01.zip'
-    dest 'assets/geoip.zip'
-    onlyIfNewer true
-}
-
-task downloadTorBinaryArm(type: Download) {
-    src 'https://briarproject.org/build/tor-0.2.7.6-arm.zip'
-    dest 'assets/tor-arm.zip'
-    onlyIfNewer true
-}
-
-task downloadTorBinaryArmPie(type: Download) {
-    src 'https://briarproject.org/build/tor-0.2.7.6-arm-pie.zip'
-    dest 'assets/tor-arm-pie.zip'
-    onlyIfNewer true
-}
-
-task downloadTorBinaryX86(type: Download) {
-    src 'https://briarproject.org/build/tor-0.2.7.6-x86.zip'
-    dest 'assets/tor-x86.zip'
-    onlyIfNewer true
-}
-
-task downloadTorBinaryX86Pie(type: Download) {
-    src 'https://briarproject.org/build/tor-0.2.7.6-x86-pie.zip'
-    dest 'assets/tor-x86-pie.zip'
-    onlyIfNewer true
-}
-
-task verifyTorGeoIp(type: Verify, dependsOn: 'downloadTorGeoIp') {
-    src 'assets/geoip.zip'
-    algorithm 'SHA-256'
-    checksum '9bcdaf0a7ba0933735328d8ec466c25c25dbb459efc2bce9e55c774eabea5162'
-}
-
-task verifyTorBinaryArm(type: Verify, dependsOn: 'downloadTorBinaryArm') {
-    src 'assets/tor-arm.zip'
-    algorithm 'SHA-256'
-    checksum '83272962eda701cd5d74d2418651c4ff0f0b1dff51f558a292d1a1c42bf12146'
-}
-
-task verifyTorBinaryArmPie(type: Verify, dependsOn: 'downloadTorBinaryArmPie') {
-    src 'assets/tor-arm-pie.zip'
-    algorithm 'SHA-256'
-    checksum 'd0300d1e45de11ebb24ed62b9c492be9c2e88590b7822195ab38c7a76ffcf646'
-}
-
-task verifyTorBinaryX86(type: Verify, dependsOn: 'downloadTorBinaryX86') {
-    src 'assets/tor-x86.zip'
-    algorithm 'SHA-256'
-    checksum 'b8813d97b01ee1b9c9a4233c1b9bbe9f9f6b494ae6f9cbd84de8a3911911615e'
-}
-
-task verifyTorBinaryX86Pie(type: Verify, dependsOn: 'downloadTorBinaryX86Pie') {
-    src 'assets/tor-x86-pie.zip'
-    algorithm 'SHA-256'
-    checksum '9c66e765aa196dc089951a1b2140cc8290305c2fcbf365121f99e01a233baf4e'
-}
-
-project.afterEvaluate {
-    preBuild.dependsOn {
-        [
-                'verifyTorGeoIp',
-                'verifyTorBinaryArm',
-                'verifyTorBinaryArmPie',
-                'verifyTorBinaryX86',
-                'verifyTorBinaryX86Pie'
-        ]
-    }
-}
diff --git a/briar-android/proguard-rules.txt b/briar-android/proguard-rules.txt
index feac1c8ba7f9331da91c984b0cb7fe182c5282be..88fb5b29b5ec5d8fad53c2ee53f14b5091419b94 100644
--- a/briar-android/proguard-rules.txt
+++ b/briar-android/proguard-rules.txt
@@ -1,67 +1,31 @@
--dontusemixedcaseclassnames
--dontskipnonpubliclibraryclasses
--dontpreverify
+# Android defaults and rules from ../bramble-android/proguard-rules.txt are also applied
+
 -dontobfuscate
--verbose
--useuniqueclassmembernames
-#-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-# For comfortability in case we do obfuscate
-# -renamesourcefileattribute SourceFile
 -keepattributes SourceFile, LineNumberTable, *Annotation*, Signature, InnerClasses, EnclosingMethod
 
--keep public class * extends android.app.Activity
--keep public class * extends android.app.Application
--keep public class * extends android.app.Service
--keep public class * extends android.content.BroadcastReceiver
--keep public class * extends android.content.ContentProvider
--keepclasseswithmembers class * { native <methods>; }
--keepclasseswithmembers class * {  
-	public <init> (android.content.Context, android.util.AttributeSet); 
-}
--keepclasseswithmembers class * { 
-	public <init> (android.content.Context, android.util.AttributeSet, int); 
-}
--keepclassmembers class * implements android.os.Parcelable { static android.os.Parcelable$Creator *; }
--keepclassmembers class **.R$* { public static <fields>; }
--keepclasseswithmembernames class * { native <methods>; }
--keepclassmembers enum * {
-	public static **[] values();
-	public static ** valueOf(java.lang.String);
-}
--keepclassmembers class * extends android.app.Activity { 
-	public void *(android.view.View); 
-}
-
--keep class org.h2.** { *; }
--keep class org.briarproject.** { *; }
--keep class javax.inject.** { *; }
--keep class dagger.** { *; }
+# QR codes
 -keep class com.google.zxing.Result
 
--dontwarn org.h2.**
--dontnote org.h2.**
--dontwarn net.sf.cglib.**
--dontwarn org.briarproject.plugins.tcp.**
--dontnote org.briarproject.crypto.**
--dontnote org.spongycastle.crypto.parsers.ECIESPublicKeyParser
--dontwarn net.sourceforge.jsocks.**
--dontnote android.support.**
--dontnote dagger.**
--dontwarn dagger.**
--dontnote com.google.common.**
--dontwarn com.google.common.**
-
 # RSS libraries
--keep class com.rometools.rome.feed.synd.impl.** { *;}
--keep class com.rometools.rome.io.impl.** { *;}
--keep class org.jsoup.safety.Whitelist
--dontnote com.rometools.rome.**
+-keep,includedescriptorclasses class com.rometools.rome.feed.synd.impl.** { *; }
+-keep,includedescriptorclasses class com.rometools.rome.io.impl.** { *; }
 -dontwarn javax.xml.stream.**
 -dontwarn org.jaxen.**
 -dontwarn java.nio.**
--dontwarn org.codehaus.mojo.animal_sniffer.**
+-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
 -dontwarn org.slf4j.impl.**
 
+# OkHttp does some shenanigans with Android's SSL classes
+-dontnote com.android.org.conscrypt.SSLParametersImpl
+-dontnote org.apache.harmony.xnet.provider.jsse.SSLParametersImpl
+-dontnote sun.security.ssl.SSLContextImpl
+
+# HTML sanitiser
+-keep class org.jsoup.safety.Whitelist
+
+# KeyboardAwareLinearLayout uses reflection on android.View
+-dontnote org.thoughtcrime.securesms.components.KeyboardAwareLinearLayout
+
 # Emoji
 -keep class org.thoughtcrime.securesms.**
 -keep class com.astuetz.PagerSlidingTabStrip$OnTabReselectedListener
diff --git a/briar-android/AndroidManifest.xml b/briar-android/src/main/AndroidManifest.xml
similarity index 76%
rename from briar-android/AndroidManifest.xml
rename to briar-android/src/main/AndroidManifest.xml
index 16189e3751fe53a7545e7a1e273a9b81fd32d839..dec1fbc3a80d879f4ad638dd4eab5940af2d4f4e 100644
--- a/briar-android/AndroidManifest.xml
+++ b/briar-android/src/main/AndroidManifest.xml
@@ -1,16 +1,12 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest
-	package="org.briarproject"
+	package="org.briarproject.briar"
 	xmlns:android="http://schemas.android.com/apk/res/android"
 	xmlns:tools="http://schemas.android.com/tools"
-	android:versionCode="12"
-	android:versionName="0.12">
+	android:versionCode="13"
+	android:versionName="0.13">
 
-	<uses-sdk
-		android:minSdkVersion="14"
-		android:targetSdkVersion="22"
-		tools:overrideLibrary="android.support.v14.preference"
-		/>
+	<uses-sdk tools:overrideLibrary="android.support.v14.preference"/>
 
 	<uses-feature android:name="android.hardware.bluetooth"/>
 	<uses-feature android:name="android.hardware.camera" />
@@ -39,12 +35,12 @@
 			android:name=".android.BriarService"
 			android:exported="false">
 			<intent-filter>
-				<action android:name="org.briarproject.android.BriarService"/>
+				<action android:name="org.briarproject.briar.android.BriarService"/>
 			</intent-filter>
 		</service>
 
 		<activity
-			android:name=".android.report.DevReportActivity"
+			android:name=".android.reporting.DevReportActivity"
 			android:excludeFromRecents="true"
 			android:exported="false"
 			android:finishOnTaskLaunch="true"
@@ -56,24 +52,24 @@
 		</activity>
 
 		<activity
-			android:name=".android.ExpiredActivity"
+			android:name=".android.splash.ExpiredActivity"
 			android:label="@string/app_name">
 		</activity>
 
 		<activity
-			android:name=".android.PasswordActivity"
+			android:name=".android.login.PasswordActivity"
 			android:label="@string/app_name"
 			android:windowSoftInputMode="stateVisible">
 		</activity>
 
 		<activity
-			android:name=".android.SetupActivity"
+			android:name=".android.login.SetupActivity"
 			android:label="@string/setup_title"
 			android:windowSoftInputMode="adjustResize">
 		</activity>
 
 		<activity
-			android:name=".android.SplashScreenActivity"
+			android:name=".android.splash.SplashScreenActivity"
 			android:theme="@style/BriarThemeNoActionBar.Default"
 			android:label="@string/app_name">
 			<intent-filter>
@@ -83,7 +79,7 @@
 		</activity>
 
 		<activity
-			android:name=".android.NavDrawerActivity"
+			android:name=".android.navdrawer.NavDrawerActivity"
 			android:theme="@style/BriarThemeNoActionBar.Default"
 		    android:launchMode="singleTop">
 		</activity>
@@ -92,43 +88,43 @@
 			android:name=".android.contact.ConversationActivity"
 			android:label="@string/app_name"
 			android:theme="@style/BriarThemeNoActionBar.Default"
-			android:parentActivityName=".android.NavDrawerActivity"
+			android:parentActivityName=".android.navdrawer.NavDrawerActivity"
 			android:windowSoftInputMode="stateHidden|adjustResize">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.NavDrawerActivity"
+				android:value=".android.navdrawer.NavDrawerActivity"
 				/>
 		</activity>
 
 		<activity
 			android:name=".android.privategroup.creation.CreateGroupActivity"
 			android:label="@string/groups_create_group_title"
-			android:parentActivityName=".android.NavDrawerActivity"
+			android:parentActivityName=".android.navdrawer.NavDrawerActivity"
 			android:windowSoftInputMode="adjustResize">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.NavDrawerActivity"
+				android:value=".android.navdrawer.NavDrawerActivity"
 				/>
 		</activity>
 
 		<activity
 			android:name=".android.privategroup.conversation.GroupActivity"
 			android:label="@string/app_name"
-			android:parentActivityName=".android.NavDrawerActivity"
+			android:parentActivityName=".android.navdrawer.NavDrawerActivity"
 			android:windowSoftInputMode="adjustResize|stateHidden">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.NavDrawerActivity"
+				android:value=".android.navdrawer.NavDrawerActivity"
 				/>
 		</activity>
 
 		<activity
 			android:name=".android.privategroup.invitation.GroupInvitationActivity"
 			android:label="@string/groups_invitations_title"
-			android:parentActivityName=".android.NavDrawerActivity">
+			android:parentActivityName=".android.navdrawer.NavDrawerActivity">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.NavDrawerActivity"/>
+				android:value=".android.navdrawer.NavDrawerActivity"/>
 		</activity>
 
 			<activity
@@ -166,10 +162,10 @@
 		<activity
 			android:name=".android.sharing.ForumInvitationActivity"
 			android:label="@string/forum_invitations_title"
-			android:parentActivityName=".android.NavDrawerActivity">
+			android:parentActivityName=".android.navdrawer.NavDrawerActivity">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.NavDrawerActivity"
+				android:value=".android.navdrawer.NavDrawerActivity"
 				/>
 		</activity>
 
@@ -186,22 +182,22 @@
 		<activity
 			android:name=".android.forum.CreateForumActivity"
 			android:label="@string/create_forum_title"
-			android:parentActivityName=".android.NavDrawerActivity"
+			android:parentActivityName=".android.navdrawer.NavDrawerActivity"
 			android:windowSoftInputMode="stateVisible">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.NavDrawerActivity"
+				android:value=".android.navdrawer.NavDrawerActivity"
 				/>
 		</activity>
 
 		<activity
 			android:name=".android.forum.ForumActivity"
 			android:label="@string/app_name"
-			android:parentActivityName=".android.NavDrawerActivity"
+			android:parentActivityName=".android.navdrawer.NavDrawerActivity"
 			android:windowSoftInputMode="adjustResize|stateHidden">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.NavDrawerActivity"
+				android:value=".android.navdrawer.NavDrawerActivity"
 				/>
 		</activity>
 
@@ -219,11 +215,11 @@
 		<activity
 			android:name=".android.sharing.ShareBlogActivity"
 			android:label="@string/activity_share_toolbar_header"
-			android:parentActivityName=".android.blogs.BlogActivity"
+			android:parentActivityName=".android.blog.BlogActivity"
 			android:windowSoftInputMode="adjustResize|stateHidden">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.blogs.BlogActivity"
+				android:value=".android.blog.BlogActivity"
 				/>
 		</activity>
 
@@ -240,72 +236,72 @@
 		<activity
 			android:name=".android.sharing.BlogSharingStatusActivity"
 			android:label="@string/sharing_status"
-			android:parentActivityName=".android.blogs.BlogActivity">
+			android:parentActivityName=".android.blog.BlogActivity">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.blogs.BlogActivity"
+				android:value=".android.blog.BlogActivity"
 				/>
 		</activity>
 
 		<activity
-			android:name=".android.blogs.BlogActivity"
-			android:parentActivityName=".android.NavDrawerActivity">
+			android:name=".android.blog.BlogActivity"
+			android:parentActivityName=".android.navdrawer.NavDrawerActivity">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.NavDrawerActivity"
+				android:value=".android.navdrawer.NavDrawerActivity"
 				/>
 		</activity>
 
 		<activity
-			android:name=".android.blogs.WriteBlogPostActivity"
+			android:name=".android.blog.WriteBlogPostActivity"
 			android:label="@string/blogs_write_blog_post"
-			android:parentActivityName=".android.blogs.BlogActivity"
+			android:parentActivityName=".android.blog.BlogActivity"
 			android:windowSoftInputMode="stateVisible|adjustResize">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.blogs.BlogActivity"
+				android:value=".android.blog.BlogActivity"
 				/>
 		</activity>
 
 		<activity
-			android:name=".android.blogs.ReblogActivity"
+			android:name=".android.blog.ReblogActivity"
 			android:label="@string/blogs_reblog_button"
-			android:parentActivityName=".android.blogs.BlogActivity"
+			android:parentActivityName=".android.blog.BlogActivity"
 			android:windowSoftInputMode="stateHidden">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.blogs.BlogActivity"
+				android:value=".android.blog.BlogActivity"
 				/>
 		</activity>
 
 		<activity
-			android:name=".android.blogs.RssFeedImportActivity"
+			android:name=".android.blog.RssFeedImportActivity"
 			android:label="@string/blogs_rss_feeds_import"
-			android:parentActivityName=".android.NavDrawerActivity"
+			android:parentActivityName=".android.navdrawer.NavDrawerActivity"
 			android:windowSoftInputMode="stateVisible|adjustResize">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.NavDrawerActivity"
+				android:value=".android.navdrawer.NavDrawerActivity"
 				/>
 		</activity>
 
 		<activity
-			android:name=".android.blogs.RssFeedManageActivity"
+			android:name=".android.blog.RssFeedManageActivity"
 			android:label="@string/blogs_rss_feeds_manage"
-			android:parentActivityName=".android.NavDrawerActivity">
+			android:parentActivityName=".android.navdrawer.NavDrawerActivity">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.NavDrawerActivity"
+				android:value=".android.navdrawer.NavDrawerActivity"
 				/>
 		</activity>
 
 		<activity
 			android:name=".android.invitation.AddContactActivity"
 			android:label="@string/add_contact_title"
-			android:parentActivityName=".android.NavDrawerActivity">
+			android:parentActivityName=".android.navdrawer.NavDrawerActivity">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.NavDrawerActivity"
+				android:value=".android.navdrawer.NavDrawerActivity"
 				/>
 		</activity>
 
@@ -313,10 +309,10 @@
 			android:name=".android.keyagreement.KeyAgreementActivity"
 			android:label="@string/add_contact_title"
 			android:theme="@style/BriarThemeNoActionBar.Default"
-			android:parentActivityName=".android.NavDrawerActivity">
+			android:parentActivityName=".android.navdrawer.NavDrawerActivity">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.NavDrawerActivity"/>
+				android:value=".android.navdrawer.NavDrawerActivity"/>
 		</activity>
 
 		<activity
@@ -336,12 +332,12 @@
 		</activity>
 
 		<activity
-			android:name=".android.SettingsActivity"
+			android:name=".android.settings.SettingsActivity"
 			android:label="@string/settings_button"
-			android:parentActivityName=".android.NavDrawerActivity">
+			android:parentActivityName=".android.navdrawer.NavDrawerActivity">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.NavDrawerActivity"
+				android:value=".android.navdrawer.NavDrawerActivity"
 				/>
 			<intent-filter>
 				<action android:name="android.intent.action.MANAGE_NETWORK_USAGE"/>
@@ -350,12 +346,12 @@
 		</activity>
 
 		<activity
-			android:name=".android.ChangePasswordActivity"
+			android:name=".android.login.ChangePasswordActivity"
 			android:label="@string/change_password"
-			android:parentActivityName=".android.SettingsActivity">
+			android:parentActivityName=".android.settings.SettingsActivity">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.SettingsActivity"
+				android:value=".android.settings.SettingsActivity"
 				/>
 		</activity>
 
diff --git a/briar-android/assets/emoji_activity.png b/briar-android/src/main/assets/emoji_activity.png
similarity index 100%
rename from briar-android/assets/emoji_activity.png
rename to briar-android/src/main/assets/emoji_activity.png
diff --git a/briar-android/assets/emoji_animals_nature.png b/briar-android/src/main/assets/emoji_animals_nature.png
similarity index 100%
rename from briar-android/assets/emoji_animals_nature.png
rename to briar-android/src/main/assets/emoji_animals_nature.png
diff --git a/briar-android/assets/emoji_flags.png b/briar-android/src/main/assets/emoji_flags.png
similarity index 100%
rename from briar-android/assets/emoji_flags.png
rename to briar-android/src/main/assets/emoji_flags.png
diff --git a/briar-android/assets/emoji_food_drink.png b/briar-android/src/main/assets/emoji_food_drink.png
similarity index 100%
rename from briar-android/assets/emoji_food_drink.png
rename to briar-android/src/main/assets/emoji_food_drink.png
diff --git a/briar-android/assets/emoji_objects.png b/briar-android/src/main/assets/emoji_objects.png
similarity index 100%
rename from briar-android/assets/emoji_objects.png
rename to briar-android/src/main/assets/emoji_objects.png
diff --git a/briar-android/assets/emoji_smiley_people.png b/briar-android/src/main/assets/emoji_smiley_people.png
similarity index 100%
rename from briar-android/assets/emoji_smiley_people.png
rename to briar-android/src/main/assets/emoji_smiley_people.png
diff --git a/briar-android/assets/emoji_symbols.png b/briar-android/src/main/assets/emoji_symbols.png
similarity index 100%
rename from briar-android/assets/emoji_symbols.png
rename to briar-android/src/main/assets/emoji_symbols.png
diff --git a/briar-android/assets/emoji_travel_places.png b/briar-android/src/main/assets/emoji_travel_places.png
similarity index 100%
rename from briar-android/assets/emoji_travel_places.png
rename to briar-android/src/main/assets/emoji_travel_places.png
diff --git a/briar-android/src/im/delight/android/identicons/Identicon.java b/briar-android/src/main/java/im/delight/android/identicons/Identicon.java
similarity index 100%
rename from briar-android/src/im/delight/android/identicons/Identicon.java
rename to briar-android/src/main/java/im/delight/android/identicons/Identicon.java
diff --git a/briar-android/src/im/delight/android/identicons/IdenticonDrawable.java b/briar-android/src/main/java/im/delight/android/identicons/IdenticonDrawable.java
similarity index 100%
rename from briar-android/src/im/delight/android/identicons/IdenticonDrawable.java
rename to briar-android/src/main/java/im/delight/android/identicons/IdenticonDrawable.java
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java b/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java
new file mode 100644
index 0000000000000000000000000000000000000000..e038fb7fd9085d1f3d38e7c0fb77a3f37e8f1a4f
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java
@@ -0,0 +1,147 @@
+package org.briarproject.briar.android;
+
+import org.briarproject.bramble.BrambleAndroidModule;
+import org.briarproject.bramble.BrambleCoreEagerSingletons;
+import org.briarproject.bramble.BrambleCoreModule;
+import org.briarproject.bramble.api.contact.ContactExchangeTask;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.CryptoExecutor;
+import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
+import org.briarproject.bramble.api.db.DatabaseConfig;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.invitation.InvitationTaskFactory;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementTaskFactory;
+import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
+import org.briarproject.bramble.api.keyagreement.PayloadParser;
+import org.briarproject.bramble.api.lifecycle.IoExecutor;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.plugin.ConnectionRegistry;
+import org.briarproject.bramble.api.plugin.PluginManager;
+import org.briarproject.bramble.api.settings.SettingsManager;
+import org.briarproject.bramble.api.system.AndroidExecutor;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.BriarCoreEagerSingletons;
+import org.briarproject.briar.BriarCoreModule;
+import org.briarproject.briar.android.reporting.BriarReportSender;
+import org.briarproject.briar.api.android.AndroidNotificationManager;
+import org.briarproject.briar.api.android.ReferenceManager;
+import org.briarproject.briar.api.blog.BlogManager;
+import org.briarproject.briar.api.blog.BlogPostFactory;
+import org.briarproject.briar.api.blog.BlogSharingManager;
+import org.briarproject.briar.api.feed.FeedManager;
+import org.briarproject.briar.api.forum.ForumManager;
+import org.briarproject.briar.api.forum.ForumSharingManager;
+import org.briarproject.briar.api.introduction.IntroductionManager;
+import org.briarproject.briar.api.messaging.ConversationManager;
+import org.briarproject.briar.api.messaging.MessagingManager;
+import org.briarproject.briar.api.messaging.PrivateMessageFactory;
+import org.briarproject.briar.api.privategroup.GroupMessageFactory;
+import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
+import org.briarproject.briar.api.privategroup.PrivateGroupManager;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager;
+
+import java.util.concurrent.Executor;
+
+import javax.inject.Singleton;
+
+import dagger.Component;
+
+@Singleton
+@Component(modules = {
+		BrambleCoreModule.class,
+		BriarCoreModule.class,
+		BrambleAndroidModule.class,
+		AppModule.class
+})
+public interface AndroidComponent
+		extends BrambleCoreEagerSingletons, BriarCoreEagerSingletons {
+
+	// Exposed objects
+	@CryptoExecutor
+	Executor cryptoExecutor();
+
+	PasswordStrengthEstimator passwordStrengthIndicator();
+
+	CryptoComponent cryptoComponent();
+
+	DatabaseConfig databaseConfig();
+
+	ReferenceManager referenceMangager();
+
+	@DatabaseExecutor
+	Executor databaseExecutor();
+
+	LifecycleManager lifecycleManager();
+
+	IdentityManager identityManager();
+
+	PluginManager pluginManager();
+
+	EventBus eventBus();
+
+	InvitationTaskFactory invitationTaskFactory();
+
+	AndroidNotificationManager androidNotificationManager();
+
+	ConnectionRegistry connectionRegistry();
+
+	ContactManager contactManager();
+
+	ConversationManager conversationManager();
+
+	MessagingManager messagingManager();
+
+	PrivateMessageFactory privateMessageFactory();
+
+	PrivateGroupManager privateGroupManager();
+
+	GroupInvitationFactory groupInvitationFactory();
+
+	GroupInvitationManager groupInvitationManager();
+
+	PrivateGroupFactory privateGroupFactory();
+
+	GroupMessageFactory groupMessageFactory();
+
+	ForumManager forumManager();
+
+	ForumSharingManager forumSharingManager();
+
+	BlogSharingManager blogSharingManager();
+
+	BlogManager blogManager();
+
+	BlogPostFactory blogPostFactory();
+
+	SettingsManager settingsManager();
+
+	ContactExchangeTask contactExchangeTask();
+
+	KeyAgreementTaskFactory keyAgreementTaskFactory();
+
+	PayloadEncoder payloadEncoder();
+
+	PayloadParser payloadParser();
+
+	IntroductionManager introductionManager();
+
+	AndroidExecutor androidExecutor();
+
+	FeedManager feedManager();
+
+	Clock clock();
+
+	@IoExecutor
+	Executor ioExecutor();
+
+	void inject(BriarService activity);
+
+	void inject(BriarReportSender briarReportSender);
+
+	// Eager singleton load
+	void inject(AppModule.EagerSingletons init);
+}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AndroidEagerSingletons.java b/briar-android/src/main/java/org/briarproject/briar/android/AndroidEagerSingletons.java
new file mode 100644
index 0000000000000000000000000000000000000000..00a2c707767d30b6214b241107826473f6b3a872
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/AndroidEagerSingletons.java
@@ -0,0 +1,8 @@
+package org.briarproject.briar.android;
+
+class AndroidEagerSingletons {
+
+	static void initEagerSingletons(AndroidComponent c) {
+		c.inject(new AppModule.EagerSingletons());
+	}
+}
diff --git a/briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/AndroidNotificationManagerImpl.java
similarity index 90%
rename from briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/AndroidNotificationManagerImpl.java
index 2e01bdcab0ddc602a62141e5fe6b21018554e433..3f1dc6d0963562ce09abb690352e50d216f1e6f4 100644
--- a/briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/AndroidNotificationManagerImpl.java
@@ -1,4 +1,4 @@
-package org.briarproject.android;
+package org.briarproject.briar.android;
 
 import android.app.Application;
 import android.app.NotificationManager;
@@ -13,33 +13,36 @@ import android.support.annotation.UiThread;
 import android.support.v4.app.NotificationCompat;
 import android.support.v4.app.TaskStackBuilder;
 
-import org.briarproject.R;
-import org.briarproject.android.api.AndroidExecutor;
-import org.briarproject.android.api.AndroidNotificationManager;
-import org.briarproject.android.contact.ConversationActivity;
-import org.briarproject.android.forum.ForumActivity;
-import org.briarproject.android.privategroup.conversation.GroupActivity;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.event.BlogPostAddedEvent;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.ForumPostReceivedEvent;
-import org.briarproject.api.event.GroupMessageAddedEvent;
-import org.briarproject.api.event.IntroductionRequestReceivedEvent;
-import org.briarproject.api.event.IntroductionResponseReceivedEvent;
-import org.briarproject.api.event.IntroductionSucceededEvent;
-import org.briarproject.api.event.InvitationRequestReceivedEvent;
-import org.briarproject.api.event.InvitationResponseReceivedEvent;
-import org.briarproject.api.event.PrivateMessageReceivedEvent;
-import org.briarproject.api.event.SettingsUpdatedEvent;
-import org.briarproject.api.lifecycle.Service;
-import org.briarproject.api.lifecycle.ServiceException;
-import org.briarproject.api.settings.Settings;
-import org.briarproject.api.settings.SettingsManager;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.lifecycle.Service;
+import org.briarproject.bramble.api.lifecycle.ServiceException;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.settings.Settings;
+import org.briarproject.bramble.api.settings.SettingsManager;
+import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.system.AndroidExecutor;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.contact.ConversationActivity;
+import org.briarproject.briar.android.forum.ForumActivity;
+import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
+import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
+import org.briarproject.briar.api.android.AndroidNotificationManager;
+import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
+import org.briarproject.briar.api.forum.event.ForumPostReceivedEvent;
+import org.briarproject.briar.api.introduction.event.IntroductionRequestReceivedEvent;
+import org.briarproject.briar.api.introduction.event.IntroductionResponseReceivedEvent;
+import org.briarproject.briar.api.introduction.event.IntroductionSucceededEvent;
+import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent;
+import org.briarproject.briar.api.privategroup.event.GroupMessageAddedEvent;
+import org.briarproject.briar.api.sharing.event.InvitationRequestReceivedEvent;
+import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -50,6 +53,7 @@ import java.util.concurrent.Future;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.logging.Logger;
 
+import javax.annotation.concurrent.ThreadSafe;
 import javax.inject.Inject;
 
 import static android.app.Notification.DEFAULT_LIGHTS;
@@ -62,16 +66,19 @@ import static android.support.v4.app.NotificationCompat.CATEGORY_MESSAGE;
 import static android.support.v4.app.NotificationCompat.CATEGORY_SOCIAL;
 import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.android.BriarActivity.GROUP_ID;
-import static org.briarproject.android.NavDrawerActivity.INTENT_BLOGS;
-import static org.briarproject.android.NavDrawerActivity.INTENT_CONTACTS;
-import static org.briarproject.android.NavDrawerActivity.INTENT_FORUMS;
-import static org.briarproject.android.NavDrawerActivity.INTENT_GROUPS;
-import static org.briarproject.android.contact.ConversationActivity.CONTACT_ID;
-import static org.briarproject.android.fragment.SettingsFragment.PREF_NOTIFY_BLOG;
-import static org.briarproject.android.fragment.SettingsFragment.PREF_NOTIFY_GROUP;
-import static org.briarproject.android.fragment.SettingsFragment.SETTINGS_NAMESPACE;
-
+import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
+import static org.briarproject.briar.android.contact.ConversationActivity.CONTACT_ID;
+import static org.briarproject.briar.android.navdrawer.NavDrawerActivity.INTENT_BLOGS;
+import static org.briarproject.briar.android.navdrawer.NavDrawerActivity.INTENT_CONTACTS;
+import static org.briarproject.briar.android.navdrawer.NavDrawerActivity.INTENT_FORUMS;
+import static org.briarproject.briar.android.navdrawer.NavDrawerActivity.INTENT_GROUPS;
+import static org.briarproject.briar.android.settings.SettingsFragment.PREF_NOTIFY_BLOG;
+import static org.briarproject.briar.android.settings.SettingsFragment.PREF_NOTIFY_GROUP;
+import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
+
+@ThreadSafe
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 		Service, EventListener {
 
diff --git a/briar-android/src/org/briarproject/android/AppModule.java b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java
similarity index 67%
rename from briar-android/src/org/briarproject/android/AppModule.java
rename to briar-android/src/main/java/org/briarproject/briar/android/AppModule.java
index f0f1954e42303fa54ffabf993e3065d930cd81db..667b4ee2919447712ae626d9184d86ffcc90b8eb 100644
--- a/briar-android/src/org/briarproject/android/AppModule.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java
@@ -1,22 +1,26 @@
-package org.briarproject.android;
+package org.briarproject.briar.android;
 
 import android.app.Application;
 
-import org.briarproject.android.api.AndroidNotificationManager;
-import org.briarproject.android.api.ReferenceManager;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.PublicKey;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.db.DatabaseConfig;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.reporting.DevConfig;
-import org.briarproject.api.ui.UiCallback;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.PublicKey;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.db.DatabaseConfig;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.reporting.DevConfig;
+import org.briarproject.bramble.api.ui.UiCallback;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.api.android.AndroidNotificationManager;
+import org.briarproject.briar.api.android.ReferenceManager;
 
 import java.io.File;
 import java.security.GeneralSecurityException;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
@@ -24,8 +28,8 @@ import dagger.Module;
 import dagger.Provides;
 
 import static android.content.Context.MODE_PRIVATE;
-import static org.briarproject.api.reporting.ReportingConstants.DEV_ONION_ADDRESS;
-import static org.briarproject.api.reporting.ReportingConstants.DEV_PUBLIC_KEY_HEX;
+import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_ONION_ADDRESS;
+import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_PUBLIC_KEY_HEX;
 
 @Module
 public class AppModule {
@@ -74,9 +78,11 @@ public class AppModule {
 	@Singleton
 	DatabaseConfig provideDatabaseConfig(Application app) {
 		final File dir = app.getApplicationContext().getDir("db", MODE_PRIVATE);
-		return new DatabaseConfig() {
+		@MethodsNotNullByDefault
+		@ParametersNotNullByDefault
+		DatabaseConfig databaseConfig = new DatabaseConfig() {
 
-			private volatile SecretKey key = null;
+			private volatile SecretKey key;
 			private volatile String nickname;
 
 			@Override
@@ -102,11 +108,13 @@ public class AppModule {
 			}
 
 			@Override
+			@Nullable
 			public String getLocalAuthorName() {
 				return nickname;
 			}
 
 			@Override
+			@Nullable
 			public SecretKey getEncryptionKey() {
 				return key;
 			}
@@ -116,12 +124,14 @@ public class AppModule {
 				return Long.MAX_VALUE;
 			}
 		};
+		return databaseConfig;
 	}
 
 	@Provides
 	@Singleton
 	DevConfig provideDevConfig(final CryptoComponent crypto) {
-		return new DevConfig() {
+		@NotNullByDefault
+		DevConfig devConfig = new DevConfig() {
 
 			@Override
 			public PublicKey getDevPublicKey() {
@@ -138,6 +148,7 @@ public class AppModule {
 				return DEV_ONION_ADDRESS;
 			}
 		};
+		return devConfig;
 	}
 
 	@Provides
diff --git a/briar-android/src/org/briarproject/android/BriarApplication.java b/briar-android/src/main/java/org/briarproject/briar/android/BriarApplication.java
similarity index 84%
rename from briar-android/src/org/briarproject/android/BriarApplication.java
rename to briar-android/src/main/java/org/briarproject/briar/android/BriarApplication.java
index cd28990adcaefb0cd28629747175e1b596629f13..bf78cecfa1b00eed4e17012cb187e123f50e2d63 100644
--- a/briar-android/src/org/briarproject/android/BriarApplication.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/BriarApplication.java
@@ -1,4 +1,4 @@
-package org.briarproject.android;
+package org.briarproject.briar.android;
 
 /**
  * This exists so that the Application object will not necessarily be cast
diff --git a/briar-android/src/org/briarproject/android/BriarApplicationImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/BriarApplicationImpl.java
similarity index 83%
rename from briar-android/src/org/briarproject/android/BriarApplicationImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/BriarApplicationImpl.java
index c78ff2dfccf74e06d7346f374982f44d3be03173..07f3f6c4b1c511863b2f0bcf7d686e283d4e865c 100644
--- a/briar-android/src/org/briarproject/android/BriarApplicationImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/BriarApplicationImpl.java
@@ -1,4 +1,4 @@
-package org.briarproject.android;
+package org.briarproject.briar.android;
 
 import android.app.Application;
 import android.content.Context;
@@ -6,11 +6,12 @@ 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.report.BriarReportPrimer;
-import org.briarproject.android.report.BriarReportSenderFactory;
-import org.briarproject.android.report.DevReportActivity;
+import org.briarproject.bramble.BrambleCoreModule;
+import org.briarproject.briar.BriarCoreModule;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.reporting.BriarReportPrimer;
+import org.briarproject.briar.android.reporting.BriarReportSenderFactory;
+import org.briarproject.briar.android.reporting.DevReportActivity;
 
 import java.util.logging.Logger;
 
@@ -79,7 +80,8 @@ public class BriarApplicationImpl extends Application
 
 		// We need to load the eager singletons directly after making the
 		// dependency graphs
-		CoreModule.initEagerSingletons(applicationComponent);
+		BrambleCoreModule.initEagerSingletons(applicationComponent);
+		BriarCoreModule.initEagerSingletons(applicationComponent);
 		AndroidEagerSingletons.initEagerSingletons(applicationComponent);
 	}
 
diff --git a/briar-android/src/org/briarproject/android/BriarService.java b/briar-android/src/main/java/org/briarproject/briar/android/BriarService.java
similarity index 91%
rename from briar-android/src/org/briarproject/android/BriarService.java
rename to briar-android/src/main/java/org/briarproject/briar/android/BriarService.java
index 4707a41a14fa01acca04057c842ef52ec573c4cd..f7eabd5086e7c5f911909d574be7d97caa38262a 100644
--- a/briar-android/src/org/briarproject/android/BriarService.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/BriarService.java
@@ -1,4 +1,4 @@
-package org.briarproject.android;
+package org.briarproject.briar.android;
 
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -11,11 +11,12 @@ import android.os.Build;
 import android.os.IBinder;
 import android.support.v4.app.NotificationCompat;
 
-import org.briarproject.R;
-import org.briarproject.android.api.AndroidExecutor;
-import org.briarproject.api.db.DatabaseConfig;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.lifecycle.LifecycleManager.StartResult;
+import org.briarproject.bramble.api.db.DatabaseConfig;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult;
+import org.briarproject.bramble.api.system.AndroidExecutor;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
 
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -31,8 +32,8 @@ import static android.support.v4.app.NotificationCompat.CATEGORY_SERVICE;
 import static android.support.v4.app.NotificationCompat.PRIORITY_MIN;
 import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.lifecycle.LifecycleManager.StartResult.ALREADY_RUNNING;
-import static org.briarproject.api.lifecycle.LifecycleManager.StartResult.SUCCESS;
+import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.ALREADY_RUNNING;
+import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SUCCESS;
 
 public class BriarService extends Service {
 
diff --git a/briar-android/src/org/briarproject/android/DestroyableContext.java b/briar-android/src/main/java/org/briarproject/briar/android/DestroyableContext.java
similarity index 70%
rename from briar-android/src/org/briarproject/android/DestroyableContext.java
rename to briar-android/src/main/java/org/briarproject/briar/android/DestroyableContext.java
index 75faa0d104267707287daf8644f6a966b98ba0de..26d9281435f69cd27ee8934b34f1d0f5f7445ca7 100644
--- a/briar-android/src/org/briarproject/android/DestroyableContext.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/DestroyableContext.java
@@ -1,4 +1,4 @@
-package org.briarproject.android;
+package org.briarproject.briar.android;
 
 public interface DestroyableContext {
 
diff --git a/briar-android/src/org/briarproject/android/ReferenceManagerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/ReferenceManagerImpl.java
similarity index 88%
rename from briar-android/src/org/briarproject/android/ReferenceManagerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/ReferenceManagerImpl.java
index d5959a622e2988bf951643d3308e82b7e6a6d1ef..99fa824980fbb40351e4b9181cd9ec4517df66b6 100644
--- a/briar-android/src/org/briarproject/android/ReferenceManagerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/ReferenceManagerImpl.java
@@ -1,6 +1,6 @@
-package org.briarproject.android;
+package org.briarproject.briar.android;
 
-import static java.util.logging.Level.INFO;
+import org.briarproject.briar.api.android.ReferenceManager;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -8,7 +8,7 @@ import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.logging.Logger;
 
-import org.briarproject.android.api.ReferenceManager;
+import static java.util.logging.Level.INFO;
 
 class ReferenceManagerImpl implements ReferenceManager {
 
@@ -18,10 +18,10 @@ class ReferenceManagerImpl implements ReferenceManager {
 	private final Lock lock = new ReentrantLock();
 
 	// The following are locking: lock
-	private final Map<Class<?>, Map<Long, Object>> outerMap =
-			new HashMap<Class<?>, Map<Long, Object>>();
+	private final Map<Class<?>, Map<Long, Object>> outerMap = new HashMap<>();
 	private long nextHandle = 0;
 
+	@Override
 	public <T> T getReference(long handle, Class<T> c) {
 		lock.lock();
 		try {
@@ -41,12 +41,13 @@ class ReferenceManagerImpl implements ReferenceManager {
 
 	}
 
+	@Override
 	public <T> long putReference(T reference, Class<T> c) {
 		lock.lock();
 		try {
 			Map<Long, Object> innerMap = outerMap.get(c);
 			if (innerMap == null) {
-				innerMap = new HashMap<Long, Object>();
+				innerMap = new HashMap<>();
 				outerMap.put(c, innerMap);
 			}
 			long handle = nextHandle++;
@@ -61,6 +62,7 @@ class ReferenceManagerImpl implements ReferenceManager {
 		}
 	}
 
+	@Override
 	public <T> T removeReference(long handle, Class<T> c) {
 		lock.lock();
 		try {
diff --git a/briar-android/src/org/briarproject/android/StartupFailureActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/StartupFailureActivity.java
similarity index 80%
rename from briar-android/src/org/briarproject/android/StartupFailureActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/StartupFailureActivity.java
index b258369391ff701b735b130d1ee901c46d22ccb7..51ee125d5319e7fd4e2e6aef08c4cd1919e47c85 100644
--- a/briar-android/src/org/briarproject/android/StartupFailureActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/StartupFailureActivity.java
@@ -1,13 +1,15 @@
-package org.briarproject.android;
+package org.briarproject.briar.android;
 
 import android.app.NotificationManager;
 import android.content.Intent;
 import android.os.Bundle;
 import android.widget.TextView;
 
-import org.briarproject.R;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BaseActivity;
 
-import static org.briarproject.api.lifecycle.LifecycleManager.StartResult;
+import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult;
 
 public class StartupFailureActivity extends BaseActivity {
 
diff --git a/briar-android/src/org/briarproject/android/TestingConstants.java b/briar-android/src/main/java/org/briarproject/briar/android/TestingConstants.java
similarity index 87%
rename from briar-android/src/org/briarproject/android/TestingConstants.java
rename to briar-android/src/main/java/org/briarproject/briar/android/TestingConstants.java
index 26ae9485208d0000a631a2bc5a48ff5befc6a4dd..5739b5e76c7c8b8ff5bd720c4a1e477705b2cd86 100644
--- a/briar-android/src/org/briarproject/android/TestingConstants.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/TestingConstants.java
@@ -1,4 +1,4 @@
-package org.briarproject.android;
+package org.briarproject.briar.android;
 
 import java.util.logging.Level;
 
@@ -22,5 +22,5 @@ public interface TestingConstants {
 	 * Unfortunately this also prevents the user from taking screenshots
 	 * intentionally.
 	 */
-	boolean PREVENT_SCREENSHOTS = TESTING ? false : true;
+	boolean PREVENT_SCREENSHOTS = !TESTING;
 }
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java b/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java
new file mode 100644
index 0000000000000000000000000000000000000000..432cd87947761d69990d0ba6f61cfc5372cea399
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java
@@ -0,0 +1,191 @@
+package org.briarproject.briar.android.activity;
+
+import android.app.Activity;
+
+import org.briarproject.briar.android.AndroidComponent;
+import org.briarproject.briar.android.blog.BlogActivity;
+import org.briarproject.briar.android.blog.BlogFragment;
+import org.briarproject.briar.android.blog.BlogModule;
+import org.briarproject.briar.android.blog.BlogPostFragment;
+import org.briarproject.briar.android.blog.FeedFragment;
+import org.briarproject.briar.android.blog.FeedPostFragment;
+import org.briarproject.briar.android.blog.ReblogActivity;
+import org.briarproject.briar.android.blog.ReblogFragment;
+import org.briarproject.briar.android.blog.RssFeedImportActivity;
+import org.briarproject.briar.android.blog.RssFeedManageActivity;
+import org.briarproject.briar.android.blog.WriteBlogPostActivity;
+import org.briarproject.briar.android.contact.ContactListFragment;
+import org.briarproject.briar.android.contact.ContactModule;
+import org.briarproject.briar.android.contact.ConversationActivity;
+import org.briarproject.briar.android.forum.CreateForumActivity;
+import org.briarproject.briar.android.forum.ForumActivity;
+import org.briarproject.briar.android.forum.ForumListFragment;
+import org.briarproject.briar.android.forum.ForumModule;
+import org.briarproject.briar.android.introduction.ContactChooserFragment;
+import org.briarproject.briar.android.introduction.IntroductionActivity;
+import org.briarproject.briar.android.introduction.IntroductionMessageFragment;
+import org.briarproject.briar.android.invitation.AddContactActivity;
+import org.briarproject.briar.android.keyagreement.IntroFragment;
+import org.briarproject.briar.android.keyagreement.KeyAgreementActivity;
+import org.briarproject.briar.android.keyagreement.ShowQrCodeFragment;
+import org.briarproject.briar.android.login.ChangePasswordActivity;
+import org.briarproject.briar.android.login.PasswordActivity;
+import org.briarproject.briar.android.login.SetupActivity;
+import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
+import org.briarproject.briar.android.panic.PanicPreferencesActivity;
+import org.briarproject.briar.android.panic.PanicResponderActivity;
+import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
+import org.briarproject.briar.android.privategroup.conversation.GroupConversationModule;
+import org.briarproject.briar.android.privategroup.creation.CreateGroupActivity;
+import org.briarproject.briar.android.privategroup.creation.CreateGroupFragment;
+import org.briarproject.briar.android.privategroup.creation.CreateGroupMessageFragment;
+import org.briarproject.briar.android.privategroup.creation.GroupCreateModule;
+import org.briarproject.briar.android.privategroup.creation.GroupInviteActivity;
+import org.briarproject.briar.android.privategroup.creation.GroupInviteFragment;
+import org.briarproject.briar.android.privategroup.invitation.GroupInvitationActivity;
+import org.briarproject.briar.android.privategroup.invitation.GroupInvitationModule;
+import org.briarproject.briar.android.privategroup.list.GroupListFragment;
+import org.briarproject.briar.android.privategroup.list.GroupListModule;
+import org.briarproject.briar.android.privategroup.memberlist.GroupMemberListActivity;
+import org.briarproject.briar.android.privategroup.memberlist.GroupMemberModule;
+import org.briarproject.briar.android.privategroup.reveal.GroupRevealModule;
+import org.briarproject.briar.android.privategroup.reveal.RevealContactsActivity;
+import org.briarproject.briar.android.privategroup.reveal.RevealContactsFragment;
+import org.briarproject.briar.android.settings.SettingsActivity;
+import org.briarproject.briar.android.sharing.BlogInvitationActivity;
+import org.briarproject.briar.android.sharing.BlogSharingStatusActivity;
+import org.briarproject.briar.android.sharing.ForumInvitationActivity;
+import org.briarproject.briar.android.sharing.ForumSharingStatusActivity;
+import org.briarproject.briar.android.sharing.ShareBlogActivity;
+import org.briarproject.briar.android.sharing.ShareBlogFragment;
+import org.briarproject.briar.android.sharing.ShareBlogMessageFragment;
+import org.briarproject.briar.android.sharing.ShareForumActivity;
+import org.briarproject.briar.android.sharing.ShareForumFragment;
+import org.briarproject.briar.android.sharing.ShareForumMessageFragment;
+import org.briarproject.briar.android.sharing.SharingModule;
+import org.briarproject.briar.android.splash.SplashScreenActivity;
+import org.thoughtcrime.securesms.components.emoji.EmojiProvider;
+import org.thoughtcrime.securesms.components.emoji.RecentEmojiPageModel;
+
+import dagger.Component;
+
+@ActivityScope
+@Component(
+		modules = {ActivityModule.class, ForumModule.class, SharingModule.class,
+				BlogModule.class, ContactModule.class, GroupListModule.class,
+				GroupCreateModule.class, GroupInvitationModule.class,
+				GroupConversationModule.class, GroupMemberModule.class,
+				GroupRevealModule.class},
+		dependencies = AndroidComponent.class)
+public interface ActivityComponent {
+
+	Activity activity();
+
+	void inject(SplashScreenActivity activity);
+
+	void inject(SetupActivity activity);
+
+	void inject(NavDrawerActivity activity);
+
+	void inject(PasswordActivity activity);
+
+	void inject(PanicResponderActivity activity);
+
+	void inject(PanicPreferencesActivity activity);
+
+	void inject(AddContactActivity activity);
+
+	void inject(KeyAgreementActivity activity);
+
+	void inject(ConversationActivity activity);
+
+	void inject(ForumInvitationActivity activity);
+
+	void inject(BlogInvitationActivity activity);
+
+	void inject(CreateGroupActivity activity);
+
+	void inject(GroupActivity activity);
+
+	void inject(GroupInviteActivity activity);
+
+	void inject(GroupInvitationActivity activity);
+
+	void inject(GroupMemberListActivity activity);
+
+	void inject(RevealContactsActivity activity);
+
+	void inject(CreateForumActivity activity);
+
+	void inject(ShareForumActivity activity);
+
+	void inject(ShareBlogActivity activity);
+
+	void inject(ForumSharingStatusActivity activity);
+
+	void inject(BlogSharingStatusActivity activity);
+
+	void inject(ForumActivity activity);
+
+	void inject(BlogActivity activity);
+
+	void inject(WriteBlogPostActivity activity);
+
+	void inject(BlogFragment fragment);
+
+	void inject(BlogPostFragment fragment);
+
+	void inject(FeedPostFragment fragment);
+
+	void inject(ReblogFragment fragment);
+
+	void inject(ReblogActivity activity);
+
+	void inject(SettingsActivity activity);
+
+	void inject(ChangePasswordActivity activity);
+
+	void inject(IntroductionActivity activity);
+
+	void inject(RssFeedImportActivity activity);
+
+	void inject(RssFeedManageActivity activity);
+
+	void inject(EmojiProvider emojiProvider);
+
+	void inject(RecentEmojiPageModel recentEmojiPageModel);
+
+	// Fragments
+	void inject(ContactListFragment fragment);
+
+	void inject(CreateGroupFragment fragment);
+
+	void inject(CreateGroupMessageFragment fragment);
+
+	void inject(GroupListFragment fragment);
+
+	void inject(GroupInviteFragment fragment);
+
+	void inject(RevealContactsFragment activity);
+
+	void inject(ForumListFragment fragment);
+
+	void inject(FeedFragment fragment);
+
+	void inject(IntroFragment fragment);
+
+	void inject(ShowQrCodeFragment fragment);
+
+	void inject(ContactChooserFragment fragment);
+
+	void inject(ShareForumFragment fragment);
+
+	void inject(ShareForumMessageFragment fragment);
+
+	void inject(ShareBlogFragment fragment);
+
+	void inject(ShareBlogMessageFragment fragment);
+
+	void inject(IntroductionMessageFragment fragment);
+
+}
diff --git a/briar-android/src/org/briarproject/android/ActivityModule.java b/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityModule.java
similarity index 65%
rename from briar-android/src/org/briarproject/android/ActivityModule.java
rename to briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityModule.java
index 0402ef56fc46948dd0d29b508e433d462cd005af..2a00be5ccfd4d5eb1a0810adf73945933091e61a 100644
--- a/briar-android/src/org/briarproject/android/ActivityModule.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityModule.java
@@ -1,26 +1,26 @@
-package org.briarproject.android;
+package org.briarproject.briar.android.activity;
 
 import android.app.Activity;
 import android.content.SharedPreferences;
 
-import org.briarproject.android.controller.BriarController;
-import org.briarproject.android.controller.BriarControllerImpl;
-import org.briarproject.android.controller.ConfigController;
-import org.briarproject.android.controller.ConfigControllerImpl;
-import org.briarproject.android.controller.DbController;
-import org.briarproject.android.controller.DbControllerImpl;
-import org.briarproject.android.controller.NavDrawerController;
-import org.briarproject.android.controller.NavDrawerControllerImpl;
-import org.briarproject.android.controller.PasswordController;
-import org.briarproject.android.controller.PasswordControllerImpl;
-import org.briarproject.android.controller.SetupController;
-import org.briarproject.android.controller.SetupControllerImpl;
+import org.briarproject.briar.android.controller.BriarController;
+import org.briarproject.briar.android.controller.BriarControllerImpl;
+import org.briarproject.briar.android.controller.ConfigController;
+import org.briarproject.briar.android.controller.ConfigControllerImpl;
+import org.briarproject.briar.android.controller.DbController;
+import org.briarproject.briar.android.controller.DbControllerImpl;
+import org.briarproject.briar.android.login.PasswordController;
+import org.briarproject.briar.android.login.PasswordControllerImpl;
+import org.briarproject.briar.android.login.SetupController;
+import org.briarproject.briar.android.login.SetupControllerImpl;
+import org.briarproject.briar.android.navdrawer.NavDrawerController;
+import org.briarproject.briar.android.navdrawer.NavDrawerControllerImpl;
 
 import dagger.Module;
 import dagger.Provides;
 
 import static android.content.Context.MODE_PRIVATE;
-import static org.briarproject.android.BriarService.BriarServiceConnection;
+import static org.briarproject.briar.android.BriarService.BriarServiceConnection;
 
 @Module
 public class ActivityModule {
diff --git a/briar-android/src/org/briarproject/android/ActivityScope.java b/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityScope.java
similarity index 79%
rename from briar-android/src/org/briarproject/android/ActivityScope.java
rename to briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityScope.java
index a6ceb30ab7d9896edcf523aa2d6d22ed377b2fde..c3ea7520ae78410d19fcd88f4ce22e1a925a3ad9 100644
--- a/briar-android/src/org/briarproject/android/ActivityScope.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityScope.java
@@ -1,4 +1,4 @@
-package org.briarproject.android;
+package org.briarproject.briar.android.activity;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/briar-android/src/org/briarproject/android/BaseActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/activity/BaseActivity.java
similarity index 85%
rename from briar-android/src/org/briarproject/android/BaseActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/activity/BaseActivity.java
index 02395fbf10775009a93b15cc21c7c8f0c587e01e..699985ee6d418d72034a14f7090534066e1f0db3 100644
--- a/briar-android/src/org/briarproject/android/BaseActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/activity/BaseActivity.java
@@ -1,21 +1,25 @@
-package org.briarproject.android;
+package org.briarproject.briar.android.activity;
 
 import android.os.Bundle;
 import android.os.IBinder;
-import android.support.annotation.Nullable;
 import android.support.v7.app.AppCompatActivity;
 import android.view.View;
 import android.view.inputmethod.InputMethodManager;
 
-import org.briarproject.android.controller.ActivityLifecycleController;
-import org.briarproject.android.forum.ForumModule;
+import org.briarproject.briar.android.AndroidComponent;
+import org.briarproject.briar.android.BriarApplication;
+import org.briarproject.briar.android.DestroyableContext;
+import org.briarproject.briar.android.controller.ActivityLifecycleController;
+import org.briarproject.briar.android.forum.ForumModule;
 
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.annotation.Nullable;
+
 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
 import static android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT;
-import static org.briarproject.android.TestingConstants.PREVENT_SCREENSHOTS;
+import static org.briarproject.briar.android.TestingConstants.PREVENT_SCREENSHOTS;
 
 public abstract class BaseActivity extends AppCompatActivity
 		implements DestroyableContext {
diff --git a/briar-android/src/org/briarproject/android/BriarActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/activity/BriarActivity.java
similarity index 87%
rename from briar-android/src/org/briarproject/android/BriarActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/activity/BriarActivity.java
index 9d162b62d6702b4863c888f1afafd51041235d14..c590eaddb451455da6cad755e63880c087bb7356 100644
--- a/briar-android/src/org/briarproject/android/BriarActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/activity/BriarActivity.java
@@ -1,13 +1,14 @@
-package org.briarproject.android;
+package org.briarproject.briar.android.activity;
 
 import android.annotation.SuppressLint;
 import android.content.Intent;
 import android.os.Build;
 
-import org.briarproject.android.controller.BriarController;
-import org.briarproject.android.controller.DbController;
-import org.briarproject.android.controller.handler.UiResultHandler;
-import org.briarproject.android.panic.ExitActivity;
+import org.briarproject.briar.android.controller.BriarController;
+import org.briarproject.briar.android.controller.DbController;
+import org.briarproject.briar.android.controller.handler.UiResultHandler;
+import org.briarproject.briar.android.login.PasswordActivity;
+import org.briarproject.briar.android.panic.ExitActivity;
 
 import java.util.logging.Logger;
 
diff --git a/briar-android/src/org/briarproject/android/BriarFragmentActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/activity/BriarFragmentActivity.java
similarity index 68%
rename from briar-android/src/org/briarproject/android/BriarFragmentActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/activity/BriarFragmentActivity.java
index 70443553014378783e39d1844d63d4edd19abe9c..5b18421dfd24c9cac0c8a68e62e7c3c58102a486 100644
--- a/briar-android/src/org/briarproject/android/BriarFragmentActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/activity/BriarFragmentActivity.java
@@ -1,16 +1,13 @@
-package org.briarproject.android;
+package org.briarproject.briar.android.activity;
 
 import android.support.annotation.AnimRes;
 import android.support.v4.app.FragmentTransaction;
-import android.support.v7.app.ActionBar;
 import android.support.v7.app.AlertDialog;
 
-import org.briarproject.R;
-import org.briarproject.android.blogs.FeedFragment;
-import org.briarproject.android.contact.ContactListFragment;
-import org.briarproject.android.forum.ForumListFragment;
-import org.briarproject.android.fragment.BaseFragment;
-import org.briarproject.android.privategroup.list.GroupListFragment;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.contact.ContactListFragment;
+import org.briarproject.briar.android.fragment.BaseFragment;
+import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
 
 import static android.support.v4.app.FragmentManager.POP_BACK_STACK_INCLUSIVE;
 
@@ -20,23 +17,7 @@ import static android.support.v4.app.FragmentManager.POP_BACK_STACK_INCLUSIVE;
  */
 public abstract class BriarFragmentActivity extends BriarActivity {
 
-	private void updateToolbarTitle(String fragmentTag) {
-		ActionBar actionBar = getSupportActionBar();
-		if (actionBar == null)
-			return;
-
-		if (fragmentTag.equals(ContactListFragment.TAG)) {
-			actionBar.setTitle(R.string.contact_list_button);
-		} else if (fragmentTag.equals(GroupListFragment.TAG)) {
-			actionBar.setTitle(R.string.groups_button);
-		} else if (fragmentTag.equals(ForumListFragment.TAG)) {
-			actionBar.setTitle(R.string.forums_button);
-		} else if (fragmentTag.equals(FeedFragment.TAG)) {
-			actionBar.setTitle(R.string.blogs_button);
-		}
-	}
-
-	void clearBackStack() {
+	protected void clearBackStack() {
 		getSupportFragmentManager().popBackStackImmediate(null,
 				POP_BACK_STACK_INCLUSIVE);
 	}
@@ -60,7 +41,6 @@ public abstract class BriarFragmentActivity extends BriarActivity {
 	}
 
 	public void onFragmentCreated(String tag) {
-		updateToolbarTitle(tag);
 	}
 
 	protected void startFragment(BaseFragment fragment) {
@@ -69,7 +49,7 @@ public abstract class BriarFragmentActivity extends BriarActivity {
 		else startFragment(fragment, true);
 	}
 
-	void showMessageDialog(int titleStringId, int msgStringId) {
+	protected void showMessageDialog(int titleStringId, int msgStringId) {
 		// TODO replace with custom dialog fragment ?
 		AlertDialog.Builder builder = new AlertDialog.Builder(this,
 				R.style.BriarDialogTheme);
diff --git a/briar-android/src/org/briarproject/android/blogs/BaseController.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/BaseController.java
similarity index 59%
rename from briar-android/src/org/briarproject/android/blogs/BaseController.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/BaseController.java
index 6b81243ec6c1fbdb8dda0d6dcbbf812545107fae..3d43ffce97670f91604b7b3bee59c37de6492f00 100644
--- a/briar-android/src/org/briarproject/android/blogs/BaseController.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/BaseController.java
@@ -1,19 +1,21 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 
-import org.briarproject.android.DestroyableContext;
-import org.briarproject.android.controller.handler.ExceptionHandler;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.api.blogs.BlogPostHeader;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.android.DestroyableContext;
+import org.briarproject.briar.android.controller.handler.ExceptionHandler;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.briar.api.blog.BlogPostHeader;
 
 import java.util.Collection;
 
+import javax.annotation.Nullable;
+
+@NotNullByDefault
 interface BaseController {
 
 	@UiThread
diff --git a/briar-android/src/org/briarproject/android/blogs/BaseControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/BaseControllerImpl.java
similarity index 83%
rename from briar-android/src/org/briarproject/android/blogs/BaseControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/BaseControllerImpl.java
index 04d9e2d164bed702e1cbee888a5cac938c953f91..41dbf65569f9ea53af0b06c42bbea54ec39f63c7 100644
--- a/briar-android/src/org/briarproject/android/blogs/BaseControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/BaseControllerImpl.java
@@ -1,25 +1,26 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
 import android.support.annotation.CallSuper;
-import android.support.annotation.Nullable;
-
-import org.briarproject.android.api.AndroidNotificationManager;
-import org.briarproject.android.controller.DbControllerImpl;
-import org.briarproject.android.controller.handler.ExceptionHandler;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.api.blogs.Blog;
-import org.briarproject.api.blogs.BlogCommentHeader;
-import org.briarproject.api.blogs.BlogManager;
-import org.briarproject.api.blogs.BlogPostHeader;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.android.controller.DbControllerImpl;
+import org.briarproject.briar.android.controller.handler.ExceptionHandler;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.briar.api.android.AndroidNotificationManager;
+import org.briarproject.briar.api.blog.Blog;
+import org.briarproject.briar.api.blog.BlogCommentHeader;
+import org.briarproject.briar.api.blog.BlogManager;
+import org.briarproject.briar.api.blog.BlogPostHeader;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -28,9 +29,13 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executor;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
+
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 abstract class BaseControllerImpl extends DbControllerImpl
 		implements BaseController, EventListener {
 
@@ -99,7 +104,6 @@ abstract class BaseControllerImpl extends DbControllerImpl
 	@Override
 	public void loadBlogPosts(final GroupId groupId,
 			final ResultExceptionHandler<Collection<BlogPostItem>, DbException> handler) {
-		if (groupId == null) throw new IllegalStateException();
 		runOnDbThread(new Runnable() {
 			@Override
 			public void run() {
@@ -217,8 +221,6 @@ abstract class BaseControllerImpl extends DbControllerImpl
 
 	private BlogPostHeader getPostHeader(GroupId g, MessageId m)
 			throws DbException {
-
-		if (g == null) throw new IllegalStateException();
 		BlogPostHeader header = headerCache.get(m);
 		if (header == null) {
 			header = blogManager.getPostHeader(g, m);
@@ -245,7 +247,7 @@ abstract class BaseControllerImpl extends DbControllerImpl
 		String body = bodyCache.get(m);
 		if (body == null) {
 			body = blogManager.getPostBody(m);
-			if (body != null) bodyCache.put(m, body);
+			bodyCache.put(m, body);
 		}
 		//noinspection ConstantConditions
 		return body;
diff --git a/briar-android/src/org/briarproject/android/blogs/BasePostFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/BasePostFragment.java
similarity index 83%
rename from briar-android/src/org/briarproject/android/blogs/BasePostFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/BasePostFragment.java
index 8717acac1fde806184e03ecc9d92e6f3ac181cae..a6be4cd3fd90cf80f178bc057a4fbb3d3bf66d69 100644
--- a/briar-android/src/org/briarproject/android/blogs/BasePostFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/BasePostFragment.java
@@ -1,24 +1,25 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
 import android.os.Bundle;
 import android.support.annotation.CallSuper;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ProgressBar;
 
-import org.briarproject.R;
-import org.briarproject.android.fragment.BaseFragment;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.fragment.BaseFragment;
 
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
+
 import static android.view.View.INVISIBLE;
 import static android.view.View.VISIBLE;
-import static org.briarproject.android.util.AndroidUtils.MIN_RESOLUTION;
+import static org.briarproject.briar.android.util.UiUtils.MIN_RESOLUTION;
 
 @UiThread
 @MethodsNotNullByDefault
diff --git a/briar-android/src/org/briarproject/android/blogs/BlogActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogActivity.java
similarity index 76%
rename from briar-android/src/org/briarproject/android/blogs/BlogActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/BlogActivity.java
index a52d4437664e94ac689eb19883fda60fd1641994..700ecf40ae69a08e39e7d480731e49730167386f 100644
--- a/briar-android/src/org/briarproject/android/blogs/BlogActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogActivity.java
@@ -1,14 +1,14 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
 import android.content.Intent;
 import android.os.Bundle;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.BriarActivity;
-import org.briarproject.android.blogs.BlogPostAdapter.OnBlogPostClickListener;
-import org.briarproject.android.fragment.BaseFragment.BaseFragmentListener;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BriarActivity;
+import org.briarproject.briar.android.blog.BlogPostAdapter.OnBlogPostClickListener;
+import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
 
 import javax.inject.Inject;
 
diff --git a/briar-android/src/org/briarproject/android/blogs/BlogCommentItem.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogCommentItem.java
similarity index 90%
rename from briar-android/src/org/briarproject/android/blogs/BlogCommentItem.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/BlogCommentItem.java
index b463e3130261d81b4a31965befd596ebb7b268e5..2ef640d37b76bf046680eb1b68b79f8615884c4a 100644
--- a/briar-android/src/org/briarproject/android/blogs/BlogCommentItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogCommentItem.java
@@ -1,7 +1,7 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
-import org.briarproject.api.blogs.BlogCommentHeader;
-import org.briarproject.api.blogs.BlogPostHeader;
+import org.briarproject.briar.api.blog.BlogCommentHeader;
+import org.briarproject.briar.api.blog.BlogPostHeader;
 
 import java.util.ArrayList;
 import java.util.Collections;
diff --git a/briar-android/src/org/briarproject/android/blogs/BlogController.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogController.java
similarity index 55%
rename from briar-android/src/org/briarproject/android/blogs/BlogController.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/BlogController.java
index ba02cacd1c594772b806a4a8cb4c1b37437175dd..c58e41e74e6e4e7e0b911749dfd0235a5c1facaa 100644
--- a/briar-android/src/org/briarproject/android/blogs/BlogController.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogController.java
@@ -1,12 +1,14 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
 
 import java.util.Collection;
 
+@NotNullByDefault
 public interface BlogController extends BaseController {
 
 	void setGroupId(GroupId g);
diff --git a/briar-android/src/org/briarproject/android/blogs/BlogControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogControllerImpl.java
similarity index 75%
rename from briar-android/src/org/briarproject/android/blogs/BlogControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/BlogControllerImpl.java
index abc5108e94a78f246fcbeaa7befbcc8570a7f2fc..43877cc3df2019a86ac4059a57f52f4080ea0f08 100644
--- a/briar-android/src/org/briarproject/android/blogs/BlogControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogControllerImpl.java
@@ -1,24 +1,26 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
 import android.app.Activity;
 
-import org.briarproject.android.api.AndroidNotificationManager;
-import org.briarproject.android.controller.ActivityLifecycleController;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.api.blogs.Blog;
-import org.briarproject.api.blogs.BlogManager;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.event.BlogPostAddedEvent;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.GroupRemovedEvent;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
+import org.briarproject.briar.android.controller.ActivityLifecycleController;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.briar.api.android.AndroidNotificationManager;
+import org.briarproject.briar.api.blog.Blog;
+import org.briarproject.briar.api.blog.BlogManager;
+import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
 
 import java.util.Collection;
 import java.util.concurrent.Executor;
@@ -29,6 +31,8 @@ import javax.inject.Inject;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 class BlogControllerImpl extends BaseControllerImpl
 		implements ActivityLifecycleController, BlogController, EventListener {
 
diff --git a/briar-android/src/org/briarproject/android/blogs/BlogFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogFragment.java
similarity index 87%
rename from briar-android/src/org/briarproject/android/blogs/BlogFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/BlogFragment.java
index a7273fd61fcd40d1dc476350326e5a9281cb0a6f..10dd6d72010a954f51a8cd81f2829009d21374e4 100644
--- a/briar-android/src/org/briarproject/android/blogs/BlogFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogFragment.java
@@ -1,9 +1,8 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.os.Bundle;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.support.design.widget.Snackbar;
 import android.support.v4.app.ActivityOptionsCompat;
@@ -18,24 +17,25 @@ import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Toast;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.blogs.BaseController.BlogListener;
-import org.briarproject.android.blogs.BlogPostAdapter.OnBlogPostClickListener;
-import org.briarproject.android.controller.handler.UiResultExceptionHandler;
-import org.briarproject.android.fragment.BaseFragment;
-import org.briarproject.android.sharing.BlogSharingStatusActivity;
-import org.briarproject.android.sharing.ShareBlogActivity;
-import org.briarproject.android.view.BriarRecyclerView;
-import org.briarproject.api.blogs.BlogPostHeader;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.blog.BaseController.BlogListener;
+import org.briarproject.briar.android.blog.BlogPostAdapter.OnBlogPostClickListener;
+import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
+import org.briarproject.briar.android.fragment.BaseFragment;
+import org.briarproject.briar.android.sharing.BlogSharingStatusActivity;
+import org.briarproject.briar.android.sharing.ShareBlogActivity;
+import org.briarproject.briar.android.view.BriarRecyclerView;
+import org.briarproject.briar.api.blog.BlogPostHeader;
 
 import java.util.Collection;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import static android.app.Activity.RESULT_OK;
@@ -43,9 +43,9 @@ import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
 import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
 import static android.support.v4.app.ActivityOptionsCompat.makeCustomAnimation;
 import static android.widget.Toast.LENGTH_SHORT;
-import static org.briarproject.android.BriarActivity.GROUP_ID;
-import static org.briarproject.android.blogs.BlogActivity.REQUEST_SHARE;
-import static org.briarproject.android.blogs.BlogActivity.REQUEST_WRITE_POST;
+import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
+import static org.briarproject.briar.android.blog.BlogActivity.REQUEST_SHARE;
+import static org.briarproject.briar.android.blog.BlogActivity.REQUEST_WRITE_POST;
 
 @UiThread
 @MethodsNotNullByDefault
diff --git a/briar-android/src/org/briarproject/android/blogs/BlogItem.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogItem.java
similarity index 79%
rename from briar-android/src/org/briarproject/android/blogs/BlogItem.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/BlogItem.java
index 691f9cb754b8fb5f07ce9000fa553f0c93ba3718..f0ea9b48dcd030e32ad6ee293a3aa0520c24950e 100644
--- a/briar-android/src/org/briarproject/android/blogs/BlogItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogItem.java
@@ -1,6 +1,6 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
-import org.briarproject.api.blogs.Blog;
+import org.briarproject.briar.api.blog.Blog;
 
 class BlogItem {
 
diff --git a/briar-android/src/org/briarproject/android/blogs/BlogModule.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogModule.java
similarity index 71%
rename from briar-android/src/org/briarproject/android/blogs/BlogModule.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/BlogModule.java
index f4392e90a438b68ad924c20a382a569f974b27f0..01e80dcb6498dc1fdaa31b3ce7ae5bf8852ee079 100644
--- a/briar-android/src/org/briarproject/android/blogs/BlogModule.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogModule.java
@@ -1,7 +1,7 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
-import org.briarproject.android.ActivityScope;
-import org.briarproject.android.BaseActivity;
+import org.briarproject.briar.android.activity.ActivityScope;
+import org.briarproject.briar.android.activity.BaseActivity;
 
 import dagger.Module;
 import dagger.Provides;
diff --git a/briar-android/src/org/briarproject/android/blogs/BlogPostAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogPostAdapter.java
similarity index 90%
rename from briar-android/src/org/briarproject/android/blogs/BlogPostAdapter.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/BlogPostAdapter.java
index ae67d9cfcec82119979d41108c304df58a5afce9..febca0327d247a82b52f08fab94f8710641db092 100644
--- a/briar-android/src/org/briarproject/android/blogs/BlogPostAdapter.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogPostAdapter.java
@@ -1,12 +1,12 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
 import android.content.Context;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
-import org.briarproject.R;
-import org.briarproject.android.util.BriarAdapter;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.util.BriarAdapter;
 
 class BlogPostAdapter
 		extends BriarAdapter<BlogPostItem, BlogPostViewHolder> {
diff --git a/briar-android/src/org/briarproject/android/blogs/BlogPostFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogPostFragment.java
similarity index 77%
rename from briar-android/src/org/briarproject/android/blogs/BlogPostFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/BlogPostFragment.java
index 2a0ecf19297eb2157449bcdd38c77fab45e8fe48..8c9f4ae21c21c7d02162e8272eaa30f525ef81e1 100644
--- a/briar-android/src/org/briarproject/android/blogs/BlogPostFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogPostFragment.java
@@ -1,19 +1,19 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
 import android.os.Bundle;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.controller.handler.UiResultExceptionHandler;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 @UiThread
diff --git a/briar-android/src/org/briarproject/android/blogs/BlogPostItem.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogPostItem.java
similarity index 79%
rename from briar-android/src/org/briarproject/android/blogs/BlogPostItem.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/BlogPostItem.java
index debcfd544686a6f2de9818ecba92ac36fb231263..d8561ad4d0401e0256ae61c0be6f1c068db7511e 100644
--- a/briar-android/src/org/briarproject/android/blogs/BlogPostItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogPostItem.java
@@ -1,14 +1,14 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
 import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
 
-import org.briarproject.api.blogs.BlogPostHeader;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.Author.Status;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.blog.BlogPostHeader;
 
+import javax.annotation.Nullable;
 import javax.annotation.concurrent.NotThreadSafe;
 
 @NotThreadSafe
diff --git a/briar-android/src/org/briarproject/android/blogs/BlogPostViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogPostViewHolder.java
similarity index 83%
rename from briar-android/src/org/briarproject/android/blogs/BlogPostViewHolder.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/BlogPostViewHolder.java
index 784e60b7f3f5b6a869344d03a00abaebd74d786e..5187537d9ee5ff932a23f0a3a846153e05539dba 100644
--- a/briar-android/src/org/briarproject/android/blogs/BlogPostViewHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogPostViewHolder.java
@@ -1,10 +1,9 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Build;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.support.v4.app.ActivityCompat;
 import android.support.v4.app.ActivityOptionsCompat;
@@ -18,24 +17,26 @@ import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.TextView;
 
-import org.briarproject.R;
-import org.briarproject.android.blogs.BlogPostAdapter.OnBlogPostClickListener;
-import org.briarproject.android.view.AuthorView;
-import org.briarproject.api.blogs.BlogCommentHeader;
-import org.briarproject.api.blogs.BlogPostHeader;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.blog.BlogPostAdapter.OnBlogPostClickListener;
+import org.briarproject.briar.android.view.AuthorView;
+import org.briarproject.briar.api.blog.BlogCommentHeader;
+import org.briarproject.briar.api.blog.BlogPostHeader;
+
+import javax.annotation.Nullable;
 
 import static android.support.v4.app.ActivityOptionsCompat.makeSceneTransitionAnimation;
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
-import static org.briarproject.android.BriarActivity.GROUP_ID;
-import static org.briarproject.android.blogs.BasePostFragment.POST_ID;
-import static org.briarproject.android.util.AndroidUtils.TEASER_LENGTH;
-import static org.briarproject.android.util.AndroidUtils.getSpanned;
-import static org.briarproject.android.util.AndroidUtils.getTeaser;
-import static org.briarproject.android.util.AndroidUtils.makeLinksClickable;
-import static org.briarproject.api.blogs.MessageType.POST;
+import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
+import static org.briarproject.briar.android.blog.BasePostFragment.POST_ID;
+import static org.briarproject.briar.android.util.UiUtils.TEASER_LENGTH;
+import static org.briarproject.briar.android.util.UiUtils.getSpanned;
+import static org.briarproject.briar.android.util.UiUtils.getTeaser;
+import static org.briarproject.briar.android.util.UiUtils.makeLinksClickable;
+import static org.briarproject.briar.api.blog.MessageType.POST;
 
 @UiThread
 class BlogPostViewHolder extends RecyclerView.ViewHolder {
diff --git a/briar-android/src/org/briarproject/android/blogs/FeedController.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/FeedController.java
similarity index 60%
rename from briar-android/src/org/briarproject/android/blogs/FeedController.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/FeedController.java
index 76ab1baa23bf0e351f2fac7997b7c9c9ead97f34..4c28281ca3ec3f77d901305ae93813ec1e5139b9 100644
--- a/briar-android/src/org/briarproject/android/blogs/FeedController.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/FeedController.java
@@ -1,14 +1,15 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
 import android.support.annotation.UiThread;
 
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.api.blogs.Blog;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.briar.api.blog.Blog;
 
 import java.util.Collection;
 
+@NotNullByDefault
 public interface FeedController extends BaseController {
 
 	void loadBlogPosts(
diff --git a/briar-android/src/org/briarproject/android/blogs/FeedControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/FeedControllerImpl.java
similarity index 74%
rename from briar-android/src/org/briarproject/android/blogs/FeedControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/FeedControllerImpl.java
index 1c5cee0ca2b359c5e18ebb836e0a6cfff3137879..1d02c8fdc197cd99c58cd6a3c3497c301202c0e4 100644
--- a/briar-android/src/org/briarproject/android/blogs/FeedControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/FeedControllerImpl.java
@@ -1,21 +1,23 @@
-package org.briarproject.android.blogs;
-
-import org.briarproject.android.api.AndroidNotificationManager;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.api.blogs.Blog;
-import org.briarproject.api.blogs.BlogManager;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.NoSuchGroupException;
-import org.briarproject.api.db.NoSuchMessageException;
-import org.briarproject.api.event.BlogPostAddedEvent;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.GroupAddedEvent;
-import org.briarproject.api.event.GroupRemovedEvent;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.lifecycle.LifecycleManager;
+package org.briarproject.briar.android.blog;
+
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.NoSuchGroupException;
+import org.briarproject.bramble.api.db.NoSuchMessageException;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.event.GroupAddedEvent;
+import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.briar.api.android.AndroidNotificationManager;
+import org.briarproject.briar.api.blog.Blog;
+import org.briarproject.briar.api.blog.BlogManager;
+import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -26,8 +28,10 @@ import javax.inject.Inject;
 
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.blogs.BlogManager.CLIENT_ID;
+import static org.briarproject.briar.api.blog.BlogManager.CLIENT_ID;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 class FeedControllerImpl extends BaseControllerImpl
 		implements FeedController {
 
diff --git a/briar-android/src/org/briarproject/android/blogs/FeedFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/FeedFragment.java
similarity index 87%
rename from briar-android/src/org/briarproject/android/blogs/FeedFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/FeedFragment.java
index e829c08962d5ca0193203f01c3f3dd381b91e946..0eee3cd8bc3af801d7bba5b1ef2f2d32197bfc4c 100644
--- a/briar-android/src/org/briarproject/android/blogs/FeedFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/FeedFragment.java
@@ -1,8 +1,7 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
 import android.content.Intent;
 import android.os.Bundle;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.support.design.widget.Snackbar;
 import android.support.v4.app.ActivityOptionsCompat;
@@ -16,29 +15,30 @@ import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.blogs.BlogPostAdapter.OnBlogPostClickListener;
-import org.briarproject.android.blogs.FeedController.FeedListener;
-import org.briarproject.android.controller.handler.UiResultExceptionHandler;
-import org.briarproject.android.fragment.BaseFragment;
-import org.briarproject.android.view.BriarRecyclerView;
-import org.briarproject.api.blogs.Blog;
-import org.briarproject.api.blogs.BlogPostHeader;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.blog.BlogPostAdapter.OnBlogPostClickListener;
+import org.briarproject.briar.android.blog.FeedController.FeedListener;
+import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
+import org.briarproject.briar.android.fragment.BaseFragment;
+import org.briarproject.briar.android.view.BriarRecyclerView;
+import org.briarproject.briar.api.blog.Blog;
+import org.briarproject.briar.api.blog.BlogPostHeader;
 
 import java.util.Collection;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import static android.app.Activity.RESULT_OK;
 import static android.support.design.widget.Snackbar.LENGTH_LONG;
 import static android.support.v4.app.ActivityOptionsCompat.makeCustomAnimation;
-import static org.briarproject.android.BriarActivity.GROUP_ID;
-import static org.briarproject.android.blogs.BlogActivity.REQUEST_WRITE_POST;
+import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
+import static org.briarproject.briar.android.blog.BlogActivity.REQUEST_WRITE_POST;
 
 @UiThread
 @MethodsNotNullByDefault
diff --git a/briar-android/src/org/briarproject/android/blogs/FeedPostFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/FeedPostFragment.java
similarity index 75%
rename from briar-android/src/org/briarproject/android/blogs/FeedPostFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/FeedPostFragment.java
index 73ec81a3ea0d7784ec97824d00ef206dce4ff0a0..799c170a9efb95fe87d96b56a149b2ac1bafa933 100644
--- a/briar-android/src/org/briarproject/android/blogs/FeedPostFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/FeedPostFragment.java
@@ -1,23 +1,23 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
 import android.os.Bundle;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.controller.handler.UiResultExceptionHandler;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
-import static org.briarproject.android.BriarActivity.GROUP_ID;
+import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
 
 @UiThread
 @MethodsNotNullByDefault
diff --git a/briar-android/src/org/briarproject/android/blogs/ReblogActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/ReblogActivity.java
similarity index 79%
rename from briar-android/src/org/briarproject/android/blogs/ReblogActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/ReblogActivity.java
index 8f04dc1db2df71ed1a422e5c822e9503721e911d..94194d682d28e49e56b304a73b67ea65f71fc45f 100644
--- a/briar-android/src/org/briarproject/android/blogs/ReblogActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/ReblogActivity.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
 import android.annotation.TargetApi;
 import android.content.Intent;
@@ -8,14 +8,14 @@ import android.transition.Fade;
 import android.transition.Transition;
 import android.view.MenuItem;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.BriarActivity;
-import org.briarproject.android.fragment.BaseFragment.BaseFragmentListener;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BriarActivity;
+import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
 
-import static org.briarproject.android.blogs.BasePostFragment.POST_ID;
+import static org.briarproject.briar.android.blog.BasePostFragment.POST_ID;
 
 public class ReblogActivity extends BriarActivity implements
 		BaseFragmentListener {
diff --git a/briar-android/src/org/briarproject/android/blogs/ReblogFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/ReblogFragment.java
similarity index 79%
rename from briar-android/src/org/briarproject/android/blogs/ReblogFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/ReblogFragment.java
index 1c9655336a10559d6198294b4f53eb1c769d12b6..d9093a79da5baffad77a6d423352e48e7938fdc7 100644
--- a/briar-android/src/org/briarproject/android/blogs/ReblogFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/ReblogFragment.java
@@ -1,34 +1,34 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
 import android.os.Bundle;
-import android.support.annotation.Nullable;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ProgressBar;
 import android.widget.ScrollView;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.controller.handler.UiExceptionHandler;
-import org.briarproject.android.controller.handler.UiResultExceptionHandler;
-import org.briarproject.android.fragment.BaseFragment;
-import org.briarproject.android.view.TextInputView;
-import org.briarproject.android.view.TextInputView.TextInputListener;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.controller.handler.UiExceptionHandler;
+import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
+import org.briarproject.briar.android.fragment.BaseFragment;
+import org.briarproject.briar.android.view.TextInputView;
+import org.briarproject.briar.android.view.TextInputView.TextInputListener;
+
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import static android.view.View.FOCUS_DOWN;
 import static android.view.View.GONE;
 import static android.view.View.INVISIBLE;
 import static android.view.View.VISIBLE;
-import static org.briarproject.android.BriarActivity.GROUP_ID;
-import static org.briarproject.android.blogs.BasePostFragment.POST_ID;
+import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
+import static org.briarproject.briar.android.blog.BasePostFragment.POST_ID;
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
diff --git a/briar-android/src/org/briarproject/android/blogs/RssFeedAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/RssFeedAdapter.java
similarity index 89%
rename from briar-android/src/org/briarproject/android/blogs/RssFeedAdapter.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/RssFeedAdapter.java
index aa92468158054470d8377118fb1edf3659cf54ed..3052e3694f22d42ac3001d3c3e7208b93b0fc9b8 100644
--- a/briar-android/src/org/briarproject/android/blogs/RssFeedAdapter.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/RssFeedAdapter.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
 import android.content.Context;
 import android.support.v7.widget.RecyclerView;
@@ -9,10 +9,10 @@ import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.TextView;
 
-import org.briarproject.R;
-import org.briarproject.android.util.AndroidUtils;
-import org.briarproject.android.util.BriarAdapter;
-import org.briarproject.api.feed.Feed;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.util.BriarAdapter;
+import org.briarproject.briar.android.util.UiUtils;
+import org.briarproject.briar.api.feed.Feed;
 
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
@@ -65,8 +65,8 @@ class RssFeedAdapter extends BriarAdapter<Feed, RssFeedAdapter.FeedViewHolder> {
 		}
 
 		// Imported and Last Updated
-		ui.imported.setText(AndroidUtils.formatDate(ctx, item.getAdded()));
-		ui.updated.setText(AndroidUtils.formatDate(ctx, item.getUpdated()));
+		ui.imported.setText(UiUtils.formatDate(ctx, item.getAdded()));
+		ui.updated.setText(UiUtils.formatDate(ctx, item.getUpdated()));
 
 		// Description
 		if (item.getDescription() != null) {
diff --git a/briar-android/src/org/briarproject/android/blogs/RssFeedImportActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/RssFeedImportActivity.java
similarity index 91%
rename from briar-android/src/org/briarproject/android/blogs/RssFeedImportActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/RssFeedImportActivity.java
index 2150b31badd6b1c2bc064320addc625123995740..7e2085818265acdf4dd09b2d556e726828438f3b 100644
--- a/briar-android/src/org/briarproject/android/blogs/RssFeedImportActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/RssFeedImportActivity.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
 import android.content.DialogInterface;
 import android.content.Intent;
@@ -13,13 +13,13 @@ import android.widget.Button;
 import android.widget.EditText;
 import android.widget.ProgressBar;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.BriarActivity;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.feed.FeedManager;
-import org.briarproject.api.lifecycle.IoExecutor;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.lifecycle.IoExecutor;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BriarActivity;
+import org.briarproject.briar.api.feed.FeedManager;
 
 import java.io.IOException;
 import java.util.concurrent.Executor;
diff --git a/briar-android/src/org/briarproject/android/blogs/RssFeedManageActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/RssFeedManageActivity.java
similarity index 88%
rename from briar-android/src/org/briarproject/android/blogs/RssFeedManageActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/RssFeedManageActivity.java
index ecffd0cd2007c7349b7a3766685cf93434909ef8..5229018572f34153c668551fbf868eac0262fda5 100644
--- a/briar-android/src/org/briarproject/android/blogs/RssFeedManageActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/RssFeedManageActivity.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
 import android.content.Intent;
 import android.os.Bundle;
@@ -10,15 +10,15 @@ import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.BriarActivity;
-import org.briarproject.android.blogs.RssFeedAdapter.RssFeedListener;
-import org.briarproject.android.view.BriarRecyclerView;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.feed.Feed;
-import org.briarproject.api.feed.FeedManager;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BriarActivity;
+import org.briarproject.briar.android.blog.RssFeedAdapter.RssFeedListener;
+import org.briarproject.briar.android.view.BriarRecyclerView;
+import org.briarproject.briar.api.feed.Feed;
+import org.briarproject.briar.api.feed.FeedManager;
 
 import java.util.List;
 import java.util.logging.Logger;
diff --git a/briar-android/src/org/briarproject/android/blogs/WriteBlogPostActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/WriteBlogPostActivity.java
similarity index 80%
rename from briar-android/src/org/briarproject/android/blogs/WriteBlogPostActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/blog/WriteBlogPostActivity.java
index 6dccc168564b19f1e803ff11518a629ae1fe181f..1217d94b714ea89966bee32edc11413937157b27 100644
--- a/briar-android/src/org/briarproject/android/blogs/WriteBlogPostActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/WriteBlogPostActivity.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.blogs;
+package org.briarproject.briar.android.blog;
 
 import android.content.Intent;
 import android.os.Bundle;
@@ -10,21 +10,21 @@ import android.widget.ProgressBar;
 import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.BriarActivity;
-import org.briarproject.android.api.AndroidNotificationManager;
-import org.briarproject.android.view.TextInputView;
-import org.briarproject.android.view.TextInputView.TextInputListener;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.blogs.BlogManager;
-import org.briarproject.api.blogs.BlogPost;
-import org.briarproject.api.blogs.BlogPostFactory;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BriarActivity;
+import org.briarproject.briar.android.view.TextInputView;
+import org.briarproject.briar.android.view.TextInputView.TextInputListener;
+import org.briarproject.briar.api.android.AndroidNotificationManager;
+import org.briarproject.briar.api.blog.BlogManager;
+import org.briarproject.briar.api.blog.BlogPost;
+import org.briarproject.briar.api.blog.BlogPostFactory;
 
 import java.security.GeneralSecurityException;
 import java.util.logging.Logger;
@@ -34,7 +34,7 @@ import javax.inject.Inject;
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_POST_BODY_LENGTH;
+import static org.briarproject.briar.api.blog.BlogConstants.MAX_BLOG_POST_BODY_LENGTH;
 
 public class WriteBlogPostActivity extends BriarActivity
 		implements OnEditorActionListener, TextInputListener {
diff --git a/briar-android/src/org/briarproject/android/contact/BaseContactListAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/BaseContactListAdapter.java
similarity index 87%
rename from briar-android/src/org/briarproject/android/contact/BaseContactListAdapter.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/BaseContactListAdapter.java
index 22e8391485f913402c89f51826c2a8180962818c..fb89f85d1be08462ab29a24f38f986bec37f601f 100644
--- a/briar-android/src/org/briarproject/android/contact/BaseContactListAdapter.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/BaseContactListAdapter.java
@@ -1,11 +1,12 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
 import android.content.Context;
-import android.support.annotation.Nullable;
 import android.view.View;
 
-import org.briarproject.android.util.BriarAdapter;
-import org.briarproject.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.briar.android.util.BriarAdapter;
+
+import javax.annotation.Nullable;
 
 import static android.support.v7.util.SortedList.INVALID_POSITION;
 
diff --git a/briar-android/src/org/briarproject/android/contact/ContactItem.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactItem.java
similarity index 62%
rename from briar-android/src/org/briarproject/android/contact/ContactItem.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ContactItem.java
index eaa7f66c578d2ed1c908504e6aed4e61164a817f..720a9d6df33ddc445b32af1ea2a7121d8a589655 100644
--- a/briar-android/src/org/briarproject/android/contact/ContactItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactItem.java
@@ -1,7 +1,7 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import javax.annotation.concurrent.NotThreadSafe;
 
diff --git a/briar-android/src/org/briarproject/android/contact/ContactItemViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactItemViewHolder.java
similarity index 78%
rename from briar-android/src/org/briarproject/android/contact/ContactItemViewHolder.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ContactItemViewHolder.java
index 46a81762b60f21b1473f5b0cc95dbfe55a53495b..3791c6c34323906fb09e0b8b238374ec78acaeb2 100644
--- a/briar-android/src/org/briarproject/android/contact/ContactItemViewHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactItemViewHolder.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
 import android.support.annotation.UiThread;
 import android.support.v7.widget.RecyclerView;
@@ -7,11 +7,12 @@ import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.TextView;
 
-import org.briarproject.R;
-import org.briarproject.android.contact.BaseContactListAdapter.OnContactClickListener;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.contact.BaseContactListAdapter.OnContactClickListener;
+
+import javax.annotation.Nullable;
 
 import im.delight.android.identicons.IdenticonDrawable;
 
diff --git a/briar-android/src/org/briarproject/android/contact/ContactListAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListAdapter.java
similarity index 93%
rename from briar-android/src/org/briarproject/android/contact/ContactListAdapter.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListAdapter.java
index 707ceeacdd4c787d4a585b4055f477a8b21eef90..5eb17f7439d80cff1bd5c56d900017358eb26963 100644
--- a/briar-android/src/org/briarproject/android/contact/ContactListAdapter.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListAdapter.java
@@ -1,11 +1,11 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
 import android.content.Context;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
-import org.briarproject.R;
+import org.briarproject.briar.R;
 
 public class ContactListAdapter extends
 		BaseContactListAdapter<ContactListItem, ContactListItemViewHolder> {
diff --git a/briar-android/src/org/briarproject/android/contact/ContactListFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListFragment.java
similarity index 77%
rename from briar-android/src/org/briarproject/android/contact/ContactListFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListFragment.java
index a14bbc0d574fd6ca56d85892fa2ae7c5df99b4de..af242e9454da5a6318ba8660385d16d62f02f43c 100644
--- a/briar-android/src/org/briarproject/android/contact/ContactListFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListFragment.java
@@ -1,9 +1,8 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
 import android.content.Intent;
 import android.os.Build;
 import android.os.Bundle;
-import android.support.annotation.Nullable;
 import android.support.v4.app.ActivityCompat;
 import android.support.v4.app.ActivityOptionsCompat;
 import android.support.v4.util.Pair;
@@ -15,52 +14,57 @@ import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.api.AndroidNotificationManager;
-import org.briarproject.android.contact.BaseContactListAdapter.OnContactClickListener;
-import org.briarproject.android.fragment.BaseFragment;
-import org.briarproject.android.keyagreement.KeyAgreementActivity;
-import org.briarproject.android.view.BriarRecyclerView;
-import org.briarproject.api.clients.BaseMessageHeader;
-import org.briarproject.api.clients.MessageTracker.GroupCount;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.NoSuchContactException;
-import org.briarproject.api.event.ContactConnectedEvent;
-import org.briarproject.api.event.ContactDisconnectedEvent;
-import org.briarproject.api.event.ContactRemovedEvent;
-import org.briarproject.api.event.ContactStatusChangedEvent;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.IntroductionRequestReceivedEvent;
-import org.briarproject.api.event.IntroductionResponseReceivedEvent;
-import org.briarproject.api.event.InvitationRequestReceivedEvent;
-import org.briarproject.api.event.InvitationResponseReceivedEvent;
-import org.briarproject.api.event.PrivateMessageReceivedEvent;
-import org.briarproject.api.introduction.IntroductionRequest;
-import org.briarproject.api.introduction.IntroductionResponse;
-import org.briarproject.api.messaging.ConversationManager;
-import org.briarproject.api.messaging.PrivateMessageHeader;
-import org.briarproject.api.plugins.ConnectionRegistry;
-import org.briarproject.api.sharing.InvitationRequest;
-import org.briarproject.api.sharing.InvitationResponse;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
+import org.briarproject.bramble.api.contact.event.ContactStatusChangedEvent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.NoSuchContactException;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.plugin.ConnectionRegistry;
+import org.briarproject.bramble.api.plugin.event.ContactConnectedEvent;
+import org.briarproject.bramble.api.plugin.event.ContactDisconnectedEvent;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.contact.BaseContactListAdapter.OnContactClickListener;
+import org.briarproject.briar.android.fragment.BaseFragment;
+import org.briarproject.briar.android.keyagreement.KeyAgreementActivity;
+import org.briarproject.briar.android.view.BriarRecyclerView;
+import org.briarproject.briar.api.android.AndroidNotificationManager;
+import org.briarproject.briar.api.client.BaseMessageHeader;
+import org.briarproject.briar.api.client.MessageTracker.GroupCount;
+import org.briarproject.briar.api.introduction.IntroductionRequest;
+import org.briarproject.briar.api.introduction.IntroductionResponse;
+import org.briarproject.briar.api.introduction.event.IntroductionRequestReceivedEvent;
+import org.briarproject.briar.api.introduction.event.IntroductionResponseReceivedEvent;
+import org.briarproject.briar.api.messaging.ConversationManager;
+import org.briarproject.briar.api.messaging.PrivateMessageHeader;
+import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent;
+import org.briarproject.briar.api.sharing.InvitationRequest;
+import org.briarproject.briar.api.sharing.InvitationResponse;
+import org.briarproject.briar.api.sharing.event.InvitationRequestReceivedEvent;
+import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import static android.support.v4.app.ActivityOptionsCompat.makeSceneTransitionAnimation;
 import static android.support.v4.view.ViewCompat.getTransitionName;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.android.contact.ConversationActivity.CONTACT_ID;
+import static org.briarproject.briar.android.contact.ConversationActivity.CONTACT_ID;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 public class ContactListFragment extends BaseFragment implements EventListener {
 
 	public static final String TAG = ContactListFragment.class.getName();
@@ -101,8 +105,9 @@ public class ContactListFragment extends BaseFragment implements EventListener {
 
 	@Nullable
 	@Override
-	public View onCreateView(LayoutInflater inflater, ViewGroup container,
-			Bundle savedInstanceState) {
+	public View onCreateView(LayoutInflater inflater,
+			@Nullable ViewGroup container,
+			@Nullable Bundle savedInstanceState) {
 
 		View contentView = inflater.inflate(R.layout.list, container, false);
 
diff --git a/briar-android/src/org/briarproject/android/contact/ContactListItem.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListItem.java
similarity index 79%
rename from briar-android/src/org/briarproject/android/contact/ContactListItem.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListItem.java
index 18e4946c16fe685c82e386dc5edc98d25324f2fb..d6e839afa69083571fb92a33e2222e370a3b50b5 100644
--- a/briar-android/src/org/briarproject/android/contact/ContactListItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListItem.java
@@ -1,8 +1,8 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
-import org.briarproject.api.clients.MessageTracker.GroupCount;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.api.client.MessageTracker.GroupCount;
 
 import javax.annotation.concurrent.NotThreadSafe;
 
diff --git a/briar-android/src/org/briarproject/android/contact/ContactListItemViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListItemViewHolder.java
similarity index 71%
rename from briar-android/src/org/briarproject/android/contact/ContactListItemViewHolder.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListItemViewHolder.java
index acbd27d82d0e26826b48fcfb180ad1c0f05e02db..649e3782f98474b9ded132d372f11687edd06752 100644
--- a/briar-android/src/org/briarproject/android/contact/ContactListItemViewHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListItemViewHolder.java
@@ -1,19 +1,20 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
 import android.support.annotation.UiThread;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.TextView;
 
-import org.briarproject.R;
-import org.briarproject.android.contact.BaseContactListAdapter.OnContactClickListener;
-import org.briarproject.android.util.AndroidUtils;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.contact.BaseContactListAdapter.OnContactClickListener;
+import org.briarproject.briar.android.util.UiUtils;
+
+import javax.annotation.Nullable;
 
 import static android.support.v4.view.ViewCompat.setTransitionName;
-import static org.briarproject.android.util.AndroidUtils.formatDate;
+import static org.briarproject.briar.android.util.UiUtils.formatDate;
 
 @UiThread
 @NotNullByDefault
@@ -60,8 +61,8 @@ class ContactListItemViewHolder extends ContactItemViewHolder<ContactListItem> {
 		}
 
 		ContactId c = item.getContact().getId();
-		setTransitionName(avatar, AndroidUtils.getAvatarTransitionName(c));
-		setTransitionName(bulb, AndroidUtils.getBulbTransitionName(c));
+		setTransitionName(avatar, UiUtils.getAvatarTransitionName(c));
+		setTransitionName(bulb, UiUtils.getBulbTransitionName(c));
 	}
 
 }
diff --git a/briar-android/src/org/briarproject/android/contact/ContactModule.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactModule.java
similarity index 56%
rename from briar-android/src/org/briarproject/android/contact/ContactModule.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ContactModule.java
index b9bf00e24de8034e2ab88e8f9b036d6d8cfc1ed0..8dce03cbc40d35317f9a4289bdbe94f4eef9fa3a 100644
--- a/briar-android/src/org/briarproject/android/contact/ContactModule.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactModule.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
 import dagger.Module;
 
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationActivity.java
similarity index 86%
rename from briar-android/src/org/briarproject/android/contact/ConversationActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationActivity.java
index 02779ce44285f92166989d84846bfa0053e719b6..7d832eff825ae4f7555c669fbbbe1db90741de9c 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationActivity.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
 import android.content.DialogInterface;
 import android.content.Intent;
@@ -24,64 +24,63 @@ import android.widget.ImageView;
 import android.widget.TextView;
 import android.widget.Toast;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.BriarActivity;
-import org.briarproject.android.api.AndroidNotificationManager;
-import org.briarproject.android.contact.ConversationAdapter.ConversationListener;
-import org.briarproject.android.introduction.IntroductionActivity;
-import org.briarproject.android.util.AndroidUtils;
-import org.briarproject.android.view.BriarRecyclerView;
-import org.briarproject.android.view.TextInputView;
-import org.briarproject.android.view.TextInputView.TextInputListener;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.blogs.BlogSharingManager;
-import org.briarproject.api.clients.ProtocolStateException;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.crypto.CryptoExecutor;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.NoSuchContactException;
-import org.briarproject.api.event.ContactConnectedEvent;
-import org.briarproject.api.event.ContactDisconnectedEvent;
-import org.briarproject.api.event.ContactRemovedEvent;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.IntroductionRequestReceivedEvent;
-import org.briarproject.api.event.IntroductionResponseReceivedEvent;
-import org.briarproject.api.event.InvitationRequestReceivedEvent;
-import org.briarproject.api.event.InvitationResponseReceivedEvent;
-import org.briarproject.api.event.MessagesAckedEvent;
-import org.briarproject.api.event.MessagesSentEvent;
-import org.briarproject.api.event.PrivateMessageReceivedEvent;
-import org.briarproject.api.forum.ForumSharingManager;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.introduction.IntroductionManager;
-import org.briarproject.api.introduction.IntroductionMessage;
-import org.briarproject.api.introduction.IntroductionRequest;
-import org.briarproject.api.introduction.IntroductionResponse;
-import org.briarproject.api.messaging.MessagingManager;
-import org.briarproject.api.messaging.PrivateMessage;
-import org.briarproject.api.messaging.PrivateMessageFactory;
-import org.briarproject.api.messaging.PrivateMessageHeader;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.plugins.ConnectionRegistry;
-import org.briarproject.api.privategroup.invitation.GroupInvitationManager;
-import org.briarproject.api.settings.Settings;
-import org.briarproject.api.settings.SettingsManager;
-import org.briarproject.api.sharing.InvitationMessage;
-import org.briarproject.api.sharing.InvitationRequest;
-import org.briarproject.api.sharing.InvitationResponse;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.util.StringUtils;
-import org.jetbrains.annotations.NotNull;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
+import org.briarproject.bramble.api.crypto.CryptoExecutor;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.NoSuchContactException;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.plugin.ConnectionRegistry;
+import org.briarproject.bramble.api.plugin.event.ContactConnectedEvent;
+import org.briarproject.bramble.api.plugin.event.ContactDisconnectedEvent;
+import org.briarproject.bramble.api.settings.Settings;
+import org.briarproject.bramble.api.settings.SettingsManager;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.event.MessagesAckedEvent;
+import org.briarproject.bramble.api.sync.event.MessagesSentEvent;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BriarActivity;
+import org.briarproject.briar.android.contact.ConversationAdapter.ConversationListener;
+import org.briarproject.briar.android.introduction.IntroductionActivity;
+import org.briarproject.briar.android.util.UiUtils;
+import org.briarproject.briar.android.view.BriarRecyclerView;
+import org.briarproject.briar.android.view.TextInputView;
+import org.briarproject.briar.android.view.TextInputView.TextInputListener;
+import org.briarproject.briar.api.android.AndroidNotificationManager;
+import org.briarproject.briar.api.blog.BlogSharingManager;
+import org.briarproject.briar.api.client.ProtocolStateException;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.forum.ForumSharingManager;
+import org.briarproject.briar.api.introduction.IntroductionManager;
+import org.briarproject.briar.api.introduction.IntroductionMessage;
+import org.briarproject.briar.api.introduction.IntroductionRequest;
+import org.briarproject.briar.api.introduction.IntroductionResponse;
+import org.briarproject.briar.api.introduction.event.IntroductionRequestReceivedEvent;
+import org.briarproject.briar.api.introduction.event.IntroductionResponseReceivedEvent;
+import org.briarproject.briar.api.messaging.MessagingManager;
+import org.briarproject.briar.api.messaging.PrivateMessage;
+import org.briarproject.briar.api.messaging.PrivateMessageFactory;
+import org.briarproject.briar.api.messaging.PrivateMessageHeader;
+import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager;
+import org.briarproject.briar.api.sharing.InvitationMessage;
+import org.briarproject.briar.api.sharing.InvitationRequest;
+import org.briarproject.briar.api.sharing.InvitationResponse;
+import org.briarproject.briar.api.sharing.event.InvitationRequestReceivedEvent;
+import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -93,6 +92,7 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executor;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import de.hdodenhof.circleimageview.CircleImageView;
@@ -105,8 +105,8 @@ import static android.support.v7.util.SortedList.INVALID_POSITION;
 import static android.widget.Toast.LENGTH_SHORT;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.android.fragment.SettingsFragment.SETTINGS_NAMESPACE;
-import static org.briarproject.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
+import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
+import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
@@ -166,7 +166,7 @@ public class ConversationActivity extends BriarActivity
 
 	@SuppressWarnings("ConstantConditions")
 	@Override
-	public void onCreate(Bundle state) {
+	public void onCreate(@Nullable Bundle state) {
 		super.onCreate(state);
 
 		Intent i = getIntent();
@@ -195,9 +195,9 @@ public class ConversationActivity extends BriarActivity
 		}
 
 		ViewCompat.setTransitionName(toolbarAvatar,
-				AndroidUtils.getAvatarTransitionName(contactId));
+				UiUtils.getAvatarTransitionName(contactId));
 		ViewCompat.setTransitionName(toolbarStatus,
-				AndroidUtils.getBulbTransitionName(contactId));
+				UiUtils.getBulbTransitionName(contactId));
 
 		adapter = new ConversationAdapter(this, this);
 		list = (BriarRecyclerView) findViewById(R.id.conversationView);
@@ -833,7 +833,7 @@ public class ConversationActivity extends BriarActivity
 
 	@UiThread
 	@Override
-	public void respondToRequest(@NotNull final ConversationRequestItem item,
+	public void respondToRequest(final ConversationRequestItem item,
 			final boolean accept) {
 		int position = adapter.findItemPosition(item);
 		if (position != INVALID_POSITION) {
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationAdapter.java
similarity index 93%
rename from briar-android/src/org/briarproject/android/contact/ConversationAdapter.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationAdapter.java
index d280bdaee78cf18bf258eebaabb84f89c3aa90c2..b8f1bb78a7485f23046919959c4f983751ca27ca 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationAdapter.java
@@ -1,17 +1,18 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
 import android.content.Context;
 import android.support.annotation.LayoutRes;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.util.SparseArray;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
-import org.briarproject.R;
-import org.briarproject.android.util.BriarAdapter;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.util.BriarAdapter;
+
+import javax.annotation.Nullable;
 
 class ConversationAdapter
 		extends BriarAdapter<ConversationItem, ConversationItemViewHolder> {
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationItem.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationItem.java
similarity index 83%
rename from briar-android/src/org/briarproject/android/contact/ConversationItem.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationItem.java
index 1a2c118e24c751448772a42f5ea005317d8a2103..faf43cf5e322b971a5e563f6bb978808b99cc305 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationItem.java
@@ -1,43 +1,43 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
 import android.content.Context;
 import android.support.annotation.LayoutRes;
 import android.support.annotation.StringRes;
 
-import org.briarproject.R;
-import org.briarproject.android.contact.ConversationRequestItem.RequestType;
-import org.briarproject.api.blogs.BlogInvitationRequest;
-import org.briarproject.api.blogs.BlogInvitationResponse;
-import org.briarproject.api.clients.BaseMessageHeader;
-import org.briarproject.api.forum.ForumInvitationRequest;
-import org.briarproject.api.forum.ForumInvitationResponse;
-import org.briarproject.api.introduction.IntroductionRequest;
-import org.briarproject.api.introduction.IntroductionResponse;
-import org.briarproject.api.messaging.PrivateMessageHeader;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.privategroup.invitation.GroupInvitationRequest;
-import org.briarproject.api.privategroup.invitation.GroupInvitationResponse;
-import org.briarproject.api.sharing.InvitationRequest;
-import org.briarproject.api.sharing.InvitationResponse;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.contact.ConversationRequestItem.RequestType;
+import org.briarproject.briar.api.blog.BlogInvitationRequest;
+import org.briarproject.briar.api.blog.BlogInvitationResponse;
+import org.briarproject.briar.api.client.BaseMessageHeader;
+import org.briarproject.briar.api.forum.ForumInvitationRequest;
+import org.briarproject.briar.api.forum.ForumInvitationResponse;
+import org.briarproject.briar.api.introduction.IntroductionRequest;
+import org.briarproject.briar.api.introduction.IntroductionResponse;
+import org.briarproject.briar.api.messaging.PrivateMessageHeader;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse;
+import org.briarproject.briar.api.sharing.InvitationRequest;
+import org.briarproject.briar.api.sharing.InvitationResponse;
 
+import javax.annotation.Nullable;
 import javax.annotation.concurrent.NotThreadSafe;
 
-import static org.briarproject.android.contact.ConversationRequestItem.RequestType.BLOG;
-import static org.briarproject.android.contact.ConversationRequestItem.RequestType.FORUM;
-import static org.briarproject.android.contact.ConversationRequestItem.RequestType.GROUP;
-import static org.briarproject.android.contact.ConversationRequestItem.RequestType.INTRODUCTION;
+import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.BLOG;
+import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.FORUM;
+import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.GROUP;
+import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.INTRODUCTION;
 
 @NotThreadSafe
 @NotNullByDefault
 abstract class ConversationItem {
 
 	protected @Nullable String body;
-	final private MessageId id;
-	final private GroupId groupId;
-	final private long time;
+	private final MessageId id;
+	private final GroupId groupId;
+	private final long time;
 	private boolean read;
 
 	ConversationItem(MessageId id, GroupId groupId, @Nullable String body,
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationItemViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationItemViewHolder.java
similarity index 72%
rename from briar-android/src/org/briarproject/android/contact/ConversationItemViewHolder.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationItemViewHolder.java
index 58a42951b98c2a9f8a92df2fb4969cdc5d120549..e58ed523c91d001f31d74f44be7e4f109aa4790e 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationItemViewHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationItemViewHolder.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
 import android.support.annotation.CallSuper;
 import android.support.annotation.UiThread;
@@ -7,10 +7,10 @@ import android.view.View;
 import android.view.ViewGroup;
 import android.widget.TextView;
 
-import org.briarproject.R;
-import org.briarproject.android.util.AndroidUtils;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.util.UiUtils;
 
 @UiThread
 @NotNullByDefault
@@ -36,7 +36,7 @@ class ConversationItemViewHolder extends ViewHolder {
 		}
 
 		long timestamp = item.getTime();
-		time.setText(AndroidUtils.formatDate(time.getContext(), timestamp));
+		time.setText(UiUtils.formatDate(time.getContext(), timestamp));
 	}
 
 }
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationMessageInItem.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationMessageInItem.java
similarity index 69%
rename from briar-android/src/org/briarproject/android/contact/ConversationMessageInItem.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationMessageInItem.java
index 23d8571366e27d46c2838e05c04d2cb796c078cc..4022f2f68c352d0a1339c3c5b158793648b00707 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationMessageInItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationMessageInItem.java
@@ -1,10 +1,10 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
 import android.support.annotation.LayoutRes;
 
-import org.briarproject.R;
-import org.briarproject.api.messaging.PrivateMessageHeader;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.api.messaging.PrivateMessageHeader;
 
 import javax.annotation.concurrent.NotThreadSafe;
 
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationMessageOutItem.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationMessageOutItem.java
similarity index 67%
rename from briar-android/src/org/briarproject/android/contact/ConversationMessageOutItem.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationMessageOutItem.java
index ee2d1a11b95884cb5b4aad0c117a46146b91dbec..082071c23b173435785478c3f3045d744927cd14 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationMessageOutItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationMessageOutItem.java
@@ -1,10 +1,10 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
 import android.support.annotation.LayoutRes;
 
-import org.briarproject.R;
-import org.briarproject.api.messaging.PrivateMessageHeader;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.api.messaging.PrivateMessageHeader;
 
 import javax.annotation.concurrent.NotThreadSafe;
 
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationMessageOutViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationMessageOutViewHolder.java
similarity index 83%
rename from briar-android/src/org/briarproject/android/contact/ConversationMessageOutViewHolder.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationMessageOutViewHolder.java
index 83d58dcee413315435edef53f126f4e86d8366ed..6c119a6c578136727f6f1480eeb852dea7487a53 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationMessageOutViewHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationMessageOutViewHolder.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
 import android.view.View;
 
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationNoticeInItem.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationNoticeInItem.java
similarity index 67%
rename from briar-android/src/org/briarproject/android/contact/ConversationNoticeInItem.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationNoticeInItem.java
index 0e70e66312ee213190994e40c67a7f7cef2f9c56..efbc6e4f7e3d9ad89b5176d83deb6d1096eafaf4 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationNoticeInItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationNoticeInItem.java
@@ -1,13 +1,13 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
 import android.support.annotation.LayoutRes;
 
-import org.briarproject.R;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.R;
 
+import javax.annotation.Nullable;
 import javax.annotation.concurrent.NotThreadSafe;
 
 @NotThreadSafe
@@ -25,7 +25,7 @@ class ConversationNoticeInItem extends ConversationItem {
 	}
 
 	@Nullable
-	public String getMsgText() {
+	String getMsgText() {
 		return msgText;
 	}
 
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationNoticeInViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationNoticeInViewHolder.java
similarity index 82%
rename from briar-android/src/org/briarproject/android/contact/ConversationNoticeInViewHolder.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationNoticeInViewHolder.java
index 7e5a60824db789619a1ca6323dfd9ffc867a425c..db6bbd89b3f804bd282e3780db778905f3da04e3 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationNoticeInViewHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationNoticeInViewHolder.java
@@ -1,12 +1,12 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
 import android.support.annotation.UiThread;
 import android.view.View;
 import android.widget.TextView;
 
-import org.briarproject.R;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.R;
 
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationNoticeOutItem.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationNoticeOutItem.java
similarity index 66%
rename from briar-android/src/org/briarproject/android/contact/ConversationNoticeOutItem.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationNoticeOutItem.java
index 78cddf3a766ea7a3402fa0ca1262001c7e93e56b..637c928b9348b519a4ca4b54f56f35d541c47548 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationNoticeOutItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationNoticeOutItem.java
@@ -1,13 +1,13 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
 import android.support.annotation.LayoutRes;
 
-import org.briarproject.R;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.R;
 
+import javax.annotation.Nullable;
 import javax.annotation.concurrent.NotThreadSafe;
 
 @NotThreadSafe
@@ -25,7 +25,7 @@ class ConversationNoticeOutItem extends ConversationOutItem {
 	}
 
 	@Nullable
-	public String getMsgText() {
+	String getMsgText() {
 		return msgText;
 	}
 
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationNoticeOutViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationNoticeOutViewHolder.java
similarity index 83%
rename from briar-android/src/org/briarproject/android/contact/ConversationNoticeOutViewHolder.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationNoticeOutViewHolder.java
index c0bdf7fcf758c42956bacd0b76c4c0b4869af560..504137ada8fe3caa13d60683129d0d53c46f6c96 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationNoticeOutViewHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationNoticeOutViewHolder.java
@@ -1,12 +1,12 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
 import android.support.annotation.UiThread;
 import android.view.View;
 import android.widget.TextView;
 
-import org.briarproject.R;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.R;
 
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationOutItem.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationOutItem.java
similarity index 59%
rename from briar-android/src/org/briarproject/android/contact/ConversationOutItem.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationOutItem.java
index 469f4b0f448fc5f6ad5610700cf308c00ee45b9a..e2aff0e3426d085054cc2750ca9f402c3251b7a1 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationOutItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationOutItem.java
@@ -1,10 +1,10 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
 
+import javax.annotation.Nullable;
 import javax.annotation.concurrent.NotThreadSafe;
 
 @NotThreadSafe
@@ -21,19 +21,19 @@ abstract class ConversationOutItem extends ConversationItem {
 		this.seen = seen;
 	}
 
-	public boolean isSent() {
+	boolean isSent() {
 		return sent;
 	}
 
-	public void setSent(boolean sent) {
+	void setSent(boolean sent) {
 		this.sent = sent;
 	}
 
-	public boolean isSeen() {
+	boolean isSeen() {
 		return seen;
 	}
 
-	public void setSeen(boolean seen) {
+	void setSeen(boolean seen) {
 		this.seen = seen;
 	}
 
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationOutItemViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationOutItemViewHolder.java
similarity index 87%
rename from briar-android/src/org/briarproject/android/contact/ConversationOutItemViewHolder.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationOutItemViewHolder.java
index 4c10ba402499c155e48d70fa40202b96ef1b018e..8e5bf264da3c7be9ab5861c6f13cc77ec13bd222 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationOutItemViewHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationOutItemViewHolder.java
@@ -1,11 +1,11 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
 import android.support.annotation.UiThread;
 import android.view.View;
 import android.widget.ImageView;
 
-import org.briarproject.R;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.R;
 
 @UiThread
 @NotNullByDefault
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationRequestItem.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationRequestItem.java
similarity index 67%
rename from briar-android/src/org/briarproject/android/contact/ConversationRequestItem.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationRequestItem.java
index f0a1cb08b40fdd73c909bae2a0912fdde6ab3c6c..3dd8dd721baf0cb58ac5909a02a477d9b22dcacc 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationRequestItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationRequestItem.java
@@ -1,21 +1,22 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
 import android.support.annotation.LayoutRes;
 
-import org.briarproject.R;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.api.client.SessionId;
 
+import javax.annotation.Nullable;
 import javax.annotation.concurrent.NotThreadSafe;
 
 @NotThreadSafe
 @NotNullByDefault
 class ConversationRequestItem extends ConversationNoticeInItem {
 
-	enum RequestType { INTRODUCTION, FORUM, BLOG, GROUP };
+	enum RequestType { INTRODUCTION, FORUM, BLOG, GROUP }
+
 	private final RequestType requestType;
 	private final SessionId sessionId;
 	private boolean answered;
@@ -30,11 +31,11 @@ class ConversationRequestItem extends ConversationNoticeInItem {
 		this.answered = answered;
 	}
 
-	public RequestType getRequestType() {
+	RequestType getRequestType() {
 		return requestType;
 	}
 
-	public SessionId getSessionId() {
+	SessionId getSessionId() {
 		return sessionId;
 	}
 
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationRequestViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationRequestViewHolder.java
similarity index 85%
rename from briar-android/src/org/briarproject/android/contact/ConversationRequestViewHolder.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationRequestViewHolder.java
index 4aa5fc3cbaf90b44da5f724a3642ac28b1ce3bf3..663e0394d27faf6edc05603380b367a0cb78535a 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationRequestViewHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationRequestViewHolder.java
@@ -1,13 +1,13 @@
-package org.briarproject.android.contact;
+package org.briarproject.briar.android.contact;
 
 import android.support.annotation.UiThread;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.Button;
 
-import org.briarproject.R;
-import org.briarproject.android.contact.ConversationAdapter.ConversationListener;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.contact.ConversationAdapter.ConversationListener;
 
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
diff --git a/briar-android/src/org/briarproject/android/contactselection/BaseContactSelectorAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseContactSelectorAdapter.java
similarity index 69%
rename from briar-android/src/org/briarproject/android/contactselection/BaseContactSelectorAdapter.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseContactSelectorAdapter.java
index c9e287b867297040f6a8e33502c350d71554251b..f6252717e041cd9718303da6bbf65af7df07abce 100644
--- a/briar-android/src/org/briarproject/android/contactselection/BaseContactSelectorAdapter.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseContactSelectorAdapter.java
@@ -1,11 +1,11 @@
-package org.briarproject.android.contactselection;
+package org.briarproject.briar.android.contactselection;
 
 import android.content.Context;
 
-import org.briarproject.android.contact.BaseContactListAdapter;
-import org.briarproject.android.contact.ContactItemViewHolder;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.android.contact.BaseContactListAdapter;
+import org.briarproject.briar.android.contact.ContactItemViewHolder;
 
 import java.util.ArrayList;
 import java.util.Collection;
diff --git a/briar-android/src/org/briarproject/android/contactselection/BaseContactSelectorFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseContactSelectorFragment.java
similarity index 74%
rename from briar-android/src/org/briarproject/android/contactselection/BaseContactSelectorFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseContactSelectorFragment.java
index fc1f400f296f1235eea60d9a392eb4f3f450fac2..1c9294fe297e3b0176fc499809ad78edd8547d15 100644
--- a/briar-android/src/org/briarproject/android/contactselection/BaseContactSelectorFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseContactSelectorFragment.java
@@ -1,35 +1,36 @@
-package org.briarproject.android.contactselection;
+package org.briarproject.briar.android.contactselection;
 
 import android.content.Context;
 import android.os.Build;
 import android.os.Bundle;
 import android.support.annotation.CallSuper;
-import android.support.annotation.Nullable;
 import android.support.v7.widget.LinearLayoutManager;
 import android.transition.Fade;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
-import org.briarproject.R;
-import org.briarproject.android.contact.BaseContactListAdapter.OnContactClickListener;
-import org.briarproject.android.contact.ContactItemViewHolder;
-import org.briarproject.android.controller.handler.UiResultExceptionHandler;
-import org.briarproject.android.fragment.BaseFragment;
-import org.briarproject.android.view.BriarRecyclerView;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.contact.BaseContactListAdapter.OnContactClickListener;
+import org.briarproject.briar.android.contact.ContactItemViewHolder;
+import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
+import org.briarproject.briar.android.fragment.BaseFragment;
+import org.briarproject.briar.android.view.BriarRecyclerView;
 
 import java.util.ArrayList;
 import java.util.Collection;
 
-import static org.briarproject.android.BriarActivity.GROUP_ID;
-import static org.briarproject.android.contactselection.ContactSelectorActivity.CONTACTS;
-import static org.briarproject.android.contactselection.ContactSelectorActivity.getContactsFromIds;
-import static org.briarproject.android.contactselection.ContactSelectorActivity.getContactsFromIntegers;
+import javax.annotation.Nullable;
+
+import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
+import static org.briarproject.briar.android.contactselection.ContactSelectorActivity.CONTACTS;
+import static org.briarproject.briar.android.contactselection.ContactSelectorActivity.getContactsFromIds;
+import static org.briarproject.briar.android.contactselection.ContactSelectorActivity.getContactsFromIntegers;
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
diff --git a/briar-android/src/org/briarproject/android/contactselection/BaseSelectableContactHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseSelectableContactHolder.java
similarity index 71%
rename from briar-android/src/org/briarproject/android/contactselection/BaseSelectableContactHolder.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseSelectableContactHolder.java
index d0b57f1328035813e5f95f78b2e0cbe65b5933bb..e0fe9a688e13aa7e772b76ea2596a44707135269 100644
--- a/briar-android/src/org/briarproject/android/contactselection/BaseSelectableContactHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/BaseSelectableContactHolder.java
@@ -1,17 +1,18 @@
-package org.briarproject.android.contactselection;
+package org.briarproject.briar.android.contactselection;
 
 import android.support.annotation.UiThread;
 import android.view.View;
 import android.widget.CheckBox;
 import android.widget.TextView;
 
-import org.briarproject.R;
-import org.briarproject.android.contact.BaseContactListAdapter.OnContactClickListener;
-import org.briarproject.android.contact.ContactItemViewHolder;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.contact.BaseContactListAdapter.OnContactClickListener;
+import org.briarproject.briar.android.contact.ContactItemViewHolder;
 
-import static org.briarproject.android.util.AndroidUtils.GREY_OUT;
+import javax.annotation.Nullable;
+
+import static org.briarproject.briar.android.util.UiUtils.GREY_OUT;
 
 @UiThread
 @NotNullByDefault
diff --git a/briar-android/src/org/briarproject/android/contactselection/ContactSelectorActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorActivity.java
similarity index 83%
rename from briar-android/src/org/briarproject/android/contactselection/ContactSelectorActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorActivity.java
index d61545f96e60a7bf200d914fef51b95742257f86..2eaaecbafe773d103ad53cb5644cbb36285b0600 100644
--- a/briar-android/src/org/briarproject/android/contactselection/ContactSelectorActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorActivity.java
@@ -1,25 +1,26 @@
-package org.briarproject.android.contactselection;
+package org.briarproject.briar.android.contactselection;
 
 import android.os.Build;
 import android.os.Bundle;
 import android.support.annotation.CallSuper;
 import android.support.annotation.LayoutRes;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.transition.Fade;
 
-import org.briarproject.R;
-import org.briarproject.android.BriarActivity;
-import org.briarproject.android.fragment.BaseFragment.BaseFragmentListener;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.BriarActivity;
+import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
 
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
+import javax.annotation.Nullable;
+
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
 public abstract class ContactSelectorActivity
diff --git a/briar-android/src/org/briarproject/android/contactselection/ContactSelectorAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorAdapter.java
similarity index 76%
rename from briar-android/src/org/briarproject/android/contactselection/ContactSelectorAdapter.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorAdapter.java
index 1b681679d15c5deeaf1843f4abac4b0443a4233f..39144d3d68a25beb2db9874c3fd82421669a2a67 100644
--- a/briar-android/src/org/briarproject/android/contactselection/ContactSelectorAdapter.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorAdapter.java
@@ -1,15 +1,15 @@
-package org.briarproject.android.contactselection;
+package org.briarproject.briar.android.contactselection;
 
 import android.content.Context;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
-import org.briarproject.R;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.R;
 
 @NotNullByDefault
-public class ContactSelectorAdapter extends
+class ContactSelectorAdapter extends
 		BaseContactSelectorAdapter<SelectableContactItem, SelectableContactHolder> {
 
 	ContactSelectorAdapter(Context context,
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorController.java b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorController.java
new file mode 100644
index 0000000000000000000000000000000000000000..778a0385334fd1ca1fd4a3e6856089d8c69e6b5a
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorController.java
@@ -0,0 +1,19 @@
+package org.briarproject.briar.android.contactselection;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.android.controller.DbController;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
+
+import java.util.Collection;
+
+@NotNullByDefault
+public interface ContactSelectorController<I extends SelectableContactItem>
+		extends DbController {
+
+	void loadContacts(GroupId g, Collection<ContactId> selection,
+			ResultExceptionHandler<Collection<I>, DbException> handler);
+
+}
diff --git a/briar-android/src/org/briarproject/android/contactselection/ContactSelectorControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorControllerImpl.java
similarity index 72%
rename from briar-android/src/org/briarproject/android/contactselection/ContactSelectorControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorControllerImpl.java
index aa198e35febee317ee54074b87af691d7cb8a042..3cd744d1545ffc967d46cb92db64760eba72c70a 100644
--- a/briar-android/src/org/briarproject/android/contactselection/ContactSelectorControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorControllerImpl.java
@@ -1,15 +1,15 @@
-package org.briarproject.android.contactselection;
+package org.briarproject.briar.android.contactselection;
 
-import org.briarproject.android.controller.DbControllerImpl;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.android.controller.DbControllerImpl;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
 
 import java.util.ArrayList;
 import java.util.Collection;
diff --git a/briar-android/src/org/briarproject/android/contactselection/ContactSelectorFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorFragment.java
similarity index 83%
rename from briar-android/src/org/briarproject/android/contactselection/ContactSelectorFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorFragment.java
index 0e24b157d0675e1db1fc3e2e5c8cadcac700a174..07908ac8b87662f6bdacbe0c938387e213ddc407 100644
--- a/briar-android/src/org/briarproject/android/contactselection/ContactSelectorFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorFragment.java
@@ -1,14 +1,14 @@
-package org.briarproject.android.contactselection;
+package org.briarproject.briar.android.contactselection;
 
 import android.content.Context;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 
-import org.briarproject.R;
-import org.briarproject.android.contact.BaseContactListAdapter.OnContactClickListener;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.contact.BaseContactListAdapter.OnContactClickListener;
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
diff --git a/briar-android/src/org/briarproject/android/contactselection/ContactSelectorListener.java b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorListener.java
similarity index 50%
rename from briar-android/src/org/briarproject/android/contactselection/ContactSelectorListener.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorListener.java
index b844c35f64024c2b90881cc7ceba7cf9dc42af8d..ec9cb0040dca3ea144298a2855d4f6306ffb2e3b 100644
--- a/briar-android/src/org/briarproject/android/contactselection/ContactSelectorListener.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorListener.java
@@ -1,10 +1,10 @@
-package org.briarproject.android.contactselection;
+package org.briarproject.briar.android.contactselection;
 
 import android.support.annotation.UiThread;
 
-import org.briarproject.android.DestroyableContext;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.android.DestroyableContext;
 
 import java.util.Collection;
 
diff --git a/briar-android/src/org/briarproject/android/contactselection/SelectableContactHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/SelectableContactHolder.java
similarity index 62%
rename from briar-android/src/org/briarproject/android/contactselection/SelectableContactHolder.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contactselection/SelectableContactHolder.java
index 0ab5ecc4d66d14d99865c759c664785d47c55214..b4435d6cf0fa9b83b87c5866933fa95e6fdb0178 100644
--- a/briar-android/src/org/briarproject/android/contactselection/SelectableContactHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/SelectableContactHolder.java
@@ -1,19 +1,19 @@
-package org.briarproject.android.contactselection;
+package org.briarproject.briar.android.contactselection;
 
 import android.support.annotation.UiThread;
 import android.view.View;
 
-import org.briarproject.android.contact.BaseContactListAdapter;
-import org.briarproject.android.contact.BaseContactListAdapter.OnContactClickListener;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.android.contact.BaseContactListAdapter.OnContactClickListener;
+
+import javax.annotation.Nullable;
 
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
 
 @UiThread
 @NotNullByDefault
-public class SelectableContactHolder
+class SelectableContactHolder
 		extends BaseSelectableContactHolder<SelectableContactItem> {
 
 	SelectableContactHolder(View v) {
diff --git a/briar-android/src/org/briarproject/android/contactselection/SelectableContactItem.java b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/SelectableContactItem.java
similarity index 68%
rename from briar-android/src/org/briarproject/android/contactselection/SelectableContactItem.java
rename to briar-android/src/main/java/org/briarproject/briar/android/contactselection/SelectableContactItem.java
index b11da75a10aff2e3c3c301f436c635c0e0930d4b..d2a53a2a42b05c031df1130cdc2bad6de8764778 100644
--- a/briar-android/src/org/briarproject/android/contactselection/SelectableContactItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contactselection/SelectableContactItem.java
@@ -1,8 +1,8 @@
-package org.briarproject.android.contactselection;
+package org.briarproject.briar.android.contactselection;
 
-import org.briarproject.android.contact.ContactItem;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.android.contact.ContactItem;
 
 import javax.annotation.concurrent.NotThreadSafe;
 
diff --git a/briar-android/src/org/briarproject/android/controller/ActivityLifecycleController.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/ActivityLifecycleController.java
similarity index 79%
rename from briar-android/src/org/briarproject/android/controller/ActivityLifecycleController.java
rename to briar-android/src/main/java/org/briarproject/briar/android/controller/ActivityLifecycleController.java
index 96d0cf4f0201539b39c35974db08e8b7be60dacb..edcb7456bec4f2b463b1f5feefd1a58d7c72e21b 100644
--- a/briar-android/src/org/briarproject/android/controller/ActivityLifecycleController.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/ActivityLifecycleController.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.controller;
+package org.briarproject.briar.android.controller;
 
 import android.app.Activity;
 
diff --git a/briar-android/src/org/briarproject/android/controller/BriarController.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/BriarController.java
similarity index 60%
rename from briar-android/src/org/briarproject/android/controller/BriarController.java
rename to briar-android/src/main/java/org/briarproject/briar/android/controller/BriarController.java
index cbb61cde1e58c3b94d0005ed0fc398bef24f7dde..38c1ca93b871a33e551bbafc4811cac86ade257e 100644
--- a/briar-android/src/org/briarproject/android/controller/BriarController.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/BriarController.java
@@ -1,6 +1,6 @@
-package org.briarproject.android.controller;
+package org.briarproject.briar.android.controller;
 
-import org.briarproject.android.controller.handler.ResultHandler;
+import org.briarproject.briar.android.controller.handler.ResultHandler;
 
 public interface BriarController extends ActivityLifecycleController {
 
diff --git a/briar-android/src/org/briarproject/android/controller/BriarControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/BriarControllerImpl.java
similarity index 87%
rename from briar-android/src/org/briarproject/android/controller/BriarControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/controller/BriarControllerImpl.java
index f49d6485f7b58e4673e06f4f40e1125275e85610..3d15ff7a2f6bca39d9d81e9ae11ac1ed5485920e 100644
--- a/briar-android/src/org/briarproject/android/controller/BriarControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/BriarControllerImpl.java
@@ -1,14 +1,14 @@
-package org.briarproject.android.controller;
+package org.briarproject.briar.android.controller;
 
 import android.app.Activity;
 import android.content.Intent;
 import android.os.IBinder;
 import android.support.annotation.CallSuper;
 
-import org.briarproject.android.BriarService;
-import org.briarproject.android.BriarService.BriarServiceConnection;
-import org.briarproject.android.controller.handler.ResultHandler;
-import org.briarproject.api.db.DatabaseConfig;
+import org.briarproject.bramble.api.db.DatabaseConfig;
+import org.briarproject.briar.android.BriarService;
+import org.briarproject.briar.android.BriarService.BriarServiceConnection;
+import org.briarproject.briar.android.controller.handler.ResultHandler;
 
 import java.util.logging.Logger;
 
diff --git a/briar-android/src/org/briarproject/android/controller/ConfigController.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigController.java
similarity index 54%
rename from briar-android/src/org/briarproject/android/controller/ConfigController.java
rename to briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigController.java
index 7ce5233033d1726246102e0601524435bf72c1fa..d6bc554f6ee29d356e0e70d68f5a56f60b6a15d1 100644
--- a/briar-android/src/org/briarproject/android/controller/ConfigController.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigController.java
@@ -1,9 +1,15 @@
-package org.briarproject.android.controller;
+package org.briarproject.briar.android.controller;
 
 import android.content.Context;
 
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.Nullable;
+
+@NotNullByDefault
 public interface ConfigController {
 
+	@Nullable
 	String getEncryptedDatabaseKey();
 
 	void storeEncryptedDatabaseKey(String hex);
diff --git a/briar-android/src/org/briarproject/android/controller/ConfigControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigControllerImpl.java
similarity index 75%
rename from briar-android/src/org/briarproject/android/controller/ConfigControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigControllerImpl.java
index 33ca3253266ee188052b85790222f2460cb79176..0af60bb981d993699630a665699b2dfbf769aef4 100644
--- a/briar-android/src/org/briarproject/android/controller/ConfigControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigControllerImpl.java
@@ -1,13 +1,16 @@
-package org.briarproject.android.controller;
+package org.briarproject.briar.android.controller;
 
 import android.content.Context;
 import android.content.SharedPreferences;
 
-import org.briarproject.android.util.AndroidUtils;
-import org.briarproject.api.db.DatabaseConfig;
+import org.briarproject.bramble.api.db.DatabaseConfig;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.util.AndroidUtils;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
+@NotNullByDefault
 public class ConfigControllerImpl implements ConfigController {
 
 	private static final String PREF_DB_KEY = "key";
@@ -16,7 +19,7 @@ public class ConfigControllerImpl implements ConfigController {
 	protected final DatabaseConfig databaseConfig;
 
 	@Inject
-	ConfigControllerImpl(SharedPreferences briarPrefs,
+	public ConfigControllerImpl(SharedPreferences briarPrefs,
 			DatabaseConfig databaseConfig) {
 		this.briarPrefs = briarPrefs;
 		this.databaseConfig = databaseConfig;
@@ -24,6 +27,7 @@ public class ConfigControllerImpl implements ConfigController {
 	}
 
 	@Override
+	@Nullable
 	public String getEncryptedDatabaseKey() {
 		return briarPrefs.getString(PREF_DB_KEY, null);
 	}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/controller/DbController.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/DbController.java
new file mode 100644
index 0000000000000000000000000000000000000000..8f9fc3be1f318feaf459d194db7ffcb5709aa75b
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/DbController.java
@@ -0,0 +1,9 @@
+package org.briarproject.briar.android.controller;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+public interface DbController {
+
+	void runOnDbThread(Runnable task);
+}
diff --git a/briar-android/src/org/briarproject/android/controller/DbControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/DbControllerImpl.java
similarity index 74%
rename from briar-android/src/org/briarproject/android/controller/DbControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/controller/DbControllerImpl.java
index c13576819e54795b8a0606711918b16d62ac8413..eaeb7a06ec1c15fbc58e42a2d27c03bb8124eda8 100644
--- a/briar-android/src/org/briarproject/android/controller/DbControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/DbControllerImpl.java
@@ -1,13 +1,17 @@
-package org.briarproject.android.controller;
+package org.briarproject.briar.android.controller;
 
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.util.concurrent.Executor;
 import java.util.logging.Logger;
 
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
+@Immutable
+@NotNullByDefault
 public class DbControllerImpl implements DbController {
 
 	private static final Logger LOG =
diff --git a/briar-android/src/org/briarproject/android/controller/handler/ExceptionHandler.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/handler/ExceptionHandler.java
similarity index 61%
rename from briar-android/src/org/briarproject/android/controller/handler/ExceptionHandler.java
rename to briar-android/src/main/java/org/briarproject/briar/android/controller/handler/ExceptionHandler.java
index 6d8719a64833f07c26d26e0179d761d80d5d926e..d283a39f65ab7a4f77e81d75bfeb0c5227993cab 100644
--- a/briar-android/src/org/briarproject/android/controller/handler/ExceptionHandler.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/handler/ExceptionHandler.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.controller.handler;
+package org.briarproject.briar.android.controller.handler;
 
 public interface ExceptionHandler<E extends Exception> {
 
diff --git a/briar-android/src/org/briarproject/android/controller/handler/ResultExceptionHandler.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/handler/ResultExceptionHandler.java
similarity index 68%
rename from briar-android/src/org/briarproject/android/controller/handler/ResultExceptionHandler.java
rename to briar-android/src/main/java/org/briarproject/briar/android/controller/handler/ResultExceptionHandler.java
index b8346a565ff84ab3ad9ef37c38dd731538e6e90a..a3cd15adf78dc89fb0fd44c1bc7ccb2fc105d5ef 100644
--- a/briar-android/src/org/briarproject/android/controller/handler/ResultExceptionHandler.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/handler/ResultExceptionHandler.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.controller.handler;
+package org.briarproject.briar.android.controller.handler;
 
 public interface ResultExceptionHandler<R, E extends Exception>
 		extends ExceptionHandler<E> {
diff --git a/briar-android/src/org/briarproject/android/controller/handler/ResultHandler.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/handler/ResultHandler.java
similarity index 52%
rename from briar-android/src/org/briarproject/android/controller/handler/ResultHandler.java
rename to briar-android/src/main/java/org/briarproject/briar/android/controller/handler/ResultHandler.java
index 601ff294d50136b9f0b705075e15c6fd824ade86..5d11a6a919e29c0d350ab314c38cd346d784d8e6 100644
--- a/briar-android/src/org/briarproject/android/controller/handler/ResultHandler.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/handler/ResultHandler.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.controller.handler;
+package org.briarproject.briar.android.controller.handler;
 
 public interface ResultHandler<R> {
 
diff --git a/briar-android/src/org/briarproject/android/controller/handler/UiExceptionHandler.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/handler/UiExceptionHandler.java
similarity index 77%
rename from briar-android/src/org/briarproject/android/controller/handler/UiExceptionHandler.java
rename to briar-android/src/main/java/org/briarproject/briar/android/controller/handler/UiExceptionHandler.java
index 90db65fcd38d71e7897f2bfa43643021adf00777..98ea082ee30eba673a791aa0ba39f0fafb540eb6 100644
--- a/briar-android/src/org/briarproject/android/controller/handler/UiExceptionHandler.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/handler/UiExceptionHandler.java
@@ -1,9 +1,9 @@
-package org.briarproject.android.controller.handler;
+package org.briarproject.briar.android.controller.handler;
 
 import android.support.annotation.UiThread;
 
-import org.briarproject.android.DestroyableContext;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.android.DestroyableContext;
 
 import javax.annotation.concurrent.Immutable;
 
diff --git a/briar-android/src/org/briarproject/android/controller/handler/UiResultExceptionHandler.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/handler/UiResultExceptionHandler.java
similarity index 76%
rename from briar-android/src/org/briarproject/android/controller/handler/UiResultExceptionHandler.java
rename to briar-android/src/main/java/org/briarproject/briar/android/controller/handler/UiResultExceptionHandler.java
index 8fd4ab4fc9b9ea7d650848f891f6f254c3b48323..d3ee2d7c83453c65eade3d0240e20231c1279673 100644
--- a/briar-android/src/org/briarproject/android/controller/handler/UiResultExceptionHandler.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/handler/UiResultExceptionHandler.java
@@ -1,9 +1,9 @@
-package org.briarproject.android.controller.handler;
+package org.briarproject.briar.android.controller.handler;
 
 import android.support.annotation.UiThread;
 
-import org.briarproject.android.DestroyableContext;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.android.DestroyableContext;
 
 import javax.annotation.concurrent.Immutable;
 
diff --git a/briar-android/src/org/briarproject/android/controller/handler/UiResultHandler.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/handler/UiResultHandler.java
similarity index 80%
rename from briar-android/src/org/briarproject/android/controller/handler/UiResultHandler.java
rename to briar-android/src/main/java/org/briarproject/briar/android/controller/handler/UiResultHandler.java
index 6516ff71519886c95f732f51a80cd900915809d0..89bd919d4d6e85c831d681d3e5cdac692c83df7d 100644
--- a/briar-android/src/org/briarproject/android/controller/handler/UiResultHandler.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/handler/UiResultHandler.java
@@ -1,8 +1,8 @@
-package org.briarproject.android.controller.handler;
+package org.briarproject.briar.android.controller.handler;
 
 import android.support.annotation.UiThread;
 
-import org.briarproject.android.DestroyableContext;
+import org.briarproject.briar.android.DestroyableContext;
 
 public abstract class UiResultHandler<R> implements ResultHandler<R> {
 
diff --git a/briar-android/src/org/briarproject/android/forum/CreateForumActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/forum/CreateForumActivity.java
similarity index 83%
rename from briar-android/src/org/briarproject/android/forum/CreateForumActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/forum/CreateForumActivity.java
index 4c902459998fd68ce540933aa72f1295869b2c34..86822c7a2a53fe6eb5fc1e26dd0c67af134f278b 100644
--- a/briar-android/src/org/briarproject/android/forum/CreateForumActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/forum/CreateForumActivity.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.forum;
+package org.briarproject.briar.android.forum;
 
 import android.content.Intent;
 import android.os.Bundle;
@@ -14,16 +14,19 @@ import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
 import android.widget.Toast;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.BriarActivity;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BriarActivity;
+import org.briarproject.briar.api.forum.Forum;
+import org.briarproject.briar.api.forum.ForumManager;
 
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import static android.view.View.GONE;
@@ -31,8 +34,10 @@ import static android.view.View.VISIBLE;
 import static android.widget.Toast.LENGTH_LONG;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
+import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 public class CreateForumActivity extends BriarActivity
 		implements OnEditorActionListener, OnClickListener {
 
@@ -49,7 +54,7 @@ public class CreateForumActivity extends BriarActivity
 	protected volatile ForumManager forumManager;
 
 	@Override
-	public void onCreate(Bundle state) {
+	public void onCreate(@Nullable Bundle state) {
 		super.onCreate(state);
 
 		setContentView(R.layout.activity_create_forum);
diff --git a/briar-android/src/org/briarproject/android/forum/ForumActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumActivity.java
similarity index 83%
rename from briar-android/src/org/briarproject/android/forum/ForumActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/forum/ForumActivity.java
index 0fe164367f3e1b8c26bd18f64e15ad88d59e8cf9..ad961043d48e52dfdbd112b89289550af27cc457 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumActivity.java
@@ -1,11 +1,10 @@
-package org.briarproject.android.forum;
+package org.briarproject.briar.android.forum;
 
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
 import android.content.Intent;
 import android.os.Bundle;
 import android.support.annotation.LayoutRes;
-import android.support.annotation.Nullable;
 import android.support.annotation.StringRes;
 import android.support.v4.app.ActivityCompat;
 import android.support.v4.app.ActivityOptionsCompat;
@@ -16,27 +15,28 @@ import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.widget.Toast;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.controller.handler.UiResultExceptionHandler;
-import org.briarproject.android.sharing.ForumSharingStatusActivity;
-import org.briarproject.android.sharing.ShareForumActivity;
-import org.briarproject.android.threaded.ThreadItemAdapter;
-import org.briarproject.android.threaded.ThreadListActivity;
-import org.briarproject.android.threaded.ThreadListController;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumPostHeader;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
+import org.briarproject.briar.android.sharing.ForumSharingStatusActivity;
+import org.briarproject.briar.android.sharing.ShareForumActivity;
+import org.briarproject.briar.android.threaded.ThreadItemAdapter;
+import org.briarproject.briar.android.threaded.ThreadListActivity;
+import org.briarproject.briar.android.threaded.ThreadListController;
+import org.briarproject.briar.api.forum.Forum;
+import org.briarproject.briar.api.forum.ForumPostHeader;
+
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
 import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
 import static android.support.v4.app.ActivityOptionsCompat.makeCustomAnimation;
 import static android.widget.Toast.LENGTH_SHORT;
-import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
+import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumController.java b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumController.java
new file mode 100644
index 0000000000000000000000000000000000000000..8b99ab1741f6341cd1e6750b11d86bb3c2d9e81b
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumController.java
@@ -0,0 +1,12 @@
+package org.briarproject.briar.android.forum;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.android.threaded.ThreadListController;
+import org.briarproject.briar.api.forum.Forum;
+import org.briarproject.briar.api.forum.ForumPostHeader;
+
+@NotNullByDefault
+interface ForumController
+		extends ThreadListController<Forum, ForumItem, ForumPostHeader> {
+
+}
diff --git a/briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumControllerImpl.java
similarity index 70%
rename from briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/forum/ForumControllerImpl.java
index 7cc859614d2f8e2d5b58a21dc3c5067753cd89c8..3b9f91f6178b23a2e086727d2493b26beeddf189 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumControllerImpl.java
@@ -1,39 +1,40 @@
-package org.briarproject.android.forum;
-
-import android.support.annotation.Nullable;
-
-import org.briarproject.android.api.AndroidNotificationManager;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.android.threaded.ThreadListController.ThreadListListener;
-import org.briarproject.android.threaded.ThreadListControllerImpl;
-import org.briarproject.api.clients.MessageTracker.GroupCount;
-import org.briarproject.api.crypto.CryptoExecutor;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.ForumPostReceivedEvent;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.forum.ForumPost;
-import org.briarproject.api.forum.ForumPostHeader;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.system.Clock;
+package org.briarproject.briar.android.forum;
+
+import org.briarproject.bramble.api.crypto.CryptoExecutor;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.briar.android.threaded.ThreadListController.ThreadListListener;
+import org.briarproject.briar.android.threaded.ThreadListControllerImpl;
+import org.briarproject.briar.api.android.AndroidNotificationManager;
+import org.briarproject.briar.api.client.MessageTracker.GroupCount;
+import org.briarproject.briar.api.forum.Forum;
+import org.briarproject.briar.api.forum.ForumManager;
+import org.briarproject.briar.api.forum.ForumPost;
+import org.briarproject.briar.api.forum.ForumPostHeader;
+import org.briarproject.briar.api.forum.event.ForumPostReceivedEvent;
 
 import java.util.Collection;
 import java.util.concurrent.Executor;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import static java.lang.Math.max;
 import static java.util.logging.Level.WARNING;
 
-class ForumControllerImpl
-		extends ThreadListControllerImpl<Forum, ForumItem, ForumPostHeader, ForumPost, ThreadListListener<ForumPostHeader>>
+@NotNullByDefault
+class ForumControllerImpl extends
+		ThreadListControllerImpl<Forum, ForumItem, ForumPostHeader, ForumPost, ThreadListListener<ForumPostHeader>>
 		implements ForumController {
 
 	private static final Logger LOG =
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumItem.java b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumItem.java
new file mode 100644
index 0000000000000000000000000000000000000000..51070e9068b0454b5d0be3aa183f210b3c00abc8
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumItem.java
@@ -0,0 +1,25 @@
+package org.briarproject.briar.android.forum;
+
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.android.threaded.ThreadItem;
+import org.briarproject.briar.api.forum.ForumPostHeader;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.NotThreadSafe;
+
+@NotThreadSafe
+class ForumItem extends ThreadItem {
+
+	ForumItem(ForumPostHeader h, String body) {
+		super(h.getId(), h.getParentId(), body, h.getTimestamp(), h.getAuthor(),
+				h.getAuthorStatus(), h.isRead());
+	}
+
+	ForumItem(MessageId messageId, @Nullable MessageId parentId, String text,
+			long timestamp, Author author, Status status) {
+		super(messageId, parentId, text, timestamp, author, status, true);
+	}
+
+}
diff --git a/briar-android/src/org/briarproject/android/forum/ForumListAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumListAdapter.java
similarity index 87%
rename from briar-android/src/org/briarproject/android/forum/ForumListAdapter.java
rename to briar-android/src/main/java/org/briarproject/briar/android/forum/ForumListAdapter.java
index 040b81662b884d6394d67fdcdc8b16ea31ea489d..46d8007fbe6a2868035e067e36c5cf78b2b69582 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumListAdapter.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumListAdapter.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.forum;
+package org.briarproject.briar.android.forum;
 
 import android.content.Context;
 import android.content.Intent;
@@ -9,18 +9,18 @@ import android.view.View;
 import android.view.ViewGroup;
 import android.widget.TextView;
 
-import org.briarproject.R;
-import org.briarproject.android.util.AndroidUtils;
-import org.briarproject.android.util.BriarAdapter;
-import org.briarproject.android.view.TextAvatarView;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.util.BriarAdapter;
+import org.briarproject.briar.android.util.UiUtils;
+import org.briarproject.briar.android.view.TextAvatarView;
+import org.briarproject.briar.api.forum.Forum;
 
 import static android.support.v7.util.SortedList.INVALID_POSITION;
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
-import static org.briarproject.android.BriarActivity.GROUP_ID;
-import static org.briarproject.android.BriarActivity.GROUP_NAME;
+import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
+import static org.briarproject.briar.android.activity.BriarActivity.GROUP_NAME;
 
 class ForumListAdapter
 		extends BriarAdapter<ForumListItem, ForumListAdapter.ForumViewHolder> {
@@ -72,7 +72,7 @@ class ForumListAdapter
 			ui.date.setVisibility(GONE);
 		} else {
 			long timestamp = item.getTimestamp();
-			ui.date.setText(AndroidUtils.formatDate(ctx, timestamp));
+			ui.date.setText(UiUtils.formatDate(ctx, timestamp));
 			ui.date.setVisibility(VISIBLE);
 		}
 
diff --git a/briar-android/src/org/briarproject/android/forum/ForumListFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumListFragment.java
similarity index 80%
rename from briar-android/src/org/briarproject/android/forum/ForumListFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/forum/ForumListFragment.java
index 9fb886f43551b36319678589eba46feccfd062d5..5b40f28dc728440f31f0c6785371fc633e7cf50e 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumListFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumListFragment.java
@@ -1,8 +1,7 @@
-package org.briarproject.android.forum;
+package org.briarproject.briar.android.forum;
 
 import android.content.Intent;
 import android.os.Bundle;
-import android.support.annotation.Nullable;
 import android.support.design.widget.Snackbar;
 import android.support.v4.content.ContextCompat;
 import android.support.v7.widget.LinearLayoutManager;
@@ -14,38 +13,43 @@ import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.api.AndroidNotificationManager;
-import org.briarproject.android.fragment.BaseEventFragment;
-import org.briarproject.android.sharing.ForumInvitationActivity;
-import org.briarproject.android.view.BriarRecyclerView;
-import org.briarproject.api.clients.MessageTracker.GroupCount;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.NoSuchGroupException;
-import org.briarproject.api.event.ContactRemovedEvent;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.ForumInvitationReceivedEvent;
-import org.briarproject.api.event.ForumPostReceivedEvent;
-import org.briarproject.api.event.GroupAddedEvent;
-import org.briarproject.api.event.GroupRemovedEvent;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.forum.ForumPostHeader;
-import org.briarproject.api.forum.ForumSharingManager;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.NoSuchGroupException;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.event.GroupAddedEvent;
+import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.fragment.BaseEventFragment;
+import org.briarproject.briar.android.sharing.ForumInvitationActivity;
+import org.briarproject.briar.android.view.BriarRecyclerView;
+import org.briarproject.briar.api.android.AndroidNotificationManager;
+import org.briarproject.briar.api.client.MessageTracker.GroupCount;
+import org.briarproject.briar.api.forum.Forum;
+import org.briarproject.briar.api.forum.ForumManager;
+import org.briarproject.briar.api.forum.ForumPostHeader;
+import org.briarproject.briar.api.forum.ForumSharingManager;
+import org.briarproject.briar.api.forum.event.ForumInvitationRequestReceivedEvent;
+import org.briarproject.briar.api.forum.event.ForumPostReceivedEvent;
 
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import static android.support.design.widget.Snackbar.LENGTH_INDEFINITE;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.forum.ForumManager.CLIENT_ID;
+import static org.briarproject.briar.api.forum.ForumManager.CLIENT_ID;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 public class ForumListFragment extends BaseEventFragment implements
 		OnClickListener {
 
@@ -76,8 +80,9 @@ public class ForumListFragment extends BaseEventFragment implements
 
 	@Nullable
 	@Override
-	public View onCreateView(LayoutInflater inflater, ViewGroup container,
-			Bundle savedInstanceState) {
+	public View onCreateView(LayoutInflater inflater,
+			@Nullable ViewGroup container,
+			@Nullable Bundle savedInstanceState) {
 
 		View contentView =
 				inflater.inflate(R.layout.fragment_forum_list, container,
@@ -251,7 +256,7 @@ public class ForumListFragment extends BaseEventFragment implements
 			ForumPostReceivedEvent f = (ForumPostReceivedEvent) e;
 			LOG.info("Forum post added, updating item");
 			updateItem(f.getGroupId(), f.getForumPostHeader());
-		} else if (e instanceof ForumInvitationReceivedEvent) {
+		} else if (e instanceof ForumInvitationRequestReceivedEvent) {
 			LOG.info("Forum invitation received, reloading available forums");
 			loadAvailableForums();
 		}
diff --git a/briar-android/src/org/briarproject/android/forum/ForumListItem.java b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumListItem.java
similarity index 76%
rename from briar-android/src/org/briarproject/android/forum/ForumListItem.java
rename to briar-android/src/main/java/org/briarproject/briar/android/forum/ForumListItem.java
index 281eb64b41fbffee6b382abfb97322134d10a2bf..5341d3f1f8f2b106b01111a29c150f391faa9976 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumListItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumListItem.java
@@ -1,8 +1,8 @@
-package org.briarproject.android.forum;
+package org.briarproject.briar.android.forum;
 
-import org.briarproject.api.clients.MessageTracker.GroupCount;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumPostHeader;
+import org.briarproject.briar.api.client.MessageTracker.GroupCount;
+import org.briarproject.briar.api.forum.Forum;
+import org.briarproject.briar.api.forum.ForumPostHeader;
 
 // This class is NOT thread-safe
 class ForumListItem {
diff --git a/briar-android/src/org/briarproject/android/forum/ForumModule.java b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumModule.java
similarity index 64%
rename from briar-android/src/org/briarproject/android/forum/ForumModule.java
rename to briar-android/src/main/java/org/briarproject/briar/android/forum/ForumModule.java
index 9b665673be1fb08427fb5cecc98990aeec198ad1..06ebbd1f9f0cd9c25d94f07b6cfb83e418c0e36a 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumModule.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumModule.java
@@ -1,7 +1,7 @@
-package org.briarproject.android.forum;
+package org.briarproject.briar.android.forum;
 
-import org.briarproject.android.ActivityScope;
-import org.briarproject.android.BaseActivity;
+import org.briarproject.briar.android.activity.ActivityScope;
+import org.briarproject.briar.android.activity.BaseActivity;
 
 import dagger.Module;
 import dagger.Provides;
diff --git a/briar-android/src/org/briarproject/android/fragment/BaseEventFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/fragment/BaseEventFragment.java
similarity index 68%
rename from briar-android/src/org/briarproject/android/fragment/BaseEventFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/fragment/BaseEventFragment.java
index cf78840532ca486968a10c09d320a57b617d63bd..6e8d1ddd4684f1d39fc8539ced18ff5156a188f1 100644
--- a/briar-android/src/org/briarproject/android/fragment/BaseEventFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/fragment/BaseEventFragment.java
@@ -1,7 +1,7 @@
-package org.briarproject.android.fragment;
+package org.briarproject.briar.android.fragment;
 
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.event.EventListener;
 
 import javax.inject.Inject;
 
diff --git a/briar-android/src/org/briarproject/android/fragment/BaseFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/fragment/BaseFragment.java
similarity index 90%
rename from briar-android/src/org/briarproject/android/fragment/BaseFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/fragment/BaseFragment.java
index 594cd841fc205249fd1472b1fb196685d635b25b..8a5923119aa73a8696e1c8cbb03bff0a8db40f8b 100644
--- a/briar-android/src/org/briarproject/android/fragment/BaseFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/fragment/BaseFragment.java
@@ -1,16 +1,17 @@
-package org.briarproject.android.fragment;
+package org.briarproject.briar.android.fragment;
 
 import android.app.Activity;
 import android.content.Context;
 import android.os.Bundle;
 import android.support.annotation.CallSuper;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.support.v4.app.Fragment;
 import android.view.MenuItem;
 
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.DestroyableContext;
+import org.briarproject.briar.android.DestroyableContext;
+import org.briarproject.briar.android.activity.ActivityComponent;
+
+import javax.annotation.Nullable;
 
 public abstract class BaseFragment extends Fragment
 		implements DestroyableContext {
diff --git a/briar-android/src/org/briarproject/android/introduction/ContactChooserFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/introduction/ContactChooserFragment.java
similarity index 80%
rename from briar-android/src/org/briarproject/android/introduction/ContactChooserFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/introduction/ContactChooserFragment.java
index 20fbd08714a7ddc77dffdb642938294ae15fbf8d..79f78b7cb92e866d3df61e015e0f4e22fe3eb966 100644
--- a/briar-android/src/org/briarproject/android/introduction/ContactChooserFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/introduction/ContactChooserFragment.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.introduction;
+package org.briarproject.briar.android.introduction;
 
 import android.content.Context;
 import android.os.Build;
@@ -9,20 +9,20 @@ import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.contact.BaseContactListAdapter.OnContactClickListener;
-import org.briarproject.android.contact.ContactListAdapter;
-import org.briarproject.android.contact.ContactListItem;
-import org.briarproject.android.fragment.BaseFragment;
-import org.briarproject.android.view.BriarRecyclerView;
-import org.briarproject.api.clients.MessageTracker.GroupCount;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.messaging.ConversationManager;
-import org.briarproject.api.plugins.ConnectionRegistry;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.plugin.ConnectionRegistry;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.contact.BaseContactListAdapter.OnContactClickListener;
+import org.briarproject.briar.android.contact.ContactListAdapter;
+import org.briarproject.briar.android.contact.ContactListItem;
+import org.briarproject.briar.android.fragment.BaseFragment;
+import org.briarproject.briar.android.view.BriarRecyclerView;
+import org.briarproject.briar.api.client.MessageTracker.GroupCount;
+import org.briarproject.briar.api.messaging.ConversationManager;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/briar-android/src/org/briarproject/android/introduction/IntroductionActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/introduction/IntroductionActivity.java
similarity index 86%
rename from briar-android/src/org/briarproject/android/introduction/IntroductionActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/introduction/IntroductionActivity.java
index 8e9d5c389ea53ef7bf6bc445eb684f73985a3e19..2b66f8e2ec47f1d36d8804573e3076ffe580b5e2 100644
--- a/briar-android/src/org/briarproject/android/introduction/IntroductionActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/introduction/IntroductionActivity.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.introduction;
+package org.briarproject.briar.android.introduction;
 
 import android.content.Intent;
 import android.os.Build;
@@ -9,13 +9,12 @@ import android.transition.Fade;
 import android.view.MenuItem;
 import android.view.View;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.BriarActivity;
-import org.briarproject.android.fragment.BaseFragment;
-import org.briarproject.android.fragment.BaseFragment.BaseFragmentListener;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BriarActivity;
+import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
 
 public class IntroductionActivity extends BriarActivity
 		implements BaseFragmentListener {
diff --git a/briar-android/src/org/briarproject/android/introduction/IntroductionMessageFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/introduction/IntroductionMessageFragment.java
similarity index 88%
rename from briar-android/src/org/briarproject/android/introduction/IntroductionMessageFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/introduction/IntroductionMessageFragment.java
index f5c9c32a635bead8e019289a12515f62f1964471..c50db5a1573a48a8edd5a547a8caf089db511ca6 100644
--- a/briar-android/src/org/briarproject/android/introduction/IntroductionMessageFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/introduction/IntroductionMessageFragment.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.introduction;
+package org.briarproject.briar.android.introduction;
 
 import android.content.Context;
 import android.os.Bundle;
@@ -10,18 +10,18 @@ import android.widget.ProgressBar;
 import android.widget.TextView;
 import android.widget.Toast;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.fragment.BaseFragment;
-import org.briarproject.android.view.TextInputView;
-import org.briarproject.android.view.TextInputView.TextInputListener;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.introduction.IntroductionManager;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.fragment.BaseFragment;
+import org.briarproject.briar.android.view.TextInputView;
+import org.briarproject.briar.android.view.TextInputView.TextInputListener;
+import org.briarproject.briar.api.introduction.IntroductionManager;
 
 import java.util.logging.Logger;
 
@@ -35,7 +35,7 @@ import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
 import static android.widget.Toast.LENGTH_SHORT;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.introduction.IntroductionConstants.MAX_INTRODUCTION_MESSAGE_LENGTH;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MAX_INTRODUCTION_MESSAGE_LENGTH;
 
 public class IntroductionMessageFragment extends BaseFragment
 		implements TextInputListener {
diff --git a/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/invitation/AddContactActivity.java
similarity index 91%
rename from briar-android/src/org/briarproject/android/invitation/AddContactActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/invitation/AddContactActivity.java
index 543b2c988d9af95148d060d474b69d7052752c75..b3e42e085f26f5a46b83d52c3bb48e3ae84f294a 100644
--- a/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/invitation/AddContactActivity.java
@@ -1,22 +1,22 @@
-package org.briarproject.android.invitation;
+package org.briarproject.briar.android.invitation;
 
 import android.content.Intent;
 import android.os.Bundle;
 import android.widget.Toast;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.BriarActivity;
-import org.briarproject.android.api.ReferenceManager;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.invitation.InvitationListener;
-import org.briarproject.api.invitation.InvitationState;
-import org.briarproject.api.invitation.InvitationTask;
-import org.briarproject.api.invitation.InvitationTaskFactory;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.invitation.InvitationListener;
+import org.briarproject.bramble.api.invitation.InvitationState;
+import org.briarproject.bramble.api.invitation.InvitationTask;
+import org.briarproject.bramble.api.invitation.InvitationTaskFactory;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BriarActivity;
+import org.briarproject.briar.api.android.ReferenceManager;
 
 import java.util.logging.Logger;
 
@@ -25,9 +25,9 @@ import javax.inject.Inject;
 import static android.widget.Toast.LENGTH_LONG;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.android.invitation.ConfirmationCodeView.ConfirmationState.CONNECTED;
-import static org.briarproject.android.invitation.ConfirmationCodeView.ConfirmationState.DETAILS;
-import static org.briarproject.android.invitation.ConfirmationCodeView.ConfirmationState.WAIT_FOR_CONTACT;
+import static org.briarproject.briar.android.invitation.ConfirmationCodeView.ConfirmationState.CONNECTED;
+import static org.briarproject.briar.android.invitation.ConfirmationCodeView.ConfirmationState.DETAILS;
+import static org.briarproject.briar.android.invitation.ConfirmationCodeView.ConfirmationState.WAIT_FOR_CONTACT;
 
 public class AddContactActivity extends BriarActivity
 		implements InvitationListener {
diff --git a/briar-android/src/org/briarproject/android/invitation/AddContactView.java b/briar-android/src/main/java/org/briarproject/briar/android/invitation/AddContactView.java
similarity index 88%
rename from briar-android/src/org/briarproject/android/invitation/AddContactView.java
rename to briar-android/src/main/java/org/briarproject/briar/android/invitation/AddContactView.java
index 6a6b300be31f4e03f0ebc459df86f5d073bede7a..3ca73869a2dc568865a9ed761e2c38c20d056956 100644
--- a/briar-android/src/org/briarproject/android/invitation/AddContactView.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/invitation/AddContactView.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.invitation;
+package org.briarproject.briar.android.invitation;
 
 import android.content.Context;
 import android.widget.LinearLayout;
diff --git a/briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java b/briar-android/src/main/java/org/briarproject/briar/android/invitation/ChooseIdentityView.java
similarity index 84%
rename from briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java
rename to briar-android/src/main/java/org/briarproject/briar/android/invitation/ChooseIdentityView.java
index 8527a67a70d7c796b0f4ae334e4948196403aef9..3e6819da3dc86f7fedb84854b79e092ef5676979 100644
--- a/briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/invitation/ChooseIdentityView.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.invitation;
+package org.briarproject.briar.android.invitation;
 
 import android.content.Context;
 import android.content.Intent;
@@ -7,11 +7,11 @@ import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.Button;
 
-import org.briarproject.R;
+import org.briarproject.briar.R;
 
 import static android.bluetooth.BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE;
 import static android.bluetooth.BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION;
-import static org.briarproject.android.invitation.AddContactActivity.REQUEST_BLUETOOTH;
+import static org.briarproject.briar.android.invitation.AddContactActivity.REQUEST_BLUETOOTH;
 
 class ChooseIdentityView extends AddContactView implements OnClickListener {
 
@@ -19,6 +19,7 @@ class ChooseIdentityView extends AddContactView implements OnClickListener {
 		super(ctx);
 	}
 
+	@Override
 	void populate() {
 		removeAllViews();
 		Context ctx = getContext();
@@ -33,6 +34,7 @@ class ChooseIdentityView extends AddContactView implements OnClickListener {
 		container.loadLocalAuthor();
 	}
 
+	@Override
 	public void onClick(View view) {
 		Intent i = new Intent(ACTION_REQUEST_DISCOVERABLE);
 		i.putExtra(EXTRA_DISCOVERABLE_DURATION, 120);
diff --git a/briar-android/src/org/briarproject/android/invitation/ConfirmationCodeView.java b/briar-android/src/main/java/org/briarproject/briar/android/invitation/ConfirmationCodeView.java
similarity index 97%
rename from briar-android/src/org/briarproject/android/invitation/ConfirmationCodeView.java
rename to briar-android/src/main/java/org/briarproject/briar/android/invitation/ConfirmationCodeView.java
index bfb2cc338cf3e11825326930f7beedf0a51662c9..2bd953a9b6c39b54159c632fa7ee1792bcdfe8e9 100644
--- a/briar-android/src/org/briarproject/android/invitation/ConfirmationCodeView.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/invitation/ConfirmationCodeView.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.invitation;
+package org.briarproject.briar.android.invitation;
 
 import android.content.Context;
 import android.text.Editable;
@@ -12,7 +12,7 @@ import android.widget.Button;
 import android.widget.EditText;
 import android.widget.TextView;
 
-import org.briarproject.R;
+import org.briarproject.briar.R;
 
 import static android.content.Context.INPUT_METHOD_SERVICE;
 
@@ -31,6 +31,7 @@ class ConfirmationCodeView extends AddContactView {
 		this.state = state;
 	}
 
+	@Override
 	void populate() {
 		removeAllViews();
 		Context ctx = getContext();
diff --git a/briar-android/src/org/briarproject/android/invitation/ErrorView.java b/briar-android/src/main/java/org/briarproject/briar/android/invitation/ErrorView.java
similarity index 88%
rename from briar-android/src/org/briarproject/android/invitation/ErrorView.java
rename to briar-android/src/main/java/org/briarproject/briar/android/invitation/ErrorView.java
index fa0f8fc33e6323b477ffb2db3de819f34653ee18..ab01e333c7c3ad8195aaceacd31a48d78a672396 100644
--- a/briar-android/src/org/briarproject/android/invitation/ErrorView.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/invitation/ErrorView.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.invitation;
+package org.briarproject.briar.android.invitation;
 
 import android.content.Context;
 import android.content.Intent;
@@ -8,11 +8,11 @@ import android.view.View.OnClickListener;
 import android.widget.Button;
 import android.widget.TextView;
 
-import org.briarproject.R;
+import org.briarproject.briar.R;
 
 import static android.bluetooth.BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE;
 import static android.bluetooth.BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION;
-import static org.briarproject.android.invitation.AddContactActivity.REQUEST_BLUETOOTH;
+import static org.briarproject.briar.android.invitation.AddContactActivity.REQUEST_BLUETOOTH;
 
 class ErrorView extends AddContactView implements OnClickListener {
 
@@ -31,6 +31,7 @@ class ErrorView extends AddContactView implements OnClickListener {
 		this.explanation = explanation;
 	}
 
+	@Override
 	void populate() {
 		removeAllViews();
 		Context ctx = getContext();
@@ -49,6 +50,7 @@ class ErrorView extends AddContactView implements OnClickListener {
 		tryAgainButton.setOnClickListener(this);
 	}
 
+	@Override
 	public void onClick(View view) {
 		Intent i = new Intent(ACTION_REQUEST_DISCOVERABLE);
 		i.putExtra(EXTRA_DISCOVERABLE_DURATION, 120);
diff --git a/briar-android/src/org/briarproject/android/invitation/InvitationCodeView.java b/briar-android/src/main/java/org/briarproject/briar/android/invitation/InvitationCodeView.java
similarity index 97%
rename from briar-android/src/org/briarproject/android/invitation/InvitationCodeView.java
rename to briar-android/src/main/java/org/briarproject/briar/android/invitation/InvitationCodeView.java
index 60c221798e502cd0f40dfb5782da0aec5d25bc3f..bfc7272a6685e0fd056a52866a7577f4e2e099cd 100644
--- a/briar-android/src/org/briarproject/android/invitation/InvitationCodeView.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/invitation/InvitationCodeView.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.invitation;
+package org.briarproject.briar.android.invitation;
 
 import android.content.Context;
 import android.text.Editable;
@@ -12,7 +12,7 @@ import android.widget.Button;
 import android.widget.EditText;
 import android.widget.TextView;
 
-import org.briarproject.R;
+import org.briarproject.briar.R;
 
 import static android.content.Context.INPUT_METHOD_SERVICE;
 
@@ -29,6 +29,7 @@ class InvitationCodeView extends AddContactView {
 		this(ctx, false);
 	}
 
+	@Override
 	void populate() {
 		removeAllViews();
 		Context ctx = getContext();
diff --git a/briar-android/src/org/briarproject/android/view/CameraView.java b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/CameraView.java
similarity index 98%
rename from briar-android/src/org/briarproject/android/view/CameraView.java
rename to briar-android/src/main/java/org/briarproject/briar/android/keyagreement/CameraView.java
index 962b8466741f2c26a44c7004f44a1128ddbb25ba..89bb71a94ad8bc2ef767a0f2efb36e1ff58855eb 100644
--- a/briar-android/src/org/briarproject/android/view/CameraView.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/CameraView.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.view;
+package org.briarproject.briar.android.keyagreement;
 
 import android.content.Context;
 import android.hardware.Camera;
@@ -13,9 +13,8 @@ import android.view.Surface;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
 
-import org.briarproject.android.util.PreviewConsumer;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
 
 import java.io.IOException;
 import java.util.List;
diff --git a/briar-android/src/org/briarproject/android/keyagreement/IntroFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/IntroFragment.java
similarity index 73%
rename from briar-android/src/org/briarproject/android/keyagreement/IntroFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/keyagreement/IntroFragment.java
index 6ce313f372313df927fcdef120e73b65711d3da9..db37ed93306a3484b228769153b8499ddd44f107 100644
--- a/briar-android/src/org/briarproject/android/keyagreement/IntroFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/IntroFragment.java
@@ -1,20 +1,25 @@
-package org.briarproject.android.keyagreement;
+package org.briarproject.briar.android.keyagreement;
 
 import android.content.Context;
 import android.os.Bundle;
-import android.support.annotation.Nullable;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.widget.ScrollView;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.fragment.BaseFragment;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.fragment.BaseFragment;
+
+import javax.annotation.Nullable;
 
 import static android.view.View.FOCUS_DOWN;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 public class IntroFragment extends BaseFragment {
 
 	interface IntroScreenSeenListener {
@@ -27,9 +32,9 @@ public class IntroFragment extends BaseFragment {
 	private ScrollView scrollView;
 
 	public static IntroFragment newInstance() {
-		
+
 		Bundle args = new Bundle();
-		
+
 		IntroFragment fragment = new IntroFragment();
 		fragment.setArguments(args);
 		return fragment;
@@ -53,8 +58,9 @@ public class IntroFragment extends BaseFragment {
 
 	@Nullable
 	@Override
-	public View onCreateView(LayoutInflater inflater, ViewGroup container,
-			Bundle savedInstanceState) {
+	public View onCreateView(LayoutInflater inflater,
+			@Nullable ViewGroup container,
+			@Nullable Bundle savedInstanceState) {
 
 		View v = inflater.inflate(R.layout.fragment_keyagreement_id, container,
 				false);
diff --git a/briar-android/src/org/briarproject/android/keyagreement/KeyAgreementActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java
similarity index 76%
rename from briar-android/src/org/briarproject/android/keyagreement/KeyAgreementActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java
index 8a075f151d31e2d13ef6e746f5656eb58512ee6f..7d786bf2caf8d11143cab9502c46bdb5bad00069 100644
--- a/briar-android/src/org/briarproject/android/keyagreement/KeyAgreementActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java
@@ -1,34 +1,39 @@
-package org.briarproject.android.keyagreement;
+package org.briarproject.briar.android.keyagreement;
 
 import android.os.Bundle;
 import android.support.v7.widget.Toolbar;
 import android.view.MenuItem;
 import android.widget.Toast;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.BriarFragmentActivity;
-import org.briarproject.android.fragment.BaseFragment.BaseFragmentListener;
-import org.briarproject.android.keyagreement.IntroFragment.IntroScreenSeenListener;
-import org.briarproject.api.contact.ContactExchangeListener;
-import org.briarproject.api.contact.ContactExchangeTask;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.KeyAgreementFinishedEvent;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.keyagreement.KeyAgreementResult;
+import org.briarproject.bramble.api.contact.ContactExchangeListener;
+import org.briarproject.bramble.api.contact.ContactExchangeTask;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementResult;
+import org.briarproject.bramble.api.keyagreement.event.KeyAgreementFinishedEvent;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BriarFragmentActivity;
+import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
+import org.briarproject.briar.android.keyagreement.IntroFragment.IntroScreenSeenListener;
 
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import static android.widget.Toast.LENGTH_LONG;
 import static java.util.logging.Level.WARNING;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 public class KeyAgreementActivity extends BriarFragmentActivity implements
 		BaseFragmentListener, IntroScreenSeenListener, EventListener,
 		ContactExchangeListener {
@@ -55,7 +60,7 @@ public class KeyAgreementActivity extends BriarFragmentActivity implements
 
 	@SuppressWarnings("ConstantConditions")
 	@Override
-	public void onCreate(Bundle state) {
+	public void onCreate(@Nullable Bundle state) {
 		super.onCreate(state);
 		setContentView(R.layout.activity_plain);
 
diff --git a/briar-android/src/org/briarproject/android/util/PreviewConsumer.java b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/PreviewConsumer.java
similarity index 52%
rename from briar-android/src/org/briarproject/android/util/PreviewConsumer.java
rename to briar-android/src/main/java/org/briarproject/briar/android/keyagreement/PreviewConsumer.java
index fbe2b67269bc6763c5b8ca3fbf56482833e52a81..9e5d7a5e9239d1c402e93210960f8f59de09ebec 100644
--- a/briar-android/src/org/briarproject/android/util/PreviewConsumer.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/PreviewConsumer.java
@@ -1,10 +1,13 @@
-package org.briarproject.android.util;
+package org.briarproject.briar.android.keyagreement;
 
 import android.hardware.Camera;
 import android.support.annotation.UiThread;
 
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
 @SuppressWarnings("deprecation")
-public interface PreviewConsumer {
+@NotNullByDefault
+interface PreviewConsumer {
 
 	@UiThread
 	void start(Camera camera);
diff --git a/briar-android/src/org/briarproject/android/util/QrCodeDecoder.java b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/QrCodeDecoder.java
similarity index 84%
rename from briar-android/src/org/briarproject/android/util/QrCodeDecoder.java
rename to briar-android/src/main/java/org/briarproject/briar/android/keyagreement/QrCodeDecoder.java
index 0e9530c087d656b014c672108e0238be5370bd1f..e69dc2da711decff1ef315a621ca391e926d64fe 100644
--- a/briar-android/src/org/briarproject/android/util/QrCodeDecoder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/QrCodeDecoder.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.util;
+package org.briarproject.briar.android.keyagreement;
 
 import android.hardware.Camera;
 import android.hardware.Camera.PreviewCallback;
@@ -15,12 +15,18 @@ import com.google.zxing.Result;
 import com.google.zxing.common.HybridBinarizer;
 import com.google.zxing.qrcode.QRCodeReader;
 
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+
 import java.util.logging.Logger;
 
 import static java.util.logging.Level.INFO;
 
 @SuppressWarnings("deprecation")
-public class QrCodeDecoder implements PreviewConsumer, PreviewCallback {
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
+class QrCodeDecoder implements PreviewConsumer, PreviewCallback {
 
 	private static final Logger LOG =
 			Logger.getLogger(QrCodeDecoder.class.getName());
@@ -30,7 +36,7 @@ public class QrCodeDecoder implements PreviewConsumer, PreviewCallback {
 
 	private Camera camera = null;
 
-	public QrCodeDecoder(ResultCallback callback) {
+	QrCodeDecoder(ResultCallback callback) {
 		this.callback = callback;
 	}
 
@@ -99,7 +105,8 @@ public class QrCodeDecoder implements PreviewConsumer, PreviewCallback {
 		}
 	}
 
-	public interface ResultCallback {
+	@NotNullByDefault
+	interface ResultCallback {
 
 		void handleResult(Result result);
 	}
diff --git a/briar-android/src/org/briarproject/android/util/QrCodeUtils.java b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/QrCodeUtils.java
similarity index 84%
rename from briar-android/src/org/briarproject/android/util/QrCodeUtils.java
rename to briar-android/src/main/java/org/briarproject/briar/android/keyagreement/QrCodeUtils.java
index 57a092eeb242f67f3f8f219fa892732512c43f3f..43286f6fd5ae737daceeec0f21c4212b4a13aa75 100644
--- a/briar-android/src/org/briarproject/android/util/QrCodeUtils.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/QrCodeUtils.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.util;
+package org.briarproject.briar.android.keyagreement;
 
 import android.graphics.Bitmap;
 import android.util.DisplayMetrics;
@@ -7,23 +7,26 @@ import com.google.zxing.WriterException;
 import com.google.zxing.common.BitMatrix;
 import com.google.zxing.qrcode.QRCodeWriter;
 
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
+
 import static android.graphics.Bitmap.Config.ARGB_8888;
 import static android.graphics.Color.BLACK;
 import static android.graphics.Color.WHITE;
 import static com.google.zxing.BarcodeFormat.QR_CODE;
 import static java.util.logging.Level.WARNING;
 
-public class QrCodeUtils {
+@NotNullByDefault
+class QrCodeUtils {
 
 	private static final Logger LOG =
 			Logger.getLogger(QrCodeUtils.class.getName());
 
 	@Nullable
-	public static Bitmap createQrCode(DisplayMetrics dm, String input) {
+	static Bitmap createQrCode(DisplayMetrics dm, String input) {
 		int smallestDimen = Math.min(dm.widthPixels, dm.heightPixels);
 		try {
 			// Generate QR code
diff --git a/briar-android/src/org/briarproject/android/keyagreement/ShowQrCodeFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/ShowQrCodeFragment.java
similarity index 83%
rename from briar-android/src/org/briarproject/android/keyagreement/ShowQrCodeFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/keyagreement/ShowQrCodeFragment.java
index 073a97132ff3c9f62ea811bfd44fa03e47301340..f20bb4d78c0ebe885c13f74966486be3db6f7f99 100644
--- a/briar-android/src/org/briarproject/android/keyagreement/ShowQrCodeFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/ShowQrCodeFragment.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.keyagreement;
+package org.briarproject.briar.android.keyagreement;
 
 import android.bluetooth.BluetoothAdapter;
 import android.content.BroadcastReceiver;
@@ -8,7 +8,6 @@ import android.content.IntentFilter;
 import android.graphics.Bitmap;
 import android.os.AsyncTask;
 import android.os.Bundle;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.util.Base64;
 import android.util.DisplayMetrics;
@@ -22,31 +21,31 @@ import android.widget.Toast;
 
 import com.google.zxing.Result;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.api.AndroidExecutor;
-import org.briarproject.android.fragment.BaseEventFragment;
-import org.briarproject.android.util.QrCodeDecoder;
-import org.briarproject.android.util.QrCodeUtils;
-import org.briarproject.android.view.CameraView;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.KeyAgreementAbortedEvent;
-import org.briarproject.api.event.KeyAgreementFailedEvent;
-import org.briarproject.api.event.KeyAgreementFinishedEvent;
-import org.briarproject.api.event.KeyAgreementListeningEvent;
-import org.briarproject.api.event.KeyAgreementStartedEvent;
-import org.briarproject.api.event.KeyAgreementWaitingEvent;
-import org.briarproject.api.keyagreement.KeyAgreementTask;
-import org.briarproject.api.keyagreement.KeyAgreementTaskFactory;
-import org.briarproject.api.keyagreement.Payload;
-import org.briarproject.api.keyagreement.PayloadEncoder;
-import org.briarproject.api.keyagreement.PayloadParser;
-import org.briarproject.api.lifecycle.IoExecutor;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementTask;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementTaskFactory;
+import org.briarproject.bramble.api.keyagreement.Payload;
+import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
+import org.briarproject.bramble.api.keyagreement.PayloadParser;
+import org.briarproject.bramble.api.keyagreement.event.KeyAgreementAbortedEvent;
+import org.briarproject.bramble.api.keyagreement.event.KeyAgreementFailedEvent;
+import org.briarproject.bramble.api.keyagreement.event.KeyAgreementFinishedEvent;
+import org.briarproject.bramble.api.keyagreement.event.KeyAgreementListeningEvent;
+import org.briarproject.bramble.api.keyagreement.event.KeyAgreementStartedEvent;
+import org.briarproject.bramble.api.keyagreement.event.KeyAgreementWaitingEvent;
+import org.briarproject.bramble.api.lifecycle.IoExecutor;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.system.AndroidExecutor;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.fragment.BaseEventFragment;
 
 import java.io.IOException;
 import java.util.concurrent.Executor;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import static android.bluetooth.BluetoothAdapter.ACTION_STATE_CHANGED;
@@ -58,6 +57,8 @@ import static android.view.View.VISIBLE;
 import static android.widget.Toast.LENGTH_LONG;
 import static java.util.logging.Level.INFO;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 public class ShowQrCodeFragment extends BaseEventFragment
 		implements QrCodeDecoder.ResultCallback {
 
@@ -108,14 +109,15 @@ public class ShowQrCodeFragment extends BaseEventFragment
 
 	@Nullable
 	@Override
-	public View onCreateView(LayoutInflater inflater, ViewGroup container,
-			Bundle savedInstanceState) {
+	public View onCreateView(LayoutInflater inflater,
+			@Nullable ViewGroup container,
+			@Nullable Bundle savedInstanceState) {
 		return inflater.inflate(R.layout.fragment_keyagreement_qr, container,
 				false);
 	}
 
 	@Override
-	public void onViewCreated(View view, Bundle savedInstanceState) {
+	public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
 		super.onViewCreated(view, savedInstanceState);
 
 		cameraView = (CameraView) view.findViewById(R.id.camera_view);
@@ -129,7 +131,7 @@ public class ShowQrCodeFragment extends BaseEventFragment
 	}
 
 	@Override
-	public void onActivityCreated(Bundle savedInstanceState) {
+	public void onActivityCreated(@Nullable Bundle savedInstanceState) {
 		super.onActivityCreated(savedInstanceState);
 
 		getActivity().setRequestedOrientation(SCREEN_ORIENTATION_NOSENSOR);
@@ -173,7 +175,7 @@ public class ShowQrCodeFragment extends BaseEventFragment
 	@UiThread
 	private void startListening() {
 		final KeyAgreementTask oldTask = task;
-		final KeyAgreementTask newTask = keyAgreementTaskFactory.getTask();
+		final KeyAgreementTask newTask = keyAgreementTaskFactory.createTask();
 		task = newTask;
 		ioExecutor.execute(new Runnable() {
 			@Override
@@ -265,7 +267,7 @@ public class ShowQrCodeFragment extends BaseEventFragment
 			}
 
 			@Override
-			protected void onPostExecute(Bitmap bitmap) {
+			protected void onPostExecute(@Nullable Bitmap bitmap) {
 				if (bitmap != null && !isDetached()) {
 					qrCode.setImageBitmap(bitmap);
 					// Simple fade-in animation
diff --git a/briar-android/src/org/briarproject/android/ChangePasswordActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/login/ChangePasswordActivity.java
similarity index 87%
rename from briar-android/src/org/briarproject/android/ChangePasswordActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/login/ChangePasswordActivity.java
index 4c93924ea80b997bd8637596b80d1cc327fbddc4..6b6c717feb0f4886109df015da8d5fb32710feb3 100644
--- a/briar-android/src/org/briarproject/android/ChangePasswordActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/ChangePasswordActivity.java
@@ -1,4 +1,4 @@
-package org.briarproject.android;
+package org.briarproject.briar.android.login;
 
 import android.os.Bundle;
 import android.support.annotation.NonNull;
@@ -15,22 +15,20 @@ import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
 import android.widget.Toast;
 
-import org.briarproject.R;
-import org.briarproject.android.controller.PasswordController;
-import org.briarproject.android.controller.SetupController;
-import org.briarproject.android.controller.handler.UiResultHandler;
-import org.briarproject.android.util.AndroidUtils;
-import org.briarproject.android.util.StrengthMeter;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BaseActivity;
+import org.briarproject.briar.android.controller.handler.UiResultHandler;
+import org.briarproject.briar.android.util.UiUtils;
 
 import javax.inject.Inject;
 
 import static android.view.View.INVISIBLE;
 import static android.view.View.VISIBLE;
-import static org.briarproject.api.crypto.PasswordStrengthEstimator.WEAK;
+import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.WEAK;
 
 public class ChangePasswordActivity extends BaseActivity
-		implements OnClickListener,
-		OnEditorActionListener {
+		implements OnClickListener, OnEditorActionListener {
 
 	@Inject
 	protected PasswordController passwordController;
@@ -109,10 +107,10 @@ public class ChangePasswordActivity extends BaseActivity
 		float strength =
 				setupController.estimatePasswordStrength(firstPassword);
 		strengthMeter.setStrength(strength);
-		AndroidUtils.setError(newPasswordEntryWrapper,
+		UiUtils.setError(newPasswordEntryWrapper,
 				getString(R.string.password_too_weak),
 				firstPassword.length() > 0 && strength < WEAK);
-		AndroidUtils.setError(newPasswordConfirmationWrapper,
+		UiUtils.setError(newPasswordConfirmationWrapper,
 				getString(R.string.passwords_do_not_match),
 				secondPassword.length() > 0 && !passwordsMatch);
 		changePasswordButton.setEnabled(
@@ -150,7 +148,7 @@ public class ChangePasswordActivity extends BaseActivity
 	}
 
 	private void tryAgain() {
-		AndroidUtils.setError(currentPasswordEntryWrapper,
+		UiUtils.setError(currentPasswordEntryWrapper,
 				getString(R.string.try_again), true);
 		changePasswordButton.setVisibility(VISIBLE);
 		progress.setVisibility(INVISIBLE);
diff --git a/briar-android/src/org/briarproject/android/PasswordActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordActivity.java
similarity index 89%
rename from briar-android/src/org/briarproject/android/PasswordActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/login/PasswordActivity.java
index 751b6adcdb97b7dff491fdefc13a3f1dea512786..3606f077f1428d0199c7f434417d4b65a7d31f32 100644
--- a/briar-android/src/org/briarproject/android/PasswordActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordActivity.java
@@ -1,4 +1,4 @@
-package org.briarproject.android;
+package org.briarproject.briar.android.login;
 
 import android.content.DialogInterface;
 import android.content.Intent;
@@ -16,10 +16,11 @@ import android.widget.ProgressBar;
 import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
 
-import org.briarproject.R;
-import org.briarproject.android.controller.PasswordController;
-import org.briarproject.android.controller.handler.UiResultHandler;
-import org.briarproject.android.util.AndroidUtils;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BaseActivity;
+import org.briarproject.briar.android.controller.handler.UiResultHandler;
+import org.briarproject.briar.android.util.UiUtils;
 
 import javax.inject.Inject;
 
@@ -70,7 +71,7 @@ public class PasswordActivity extends BaseActivity {
 			@Override
 			public void onTextChanged(CharSequence s, int start, int before,
 					int count) {
-				if (count > 0) AndroidUtils.setError(input, null, false);
+				if (count > 0) UiUtils.setError(input, null, false);
 			}
 
 			@Override
@@ -140,7 +141,7 @@ public class PasswordActivity extends BaseActivity {
 	}
 
 	private void tryAgain() {
-		AndroidUtils.setError(input, getString(R.string.try_again), true);
+		UiUtils.setError(input, getString(R.string.try_again), true);
 		signInButton.setVisibility(VISIBLE);
 		progress.setVisibility(INVISIBLE);
 		password.setText("");
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordController.java b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordController.java
new file mode 100644
index 0000000000000000000000000000000000000000..209b5ac4a7935062a2057908fe1a48e77c341437
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordController.java
@@ -0,0 +1,15 @@
+package org.briarproject.briar.android.login;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.android.controller.ConfigController;
+import org.briarproject.briar.android.controller.handler.ResultHandler;
+
+@NotNullByDefault
+public interface PasswordController extends ConfigController {
+
+	void validatePassword(String password,
+			ResultHandler<Boolean> resultHandler);
+
+	void changePassword(String password, String newPassword,
+			ResultHandler<Boolean> resultHandler);
+}
diff --git a/briar-android/src/org/briarproject/android/controller/PasswordControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordControllerImpl.java
similarity index 81%
rename from briar-android/src/org/briarproject/android/controller/PasswordControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/login/PasswordControllerImpl.java
index 9ea926474c97ab82c91d997e2be10344f2846d1c..ac01eba475c8e68fd8fdc6a5185f1f1fbfa5f627 100644
--- a/briar-android/src/org/briarproject/android/controller/PasswordControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordControllerImpl.java
@@ -1,13 +1,15 @@
-package org.briarproject.android.controller;
+package org.briarproject.briar.android.login;
 
 import android.content.SharedPreferences;
 
-import org.briarproject.android.controller.handler.ResultHandler;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.CryptoExecutor;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.db.DatabaseConfig;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.CryptoExecutor;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.db.DatabaseConfig;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.android.controller.ConfigControllerImpl;
+import org.briarproject.briar.android.controller.handler.ResultHandler;
 
 import java.util.concurrent.Executor;
 import java.util.logging.Logger;
@@ -16,6 +18,7 @@ import javax.inject.Inject;
 
 import static java.util.logging.Level.INFO;
 
+@NotNullByDefault
 public class PasswordControllerImpl extends ConfigControllerImpl
 		implements PasswordController {
 
diff --git a/briar-android/src/org/briarproject/android/SetupActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/login/SetupActivity.java
similarity index 85%
rename from briar-android/src/org/briarproject/android/SetupActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/login/SetupActivity.java
index 0dcce3d72a28a3d4eeed9bee8584cf1c97e38a99..be3627dc8f01a89c80b0c92d85cdcb9946e2533f 100644
--- a/briar-android/src/org/briarproject/android/SetupActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/SetupActivity.java
@@ -1,4 +1,4 @@
-package org.briarproject.android;
+package org.briarproject.briar.android.login;
 
 import android.content.Intent;
 import android.os.Bundle;
@@ -14,12 +14,13 @@ import android.widget.ProgressBar;
 import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
 
-import org.briarproject.R;
-import org.briarproject.android.controller.SetupController;
-import org.briarproject.android.controller.handler.UiResultHandler;
-import org.briarproject.android.util.AndroidUtils;
-import org.briarproject.android.util.StrengthMeter;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BaseActivity;
+import org.briarproject.briar.android.controller.handler.UiResultHandler;
+import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
+import org.briarproject.briar.android.util.UiUtils;
 
 import javax.inject.Inject;
 
@@ -27,8 +28,8 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.view.View.GONE;
 import static android.view.View.INVISIBLE;
 import static android.view.View.VISIBLE;
-import static org.briarproject.api.crypto.PasswordStrengthEstimator.WEAK;
-import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
+import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.WEAK;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
 
 public class SetupActivity extends BaseActivity implements OnClickListener,
 		OnEditorActionListener {
@@ -107,13 +108,13 @@ public class SetupActivity extends BaseActivity implements OnClickListener,
 		float strength =
 				setupController.estimatePasswordStrength(firstPassword);
 		strengthMeter.setStrength(strength);
-		AndroidUtils.setError(nicknameEntryWrapper,
+		UiUtils.setError(nicknameEntryWrapper,
 				getString(R.string.name_too_long),
 				nicknameLength > MAX_AUTHOR_NAME_LENGTH);
-		AndroidUtils.setError(passwordEntryWrapper,
+		UiUtils.setError(passwordEntryWrapper,
 				getString(R.string.password_too_weak),
 				firstPassword.length() > 0 && strength < WEAK);
-		AndroidUtils.setError(passwordConfirmationWrapper,
+		UiUtils.setError(passwordConfirmationWrapper,
 				getString(R.string.passwords_do_not_match),
 				secondPassword.length() > 0 && !passwordsMatch);
 		createAccountButton.setEnabled(nicknameLength > 0
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/SetupController.java b/briar-android/src/main/java/org/briarproject/briar/android/login/SetupController.java
new file mode 100644
index 0000000000000000000000000000000000000000..5e72acb931614629355ff6db3060f9b85be625f0
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/SetupController.java
@@ -0,0 +1,14 @@
+package org.briarproject.briar.android.login;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.android.controller.handler.ResultHandler;
+
+@NotNullByDefault
+public interface SetupController {
+
+	float estimatePasswordStrength(String password);
+
+	void storeAuthorInfo(String nickname, String password,
+			ResultHandler<Void> resultHandler);
+
+}
diff --git a/briar-android/src/org/briarproject/android/controller/SetupControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/login/SetupControllerImpl.java
similarity index 70%
rename from briar-android/src/org/briarproject/android/controller/SetupControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/login/SetupControllerImpl.java
index 356137008cc0b46aaad536d61e76c0fdb0dffeb5..f413ca736171fdaeb6f9bc9d6fcaadf6a5c37507 100644
--- a/briar-android/src/org/briarproject/android/controller/SetupControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/SetupControllerImpl.java
@@ -1,18 +1,20 @@
-package org.briarproject.android.controller;
+package org.briarproject.briar.android.login;
 
 import android.content.SharedPreferences;
 
-import org.briarproject.android.controller.handler.ResultHandler;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.CryptoExecutor;
-import org.briarproject.api.crypto.PasswordStrengthEstimator;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.db.DatabaseConfig;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.CryptoExecutor;
+import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.db.DatabaseConfig;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.android.controller.handler.ResultHandler;
 
 import java.util.concurrent.Executor;
 
 import javax.inject.Inject;
 
+@NotNullByDefault
 public class SetupControllerImpl extends PasswordControllerImpl
 		implements SetupController {
 
diff --git a/briar-android/src/org/briarproject/android/util/StrengthMeter.java b/briar-android/src/main/java/org/briarproject/briar/android/login/StrengthMeter.java
similarity index 85%
rename from briar-android/src/org/briarproject/android/util/StrengthMeter.java
rename to briar-android/src/main/java/org/briarproject/briar/android/login/StrengthMeter.java
index 83fb20b8f1221916ca97f4b95d633376507b891e..b740c143196b62b9c7c5094af3a1e547d474d3ee 100644
--- a/briar-android/src/org/briarproject/android/util/StrengthMeter.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/StrengthMeter.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.util;
+package org.briarproject.briar.android.login;
 
 import android.content.Context;
 import android.graphics.Color;
@@ -15,10 +15,10 @@ import static android.graphics.Paint.Style.FILL;
 import static android.graphics.Paint.Style.STROKE;
 import static android.graphics.drawable.ClipDrawable.HORIZONTAL;
 import static android.view.Gravity.LEFT;
-import static org.briarproject.api.crypto.PasswordStrengthEstimator.QUITE_STRONG;
-import static org.briarproject.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
-import static org.briarproject.api.crypto.PasswordStrengthEstimator.STRONG;
-import static org.briarproject.api.crypto.PasswordStrengthEstimator.WEAK;
+import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_STRONG;
+import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
+import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.STRONG;
+import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.WEAK;
 
 public class StrengthMeter extends ProgressBar {
 
diff --git a/briar-android/src/org/briarproject/android/NavDrawerActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java
similarity index 82%
rename from briar-android/src/org/briarproject/android/NavDrawerActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java
index b84afd8b96e2ff6263b599adca96c9733adc6d16..e2edf7c98dc9fcfa8af242bc0117352848565a14 100644
--- a/briar-android/src/org/briarproject/android/NavDrawerActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java
@@ -1,4 +1,4 @@
-package org.briarproject.android;
+package org.briarproject.briar.android.navdrawer;
 
 import android.content.Context;
 import android.content.Intent;
@@ -9,6 +9,7 @@ import android.os.Bundle;
 import android.support.design.widget.NavigationView;
 import android.support.design.widget.NavigationView.OnNavigationItemSelectedListener;
 import android.support.v4.widget.DrawerLayout;
+import android.support.v7.app.ActionBar;
 import android.support.v7.app.ActionBarDrawerToggle;
 import android.support.v7.widget.Toolbar;
 import android.view.LayoutInflater;
@@ -20,18 +21,19 @@ import android.widget.GridView;
 import android.widget.ImageView;
 import android.widget.TextView;
 
-import org.briarproject.R;
-import org.briarproject.android.blogs.FeedFragment;
-import org.briarproject.android.contact.ContactListFragment;
-import org.briarproject.android.controller.NavDrawerController;
-import org.briarproject.android.controller.TransportStateListener;
-import org.briarproject.android.forum.ForumListFragment;
-import org.briarproject.android.fragment.BaseFragment.BaseFragmentListener;
-import org.briarproject.android.privategroup.list.GroupListFragment;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.plugins.BluetoothConstants;
-import org.briarproject.api.plugins.LanTcpConstants;
-import org.briarproject.api.plugins.TorConstants;
+import org.briarproject.bramble.api.plugin.BluetoothConstants;
+import org.briarproject.bramble.api.plugin.LanTcpConstants;
+import org.briarproject.bramble.api.plugin.TorConstants;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BriarFragmentActivity;
+import org.briarproject.briar.android.blog.FeedFragment;
+import org.briarproject.briar.android.contact.ContactListFragment;
+import org.briarproject.briar.android.forum.ForumListFragment;
+import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
+import org.briarproject.briar.android.privategroup.list.GroupListFragment;
+import org.briarproject.briar.android.settings.SettingsActivity;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -41,17 +43,15 @@ import javax.inject.Inject;
 
 import static android.support.v4.view.GravityCompat.START;
 import static android.support.v4.widget.DrawerLayout.LOCK_MODE_LOCKED_CLOSED;
-import static android.support.v4.widget.DrawerLayout.LOCK_MODE_UNLOCKED;
-import static android.view.View.INVISIBLE;
 
 public class NavDrawerActivity extends BriarFragmentActivity implements
 		BaseFragmentListener, TransportStateListener,
 		OnNavigationItemSelectedListener {
 
-	static final String INTENT_CONTACTS = "intent_contacts";
-	static final String INTENT_GROUPS = "intent_groups";
-	static final String INTENT_FORUMS = "intent_forums";
-	static final String INTENT_BLOGS = "intent_blogs";
+	public static final String INTENT_CONTACTS = "intent_contacts";
+	public static final String INTENT_GROUPS = "intent_groups";
+	public static final String INTENT_FORUMS = "intent_forums";
+	public static final String INTENT_BLOGS = "intent_blogs";
 
 	private static final Logger LOG =
 			Logger.getLogger(NavDrawerActivity.class.getName());
@@ -178,6 +178,24 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
 		}
 	}
 
+	@Override
+	public void onFragmentCreated(String tag) {
+		super.onFragmentCreated(tag);
+
+		ActionBar actionBar = getSupportActionBar();
+		if (actionBar == null) return;
+
+		if (tag.equals(ContactListFragment.TAG)) {
+			actionBar.setTitle(R.string.contact_list_button);
+		} else if (tag.equals(GroupListFragment.TAG)) {
+			actionBar.setTitle(R.string.groups_button);
+		} else if (tag.equals(ForumListFragment.TAG)) {
+			actionBar.setTitle(R.string.forums_button);
+		} else if (tag.equals(FeedFragment.TAG)) {
+			actionBar.setTitle(R.string.blogs_button);
+		}
+	}
+
 	@Override
 	public boolean onNavigationItemSelected(MenuItem item) {
 		drawerLayout.closeDrawer(START);
@@ -190,7 +208,6 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
 		return true;
 	}
 
-
 	@Override
 	public void onBackPressed() {
 		if (getSupportFragmentManager().getBackStackEntryCount() == 0
@@ -218,22 +235,11 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
 
 	@Override
 	protected void signOut() {
-		showLoadingScreen(true, R.string.progress_title_logout);
-		super.signOut();
-	}
-
-	public void showLoadingScreen(boolean isBlocking, int stringId) {
-		if (isBlocking) {
-			// Disable navigation drawer slide to open
-			drawerLayout.setDrawerLockMode(LOCK_MODE_LOCKED_CLOSED);
-		}
-		progressTitle.setText(stringId);
+		// Disable navigation drawer slide to open
+		drawerLayout.setDrawerLockMode(LOCK_MODE_LOCKED_CLOSED);
+		progressTitle.setText(R.string.progress_title_logout);
 		progressViewGroup.setVisibility(View.VISIBLE);
-	}
-
-	public void hideLoadingScreen() {
-		drawerLayout.setDrawerLockMode(LOCK_MODE_UNLOCKED);
-		progressViewGroup.setVisibility(INVISIBLE);
+		super.signOut();
 	}
 
 	private void initializeTransports(final LayoutInflater inflater) {
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerController.java b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerController.java
new file mode 100644
index 0000000000000000000000000000000000000000..424fdb1add6117f9636dcc826cc925a31a696ae5
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerController.java
@@ -0,0 +1,12 @@
+package org.briarproject.briar.android.navdrawer;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.briar.android.controller.ActivityLifecycleController;
+
+@NotNullByDefault
+public interface NavDrawerController extends ActivityLifecycleController {
+
+	boolean isTransportRunning(TransportId transportId);
+
+}
diff --git a/briar-android/src/org/briarproject/android/controller/NavDrawerControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerControllerImpl.java
similarity index 69%
rename from briar-android/src/org/briarproject/android/controller/NavDrawerControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerControllerImpl.java
index fb75cfce2a509b2f6f0d495870e8c6aff7e86fbe..26d945baaefd17a7e8056e8bf2edf84aca486756 100644
--- a/briar-android/src/org/briarproject/android/controller/NavDrawerControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerControllerImpl.java
@@ -1,17 +1,20 @@
-package org.briarproject.android.controller;
+package org.briarproject.briar.android.navdrawer;
 
 import android.app.Activity;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.TransportDisabledEvent;
-import org.briarproject.api.event.TransportEnabledEvent;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.plugins.Plugin;
-import org.briarproject.api.plugins.PluginManager;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.plugin.Plugin;
+import org.briarproject.bramble.api.plugin.PluginManager;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.event.TransportDisabledEvent;
+import org.briarproject.bramble.api.plugin.event.TransportEnabledEvent;
+import org.briarproject.briar.android.controller.DbControllerImpl;
 
 import java.util.concurrent.Executor;
 import java.util.logging.Logger;
@@ -20,6 +23,8 @@ import javax.inject.Inject;
 
 import static java.util.logging.Level.INFO;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 public class NavDrawerControllerImpl extends DbControllerImpl
 		implements NavDrawerController, EventListener {
 
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/TransportStateListener.java b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/TransportStateListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..592263b6c8e8808fcfc08ee619abdd0cdf38b6ed
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/TransportStateListener.java
@@ -0,0 +1,9 @@
+package org.briarproject.briar.android.navdrawer;
+
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.briar.android.DestroyableContext;
+
+interface TransportStateListener extends DestroyableContext {
+
+	void stateUpdate(TransportId id, boolean enabled);
+}
diff --git a/briar-android/src/org/briarproject/android/panic/ExitActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/panic/ExitActivity.java
similarity index 74%
rename from briar-android/src/org/briarproject/android/panic/ExitActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/panic/ExitActivity.java
index 363270f26fd167cc9dc0c62b3fcf126366dee291..bd027c39c0f87eb3cd46d02c7b83f04758bd34b2 100644
--- a/briar-android/src/org/briarproject/android/panic/ExitActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/panic/ExitActivity.java
@@ -1,10 +1,10 @@
-package org.briarproject.android.panic;
+package org.briarproject.briar.android.panic;
 
 import android.os.Build;
 import android.os.Bundle;
 
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.BaseActivity;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BaseActivity;
 
 import java.util.logging.Logger;
 
diff --git a/briar-android/src/org/briarproject/android/panic/PanicPreferencesActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/panic/PanicPreferencesActivity.java
similarity index 78%
rename from briar-android/src/org/briarproject/android/panic/PanicPreferencesActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/panic/PanicPreferencesActivity.java
index 7fbd2ff97a6c304ac68131cf1f6c7f3e72daba3a..9c19c78b10e45a02609aa78d9b86729c71d8f2b7 100644
--- a/briar-android/src/org/briarproject/android/panic/PanicPreferencesActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/panic/PanicPreferencesActivity.java
@@ -1,12 +1,12 @@
-package org.briarproject.android.panic;
+package org.briarproject.briar.android.panic;
 
 import android.os.Bundle;
 import android.support.v7.app.ActionBar;
 import android.view.MenuItem;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.BriarActivity;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BriarActivity;
 
 public class PanicPreferencesActivity extends BriarActivity {
 
diff --git a/briar-android/src/org/briarproject/android/panic/PanicPreferencesFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/panic/PanicPreferencesFragment.java
similarity index 98%
rename from briar-android/src/org/briarproject/android/panic/PanicPreferencesFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/panic/PanicPreferencesFragment.java
index f62dc0385255137ee110231c543a18e9b2f37b07..9251b85b3052c7552c43f23a79c04be3e4b7335f 100644
--- a/briar-android/src/org/briarproject/android/panic/PanicPreferencesFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/panic/PanicPreferencesFragment.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.panic;
+package org.briarproject.briar.android.panic;
 
 import android.app.Activity;
 import android.content.ComponentName;
@@ -16,12 +16,13 @@ import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceFragmentCompat;
 import android.text.TextUtils;
 
-import org.briarproject.R;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.briar.R;
 
 import java.util.ArrayList;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
+
 import info.guardianproject.panic.Panic;
 import info.guardianproject.panic.PanicResponder;
 
diff --git a/briar-android/src/org/briarproject/android/panic/PanicResponderActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/panic/PanicResponderActivity.java
similarity index 85%
rename from briar-android/src/org/briarproject/android/panic/PanicResponderActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/panic/PanicResponderActivity.java
index ba8583fcac04e9cf99c11a27569251e42ad1a5a4..f79030e7fa41cbeace247ec3034b8961ba173f6e 100644
--- a/briar-android/src/org/briarproject/android/panic/PanicResponderActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/panic/PanicResponderActivity.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.panic;
+package org.briarproject.briar.android.panic;
 
 import android.content.Intent;
 import android.content.SharedPreferences;
@@ -7,10 +7,10 @@ import android.os.Build;
 import android.os.Bundle;
 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.bramble.api.system.AndroidExecutor;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BriarActivity;
+import org.briarproject.briar.android.controller.ConfigController;
 import org.iilab.IilabEngineeringRSA2048Pin;
 
 import java.util.logging.Logger;
@@ -23,9 +23,9 @@ 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;
+import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_LOCK;
+import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_PURGE;
+import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_UNINSTALL;
 
 public class PanicResponderActivity extends BriarActivity {
 
diff --git a/briar-android/src/org/briarproject/android/privategroup/VisibilityHelper.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/VisibilityHelper.java
similarity index 79%
rename from briar-android/src/org/briarproject/android/privategroup/VisibilityHelper.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/VisibilityHelper.java
index 678fde3256480cf4a76bbd78fedd64bdabdfa403..6c9de8c760a2cae70670c52c24cbd958da2d8ac2 100644
--- a/briar-android/src/org/briarproject/android/privategroup/VisibilityHelper.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/VisibilityHelper.java
@@ -1,12 +1,12 @@
-package org.briarproject.android.privategroup;
+package org.briarproject.briar.android.privategroup;
 
 import android.content.Context;
 import android.support.annotation.DrawableRes;
 
-import org.briarproject.R;
-import org.briarproject.api.privategroup.Visibility;
+import org.briarproject.briar.R;
+import org.briarproject.briar.api.privategroup.Visibility;
 
-import static org.briarproject.api.privategroup.Visibility.INVISIBLE;
+import static org.briarproject.briar.api.privategroup.Visibility.INVISIBLE;
 
 public class VisibilityHelper {
 
diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupActivity.java
similarity index 85%
rename from briar-android/src/org/briarproject/android/privategroup/conversation/GroupActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupActivity.java
index 438c061120faaa8a4549eb8e31ed4fd3abe90318..e0502432ff3dd3fe027e40a90139d868140eaa22 100644
--- a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupActivity.java
@@ -1,11 +1,10 @@
-package org.briarproject.android.privategroup.conversation;
+package org.briarproject.briar.android.privategroup.conversation;
 
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
 import android.content.Intent;
 import android.os.Bundle;
 import android.support.annotation.LayoutRes;
-import android.support.annotation.Nullable;
 import android.support.annotation.StringRes;
 import android.support.v4.app.ActivityCompat;
 import android.support.v4.app.ActivityOptionsCompat;
@@ -16,30 +15,31 @@ import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.controller.handler.UiExceptionHandler;
-import org.briarproject.android.controller.handler.UiResultExceptionHandler;
-import org.briarproject.android.privategroup.conversation.GroupController.GroupListener;
-import org.briarproject.android.privategroup.creation.GroupInviteActivity;
-import org.briarproject.android.privategroup.memberlist.GroupMemberListActivity;
-import org.briarproject.android.privategroup.reveal.RevealContactsActivity;
-import org.briarproject.android.threaded.ThreadListActivity;
-import org.briarproject.android.threaded.ThreadListController;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.privategroup.GroupMessageHeader;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.privategroup.Visibility;
-
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.controller.handler.UiExceptionHandler;
+import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
+import org.briarproject.briar.android.privategroup.conversation.GroupController.GroupListener;
+import org.briarproject.briar.android.privategroup.creation.GroupInviteActivity;
+import org.briarproject.briar.android.privategroup.memberlist.GroupMemberListActivity;
+import org.briarproject.briar.android.privategroup.reveal.RevealContactsActivity;
+import org.briarproject.briar.android.threaded.ThreadListActivity;
+import org.briarproject.briar.android.threaded.ThreadListController;
+import org.briarproject.briar.api.privategroup.GroupMessageHeader;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.privategroup.Visibility;
+
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import static android.support.v4.app.ActivityOptionsCompat.makeCustomAnimation;
 import static android.view.View.GONE;
-import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH;
+import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH;
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupController.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupController.java
new file mode 100644
index 0000000000000000000000000000000000000000..c3e03c10313aa21b2eba3f5c48b5134df3715ea6
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupController.java
@@ -0,0 +1,32 @@
+package org.briarproject.briar.android.privategroup.conversation;
+
+import android.support.annotation.UiThread;
+
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.briar.android.threaded.ThreadListController;
+import org.briarproject.briar.api.privategroup.GroupMessageHeader;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.privategroup.Visibility;
+
+public interface GroupController
+		extends
+		ThreadListController<PrivateGroup, GroupMessageItem, GroupMessageHeader> {
+
+	void loadLocalAuthor(
+			ResultExceptionHandler<LocalAuthor, DbException> handler);
+
+	void isDissolved(
+			ResultExceptionHandler<Boolean, DbException> handler);
+
+	interface GroupListener extends ThreadListListener<GroupMessageHeader> {
+		@UiThread
+		void onContactRelationshipRevealed(AuthorId memberId, Visibility v);
+
+		@UiThread
+		void onGroupDissolved();
+	}
+
+}
diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupControllerImpl.java
similarity index 75%
rename from briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupControllerImpl.java
index 7cea3d521f9a3c991e66aa4d11a40e9a8041eec6..431c66a59bf602967783880eabef8d1bf7f4bb6e 100644
--- a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupControllerImpl.java
@@ -1,41 +1,44 @@
-package org.briarproject.android.privategroup.conversation;
-
-import android.support.annotation.Nullable;
-
-import org.briarproject.android.api.AndroidNotificationManager;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.android.privategroup.conversation.GroupController.GroupListener;
-import org.briarproject.android.threaded.ThreadListControllerImpl;
-import org.briarproject.api.clients.MessageTracker.GroupCount;
-import org.briarproject.api.crypto.CryptoExecutor;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.GroupDissolvedEvent;
-import org.briarproject.api.event.GroupMessageAddedEvent;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.privategroup.ContactRelationshipRevealedEvent;
-import org.briarproject.api.privategroup.GroupMessage;
-import org.briarproject.api.privategroup.GroupMessageFactory;
-import org.briarproject.api.privategroup.GroupMessageHeader;
-import org.briarproject.api.privategroup.JoinMessageHeader;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.privategroup.PrivateGroupManager;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.system.Clock;
+package org.briarproject.briar.android.privategroup.conversation;
+
+import org.briarproject.bramble.api.crypto.CryptoExecutor;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.briar.android.privategroup.conversation.GroupController.GroupListener;
+import org.briarproject.briar.android.threaded.ThreadListControllerImpl;
+import org.briarproject.briar.api.android.AndroidNotificationManager;
+import org.briarproject.briar.api.client.MessageTracker.GroupCount;
+import org.briarproject.briar.api.privategroup.GroupMessage;
+import org.briarproject.briar.api.privategroup.GroupMessageFactory;
+import org.briarproject.briar.api.privategroup.GroupMessageHeader;
+import org.briarproject.briar.api.privategroup.JoinMessageHeader;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.privategroup.PrivateGroupManager;
+import org.briarproject.briar.api.privategroup.event.ContactRelationshipRevealedEvent;
+import org.briarproject.briar.api.privategroup.event.GroupDissolvedEvent;
+import org.briarproject.briar.api.privategroup.event.GroupMessageAddedEvent;
 
 import java.util.Collection;
 import java.util.concurrent.Executor;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import static java.lang.Math.max;
 import static java.util.logging.Level.WARNING;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 class GroupControllerImpl extends
 		ThreadListControllerImpl<PrivateGroup, GroupMessageItem, GroupMessageHeader, GroupMessage, GroupListener>
 		implements GroupController {
@@ -215,7 +218,7 @@ class GroupControllerImpl extends
 
 	@Override
 	public void isDissolved(final
-			ResultExceptionHandler<Boolean, DbException> handler) {
+	ResultExceptionHandler<Boolean, DbException> handler) {
 		runOnDbThread(new Runnable() {
 			@Override
 			public void run() {
diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupConversationModule.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupConversationModule.java
similarity index 62%
rename from briar-android/src/org/briarproject/android/privategroup/conversation/GroupConversationModule.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupConversationModule.java
index 8595b461c3af8bf097368556956d4aff8655d89c..6fa1023756e2ba2a40fd10845208c16d0d6bb480 100644
--- a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupConversationModule.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupConversationModule.java
@@ -1,7 +1,7 @@
-package org.briarproject.android.privategroup.conversation;
+package org.briarproject.briar.android.privategroup.conversation;
 
-import org.briarproject.android.ActivityScope;
-import org.briarproject.android.BaseActivity;
+import org.briarproject.briar.android.activity.ActivityScope;
+import org.briarproject.briar.android.activity.BaseActivity;
 
 import dagger.Module;
 import dagger.Provides;
diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupMessageAdapter.java
similarity index 76%
rename from briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageAdapter.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupMessageAdapter.java
index 4c94438e0739060fa29bed3fc38e24e960836001..dbf8c7b96f544f31ab392e486a33e44249dc2a1d 100644
--- a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageAdapter.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupMessageAdapter.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.privategroup.conversation;
+package org.briarproject.briar.android.privategroup.conversation;
 
 import android.support.annotation.LayoutRes;
 import android.support.annotation.UiThread;
@@ -7,13 +7,13 @@ import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
-import org.briarproject.R;
-import org.briarproject.android.threaded.BaseThreadItemViewHolder;
-import org.briarproject.android.threaded.ThreadItemAdapter;
-import org.briarproject.android.threaded.ThreadPostViewHolder;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.privategroup.Visibility;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.threaded.BaseThreadItemViewHolder;
+import org.briarproject.briar.android.threaded.ThreadItemAdapter;
+import org.briarproject.briar.android.threaded.ThreadPostViewHolder;
+import org.briarproject.briar.api.privategroup.Visibility;
 
 import static android.support.v7.widget.RecyclerView.NO_POSITION;
 
@@ -23,7 +23,7 @@ class GroupMessageAdapter extends ThreadItemAdapter<GroupMessageItem> {
 
 	private boolean isCreator = false;
 
-	public GroupMessageAdapter(ThreadItemListener<GroupMessageItem> listener,
+	GroupMessageAdapter(ThreadItemListener<GroupMessageItem> listener,
 			LinearLayoutManager layoutManager) {
 		super(listener, layoutManager);
 	}
diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageItem.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupMessageItem.java
similarity index 65%
rename from briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageItem.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupMessageItem.java
index 47104e88284b78e59bcdfa5f215327ef468034b3..79ca011d282455dc4a04f4548a18e4a9075012e2 100644
--- a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupMessageItem.java
@@ -1,15 +1,15 @@
-package org.briarproject.android.privategroup.conversation;
+package org.briarproject.briar.android.privategroup.conversation;
 
 import android.support.annotation.LayoutRes;
 import android.support.annotation.UiThread;
 
-import org.briarproject.R;
-import org.briarproject.android.threaded.ThreadItem;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.Author.Status;
-import org.briarproject.api.privategroup.GroupMessageHeader;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.threaded.ThreadItem;
+import org.briarproject.briar.api.privategroup.GroupMessageHeader;
 
 import javax.annotation.concurrent.NotThreadSafe;
 
diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/JoinMessageItem.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/JoinMessageItem.java
similarity index 68%
rename from briar-android/src/org/briarproject/android/privategroup/conversation/JoinMessageItem.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/JoinMessageItem.java
index c48f781a086605c1ce92e1ef5077d5bd4e3484a8..dfdd9202237dff2bcf8c54c14aaea510648a22c0 100644
--- a/briar-android/src/org/briarproject/android/privategroup/conversation/JoinMessageItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/JoinMessageItem.java
@@ -1,11 +1,11 @@
-package org.briarproject.android.privategroup.conversation;
+package org.briarproject.briar.android.privategroup.conversation;
 
 import android.support.annotation.LayoutRes;
 import android.support.annotation.UiThread;
 
-import org.briarproject.R;
-import org.briarproject.api.privategroup.JoinMessageHeader;
-import org.briarproject.api.privategroup.Visibility;
+import org.briarproject.briar.R;
+import org.briarproject.briar.api.privategroup.JoinMessageHeader;
+import org.briarproject.briar.api.privategroup.Visibility;
 
 import javax.annotation.concurrent.NotThreadSafe;
 
@@ -32,20 +32,21 @@ class JoinMessageItem extends GroupMessageItem {
 		return false;
 	}
 
+	@Override
 	@LayoutRes
 	public int getLayout() {
 		return R.layout.list_item_group_join_notice;
 	}
 
-	public Visibility getVisibility() {
+	Visibility getVisibility() {
 		return visibility;
 	}
 
-	public void setVisibility(Visibility visibility) {
+	void setVisibility(Visibility visibility) {
 		this.visibility = visibility;
 	}
 
-	public boolean isInitial() {
+	boolean isInitial() {
 		return isInitial;
 	}
 
diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/JoinMessageItemViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/JoinMessageItemViewHolder.java
similarity index 72%
rename from briar-android/src/org/briarproject/android/privategroup/conversation/JoinMessageItemViewHolder.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/JoinMessageItemViewHolder.java
index bf8b2298415d85462a97ced2b4a89358f9769b89..5fe8cf3996b8b4a6d002febbbec1ed0307cfa676 100644
--- a/briar-android/src/org/briarproject/android/privategroup/conversation/JoinMessageItemViewHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/JoinMessageItemViewHolder.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.privategroup.conversation;
+package org.briarproject.briar.android.privategroup.conversation;
 
 import android.content.Context;
 import android.content.Intent;
@@ -8,19 +8,19 @@ import android.widget.Button;
 import android.widget.ImageView;
 import android.widget.TextView;
 
-import org.briarproject.R;
-import org.briarproject.android.privategroup.reveal.RevealContactsActivity;
-import org.briarproject.android.threaded.BaseThreadItemViewHolder;
-import org.briarproject.android.threaded.ThreadItemAdapter;
-import org.briarproject.android.threaded.ThreadItemAdapter.ThreadItemListener;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.privategroup.reveal.RevealContactsActivity;
+import org.briarproject.briar.android.threaded.BaseThreadItemViewHolder;
+import org.briarproject.briar.android.threaded.ThreadItemAdapter;
+import org.briarproject.briar.android.threaded.ThreadItemAdapter.ThreadItemListener;
 
-import static org.briarproject.android.BriarActivity.GROUP_ID;
-import static org.briarproject.android.privategroup.VisibilityHelper.getVisibilityIcon;
-import static org.briarproject.android.privategroup.VisibilityHelper.getVisibilityString;
-import static org.briarproject.api.identity.Author.Status.OURSELVES;
-import static org.briarproject.api.identity.Author.Status.UNKNOWN;
-import static org.briarproject.api.privategroup.Visibility.INVISIBLE;
+import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
+import static org.briarproject.bramble.api.identity.Author.Status.UNKNOWN;
+import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
+import static org.briarproject.briar.android.privategroup.VisibilityHelper.getVisibilityIcon;
+import static org.briarproject.briar.android.privategroup.VisibilityHelper.getVisibilityString;
+import static org.briarproject.briar.api.privategroup.Visibility.INVISIBLE;
 
 @UiThread
 @NotNullByDefault
@@ -32,7 +32,7 @@ class JoinMessageItemViewHolder
 	private final TextView info;
 	private final Button options;
 
-	public JoinMessageItemViewHolder(View v, boolean isCreator) {
+	JoinMessageItemViewHolder(View v, boolean isCreator) {
 		super(v);
 		this.isCreator = isCreator;
 		icon = (ImageView) v.findViewById(R.id.icon);
diff --git a/briar-android/src/org/briarproject/android/privategroup/creation/BaseGroupInviteActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/BaseGroupInviteActivity.java
similarity index 65%
rename from briar-android/src/org/briarproject/android/privategroup/creation/BaseGroupInviteActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/BaseGroupInviteActivity.java
index 2f7125331bd0182ae0d897723fe662c6ef726414..d115020db9b9f199af35bd223c662aa3c289f004 100644
--- a/briar-android/src/org/briarproject/android/privategroup/creation/BaseGroupInviteActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/BaseGroupInviteActivity.java
@@ -1,20 +1,19 @@
-package org.briarproject.android.privategroup.creation;
+package org.briarproject.briar.android.privategroup.creation;
 
-import org.briarproject.R;
-import org.briarproject.android.contactselection.ContactSelectorActivity;
-import org.briarproject.android.controller.handler.UiResultExceptionHandler;
-import org.briarproject.android.sharing.BaseMessageFragment.MessageFragmentListener;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.jetbrains.annotations.NotNull;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.contactselection.ContactSelectorActivity;
+import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
+import org.briarproject.briar.android.sharing.BaseMessageFragment.MessageFragmentListener;
 
 import java.util.Collection;
 
 import javax.inject.Inject;
 
-import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_INVITATION_MSG_LENGTH;
+import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_INVITATION_MSG_LENGTH;
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
@@ -40,7 +39,7 @@ public abstract class BaseGroupInviteActivity
 	}
 
 	@Override
-	public boolean onButtonClick(@NotNull String message) {
+	public boolean onButtonClick(String message) {
 		if (groupId == null)
 			throw new IllegalStateException("GroupId was not initialized");
 		controller.sendInvitation(groupId, contacts, message,
diff --git a/briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupActivity.java
similarity index 73%
rename from briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupActivity.java
index 461989c81c91c04d433a5bf65facb72f52346b85..df6c245395ef9c48e76eb7d4c88632f497195ceb 100644
--- a/briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupActivity.java
@@ -1,20 +1,26 @@
-package org.briarproject.android.privategroup.creation;
+package org.briarproject.briar.android.privategroup.creation;
 
 import android.content.Intent;
 import android.os.Bundle;
 import android.support.v4.app.ActivityCompat;
 import android.support.v4.app.ActivityOptionsCompat;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.controller.handler.UiResultExceptionHandler;
-import org.briarproject.android.privategroup.conversation.GroupActivity;
-import org.briarproject.android.sharing.BaseMessageFragment.MessageFragmentListener;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
+import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
+import org.briarproject.briar.android.sharing.BaseMessageFragment.MessageFragmentListener;
+
+import javax.annotation.Nullable;
 
 import static android.support.v4.app.ActivityOptionsCompat.makeCustomAnimation;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 public class CreateGroupActivity extends BaseGroupInviteActivity implements
 		CreateGroupListener, MessageFragmentListener {
 
@@ -24,7 +30,7 @@ public class CreateGroupActivity extends BaseGroupInviteActivity implements
 	}
 
 	@Override
-	public void onCreate(Bundle bundle) {
+	public void onCreate(@Nullable Bundle bundle) {
 		super.onCreate(bundle);
 
 		if (bundle == null) {
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupController.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupController.java
new file mode 100644
index 0000000000000000000000000000000000000000..37f7b92a840c3c14cf592f3359b8eaae40db3367
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupController.java
@@ -0,0 +1,23 @@
+package org.briarproject.briar.android.privategroup.creation;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.android.contactselection.ContactSelectorController;
+import org.briarproject.briar.android.contactselection.SelectableContactItem;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
+
+import java.util.Collection;
+
+@NotNullByDefault
+public interface CreateGroupController
+		extends ContactSelectorController<SelectableContactItem> {
+
+	void createGroup(String name,
+			ResultExceptionHandler<GroupId, DbException> result);
+
+	void sendInvitation(GroupId g, Collection<ContactId> contacts,
+			String message, ResultExceptionHandler<Void, DbException> result);
+
+}
diff --git a/briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupControllerImpl.java
similarity index 80%
rename from briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupControllerImpl.java
index 051f5a20f9d46e378107b7bcde7c6e8b677c961d..2a694c55a21eb29acf2d6a4e0389cad417ef32c5 100644
--- a/briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupControllerImpl.java
@@ -1,27 +1,27 @@
-package org.briarproject.android.privategroup.creation;
-
-import org.briarproject.android.contactselection.ContactSelectorControllerImpl;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.crypto.CryptoExecutor;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.NoSuchContactException;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.privategroup.GroupMessage;
-import org.briarproject.api.privategroup.GroupMessageFactory;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.privategroup.PrivateGroupFactory;
-import org.briarproject.api.privategroup.PrivateGroupManager;
-import org.briarproject.api.privategroup.invitation.GroupInvitationFactory;
-import org.briarproject.api.privategroup.invitation.GroupInvitationManager;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.system.Clock;
+package org.briarproject.briar.android.privategroup.creation;
+
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.crypto.CryptoExecutor;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.NoSuchContactException;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.android.contactselection.ContactSelectorControllerImpl;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.briar.api.privategroup.GroupMessage;
+import org.briarproject.briar.api.privategroup.GroupMessageFactory;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
+import org.briarproject.briar.api.privategroup.PrivateGroupManager;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager;
 
 import java.util.ArrayList;
 import java.util.Collection;
diff --git a/briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupFragment.java
similarity index 86%
rename from briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupFragment.java
index 7f21508e38d1fc0f27b66ce6f08c3bed42780447..d0adfef241e3c3cc04057753003410b9f134409e 100644
--- a/briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupFragment.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.privategroup.creation;
+package org.briarproject.briar.android.privategroup.creation;
 
 import android.content.Context;
 import android.os.Bundle;
@@ -10,11 +10,11 @@ import android.view.ViewGroup;
 import android.widget.Button;
 import android.widget.EditText;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.fragment.BaseFragment;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.fragment.BaseFragment;
 
-import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH;
+import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH;
 
 public class CreateGroupFragment extends BaseFragment {
 
diff --git a/briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupListener.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupListener.java
similarity index 58%
rename from briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupListener.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupListener.java
index 3347be1586748e6d63e9098deb407f481302d2dd..7485acfe8c0be473faff6008335200e4f16bfc4d 100644
--- a/briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupListener.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupListener.java
@@ -1,8 +1,8 @@
-package org.briarproject.android.privategroup.creation;
+package org.briarproject.briar.android.privategroup.creation;
 
 import android.view.View;
 
-import org.briarproject.android.fragment.BaseFragment.BaseFragmentListener;
+import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
 
 interface CreateGroupListener extends BaseFragmentListener {
 
diff --git a/briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupMessageFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupMessageFragment.java
similarity index 71%
rename from briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupMessageFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupMessageFragment.java
index a261ce0167313adb3b10585127d2fcfc2856aa0e..b4c3fc670707e7ac7c6bfa85e85c23763369f43d 100644
--- a/briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupMessageFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupMessageFragment.java
@@ -1,10 +1,10 @@
-package org.briarproject.android.privategroup.creation;
+package org.briarproject.briar.android.privategroup.creation;
 
 import android.support.annotation.StringRes;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.sharing.BaseMessageFragment;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.sharing.BaseMessageFragment;
 
 public class CreateGroupMessageFragment extends BaseMessageFragment {
 
diff --git a/briar-android/src/org/briarproject/android/privategroup/creation/GroupCreateModule.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/GroupCreateModule.java
similarity index 54%
rename from briar-android/src/org/briarproject/android/privategroup/creation/GroupCreateModule.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/GroupCreateModule.java
index a553cb0ed46390dc3b3526c8932d70e4f5ccd572..fc51ac8e914779bb4ad7eae556e674baf36237fc 100644
--- a/briar-android/src/org/briarproject/android/privategroup/creation/GroupCreateModule.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/GroupCreateModule.java
@@ -1,6 +1,6 @@
-package org.briarproject.android.privategroup.creation;
+package org.briarproject.briar.android.privategroup.creation;
 
-import org.briarproject.android.ActivityScope;
+import org.briarproject.briar.android.activity.ActivityScope;
 
 import dagger.Module;
 import dagger.Provides;
@@ -10,7 +10,7 @@ public class GroupCreateModule {
 
 	@ActivityScope
 	@Provides
-	protected CreateGroupController provideCreateGroupController(
+	CreateGroupController provideCreateGroupController(
 			CreateGroupControllerImpl createGroupController) {
 		return createGroupController;
 	}
diff --git a/briar-android/src/org/briarproject/android/privategroup/creation/GroupInviteActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/GroupInviteActivity.java
similarity index 71%
rename from briar-android/src/org/briarproject/android/privategroup/creation/GroupInviteActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/GroupInviteActivity.java
index 71ce49667742570a6456033fce190d62adb0d216..794a12069f792877e545099606295601df1e922e 100644
--- a/briar-android/src/org/briarproject/android/privategroup/creation/GroupInviteActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/GroupInviteActivity.java
@@ -1,12 +1,12 @@
-package org.briarproject.android.privategroup.creation;
+package org.briarproject.briar.android.privategroup.creation;
 
 import android.content.Intent;
 import android.os.Bundle;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.sharing.BaseMessageFragment.MessageFragmentListener;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.sharing.BaseMessageFragment.MessageFragmentListener;
 
 public class GroupInviteActivity extends BaseGroupInviteActivity
 		implements MessageFragmentListener {
diff --git a/briar-android/src/org/briarproject/android/privategroup/creation/GroupInviteFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/GroupInviteFragment.java
similarity index 53%
rename from briar-android/src/org/briarproject/android/privategroup/creation/GroupInviteFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/GroupInviteFragment.java
index 6e8eab60925c1bf3690c02aff33d8f07fdd8991c..44e03ab61fec0d5d59b3b7c09bfa8680ad9928c8 100644
--- a/briar-android/src/org/briarproject/android/privategroup/creation/GroupInviteFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/GroupInviteFragment.java
@@ -1,21 +1,18 @@
-package org.briarproject.android.privategroup.creation;
+package org.briarproject.briar.android.privategroup.creation;
 
-import android.content.Context;
 import android.os.Bundle;
 
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.contact.BaseContactListAdapter;
-import org.briarproject.android.contactselection.ContactSelectorAdapter;
-import org.briarproject.android.contactselection.ContactSelectorController;
-import org.briarproject.android.contactselection.ContactSelectorFragment;
-import org.briarproject.android.contactselection.SelectableContactItem;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.contactselection.ContactSelectorController;
+import org.briarproject.briar.android.contactselection.ContactSelectorFragment;
+import org.briarproject.briar.android.contactselection.SelectableContactItem;
 
 import javax.inject.Inject;
 
-import static org.briarproject.android.BriarActivity.GROUP_ID;
+import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
diff --git a/briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/invitation/GroupInvitationActivity.java
similarity index 54%
rename from briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/invitation/GroupInvitationActivity.java
index 658a611d4d31856f7f82485d929438791b13acbf..a6dd2dd4eac2efd32189160ef07b2069532323de 100644
--- a/briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/invitation/GroupInvitationActivity.java
@@ -1,17 +1,21 @@
-package org.briarproject.android.privategroup.invitation;
+package org.briarproject.briar.android.privategroup.invitation;
 
 import android.content.Context;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.sharing.InvitationActivity;
-import org.briarproject.android.sharing.InvitationAdapter;
-import org.briarproject.api.privategroup.invitation.GroupInvitationItem;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.sharing.InvitationActivity;
+import org.briarproject.briar.android.sharing.InvitationAdapter;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationItem;
 
 import javax.inject.Inject;
 
-import static org.briarproject.android.sharing.InvitationAdapter.InvitationClickListener;
+import static org.briarproject.briar.android.sharing.InvitationAdapter.InvitationClickListener;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 public class GroupInvitationActivity
 		extends InvitationActivity<GroupInvitationItem> {
 
diff --git a/briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/invitation/GroupInvitationAdapter.java
similarity index 75%
rename from briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationAdapter.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/invitation/GroupInvitationAdapter.java
index 9c818b68070b26af9db47e26e71e88b8e02dd030..540b15df56dfd5c0353791891eb8eddfd5d59c4d 100644
--- a/briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationAdapter.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/invitation/GroupInvitationAdapter.java
@@ -1,10 +1,10 @@
-package org.briarproject.android.privategroup.invitation;
+package org.briarproject.briar.android.privategroup.invitation;
 
 import android.content.Context;
 import android.view.ViewGroup;
 
-import org.briarproject.android.sharing.InvitationAdapter;
-import org.briarproject.api.privategroup.invitation.GroupInvitationItem;
+import org.briarproject.briar.android.sharing.InvitationAdapter;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationItem;
 
 class GroupInvitationAdapter extends
 		InvitationAdapter<GroupInvitationItem, GroupInvitationViewHolder> {
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/invitation/GroupInvitationController.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/invitation/GroupInvitationController.java
new file mode 100644
index 0000000000000000000000000000000000000000..0cb87e987368db5ac3886d6da47d4b6fd18c2e0d
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/invitation/GroupInvitationController.java
@@ -0,0 +1,10 @@
+package org.briarproject.briar.android.privategroup.invitation;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.android.sharing.InvitationController;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationItem;
+
+@NotNullByDefault
+interface GroupInvitationController
+		extends InvitationController<GroupInvitationItem> {
+}
diff --git a/briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/invitation/GroupInvitationControllerImpl.java
similarity index 61%
rename from briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/invitation/GroupInvitationControllerImpl.java
index 68a8690791ee680158fbb91fef13079749ea705a..b3b3f4c59093aedb38240b2a964ab59bfbedd587 100644
--- a/briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/invitation/GroupInvitationControllerImpl.java
@@ -1,20 +1,20 @@
-package org.briarproject.android.privategroup.invitation;
+package org.briarproject.briar.android.privategroup.invitation;
 
-import org.briarproject.android.controller.handler.ExceptionHandler;
-import org.briarproject.android.sharing.InvitationControllerImpl;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.GroupInvitationRequestReceivedEvent;
-import org.briarproject.api.event.GroupInvitationResponseReceivedEvent;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.privategroup.invitation.GroupInvitationItem;
-import org.briarproject.api.privategroup.invitation.GroupInvitationManager;
-import org.briarproject.api.sync.ClientId;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.briar.android.controller.handler.ExceptionHandler;
+import org.briarproject.briar.android.sharing.InvitationControllerImpl;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.privategroup.event.GroupInvitationRequestReceivedEvent;
+import org.briarproject.briar.api.privategroup.event.GroupInvitationResponseReceivedEvent;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationItem;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager;
 
 import java.util.Collection;
 import java.util.concurrent.Executor;
@@ -22,7 +22,7 @@ import java.util.concurrent.Executor;
 import javax.inject.Inject;
 
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.privategroup.PrivateGroupManager.CLIENT_ID;
+import static org.briarproject.briar.api.privategroup.PrivateGroupManager.CLIENT_ID;
 
 @NotNullByDefault
 class GroupInvitationControllerImpl
diff --git a/briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationModule.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/invitation/GroupInvitationModule.java
similarity index 69%
rename from briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationModule.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/invitation/GroupInvitationModule.java
index b6998cd19534808c01f19562ff724a1a2f77bd57..9f3278da452c13bebbf2dccbad90a32d86a588e5 100644
--- a/briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationModule.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/invitation/GroupInvitationModule.java
@@ -1,6 +1,6 @@
-package org.briarproject.android.privategroup.invitation;
+package org.briarproject.briar.android.privategroup.invitation;
 
-import org.briarproject.android.ActivityScope;
+import org.briarproject.briar.android.activity.ActivityScope;
 
 import dagger.Module;
 import dagger.Provides;
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/invitation/GroupInvitationViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/invitation/GroupInvitationViewHolder.java
new file mode 100644
index 0000000000000000000000000000000000000000..a270de3690ead6d1e5d36d5bf3b9e4c33aeec38f
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/invitation/GroupInvitationViewHolder.java
@@ -0,0 +1,30 @@
+package org.briarproject.briar.android.privategroup.invitation;
+
+import android.view.View;
+
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.sharing.InvitationAdapter.InvitationClickListener;
+import org.briarproject.briar.android.sharing.InvitationViewHolder;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationItem;
+
+import javax.annotation.Nullable;
+
+class GroupInvitationViewHolder
+		extends InvitationViewHolder<GroupInvitationItem> {
+
+	GroupInvitationViewHolder(View v) {
+		super(v);
+	}
+
+	@Override
+	public void onBind(@Nullable final GroupInvitationItem item,
+			final InvitationClickListener<GroupInvitationItem> listener) {
+		super.onBind(item, listener);
+		if (item == null) return;
+
+		sharedBy.setText(
+				sharedBy.getContext().getString(R.string.groups_created_by,
+						item.getCreator().getAuthor().getName()));
+	}
+
+}
\ No newline at end of file
diff --git a/briar-android/src/org/briarproject/android/privategroup/list/GroupItem.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupItem.java
similarity index 74%
rename from briar-android/src/org/briarproject/android/privategroup/list/GroupItem.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupItem.java
index ded8051817fd42bedf7ca52bcefd95be37e85ac6..03a9d40b07a345396dfdc3ef615c1a9e1f629d1e 100644
--- a/briar-android/src/org/briarproject/android/privategroup/list/GroupItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupItem.java
@@ -1,11 +1,11 @@
-package org.briarproject.android.privategroup.list;
-
-import org.briarproject.api.clients.MessageTracker.GroupCount;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.privategroup.GroupMessageHeader;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.sync.GroupId;
+package org.briarproject.briar.android.privategroup.list;
+
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.api.client.MessageTracker.GroupCount;
+import org.briarproject.briar.api.privategroup.GroupMessageHeader;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
 
 // This class is not thread-safe
 @NotNullByDefault
diff --git a/briar-android/src/org/briarproject/android/privategroup/list/GroupListAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupListAdapter.java
similarity index 78%
rename from briar-android/src/org/briarproject/android/privategroup/list/GroupListAdapter.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupListAdapter.java
index b5588e3440b559f2fc38989c6b30745c1d8044ff..a42bf3a78a842b4a03c8f18a6947b167b9fe7106 100644
--- a/briar-android/src/org/briarproject/android/privategroup/list/GroupListAdapter.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupListAdapter.java
@@ -1,18 +1,21 @@
-package org.briarproject.android.privategroup.list;
+package org.briarproject.briar.android.privategroup.list;
 
 import android.content.Context;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
-import org.briarproject.R;
-import org.briarproject.android.privategroup.list.GroupViewHolder.OnGroupRemoveClickListener;
-import org.briarproject.android.util.BriarAdapter;
-import org.briarproject.api.sync.GroupId;
-import org.jetbrains.annotations.NotNull;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.privategroup.list.GroupViewHolder.OnGroupRemoveClickListener;
+import org.briarproject.briar.android.util.BriarAdapter;
 
 import static android.support.v7.util.SortedList.INVALID_POSITION;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 class GroupListAdapter extends BriarAdapter<GroupItem, GroupViewHolder> {
 
 	private final OnGroupRemoveClickListener listener;
@@ -60,7 +63,7 @@ class GroupListAdapter extends BriarAdapter<GroupItem, GroupViewHolder> {
 		return a.getId().equals(b.getId());
 	}
 
-	int findItemPosition(@NotNull GroupId g) {
+	int findItemPosition(GroupId g) {
 		for (int i = 0; i < items.size(); i++) {
 			GroupItem item = items.get(i);
 			if (item.getId().equals(g)) {
diff --git a/briar-android/src/org/briarproject/android/privategroup/list/GroupListController.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupListController.java
similarity index 57%
rename from briar-android/src/org/briarproject/android/privategroup/list/GroupListController.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupListController.java
index 433c415ecd2deff434608087903f2d82cb78ffc0..e61e3c835cda2dfc43c2e06aad1482a8938b3990 100644
--- a/briar-android/src/org/briarproject/android/privategroup/list/GroupListController.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupListController.java
@@ -1,18 +1,20 @@
-package org.briarproject.android.privategroup.list;
+package org.briarproject.briar.android.privategroup.list;
 
 import android.support.annotation.UiThread;
 
-import org.briarproject.android.DestroyableContext;
-import org.briarproject.android.controller.DbController;
-import org.briarproject.android.controller.handler.ExceptionHandler;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.privategroup.GroupMessageHeader;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.android.DestroyableContext;
+import org.briarproject.briar.android.controller.DbController;
+import org.briarproject.briar.android.controller.handler.ExceptionHandler;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.briar.api.privategroup.GroupMessageHeader;
 
 import java.util.Collection;
 
-public interface GroupListController extends DbController {
+@NotNullByDefault
+interface GroupListController extends DbController {
 
 	/**
 	 * The listener must be set right after the controller was injected
diff --git a/briar-android/src/org/briarproject/android/privategroup/list/GroupListControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupListControllerImpl.java
similarity index 76%
rename from briar-android/src/org/briarproject/android/privategroup/list/GroupListControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupListControllerImpl.java
index f756f6ffcbf0e92ccb9fda122c76faf61891bcec..4c0febda6cba7bc10dd84e63a15e3828593c83ae 100644
--- a/briar-android/src/org/briarproject/android/privategroup/list/GroupListControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupListControllerImpl.java
@@ -1,30 +1,32 @@
-package org.briarproject.android.privategroup.list;
+package org.briarproject.briar.android.privategroup.list;
 
 import android.support.annotation.CallSuper;
 
-import org.briarproject.android.api.AndroidNotificationManager;
-import org.briarproject.android.controller.DbControllerImpl;
-import org.briarproject.android.controller.handler.ExceptionHandler;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.api.clients.MessageTracker.GroupCount;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.NoSuchGroupException;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.GroupAddedEvent;
-import org.briarproject.api.event.GroupDissolvedEvent;
-import org.briarproject.api.event.GroupInvitationRequestReceivedEvent;
-import org.briarproject.api.event.GroupMessageAddedEvent;
-import org.briarproject.api.event.GroupRemovedEvent;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.privategroup.GroupMessageHeader;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.privategroup.PrivateGroupManager;
-import org.briarproject.api.privategroup.invitation.GroupInvitationManager;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.NoSuchGroupException;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.event.GroupAddedEvent;
+import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
+import org.briarproject.briar.android.controller.DbControllerImpl;
+import org.briarproject.briar.android.controller.handler.ExceptionHandler;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.briar.api.android.AndroidNotificationManager;
+import org.briarproject.briar.api.client.MessageTracker.GroupCount;
+import org.briarproject.briar.api.privategroup.GroupMessageHeader;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.privategroup.PrivateGroupManager;
+import org.briarproject.briar.api.privategroup.event.GroupDissolvedEvent;
+import org.briarproject.briar.api.privategroup.event.GroupInvitationRequestReceivedEvent;
+import org.briarproject.briar.api.privategroup.event.GroupMessageAddedEvent;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -36,8 +38,10 @@ import javax.inject.Inject;
 
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.privategroup.PrivateGroupManager.CLIENT_ID;
+import static org.briarproject.briar.api.privategroup.PrivateGroupManager.CLIENT_ID;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 class GroupListControllerImpl extends DbControllerImpl
 		implements GroupListController, EventListener {
 
diff --git a/briar-android/src/org/briarproject/android/privategroup/list/GroupListFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupListFragment.java
similarity index 84%
rename from briar-android/src/org/briarproject/android/privategroup/list/GroupListFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupListFragment.java
index 6627514bee6bde622967fa8856684ed5e89a9633..2c7e29b5a3bb893148592888f8b77553787b1213 100644
--- a/briar-android/src/org/briarproject/android/privategroup/list/GroupListFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupListFragment.java
@@ -1,8 +1,7 @@
-package org.briarproject.android.privategroup.list;
+package org.briarproject.briar.android.privategroup.list;
 
 import android.content.Intent;
 import android.os.Bundle;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.support.design.widget.Snackbar;
 import android.support.v4.app.ActivityOptionsCompat;
@@ -16,25 +15,26 @@ import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.controller.handler.UiExceptionHandler;
-import org.briarproject.android.controller.handler.UiResultExceptionHandler;
-import org.briarproject.android.fragment.BaseFragment;
-import org.briarproject.android.privategroup.creation.CreateGroupActivity;
-import org.briarproject.android.privategroup.invitation.GroupInvitationActivity;
-import org.briarproject.android.privategroup.list.GroupListController.GroupListListener;
-import org.briarproject.android.privategroup.list.GroupViewHolder.OnGroupRemoveClickListener;
-import org.briarproject.android.view.BriarRecyclerView;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.privategroup.GroupMessageHeader;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.controller.handler.UiExceptionHandler;
+import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
+import org.briarproject.briar.android.fragment.BaseFragment;
+import org.briarproject.briar.android.privategroup.creation.CreateGroupActivity;
+import org.briarproject.briar.android.privategroup.invitation.GroupInvitationActivity;
+import org.briarproject.briar.android.privategroup.list.GroupListController.GroupListListener;
+import org.briarproject.briar.android.privategroup.list.GroupViewHolder.OnGroupRemoveClickListener;
+import org.briarproject.briar.android.view.BriarRecyclerView;
+import org.briarproject.briar.api.privategroup.GroupMessageHeader;
 
 import java.util.Collection;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import static android.support.design.widget.Snackbar.LENGTH_INDEFINITE;
diff --git a/briar-android/src/org/briarproject/android/privategroup/list/GroupListModule.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupListModule.java
similarity index 67%
rename from briar-android/src/org/briarproject/android/privategroup/list/GroupListModule.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupListModule.java
index 2bf5c565431fd063378b3de11eca739ea684ea35..fcf9c09d170491ff3ef17415f4b276623555e7cd 100644
--- a/briar-android/src/org/briarproject/android/privategroup/list/GroupListModule.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupListModule.java
@@ -1,6 +1,6 @@
-package org.briarproject.android.privategroup.list;
+package org.briarproject.briar.android.privategroup.list;
 
-import org.briarproject.android.ActivityScope;
+import org.briarproject.briar.android.activity.ActivityScope;
 
 import dagger.Module;
 import dagger.Provides;
diff --git a/briar-android/src/org/briarproject/android/privategroup/list/GroupViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupViewHolder.java
similarity index 82%
rename from briar-android/src/org/briarproject/android/privategroup/list/GroupViewHolder.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupViewHolder.java
index 7f3031aec9f66d0bacbab0ebca4b0be37a014561..af676fc019784c05bf5796d828e62198cb47ddf8 100644
--- a/briar-android/src/org/briarproject/android/privategroup/list/GroupViewHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupViewHolder.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.privategroup.list;
+package org.briarproject.briar.android.privategroup.list;
 
 import android.content.Context;
 import android.content.Intent;
@@ -10,20 +10,23 @@ import android.view.ViewGroup;
 import android.widget.Button;
 import android.widget.TextView;
 
-import org.briarproject.R;
-import org.briarproject.android.privategroup.conversation.GroupActivity;
-import org.briarproject.android.util.AndroidUtils;
-import org.briarproject.android.view.TextAvatarView;
-import org.briarproject.api.sync.GroupId;
-import org.jetbrains.annotations.NotNull;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
+import org.briarproject.briar.android.util.UiUtils;
+import org.briarproject.briar.android.view.TextAvatarView;
 
 import static android.support.v4.content.ContextCompat.getColor;
 import static android.support.v4.content.ContextCompat.startActivities;
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
-import static org.briarproject.android.BriarActivity.GROUP_ID;
-import static org.briarproject.android.BriarActivity.GROUP_NAME;
+import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
+import static org.briarproject.briar.android.activity.BriarActivity.GROUP_NAME;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 class GroupViewHolder extends RecyclerView.ViewHolder {
 
 	private final static float ALPHA = 0.42f;
@@ -51,7 +54,7 @@ class GroupViewHolder extends RecyclerView.ViewHolder {
 	}
 
 	void bindView(final Context ctx, final GroupItem group,
-			@NotNull final OnGroupRemoveClickListener listener) {
+			final OnGroupRemoveClickListener listener) {
 		// Avatar
 		avatar.setText(group.getName().substring(0, 1));
 		avatar.setBackgroundBytes(group.getId().getBytes());
@@ -89,7 +92,7 @@ class GroupViewHolder extends RecyclerView.ViewHolder {
 						getColor(ctx, R.color.briar_text_secondary));
 
 				long lastUpdate = group.getTimestamp();
-				date.setText(AndroidUtils.formatDate(ctx, lastUpdate));
+				date.setText(UiUtils.formatDate(ctx, lastUpdate));
 				date.setVisibility(VISIBLE);
 				avatar.setProblem(false);
 				status.setVisibility(GONE);
diff --git a/briar-android/src/org/briarproject/android/privategroup/memberlist/GroupMemberListActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/GroupMemberListActivity.java
similarity index 69%
rename from briar-android/src/org/briarproject/android/privategroup/memberlist/GroupMemberListActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/GroupMemberListActivity.java
index a3523f85596c8d90bfd44af4f4bbf3d425dbb3f6..182a336d00bb72d1c382327b9e7fd1abb33de8c4 100644
--- a/briar-android/src/org/briarproject/android/privategroup/memberlist/GroupMemberListActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/GroupMemberListActivity.java
@@ -1,22 +1,27 @@
-package org.briarproject.android.privategroup.memberlist;
+package org.briarproject.briar.android.privategroup.memberlist;
 
 import android.content.Intent;
 import android.os.Bundle;
 import android.support.v7.widget.LinearLayoutManager;
 import android.view.MenuItem;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.BriarActivity;
-import org.briarproject.android.controller.handler.UiResultExceptionHandler;
-import org.briarproject.android.view.BriarRecyclerView;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BriarActivity;
+import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
+import org.briarproject.briar.android.view.BriarRecyclerView;
 
 import java.util.Collection;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 public class GroupMemberListActivity extends BriarActivity {
 
 	@Inject
@@ -32,7 +37,7 @@ public class GroupMemberListActivity extends BriarActivity {
 	}
 
 	@Override
-	public void onCreate(final Bundle state) {
+	public void onCreate(@Nullable final Bundle state) {
 		super.onCreate(state);
 
 		setContentView(R.layout.list);
@@ -53,7 +58,8 @@ public class GroupMemberListActivity extends BriarActivity {
 	public void onStart() {
 		super.onStart();
 		controller.loadMembers(groupId,
-				new UiResultExceptionHandler<Collection<MemberListItem>, DbException>(this) {
+				new UiResultExceptionHandler<Collection<MemberListItem>, DbException>(
+						this) {
 					@Override
 					public void onResultUi(Collection<MemberListItem> members) {
 						adapter.addAll(members);
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/GroupMemberListController.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/GroupMemberListController.java
new file mode 100644
index 0000000000000000000000000000000000000000..b2d20c35e5c2822895dfcea5087e59bde0eabcfd
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/GroupMemberListController.java
@@ -0,0 +1,15 @@
+package org.briarproject.briar.android.privategroup.memberlist;
+
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.android.controller.DbController;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
+
+import java.util.Collection;
+
+public interface GroupMemberListController extends DbController {
+
+	void loadMembers(GroupId groupId,
+			ResultExceptionHandler<Collection<MemberListItem>, DbException> handler);
+
+}
diff --git a/briar-android/src/org/briarproject/android/privategroup/memberlist/GroupMemberListControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/GroupMemberListControllerImpl.java
similarity index 70%
rename from briar-android/src/org/briarproject/android/privategroup/memberlist/GroupMemberListControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/GroupMemberListControllerImpl.java
index 8a91bee96ea53089f0750d99d65d6007dee37b52..4acd6b458e82e5aa5073cf69c6c33624375a067b 100644
--- a/briar-android/src/org/briarproject/android/privategroup/memberlist/GroupMemberListControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/GroupMemberListControllerImpl.java
@@ -1,13 +1,13 @@
-package org.briarproject.android.privategroup.memberlist;
-
-import org.briarproject.android.controller.DbControllerImpl;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.privategroup.GroupMember;
-import org.briarproject.api.privategroup.PrivateGroupManager;
-import org.briarproject.api.sync.GroupId;
+package org.briarproject.briar.android.privategroup.memberlist;
+
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.android.controller.DbControllerImpl;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.briar.api.privategroup.GroupMember;
+import org.briarproject.briar.api.privategroup.PrivateGroupManager;
 
 import java.util.ArrayList;
 import java.util.Collection;
diff --git a/briar-android/src/org/briarproject/android/privategroup/memberlist/GroupMemberModule.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/GroupMemberModule.java
similarity index 69%
rename from briar-android/src/org/briarproject/android/privategroup/memberlist/GroupMemberModule.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/GroupMemberModule.java
index e92d2e94782cb17ef3742b24e17dbf6e40583086..97758b57937d2233080cf94c6d725654a9b3a270 100644
--- a/briar-android/src/org/briarproject/android/privategroup/memberlist/GroupMemberModule.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/GroupMemberModule.java
@@ -1,6 +1,6 @@
-package org.briarproject.android.privategroup.memberlist;
+package org.briarproject.briar.android.privategroup.memberlist;
 
-import org.briarproject.android.ActivityScope;
+import org.briarproject.briar.android.activity.ActivityScope;
 
 import dagger.Module;
 import dagger.Provides;
diff --git a/briar-android/src/org/briarproject/android/privategroup/memberlist/MemberListAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListAdapter.java
similarity index 88%
rename from briar-android/src/org/briarproject/android/privategroup/memberlist/MemberListAdapter.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListAdapter.java
index be28f8e8bc261daeeffa29e1a430b8c3b406ccec..5eddb41e3af51b9290b84ebc88c594a073b19f26 100644
--- a/briar-android/src/org/briarproject/android/privategroup/memberlist/MemberListAdapter.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListAdapter.java
@@ -1,12 +1,12 @@
-package org.briarproject.android.privategroup.memberlist;
+package org.briarproject.briar.android.privategroup.memberlist;
 
 import android.content.Context;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
-import org.briarproject.R;
-import org.briarproject.android.util.BriarAdapter;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.util.BriarAdapter;
 
 class MemberListAdapter extends
 		BriarAdapter<MemberListItem, MemberListItemHolder> {
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItem.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItem.java
new file mode 100644
index 0000000000000000000000000000000000000000..b055075364204eb10fa5d647447d0158ca76fc73
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItem.java
@@ -0,0 +1,37 @@
+package org.briarproject.briar.android.privategroup.memberlist;
+
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.api.privategroup.GroupMember;
+import org.briarproject.briar.api.privategroup.Visibility;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+class MemberListItem {
+
+	private final Author member;
+	private final Status status;
+	private final Visibility visibility;
+
+	MemberListItem(GroupMember groupMember) {
+		this.member = groupMember.getAuthor();
+		this.visibility = groupMember.getVisibility();
+		this.status = groupMember.getStatus();
+	}
+
+	Author getMember() {
+		return member;
+	}
+
+	Visibility getVisibility() {
+		return visibility;
+	}
+
+	Status getStatus() {
+		return status;
+	}
+
+}
diff --git a/briar-android/src/org/briarproject/android/privategroup/memberlist/MemberListItemHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItemHolder.java
similarity index 66%
rename from briar-android/src/org/briarproject/android/privategroup/memberlist/MemberListItemHolder.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItemHolder.java
index 2bf488a412e9c2e4464b4fce7e97864028532c28..5b82c5e8b016b6ca4bc0f805cec4a4c6e0976a77 100644
--- a/briar-android/src/org/briarproject/android/privategroup/memberlist/MemberListItemHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItemHolder.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.privategroup.memberlist;
+package org.briarproject.briar.android.privategroup.memberlist;
 
 import android.support.annotation.UiThread;
 import android.support.v7.widget.RecyclerView;
@@ -6,14 +6,14 @@ import android.view.View;
 import android.widget.ImageView;
 import android.widget.TextView;
 
-import org.briarproject.R;
-import org.briarproject.android.view.AuthorView;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.view.AuthorView;
 
-import static org.briarproject.android.privategroup.VisibilityHelper.getVisibilityIcon;
-import static org.briarproject.android.privategroup.VisibilityHelper.getVisibilityString;
-import static org.briarproject.api.identity.Author.Status.OURSELVES;
-import static org.briarproject.api.identity.Author.Status.UNKNOWN;
+import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
+import static org.briarproject.bramble.api.identity.Author.Status.UNKNOWN;
+import static org.briarproject.briar.android.privategroup.VisibilityHelper.getVisibilityIcon;
+import static org.briarproject.briar.android.privategroup.VisibilityHelper.getVisibilityString;
 
 @UiThread
 @NotNullByDefault
diff --git a/briar-android/src/org/briarproject/android/privategroup/reveal/GroupRevealModule.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/GroupRevealModule.java
similarity index 69%
rename from briar-android/src/org/briarproject/android/privategroup/reveal/GroupRevealModule.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/GroupRevealModule.java
index dad020c3f6630e6a15a619ab15a787a4622f953b..b2f23bf208726dcaa600217305a63749470c7816 100644
--- a/briar-android/src/org/briarproject/android/privategroup/reveal/GroupRevealModule.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/GroupRevealModule.java
@@ -1,6 +1,6 @@
-package org.briarproject.android.privategroup.reveal;
+package org.briarproject.briar.android.privategroup.reveal;
 
-import org.briarproject.android.ActivityScope;
+import org.briarproject.briar.android.activity.ActivityScope;
 
 import dagger.Module;
 import dagger.Provides;
diff --git a/briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealContactsActivity.java
similarity index 83%
rename from briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealContactsActivity.java
index 3a7bd88ee84543d67b18ee9b78c1251e123d1f77..029d770a5a718b5cf45808aa893122477570e366 100644
--- a/briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealContactsActivity.java
@@ -1,10 +1,9 @@
-package org.briarproject.android.privategroup.reveal;
+package org.briarproject.briar.android.privategroup.reveal;
 
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.os.Bundle;
 import android.support.annotation.LayoutRes;
-import android.support.annotation.Nullable;
 import android.support.v7.app.AlertDialog;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -13,19 +12,20 @@ import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.Button;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.contactselection.ContactSelectorActivity;
-import org.briarproject.android.controller.handler.UiExceptionHandler;
-import org.briarproject.android.controller.handler.UiResultExceptionHandler;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.contactselection.ContactSelectorActivity;
+import org.briarproject.briar.android.controller.handler.UiExceptionHandler;
+import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
 
 import java.util.Collection;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 @MethodsNotNullByDefault
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealContactsController.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealContactsController.java
new file mode 100644
index 0000000000000000000000000000000000000000..52c38546b56e3f9342d468faf67532e01f517e8f
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealContactsController.java
@@ -0,0 +1,25 @@
+package org.briarproject.briar.android.privategroup.reveal;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.android.contactselection.ContactSelectorController;
+import org.briarproject.briar.android.controller.handler.ExceptionHandler;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
+
+import java.util.Collection;
+
+@NotNullByDefault
+public interface RevealContactsController
+		extends ContactSelectorController<RevealableContactItem> {
+
+	void isOnboardingNeeded(
+			ResultExceptionHandler<Boolean, DbException> handler);
+
+	void onboardingShown(ExceptionHandler<DbException> handler);
+
+	void reveal(GroupId g, Collection<ContactId> contacts,
+			ExceptionHandler<DbException> handler);
+
+}
diff --git a/briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealContactsControllerImpl.java
similarity index 75%
rename from briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealContactsControllerImpl.java
index 985708f2ed172ca28c49196cedeea147b641e815..279b80710a9314f566f176fcd7150f189013a83d 100644
--- a/briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealContactsControllerImpl.java
@@ -1,22 +1,22 @@
-package org.briarproject.android.privategroup.reveal;
-
-import org.briarproject.android.controller.DbControllerImpl;
-import org.briarproject.android.controller.handler.ExceptionHandler;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.api.clients.ProtocolStateException;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.privategroup.GroupMember;
-import org.briarproject.api.privategroup.PrivateGroupManager;
-import org.briarproject.api.privategroup.invitation.GroupInvitationManager;
-import org.briarproject.api.settings.Settings;
-import org.briarproject.api.settings.SettingsManager;
-import org.briarproject.api.sync.GroupId;
+package org.briarproject.briar.android.privategroup.reveal;
+
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.settings.Settings;
+import org.briarproject.bramble.api.settings.SettingsManager;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.android.controller.DbControllerImpl;
+import org.briarproject.briar.android.controller.handler.ExceptionHandler;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.briar.api.client.ProtocolStateException;
+import org.briarproject.briar.api.privategroup.GroupMember;
+import org.briarproject.briar.api.privategroup.PrivateGroupManager;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -28,8 +28,8 @@ import javax.inject.Inject;
 
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.android.fragment.SettingsFragment.SETTINGS_NAMESPACE;
-import static org.briarproject.api.privategroup.Visibility.INVISIBLE;
+import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
+import static org.briarproject.briar.api.privategroup.Visibility.INVISIBLE;
 
 @Immutable
 @NotNullByDefault
@@ -47,7 +47,7 @@ class RevealContactsControllerImpl extends DbControllerImpl
 	private final SettingsManager settingsManager;
 
 	@Inject
-	public RevealContactsControllerImpl(@DatabaseExecutor Executor dbExecutor,
+	RevealContactsControllerImpl(@DatabaseExecutor Executor dbExecutor,
 			LifecycleManager lifecycleManager, PrivateGroupManager groupManager,
 			GroupInvitationManager groupInvitationManager,
 			ContactManager contactManager, SettingsManager settingsManager) {
diff --git a/briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealContactsFragment.java
similarity index 67%
rename from briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealContactsFragment.java
index df34de80ff9b2b09cc3f20e0a699f0ce67781520..f2648ed12d75f027c6a1a5c87e56703b4b92e4eb 100644
--- a/briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealContactsFragment.java
@@ -1,22 +1,22 @@
-package org.briarproject.android.privategroup.reveal;
+package org.briarproject.briar.android.privategroup.reveal;
 
 import android.content.Context;
 import android.os.Bundle;
 
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.contact.BaseContactListAdapter.OnContactClickListener;
-import org.briarproject.android.contactselection.BaseContactSelectorFragment;
-import org.briarproject.android.contactselection.ContactSelectorController;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.contact.BaseContactListAdapter.OnContactClickListener;
+import org.briarproject.briar.android.contactselection.BaseContactSelectorFragment;
+import org.briarproject.briar.android.contactselection.ContactSelectorController;
 
 import java.util.Collection;
 
 import javax.inject.Inject;
 
-import static org.briarproject.android.BriarActivity.GROUP_ID;
+import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
diff --git a/briar-android/src/org/briarproject/android/privategroup/reveal/RevealableContactAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealableContactAdapter.java
similarity index 77%
rename from briar-android/src/org/briarproject/android/privategroup/reveal/RevealableContactAdapter.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealableContactAdapter.java
index c84303e788225333fbd9cc9fcf5625115aee2a4a..1ac55740e45c9e1b05e27fb3ab9b90ddd82827d0 100644
--- a/briar-android/src/org/briarproject/android/privategroup/reveal/RevealableContactAdapter.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealableContactAdapter.java
@@ -1,14 +1,14 @@
-package org.briarproject.android.privategroup.reveal;
+package org.briarproject.briar.android.privategroup.reveal;
 
 import android.content.Context;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
-import org.briarproject.R;
-import org.briarproject.android.contactselection.BaseContactSelectorAdapter;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.contactselection.BaseContactSelectorAdapter;
 
 import java.util.ArrayList;
 import java.util.Collection;
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealableContactItem.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealableContactItem.java
new file mode 100644
index 0000000000000000000000000000000000000000..48ae57ecd0bd41b7c3394dcb5dc0b65e6c087c06
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealableContactItem.java
@@ -0,0 +1,26 @@
+package org.briarproject.briar.android.privategroup.reveal;
+
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.android.contactselection.SelectableContactItem;
+import org.briarproject.briar.api.privategroup.Visibility;
+
+import javax.annotation.concurrent.NotThreadSafe;
+
+@NotThreadSafe
+@NotNullByDefault
+class RevealableContactItem extends SelectableContactItem {
+
+	private final Visibility visibility;
+
+	RevealableContactItem(Contact contact, boolean selected,
+			boolean disabled, Visibility visibility) {
+		super(contact, selected, disabled);
+		this.visibility = visibility;
+	}
+
+	Visibility getVisibility() {
+		return visibility;
+	}
+
+}
diff --git a/briar-android/src/org/briarproject/android/privategroup/reveal/RevealableContactViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealableContactViewHolder.java
similarity index 54%
rename from briar-android/src/org/briarproject/android/privategroup/reveal/RevealableContactViewHolder.java
rename to briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealableContactViewHolder.java
index 3fa6a3484c7d2711983fdfcfde4ef8d3c8aa69c6..585e2f622be02cf34ccb20e0e64771f726f990b0 100644
--- a/briar-android/src/org/briarproject/android/privategroup/reveal/RevealableContactViewHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealableContactViewHolder.java
@@ -1,23 +1,23 @@
-package org.briarproject.android.privategroup.reveal;
+package org.briarproject.briar.android.privategroup.reveal;
 
 import android.support.annotation.UiThread;
 import android.view.View;
 import android.widget.ImageView;
 
-import org.briarproject.R;
-import org.briarproject.android.contact.BaseContactListAdapter.OnContactClickListener;
-import org.briarproject.android.contactselection.BaseSelectableContactHolder;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.contact.BaseContactListAdapter.OnContactClickListener;
+import org.briarproject.briar.android.contactselection.BaseSelectableContactHolder;
 
-import static org.briarproject.android.privategroup.VisibilityHelper.getVisibilityIcon;
-import static org.briarproject.android.privategroup.VisibilityHelper.getVisibilityString;
-import static org.briarproject.android.util.AndroidUtils.GREY_OUT;
-import static org.briarproject.api.privategroup.Visibility.INVISIBLE;
+import javax.annotation.Nullable;
+
+import static org.briarproject.briar.android.privategroup.VisibilityHelper.getVisibilityIcon;
+import static org.briarproject.briar.android.privategroup.VisibilityHelper.getVisibilityString;
+import static org.briarproject.briar.android.util.UiUtils.GREY_OUT;
 
 @UiThread
 @NotNullByDefault
-public class RevealableContactViewHolder
+class RevealableContactViewHolder
 		extends BaseSelectableContactHolder<RevealableContactItem> {
 
 	private final ImageView icon;
diff --git a/briar-android/src/org/briarproject/android/report/BriarReportPrimer.java b/briar-android/src/main/java/org/briarproject/briar/android/reporting/BriarReportPrimer.java
similarity index 97%
rename from briar-android/src/org/briarproject/android/report/BriarReportPrimer.java
rename to briar-android/src/main/java/org/briarproject/briar/android/reporting/BriarReportPrimer.java
index 355690a3de0b4992afaec5391f9b17f5f33f63f2..5e046e0155af0a61bed0ea7cd9cafb13393b5812 100644
--- a/briar-android/src/org/briarproject/android/report/BriarReportPrimer.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/reporting/BriarReportPrimer.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.report;
+package org.briarproject.briar.android.reporting;
 
 import android.app.ActivityManager;
 import android.bluetooth.BluetoothAdapter;
@@ -16,7 +16,7 @@ import android.support.annotation.NonNull;
 
 import org.acra.builder.ReportBuilder;
 import org.acra.builder.ReportPrimer;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.util.StringUtils;
 
 import java.io.File;
 import java.lang.reflect.InvocationTargetException;
@@ -36,7 +36,7 @@ import static android.content.Context.WIFI_SERVICE;
 import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.ConnectivityManager.TYPE_WIFI;
 import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
-import static org.briarproject.util.PrivacyUtils.scrubMacAddress;
+import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
 
 public class BriarReportPrimer implements ReportPrimer {
 
diff --git a/briar-android/src/org/briarproject/android/report/BriarReportSender.java b/briar-android/src/main/java/org/briarproject/briar/android/reporting/BriarReportSender.java
similarity index 80%
rename from briar-android/src/org/briarproject/android/report/BriarReportSender.java
rename to briar-android/src/main/java/org/briarproject/briar/android/reporting/BriarReportSender.java
index 9594cf5842b637dc5de138532d3b2fce4e3b8bac..69654f983ea993bd87659546e759c532110881a1 100644
--- a/briar-android/src/org/briarproject/android/report/BriarReportSender.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/reporting/BriarReportSender.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.report;
+package org.briarproject.briar.android.reporting;
 
 import android.content.Context;
 import android.support.annotation.NonNull;
@@ -7,9 +7,9 @@ import org.acra.collector.CrashReportData;
 import org.acra.sender.ReportSender;
 import org.acra.sender.ReportSenderException;
 import org.acra.util.JSONReportBuilder;
-import org.briarproject.android.AndroidComponent;
-import org.briarproject.android.util.AndroidUtils;
-import org.briarproject.api.reporting.DevReporter;
+import org.briarproject.bramble.api.reporting.DevReporter;
+import org.briarproject.bramble.util.AndroidUtils;
+import org.briarproject.briar.android.AndroidComponent;
 
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -23,9 +23,9 @@ public class BriarReportSender implements ReportSender {
 	private final AndroidComponent component;
 
 	@Inject
-	protected DevReporter reporter;
+	DevReporter reporter;
 
-	public BriarReportSender(AndroidComponent component) {
+	BriarReportSender(AndroidComponent component) {
 		this.component = component;
 	}
 
diff --git a/briar-android/src/org/briarproject/android/report/BriarReportSenderFactory.java b/briar-android/src/main/java/org/briarproject/briar/android/reporting/BriarReportSenderFactory.java
similarity index 83%
rename from briar-android/src/org/briarproject/android/report/BriarReportSenderFactory.java
rename to briar-android/src/main/java/org/briarproject/briar/android/reporting/BriarReportSenderFactory.java
index 6c413781fe9790ea6243e9e18cd0fdbbd24c2a4a..c474f4a8942ab30566c600545079db5bee80ad7f 100644
--- a/briar-android/src/org/briarproject/android/report/BriarReportSenderFactory.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/reporting/BriarReportSenderFactory.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.report;
+package org.briarproject.briar.android.reporting;
 
 import android.content.Context;
 import android.support.annotation.NonNull;
@@ -6,7 +6,7 @@ import android.support.annotation.NonNull;
 import org.acra.config.ACRAConfiguration;
 import org.acra.sender.ReportSender;
 import org.acra.sender.ReportSenderFactory;
-import org.briarproject.android.BriarApplication;
+import org.briarproject.briar.android.BriarApplication;
 
 public class BriarReportSenderFactory implements ReportSenderFactory {
 
diff --git a/briar-android/src/org/briarproject/android/report/DevReportActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/reporting/DevReportActivity.java
similarity index 98%
rename from briar-android/src/org/briarproject/android/report/DevReportActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/reporting/DevReportActivity.java
index 0d142757e17849f0f3069573787e6f2c91711459..82c21c0891fe84576f8e2104bb8703b84b0e69ea 100644
--- a/briar-android/src/org/briarproject/android/report/DevReportActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/reporting/DevReportActivity.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.report;
+package org.briarproject.briar.android.reporting;
 
 import android.content.Context;
 import android.content.res.Configuration;
@@ -23,8 +23,8 @@ import org.acra.ReportField;
 import org.acra.collector.CrashReportData;
 import org.acra.dialog.BaseCrashReportDialog;
 import org.acra.file.CrashReportPersister;
-import org.briarproject.R;
-import org.briarproject.android.util.UserFeedback;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.util.UserFeedback;
 
 import java.io.File;
 import java.io.IOException;
diff --git a/briar-android/src/org/briarproject/android/SettingsActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsActivity.java
similarity index 73%
rename from briar-android/src/org/briarproject/android/SettingsActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsActivity.java
index bb783a06517004ff316d1d36763daafb61c8a0be..022963eea3321ec98876c540e442bc0528c7d04c 100644
--- a/briar-android/src/org/briarproject/android/SettingsActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsActivity.java
@@ -1,13 +1,15 @@
-package org.briarproject.android;
+package org.briarproject.briar.android.settings;
 
 import android.os.Bundle;
 import android.support.v7.app.ActionBar;
 import android.view.MenuItem;
 
-import org.briarproject.R;
-import org.briarproject.android.api.AndroidExecutor;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.settings.SettingsManager;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.settings.SettingsManager;
+import org.briarproject.bramble.api.system.AndroidExecutor;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BriarActivity;
 
 import javax.inject.Inject;
 
@@ -50,6 +52,7 @@ public class SettingsActivity extends BriarActivity {
 		return eventBus;
 	}
 
+	@Override
 	public boolean onOptionsItemSelected(MenuItem item) {
 		if (item.getItemId() == android.R.id.home) {
 			onBackPressed();
diff --git a/briar-android/src/org/briarproject/android/fragment/SettingsFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsFragment.java
similarity index 93%
rename from briar-android/src/org/briarproject/android/fragment/SettingsFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsFragment.java
index 60fab261fa399c11d9893fd0a197bba367a958d3..a9b9f6690b67c0a197d9963826f234111183b3d6 100644
--- a/briar-android/src/org/briarproject/android/fragment/SettingsFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsFragment.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.fragment;
+package org.briarproject.briar.android.settings;
 
 import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
@@ -16,19 +16,20 @@ import android.view.LayoutInflater;
 import android.view.ViewGroup;
 
 import org.acra.ACRA;
-import org.briarproject.R;
-import org.briarproject.android.SettingsActivity;
-import org.briarproject.android.api.AndroidExecutor;
-import org.briarproject.android.util.UserFeedback;
-import org.briarproject.android.widget.PreferenceDividerDecoration;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.SettingsUpdatedEvent;
-import org.briarproject.api.settings.Settings;
-import org.briarproject.api.settings.SettingsManager;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.settings.Settings;
+import org.briarproject.bramble.api.settings.SettingsManager;
+import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
+import org.briarproject.bramble.api.system.AndroidExecutor;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.util.UserFeedback;
+import org.briarproject.briar.android.widget.PreferenceDividerDecoration;
 
 import java.util.logging.Logger;
 
@@ -45,6 +46,8 @@ import static android.provider.Settings.System.DEFAULT_NOTIFICATION_URI;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 public class SettingsFragment extends PreferenceFragmentCompat
 		implements EventListener, Preference.OnPreferenceChangeListener {
 
diff --git a/briar-android/src/org/briarproject/android/sharing/BaseMessageFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/BaseMessageFragment.java
similarity index 81%
rename from briar-android/src/org/briarproject/android/sharing/BaseMessageFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/BaseMessageFragment.java
index 631c4ff866c1ff69545383f10d5c6f2a22823460..67532a44a0ba2f854be1add6a49bd937e8c4b25a 100644
--- a/briar-android/src/org/briarproject/android/sharing/BaseMessageFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/BaseMessageFragment.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
 import android.content.Context;
 import android.os.Bundle;
@@ -10,16 +10,16 @@ import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
 
-import org.briarproject.R;
-import org.briarproject.android.fragment.BaseFragment;
-import org.briarproject.android.view.LargeTextInputView;
-import org.briarproject.android.view.TextInputView.TextInputListener;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.fragment.BaseFragment;
+import org.briarproject.briar.android.view.LargeTextInputView;
+import org.briarproject.briar.android.view.TextInputView.TextInputListener;
 
 import static android.support.design.widget.Snackbar.LENGTH_SHORT;
-import static org.briarproject.api.sharing.SharingConstants.MAX_INVITATION_MESSAGE_LENGTH;
-import static org.briarproject.util.StringUtils.truncateUtf8;
+import static org.briarproject.bramble.util.StringUtils.truncateUtf8;
+import static org.briarproject.briar.api.sharing.SharingConstants.MAX_INVITATION_MESSAGE_LENGTH;
 
 public abstract class BaseMessageFragment extends BaseFragment
 		implements TextInputListener {
diff --git a/briar-android/src/org/briarproject/android/sharing/BlogInvitationActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/BlogInvitationActivity.java
similarity index 61%
rename from briar-android/src/org/briarproject/android/sharing/BlogInvitationActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/BlogInvitationActivity.java
index 54ffa984dd6fdc812c3d646f890607158a61bca8..e49b63278092298c7e9cfe80786940e962ea8aef 100644
--- a/briar-android/src/org/briarproject/android/sharing/BlogInvitationActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/BlogInvitationActivity.java
@@ -1,15 +1,19 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
 import android.content.Context;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.api.sharing.SharingInvitationItem;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.api.sharing.SharingInvitationItem;
 
 import javax.inject.Inject;
 
-import static org.briarproject.android.sharing.InvitationAdapter.InvitationClickListener;
+import static org.briarproject.briar.android.sharing.InvitationAdapter.InvitationClickListener;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 public class BlogInvitationActivity
 		extends InvitationActivity<SharingInvitationItem> {
 
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/sharing/BlogInvitationController.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/BlogInvitationController.java
new file mode 100644
index 0000000000000000000000000000000000000000..c56f96a23849cc7ba1b12df6ca7c1f69bac1b818
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/BlogInvitationController.java
@@ -0,0 +1,7 @@
+package org.briarproject.briar.android.sharing;
+
+import org.briarproject.briar.api.sharing.SharingInvitationItem;
+
+public interface BlogInvitationController
+		extends InvitationController<SharingInvitationItem> {
+}
diff --git a/briar-android/src/org/briarproject/android/sharing/BlogInvitationControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/BlogInvitationControllerImpl.java
similarity index 63%
rename from briar-android/src/org/briarproject/android/sharing/BlogInvitationControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/BlogInvitationControllerImpl.java
index 8b1a318484db34164ffece97a22764d1e0c2d301..66adb424c4b5ae853740d9c30d1ca81177d1296b 100644
--- a/briar-android/src/org/briarproject/android/sharing/BlogInvitationControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/BlogInvitationControllerImpl.java
@@ -1,18 +1,18 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
-import org.briarproject.android.controller.handler.ExceptionHandler;
-import org.briarproject.api.blogs.Blog;
-import org.briarproject.api.blogs.BlogSharingManager;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.event.BlogInvitationReceivedEvent;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sharing.SharingInvitationItem;
-import org.briarproject.api.sync.ClientId;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.briar.android.controller.handler.ExceptionHandler;
+import org.briarproject.briar.api.blog.Blog;
+import org.briarproject.briar.api.blog.BlogSharingManager;
+import org.briarproject.briar.api.blog.event.BlogInvitationRequestReceivedEvent;
+import org.briarproject.briar.api.sharing.SharingInvitationItem;
 
 import java.util.Collection;
 import java.util.concurrent.Executor;
@@ -20,7 +20,7 @@ import java.util.concurrent.Executor;
 import javax.inject.Inject;
 
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.blogs.BlogManager.CLIENT_ID;
+import static org.briarproject.briar.api.blog.BlogManager.CLIENT_ID;
 
 @NotNullByDefault
 class BlogInvitationControllerImpl
@@ -41,7 +41,7 @@ class BlogInvitationControllerImpl
 	public void eventOccurred(Event e) {
 		super.eventOccurred(e);
 
-		if (e instanceof BlogInvitationReceivedEvent) {
+		if (e instanceof BlogInvitationRequestReceivedEvent) {
 			LOG.info("Blog invitation received, reloading");
 			listener.loadInvitations(false);
 		}
diff --git a/briar-android/src/org/briarproject/android/sharing/BlogSharingStatusActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/BlogSharingStatusActivity.java
similarity index 61%
rename from briar-android/src/org/briarproject/android/sharing/BlogSharingStatusActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/BlogSharingStatusActivity.java
index fed2c2a5af49d217e6c9b1b8dfe9733a3b38b2d9..ab60768c674f3a0b88ada18277aebb87b18768a1 100644
--- a/briar-android/src/org/briarproject/android/sharing/BlogSharingStatusActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/BlogSharingStatusActivity.java
@@ -1,9 +1,10 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.api.blogs.BlogSharingManager;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.db.DbException;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.api.blog.BlogSharingManager;
 
 import java.util.Collection;
 
@@ -20,16 +21,14 @@ public class BlogSharingStatusActivity extends SharingStatusActivity {
 		component.inject(this);
 	}
 
-	/**
-	 * This must only be called from the DbThread
-	 */
+	@DatabaseExecutor
+	@Override
 	protected Collection<Contact> getSharedWith() throws DbException {
 		return blogSharingManager.getSharedWith(getGroupId());
 	}
 
-	/**
-	 * This must only be called from the DbThread
-	 */
+	@DatabaseExecutor
+	@Override
 	protected Collection<Contact> getSharedBy() throws DbException {
 		return blogSharingManager.getSharedBy(getGroupId());
 	}
diff --git a/briar-android/src/org/briarproject/android/sharing/ForumInvitationActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ForumInvitationActivity.java
similarity index 61%
rename from briar-android/src/org/briarproject/android/sharing/ForumInvitationActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/ForumInvitationActivity.java
index 37dccd442617edd04b0d61e33bb26fdb216c7f3d..59fb3683b7f12005ecb3e9009bbd624f65f745af 100644
--- a/briar-android/src/org/briarproject/android/sharing/ForumInvitationActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ForumInvitationActivity.java
@@ -1,15 +1,19 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
 import android.content.Context;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.api.sharing.SharingInvitationItem;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.api.sharing.SharingInvitationItem;
 
 import javax.inject.Inject;
 
-import static org.briarproject.android.sharing.InvitationAdapter.InvitationClickListener;
+import static org.briarproject.briar.android.sharing.InvitationAdapter.InvitationClickListener;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 public class ForumInvitationActivity
 		extends InvitationActivity<SharingInvitationItem> {
 
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/sharing/ForumInvitationController.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ForumInvitationController.java
new file mode 100644
index 0000000000000000000000000000000000000000..650cf1939e78c0c42426214c6af4970794995d04
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ForumInvitationController.java
@@ -0,0 +1,7 @@
+package org.briarproject.briar.android.sharing;
+
+import org.briarproject.briar.api.sharing.SharingInvitationItem;
+
+public interface ForumInvitationController
+		extends InvitationController<SharingInvitationItem> {
+}
diff --git a/briar-android/src/org/briarproject/android/sharing/ForumInvitationControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ForumInvitationControllerImpl.java
similarity index 60%
rename from briar-android/src/org/briarproject/android/sharing/ForumInvitationControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/ForumInvitationControllerImpl.java
index 38274956ac534b1cd8ae049376a8013897e26bc3..14e669f42435b1d2dc2f2ff240734579dd674d32 100644
--- a/briar-android/src/org/briarproject/android/sharing/ForumInvitationControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ForumInvitationControllerImpl.java
@@ -1,18 +1,18 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
-import org.briarproject.android.controller.handler.ExceptionHandler;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.ForumInvitationReceivedEvent;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumSharingManager;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sharing.SharingInvitationItem;
-import org.briarproject.api.sync.ClientId;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.briar.android.controller.handler.ExceptionHandler;
+import org.briarproject.briar.api.forum.Forum;
+import org.briarproject.briar.api.forum.ForumSharingManager;
+import org.briarproject.briar.api.forum.event.ForumInvitationRequestReceivedEvent;
+import org.briarproject.briar.api.sharing.SharingInvitationItem;
 
 import java.util.Collection;
 import java.util.concurrent.Executor;
@@ -20,7 +20,7 @@ import java.util.concurrent.Executor;
 import javax.inject.Inject;
 
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.forum.ForumManager.CLIENT_ID;
+import static org.briarproject.briar.api.forum.ForumManager.CLIENT_ID;
 
 @NotNullByDefault
 class ForumInvitationControllerImpl
@@ -41,7 +41,7 @@ class ForumInvitationControllerImpl
 	public void eventOccurred(Event e) {
 		super.eventOccurred(e);
 
-		if (e instanceof ForumInvitationReceivedEvent) {
+		if (e instanceof ForumInvitationRequestReceivedEvent) {
 			LOG.info("Forum invitation received, reloading");
 			listener.loadInvitations(false);
 		}
@@ -53,7 +53,8 @@ class ForumInvitationControllerImpl
 	}
 
 	@Override
-	protected Collection<SharingInvitationItem> getInvitations() throws DbException {
+	protected Collection<SharingInvitationItem> getInvitations()
+			throws DbException {
 		return forumSharingManager.getInvitations();
 	}
 
diff --git a/briar-android/src/org/briarproject/android/sharing/ForumSharingStatusActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ForumSharingStatusActivity.java
similarity index 61%
rename from briar-android/src/org/briarproject/android/sharing/ForumSharingStatusActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/ForumSharingStatusActivity.java
index be51ab2cf4648090fc4c0d23bdfc0fbc642578fb..fc59fd9cfdea77d7f9de067e605a76157d759c47 100644
--- a/briar-android/src/org/briarproject/android/sharing/ForumSharingStatusActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ForumSharingStatusActivity.java
@@ -1,9 +1,10 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.forum.ForumSharingManager;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.api.forum.ForumSharingManager;
 
 import java.util.Collection;
 
@@ -20,16 +21,14 @@ public class ForumSharingStatusActivity extends SharingStatusActivity {
 		component.inject(this);
 	}
 
-	/**
-	 * This must only be called from the DbThread
-	 */
+	@DatabaseExecutor
+	@Override
 	protected Collection<Contact> getSharedWith() throws DbException {
 		return forumSharingManager.getSharedWith(getGroupId());
 	}
 
-	/**
-	 * This must only be called from the DbThread
-	 */
+	@DatabaseExecutor
+	@Override
 	protected Collection<Contact> getSharedBy() throws DbException {
 		return forumSharingManager.getSharedBy(getGroupId());
 	}
diff --git a/briar-android/src/org/briarproject/android/sharing/InvitationActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/InvitationActivity.java
similarity index 80%
rename from briar-android/src/org/briarproject/android/sharing/InvitationActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/InvitationActivity.java
index b398fbd8249cc6747625f0cdf2112bb536d16f3d..1f755fe366e1b3f5f46cda5a36b9ebee0b432afd 100644
--- a/briar-android/src/org/briarproject/android/sharing/InvitationActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/InvitationActivity.java
@@ -1,28 +1,29 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
 import android.content.Context;
 import android.os.Bundle;
-import android.support.annotation.Nullable;
 import android.support.annotation.StringRes;
 import android.support.v7.widget.LinearLayoutManager;
 import android.widget.Toast;
 
-import org.briarproject.R;
-import org.briarproject.android.BriarActivity;
-import org.briarproject.android.controller.handler.UiExceptionHandler;
-import org.briarproject.android.controller.handler.UiResultExceptionHandler;
-import org.briarproject.android.sharing.InvitationController.InvitationListener;
-import org.briarproject.android.view.BriarRecyclerView;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.sharing.InvitationItem;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.BriarActivity;
+import org.briarproject.briar.android.controller.handler.UiExceptionHandler;
+import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
+import org.briarproject.briar.android.sharing.InvitationController.InvitationListener;
+import org.briarproject.briar.android.view.BriarRecyclerView;
+import org.briarproject.briar.api.sharing.InvitationItem;
 
 import java.util.Collection;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
+
 import static android.widget.Toast.LENGTH_SHORT;
-import static org.briarproject.android.sharing.InvitationAdapter.InvitationClickListener;
+import static org.briarproject.briar.android.sharing.InvitationAdapter.InvitationClickListener;
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
diff --git a/briar-android/src/org/briarproject/android/sharing/InvitationAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/InvitationAdapter.java
similarity index 85%
rename from briar-android/src/org/briarproject/android/sharing/InvitationAdapter.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/InvitationAdapter.java
index 5afd24c07c66b2750810dc195a6505dcc44e234e..1b3a4fecc64e066e6398469dfc6b95deebdc8228 100644
--- a/briar-android/src/org/briarproject/android/sharing/InvitationAdapter.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/InvitationAdapter.java
@@ -1,13 +1,13 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
 import android.content.Context;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
-import org.briarproject.R;
-import org.briarproject.android.util.BriarAdapter;
-import org.briarproject.api.sharing.InvitationItem;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.util.BriarAdapter;
+import org.briarproject.briar.api.sharing.InvitationItem;
 
 public abstract class InvitationAdapter<I extends InvitationItem, VH extends InvitationViewHolder<I>>
 		extends BriarAdapter<I, VH> {
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/sharing/InvitationController.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/InvitationController.java
new file mode 100644
index 0000000000000000000000000000000000000000..f4e3949c04b3c48272c5921593f9bf608c7a9015
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/InvitationController.java
@@ -0,0 +1,28 @@
+package org.briarproject.briar.android.sharing;
+
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.android.controller.ActivityLifecycleController;
+import org.briarproject.briar.android.controller.handler.ExceptionHandler;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.briar.api.sharing.InvitationItem;
+
+import java.util.Collection;
+
+@NotNullByDefault
+public interface InvitationController<I extends InvitationItem>
+		extends ActivityLifecycleController {
+
+	void loadInvitations(boolean clear,
+			ResultExceptionHandler<Collection<I>, DbException> handler);
+
+	void respondToInvitation(I item, boolean accept,
+			ExceptionHandler<DbException> handler);
+
+	interface InvitationListener {
+
+		void loadInvitations(boolean clear);
+
+	}
+
+}
diff --git a/briar-android/src/org/briarproject/android/sharing/InvitationControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/InvitationControllerImpl.java
similarity index 72%
rename from briar-android/src/org/briarproject/android/sharing/InvitationControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/InvitationControllerImpl.java
index b1b52aca58da293c7fe0a19fc9b488fe9a4242d2..0c0a9f426d73ada6b586a386edc39f39c8bb5575 100644
--- a/briar-android/src/org/briarproject/android/sharing/InvitationControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/InvitationControllerImpl.java
@@ -1,21 +1,23 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
 import android.app.Activity;
 import android.support.annotation.CallSuper;
 
-import org.briarproject.android.controller.DbControllerImpl;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.event.ContactRemovedEvent;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.GroupAddedEvent;
-import org.briarproject.api.event.GroupRemovedEvent;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.sharing.InvitationItem;
-import org.briarproject.api.sync.ClientId;
+import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.event.GroupAddedEvent;
+import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
+import org.briarproject.briar.android.controller.DbControllerImpl;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.briar.api.sharing.InvitationItem;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -25,6 +27,8 @@ import java.util.logging.Logger;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 public abstract class InvitationControllerImpl<I extends InvitationItem>
 		extends DbControllerImpl
 		implements InvitationController<I>, EventListener {
diff --git a/briar-android/src/org/briarproject/android/sharing/InvitationViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/InvitationViewHolder.java
similarity index 84%
rename from briar-android/src/org/briarproject/android/sharing/InvitationViewHolder.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/InvitationViewHolder.java
index 2c8337c13c3271ac3eb95d601f6bb45739c55e97..80adcfce29bc6bd979aa34e836b92dd8d6eaddb1 100644
--- a/briar-android/src/org/briarproject/android/sharing/InvitationViewHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/InvitationViewHolder.java
@@ -1,16 +1,17 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
 import android.support.annotation.CallSuper;
-import android.support.annotation.Nullable;
 import android.support.v7.widget.RecyclerView;
 import android.view.View;
 import android.widget.Button;
 import android.widget.TextView;
 
-import org.briarproject.R;
-import org.briarproject.android.sharing.InvitationAdapter.InvitationClickListener;
-import org.briarproject.android.view.TextAvatarView;
-import org.briarproject.api.sharing.InvitationItem;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.sharing.InvitationAdapter.InvitationClickListener;
+import org.briarproject.briar.android.view.TextAvatarView;
+import org.briarproject.briar.api.sharing.InvitationItem;
+
+import javax.annotation.Nullable;
 
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
diff --git a/briar-android/src/org/briarproject/android/sharing/ShareActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareActivity.java
similarity index 66%
rename from briar-android/src/org/briarproject/android/sharing/ShareActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareActivity.java
index 8924d5300af0646f64d54a2efd031838d6c5ebc8..6db3a0694d6381537f80b166c8213f3af261ac05 100644
--- a/briar-android/src/org/briarproject/android/sharing/ShareActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareActivity.java
@@ -1,22 +1,22 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
 import android.content.Intent;
 import android.os.Bundle;
 import android.support.annotation.UiThread;
 
-import org.briarproject.R;
-import org.briarproject.android.contactselection.ContactSelectorActivity;
-import org.briarproject.android.contactselection.ContactSelectorFragment;
-import org.briarproject.android.sharing.BaseMessageFragment.MessageFragmentListener;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.contactselection.ContactSelectorActivity;
+import org.briarproject.briar.android.contactselection.ContactSelectorFragment;
+import org.briarproject.briar.android.sharing.BaseMessageFragment.MessageFragmentListener;
 
 import java.util.Collection;
 
+import javax.annotation.Nullable;
+
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
 public abstract class ShareActivity extends ContactSelectorActivity
@@ -53,7 +53,7 @@ public abstract class ShareActivity extends ContactSelectorActivity
 
 	@UiThread
 	@Override
-	public boolean onButtonClick(@NotNull String message) {
+	public boolean onButtonClick(String message) {
 		share(contacts, message);
 		setResult(RESULT_OK);
 		supportFinishAfterTransition();
diff --git a/briar-android/src/org/briarproject/android/sharing/ShareBlogActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareBlogActivity.java
similarity index 68%
rename from briar-android/src/org/briarproject/android/sharing/ShareBlogActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareBlogActivity.java
index 4303f3415f85080c0fa9ec5756b871fbb21b0ed6..f395eda7bea08a1ef8286edf25f488d2c91d251c 100644
--- a/briar-android/src/org/briarproject/android/sharing/ShareBlogActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareBlogActivity.java
@@ -1,23 +1,23 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
 import android.os.Bundle;
 import android.widget.Toast;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.controller.handler.UiExceptionHandler;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.controller.handler.UiExceptionHandler;
 
 import java.util.Collection;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import static android.widget.Toast.LENGTH_SHORT;
-import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareBlogController.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareBlogController.java
new file mode 100644
index 0000000000000000000000000000000000000000..55ed2b46c4d635a68e4626b7b4699f53efcd4e1a
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareBlogController.java
@@ -0,0 +1,18 @@
+package org.briarproject.briar.android.sharing;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.android.contactselection.ContactSelectorController;
+import org.briarproject.briar.android.contactselection.SelectableContactItem;
+import org.briarproject.briar.android.controller.handler.ExceptionHandler;
+
+import java.util.Collection;
+
+public interface ShareBlogController
+		extends ContactSelectorController<SelectableContactItem> {
+
+	void share(GroupId g, Collection<ContactId> contacts, String msg,
+			ExceptionHandler<DbException> handler);
+
+}
diff --git a/briar-android/src/org/briarproject/android/sharing/ShareBlogControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareBlogControllerImpl.java
similarity index 59%
rename from briar-android/src/org/briarproject/android/sharing/ShareBlogControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareBlogControllerImpl.java
index 33e21f3d153f71b140ccc12508ee5397bc54c13b..401b88ecb0ece5bbb766941e09097833f70f8f88 100644
--- a/briar-android/src/org/briarproject/android/sharing/ShareBlogControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareBlogControllerImpl.java
@@ -1,18 +1,18 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
-import org.briarproject.android.contactselection.ContactSelectorControllerImpl;
-import org.briarproject.android.controller.handler.ExceptionHandler;
-import org.briarproject.api.blogs.BlogSharingManager;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.NoSuchContactException;
-import org.briarproject.api.db.NoSuchGroupException;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.NoSuchContactException;
+import org.briarproject.bramble.api.db.NoSuchGroupException;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.android.contactselection.ContactSelectorControllerImpl;
+import org.briarproject.briar.android.controller.handler.ExceptionHandler;
+import org.briarproject.briar.api.blog.BlogSharingManager;
 
 import java.util.Collection;
 import java.util.concurrent.Executor;
@@ -34,10 +34,8 @@ class ShareBlogControllerImpl extends ContactSelectorControllerImpl
 	private final BlogSharingManager blogSharingManager;
 
 	@Inject
-	public ShareBlogControllerImpl(
-			@DatabaseExecutor Executor dbExecutor,
-			LifecycleManager lifecycleManager,
-			ContactManager contactManager,
+	ShareBlogControllerImpl(@DatabaseExecutor Executor dbExecutor,
+			LifecycleManager lifecycleManager, ContactManager contactManager,
 			BlogSharingManager blogSharingManager) {
 		super(dbExecutor, lifecycleManager, contactManager);
 		this.blogSharingManager = blogSharingManager;
diff --git a/briar-android/src/org/briarproject/android/sharing/ShareBlogFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareBlogFragment.java
similarity index 56%
rename from briar-android/src/org/briarproject/android/sharing/ShareBlogFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareBlogFragment.java
index f055b4fb6359b3dc05a5b679838938422fbb06c6..ab0d97e1c051e02a997190868991874cb1f649ee 100644
--- a/briar-android/src/org/briarproject/android/sharing/ShareBlogFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareBlogFragment.java
@@ -1,18 +1,18 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
 import android.os.Bundle;
 
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.contactselection.ContactSelectorController;
-import org.briarproject.android.contactselection.ContactSelectorFragment;
-import org.briarproject.android.contactselection.SelectableContactItem;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.contactselection.ContactSelectorController;
+import org.briarproject.briar.android.contactselection.ContactSelectorFragment;
+import org.briarproject.briar.android.contactselection.SelectableContactItem;
 
 import javax.inject.Inject;
 
-import static org.briarproject.android.BriarActivity.GROUP_ID;
+import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
diff --git a/briar-android/src/org/briarproject/android/sharing/ShareBlogMessageFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareBlogMessageFragment.java
similarity index 87%
rename from briar-android/src/org/briarproject/android/sharing/ShareBlogMessageFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareBlogMessageFragment.java
index ccee4d8fecb028dcbf9e2ec970fd2115f7e5c2af..a963664fa0d64f43e1aa045bbc18d5ece14c197e 100644
--- a/briar-android/src/org/briarproject/android/sharing/ShareBlogMessageFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareBlogMessageFragment.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
 import android.os.Bundle;
 import android.support.annotation.StringRes;
@@ -6,8 +6,8 @@ import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
 
 public class ShareBlogMessageFragment extends BaseMessageFragment {
 
diff --git a/briar-android/src/org/briarproject/android/sharing/ShareForumActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareForumActivity.java
similarity index 68%
rename from briar-android/src/org/briarproject/android/sharing/ShareForumActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareForumActivity.java
index 51689bc2f3da60b65f1ae5bcf9e78b99e546d989..f32a49cc8b54fa4ca152013fee710977825d8290 100644
--- a/briar-android/src/org/briarproject/android/sharing/ShareForumActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareForumActivity.java
@@ -1,23 +1,23 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
 import android.os.Bundle;
 import android.widget.Toast;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.controller.handler.UiExceptionHandler;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.controller.handler.UiExceptionHandler;
 
 import java.util.Collection;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import static android.widget.Toast.LENGTH_SHORT;
-import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareForumController.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareForumController.java
new file mode 100644
index 0000000000000000000000000000000000000000..eedf45dfc092666a62b8396491a031069e09d3e7
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareForumController.java
@@ -0,0 +1,18 @@
+package org.briarproject.briar.android.sharing;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.android.contactselection.ContactSelectorController;
+import org.briarproject.briar.android.contactselection.SelectableContactItem;
+import org.briarproject.briar.android.controller.handler.ExceptionHandler;
+
+import java.util.Collection;
+
+public interface ShareForumController
+		extends ContactSelectorController<SelectableContactItem> {
+
+	void share(GroupId g, Collection<ContactId> contacts, String msg,
+			ExceptionHandler<DbException> handler);
+
+}
diff --git a/briar-android/src/org/briarproject/android/sharing/ShareForumControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareForumControllerImpl.java
similarity index 59%
rename from briar-android/src/org/briarproject/android/sharing/ShareForumControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareForumControllerImpl.java
index 73eba81b672faadf43ff9b285cab6e4e9e464f3e..93a16307b2717a856d085901b87d353969cd17d7 100644
--- a/briar-android/src/org/briarproject/android/sharing/ShareForumControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareForumControllerImpl.java
@@ -1,18 +1,18 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
-import org.briarproject.android.contactselection.ContactSelectorControllerImpl;
-import org.briarproject.android.controller.handler.ExceptionHandler;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.NoSuchContactException;
-import org.briarproject.api.db.NoSuchGroupException;
-import org.briarproject.api.forum.ForumSharingManager;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.NoSuchContactException;
+import org.briarproject.bramble.api.db.NoSuchGroupException;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.android.contactselection.ContactSelectorControllerImpl;
+import org.briarproject.briar.android.controller.handler.ExceptionHandler;
+import org.briarproject.briar.api.forum.ForumSharingManager;
 
 import java.util.Collection;
 import java.util.concurrent.Executor;
@@ -34,10 +34,8 @@ class ShareForumControllerImpl extends ContactSelectorControllerImpl
 	private final ForumSharingManager forumSharingManager;
 
 	@Inject
-	public ShareForumControllerImpl(
-			@DatabaseExecutor Executor dbExecutor,
-			LifecycleManager lifecycleManager,
-			ContactManager contactManager,
+	ShareForumControllerImpl(@DatabaseExecutor Executor dbExecutor,
+			LifecycleManager lifecycleManager, ContactManager contactManager,
 			ForumSharingManager forumSharingManager) {
 		super(dbExecutor, lifecycleManager, contactManager);
 		this.forumSharingManager = forumSharingManager;
diff --git a/briar-android/src/org/briarproject/android/sharing/ShareForumFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareForumFragment.java
similarity index 56%
rename from briar-android/src/org/briarproject/android/sharing/ShareForumFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareForumFragment.java
index 9ed8c9e58c2c4f9330891e1b9a12782e6df9e64f..c7bdd59fda8047ec0d9745364b01f54b78847545 100644
--- a/briar-android/src/org/briarproject/android/sharing/ShareForumFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareForumFragment.java
@@ -1,18 +1,18 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
 import android.os.Bundle;
 
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.contactselection.ContactSelectorController;
-import org.briarproject.android.contactselection.ContactSelectorFragment;
-import org.briarproject.android.contactselection.SelectableContactItem;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.contactselection.ContactSelectorController;
+import org.briarproject.briar.android.contactselection.ContactSelectorFragment;
+import org.briarproject.briar.android.contactselection.SelectableContactItem;
 
 import javax.inject.Inject;
 
-import static org.briarproject.android.BriarActivity.GROUP_ID;
+import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
diff --git a/briar-android/src/org/briarproject/android/sharing/ShareForumMessageFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareForumMessageFragment.java
similarity index 87%
rename from briar-android/src/org/briarproject/android/sharing/ShareForumMessageFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareForumMessageFragment.java
index a3faeb630de35101d606b194260be9aa3971c100..8a30df49ea013da8a840e1eaf6442430d2555e31 100644
--- a/briar-android/src/org/briarproject/android/sharing/ShareForumMessageFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareForumMessageFragment.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
 import android.os.Bundle;
 import android.support.annotation.StringRes;
@@ -6,8 +6,8 @@ import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
 
 public class ShareForumMessageFragment extends BaseMessageFragment {
 
diff --git a/briar-android/src/org/briarproject/android/sharing/SharingInvitationAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/SharingInvitationAdapter.java
similarity index 75%
rename from briar-android/src/org/briarproject/android/sharing/SharingInvitationAdapter.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/SharingInvitationAdapter.java
index 2964c9b930db4f376bd028d2d5d3b0db98d8796d..58732021afb519beb7c61a724d27887f233f6068 100644
--- a/briar-android/src/org/briarproject/android/sharing/SharingInvitationAdapter.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/SharingInvitationAdapter.java
@@ -1,14 +1,15 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
 import android.content.Context;
 import android.view.ViewGroup;
 
-import org.briarproject.api.sharing.SharingInvitationItem;
+import org.briarproject.briar.api.sharing.SharingInvitationItem;
 
 class SharingInvitationAdapter extends
 		InvitationAdapter<SharingInvitationItem, SharingInvitationViewHolder> {
 
-	SharingInvitationAdapter(Context ctx, InvitationClickListener listener) {
+	SharingInvitationAdapter(Context ctx,
+			InvitationClickListener<SharingInvitationItem> listener) {
 		super(ctx, SharingInvitationItem.class, listener);
 	}
 
diff --git a/briar-android/src/org/briarproject/android/sharing/SharingInvitationViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/SharingInvitationViewHolder.java
similarity index 64%
rename from briar-android/src/org/briarproject/android/sharing/SharingInvitationViewHolder.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/SharingInvitationViewHolder.java
index b10672468f1ada6f65c482c3c84576f4020527af..28c03f473ea4ab894d2bb68ce2c6d4d463f1d7bc 100644
--- a/briar-android/src/org/briarproject/android/sharing/SharingInvitationViewHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/SharingInvitationViewHolder.java
@@ -1,20 +1,21 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
-import android.support.annotation.Nullable;
 import android.view.View;
 
-import org.briarproject.R;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.sharing.SharingInvitationItem;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.R;
+import org.briarproject.briar.api.sharing.SharingInvitationItem;
 
 import java.util.ArrayList;
 import java.util.Collection;
 
-public class SharingInvitationViewHolder
+import javax.annotation.Nullable;
+
+class SharingInvitationViewHolder
 		extends InvitationViewHolder<SharingInvitationItem> {
 
-	public SharingInvitationViewHolder(View v) {
+	SharingInvitationViewHolder(View v) {
 		super(v);
 	}
 
diff --git a/briar-android/src/org/briarproject/android/sharing/SharingModule.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/SharingModule.java
similarity index 84%
rename from briar-android/src/org/briarproject/android/sharing/SharingModule.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/SharingModule.java
index de632f6b132658b3337763a5405d4f6aafd8c81a..50bcceb2ba3c88f333d584105da64b2b575ef6fa 100644
--- a/briar-android/src/org/briarproject/android/sharing/SharingModule.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/SharingModule.java
@@ -1,7 +1,7 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
-import org.briarproject.android.ActivityScope;
-import org.briarproject.android.BaseActivity;
+import org.briarproject.briar.android.activity.ActivityScope;
+import org.briarproject.briar.android.activity.BaseActivity;
 
 import dagger.Module;
 import dagger.Provides;
diff --git a/briar-android/src/org/briarproject/android/sharing/SharingStatusActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/SharingStatusActivity.java
similarity index 90%
rename from briar-android/src/org/briarproject/android/sharing/SharingStatusActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/SharingStatusActivity.java
index 4e62598ae54fff52118e03c71a7cd31736f21675..543aaf6cd8f27efaae03f092d469e53015a62c8d 100644
--- a/briar-android/src/org/briarproject/android/sharing/SharingStatusActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/SharingStatusActivity.java
@@ -1,17 +1,17 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
 import android.content.Intent;
 import android.os.Bundle;
 import android.support.v7.widget.LinearLayoutManager;
 import android.view.MenuItem;
 
-import org.briarproject.R;
-import org.briarproject.android.BriarActivity;
-import org.briarproject.android.contact.ContactItem;
-import org.briarproject.android.view.BriarRecyclerView;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.BriarActivity;
+import org.briarproject.briar.android.contact.ContactItem;
+import org.briarproject.briar.android.view.BriarRecyclerView;
 
 import java.util.ArrayList;
 import java.util.Collection;
diff --git a/briar-android/src/org/briarproject/android/sharing/SharingStatusAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/SharingStatusAdapter.java
similarity index 68%
rename from briar-android/src/org/briarproject/android/sharing/SharingStatusAdapter.java
rename to briar-android/src/main/java/org/briarproject/briar/android/sharing/SharingStatusAdapter.java
index 539d9f81f237fc74dc38ac391c25bb1e92f3f25d..b751b9b2f8051a2684163c94b5beb614b06459f0 100644
--- a/briar-android/src/org/briarproject/android/sharing/SharingStatusAdapter.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/SharingStatusAdapter.java
@@ -1,14 +1,14 @@
-package org.briarproject.android.sharing;
+package org.briarproject.briar.android.sharing;
 
 import android.content.Context;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
-import org.briarproject.R;
-import org.briarproject.android.contact.BaseContactListAdapter;
-import org.briarproject.android.contact.ContactItem;
-import org.briarproject.android.contact.ContactItemViewHolder;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.contact.BaseContactListAdapter;
+import org.briarproject.briar.android.contact.ContactItem;
+import org.briarproject.briar.android.contact.ContactItemViewHolder;
 
 class SharingStatusAdapter extends
 		BaseContactListAdapter<ContactItem, ContactItemViewHolder<ContactItem>> {
diff --git a/briar-android/src/org/briarproject/android/ExpiredActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/splash/ExpiredActivity.java
similarity index 69%
rename from briar-android/src/org/briarproject/android/ExpiredActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/splash/ExpiredActivity.java
index 65e4c60769de8e7ffebca7fa8a3b4444f603e9e2..3569cc70b8b6ea59be33466c31fe4fd9c99d196a 100644
--- a/briar-android/src/org/briarproject/android/ExpiredActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/splash/ExpiredActivity.java
@@ -1,12 +1,12 @@
-package org.briarproject.android;
+package org.briarproject.briar.android.splash;
 
 import android.app.Activity;
 import android.os.Bundle;
 
-import org.briarproject.R;
+import org.briarproject.briar.R;
 
 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
-import static org.briarproject.android.TestingConstants.PREVENT_SCREENSHOTS;
+import static org.briarproject.briar.android.TestingConstants.PREVENT_SCREENSHOTS;
 
 public class ExpiredActivity extends Activity {
 
diff --git a/briar-android/src/org/briarproject/android/SplashScreenActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/splash/SplashScreenActivity.java
similarity index 78%
rename from briar-android/src/org/briarproject/android/SplashScreenActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/splash/SplashScreenActivity.java
index 12d29096b81f2fe40f7d7e2216972b9e9234148b..6b40803d0c5a033a2fc910c454f9c46f382b9584 100644
--- a/briar-android/src/org/briarproject/android/SplashScreenActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/splash/SplashScreenActivity.java
@@ -1,4 +1,4 @@
-package org.briarproject.android;
+package org.briarproject.briar.android.splash;
 
 import android.content.Intent;
 import android.os.Bundle;
@@ -8,16 +8,20 @@ import android.os.StrictMode.ThreadPolicy;
 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.bramble.api.system.AndroidExecutor;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BaseActivity;
+import org.briarproject.briar.android.controller.ConfigController;
+import org.briarproject.briar.android.login.SetupActivity;
+import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
 
 import java.util.logging.Logger;
 
 import javax.inject.Inject;
 
-import static org.briarproject.android.TestingConstants.DEFAULT_LOG_LEVEL;
-import static org.briarproject.android.TestingConstants.TESTING;
+import static org.briarproject.briar.android.TestingConstants.DEFAULT_LOG_LEVEL;
+import static org.briarproject.briar.android.TestingConstants.TESTING;
 
 public class SplashScreenActivity extends BaseActivity {
 
diff --git a/briar-android/src/org/briarproject/android/threaded/BaseThreadItemViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/BaseThreadItemViewHolder.java
similarity index 90%
rename from briar-android/src/org/briarproject/android/threaded/BaseThreadItemViewHolder.java
rename to briar-android/src/main/java/org/briarproject/briar/android/threaded/BaseThreadItemViewHolder.java
index af8e800b33ed2d308198ffc58a914279a10abea2..6bdbb9c773cbfdeea9fdda46ab23353516a48320 100644
--- a/briar-android/src/org/briarproject/android/threaded/BaseThreadItemViewHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/BaseThreadItemViewHolder.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.threaded;
+package org.briarproject.briar.android.threaded;
 
 import android.animation.Animator;
 import android.animation.ArgbEvaluator;
@@ -13,11 +13,11 @@ import android.view.View;
 import android.view.ViewGroup;
 import android.widget.TextView;
 
-import org.briarproject.R;
-import org.briarproject.android.threaded.ThreadItemAdapter.ThreadItemListener;
-import org.briarproject.android.view.AuthorView;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.threaded.ThreadItemAdapter.ThreadItemListener;
+import org.briarproject.briar.android.view.AuthorView;
 
 @UiThread
 @NotNullByDefault
diff --git a/briar-android/src/org/briarproject/android/threaded/NestedTreeList.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/NestedTreeList.java
similarity index 80%
rename from briar-android/src/org/briarproject/android/threaded/NestedTreeList.java
rename to briar-android/src/main/java/org/briarproject/briar/android/threaded/NestedTreeList.java
index aec3c58beb0f33dae8a671c55755821cfc6aa6cd..d4fd06b7c3956cf87df2d1d696713ffe5f4c606a 100644
--- a/briar-android/src/org/briarproject/android/threaded/NestedTreeList.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/NestedTreeList.java
@@ -1,9 +1,10 @@
-package org.briarproject.android.threaded;
+package org.briarproject.briar.android.threaded;
 
 import android.support.annotation.UiThread;
 
-import org.briarproject.api.clients.MessageTree;
-import org.briarproject.clients.MessageTreeImpl;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.api.client.MessageTree;
+import org.briarproject.briar.client.MessageTreeImpl;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -11,6 +12,7 @@ import java.util.Iterator;
 import java.util.List;
 
 @UiThread
+@NotNullByDefault
 public class NestedTreeList<T extends MessageTree.MessageNode>
 		implements Iterable<T> {
 
diff --git a/briar-android/src/org/briarproject/android/threaded/ThreadItem.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItem.java
similarity index 70%
rename from briar-android/src/org/briarproject/android/threaded/ThreadItem.java
rename to briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItem.java
index e4c055e2b39a31c228ff72c77964d76dd48a5ce2..39d00f98f2085052e45dfe540ddafc7f4dccf0b1 100644
--- a/briar-android/src/org/briarproject/android/threaded/ThreadItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItem.java
@@ -1,18 +1,22 @@
-package org.briarproject.android.threaded;
+package org.briarproject.briar.android.threaded;
 
-import org.briarproject.api.clients.MessageTree.MessageNode;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.Author.Status;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.MessageTree.MessageNode;
 
+import javax.annotation.Nullable;
 import javax.annotation.concurrent.NotThreadSafe;
 
-import static org.briarproject.android.threaded.ThreadItemAdapter.UNDEFINED;
+import static org.briarproject.briar.android.threaded.ThreadItemAdapter.UNDEFINED;
 
 @NotThreadSafe
+@NotNullByDefault
 public abstract class ThreadItem implements MessageNode {
 
 	private final MessageId messageId;
+	@Nullable
 	private final MessageId parentId;
 	private final String text;
 	private final long timestamp;
@@ -23,8 +27,9 @@ public abstract class ThreadItem implements MessageNode {
 	private int descendantCount = 0;
 	private boolean isRead;
 
-	public ThreadItem(MessageId messageId, MessageId parentId, String text,
-			long timestamp, Author author, Status status, boolean isRead) {
+	public ThreadItem(MessageId messageId, @Nullable MessageId parentId,
+			String text, long timestamp, Author author, Status status,
+			boolean isRead) {
 		this.messageId = messageId;
 		this.parentId = parentId;
 		this.text = text;
@@ -48,6 +53,7 @@ public abstract class ThreadItem implements MessageNode {
 	}
 
 	@Override
+	@Nullable
 	public MessageId getParentId() {
 		return parentId;
 	}
diff --git a/briar-android/src/org/briarproject/android/threaded/ThreadItemAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java
similarity index 95%
rename from briar-android/src/org/briarproject/android/threaded/ThreadItemAdapter.java
rename to briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java
index 76b062508acdc56a81027b49fb24b7cbcec60771..a22316a353b7c6ac8131f7fab58e0afd451a1f21 100644
--- a/briar-android/src/org/briarproject/android/threaded/ThreadItemAdapter.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java
@@ -1,7 +1,6 @@
-package org.briarproject.android.threaded;
+package org.briarproject.briar.android.threaded;
 
 import android.animation.ValueAnimator;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
@@ -9,9 +8,9 @@ import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
-import org.briarproject.R;
-import org.briarproject.android.util.VersionedAdapter;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.util.VersionedAdapter;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -19,6 +18,8 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import javax.annotation.Nullable;
+
 import static android.support.v7.widget.RecyclerView.NO_POSITION;
 
 public class ThreadItemAdapter<I extends ThreadItem>
@@ -116,11 +117,11 @@ public class ThreadItemAdapter<I extends ThreadItem>
 
 	void scrollTo(I item) {
 		int visiblePos = getVisiblePos(item);
-		if (visiblePos == NO_POSITION && item.getParentId() != null) {
+		MessageId parentId = item.getParentId();
+		if (visiblePos == NO_POSITION && parentId != null) {
 			// The item is not visible due to being hidden by its parent item.
 			// Find the parent and make it visible and traverse up the parent
 			// chain if necessary to make the item visible
-			MessageId parentId = item.getParentId();
 			for (int i = items.indexOf(item) - 1; i >= 0; i--) {
 				I higherItem = items.get(i);
 				if (higherItem.getId().equals(parentId)) {
@@ -137,6 +138,7 @@ public class ThreadItemAdapter<I extends ThreadItem>
 					// parent or ancestor is hidden, we need to continue up the
 					// dependency chain
 					parentId = higherItem.getParentId();
+					if (parentId == null) throw new AssertionError();
 				}
 			}
 		}
diff --git a/briar-android/src/org/briarproject/android/threaded/ThreadListActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java
similarity index 88%
rename from briar-android/src/org/briarproject/android/threaded/ThreadListActivity.java
rename to briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java
index 615a3bf9d8e0be836f12ef7585a528ffd1204a3f..2c2d20793f90b61d9a7edba5e0a3b3d492cebb9b 100644
--- a/briar-android/src/org/briarproject/android/threaded/ThreadListActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java
@@ -1,10 +1,9 @@
-package org.briarproject.android.threaded;
+package org.briarproject.briar.android.threaded;
 
 import android.content.Intent;
 import android.os.Bundle;
 import android.support.annotation.CallSuper;
 import android.support.annotation.LayoutRes;
-import android.support.annotation.Nullable;
 import android.support.annotation.StringRes;
 import android.support.annotation.UiThread;
 import android.support.design.widget.Snackbar;
@@ -13,26 +12,28 @@ import android.support.v7.widget.LinearLayoutManager;
 import android.view.MenuItem;
 import android.view.View;
 
-import org.briarproject.R;
-import org.briarproject.android.BriarActivity;
-import org.briarproject.android.controller.handler.UiResultExceptionHandler;
-import org.briarproject.android.threaded.ThreadItemAdapter.ThreadItemListener;
-import org.briarproject.android.threaded.ThreadListController.ThreadListListener;
-import org.briarproject.android.view.BriarRecyclerView;
-import org.briarproject.android.view.TextInputView;
-import org.briarproject.android.view.TextInputView.TextInputListener;
-import org.briarproject.api.clients.NamedGroup;
-import org.briarproject.api.clients.PostHeader;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.BriarActivity;
+import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
+import org.briarproject.briar.android.threaded.ThreadItemAdapter.ThreadItemListener;
+import org.briarproject.briar.android.threaded.ThreadListController.ThreadListListener;
+import org.briarproject.briar.android.view.BriarRecyclerView;
+import org.briarproject.briar.android.view.TextInputView;
+import org.briarproject.briar.android.view.TextInputView.TextInputListener;
+import org.briarproject.briar.api.client.NamedGroup;
+import org.briarproject.briar.api.client.PostHeader;
 
 import java.util.Collection;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
+
 import static android.support.design.widget.Snackbar.make;
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
diff --git a/briar-android/src/org/briarproject/android/threaded/ThreadListController.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListController.java
similarity index 57%
rename from briar-android/src/org/briarproject/android/threaded/ThreadListController.java
rename to briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListController.java
index 19e339ea4fcdf0654906610eedfddc2f546d86a5..942a61d6806d69b16e739dc6f82fae1bda111193 100644
--- a/briar-android/src/org/briarproject/android/threaded/ThreadListController.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListController.java
@@ -1,19 +1,22 @@
-package org.briarproject.android.threaded;
+package org.briarproject.briar.android.threaded;
 
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 
-import org.briarproject.android.DestroyableContext;
-import org.briarproject.android.controller.ActivityLifecycleController;
-import org.briarproject.android.controller.handler.ExceptionHandler;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.api.clients.NamedGroup;
-import org.briarproject.api.clients.PostHeader;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.android.DestroyableContext;
+import org.briarproject.briar.android.controller.ActivityLifecycleController;
+import org.briarproject.briar.android.controller.handler.ExceptionHandler;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.briar.api.client.NamedGroup;
+import org.briarproject.briar.api.client.PostHeader;
 
 import java.util.Collection;
 
+import javax.annotation.Nullable;
+
+@NotNullByDefault
 public interface ThreadListController<G extends NamedGroup, I extends ThreadItem, H extends PostHeader>
 		extends ActivityLifecycleController {
 
diff --git a/briar-android/src/org/briarproject/android/threaded/ThreadListControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListControllerImpl.java
similarity index 84%
rename from briar-android/src/org/briarproject/android/threaded/ThreadListControllerImpl.java
rename to briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListControllerImpl.java
index f0c286aeddd38fce9dad99e329025f8339546bf2..a2db5242d9cd8bba435fa1cd50bf28d0e79e8a5e 100644
--- a/briar-android/src/org/briarproject/android/threaded/ThreadListControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListControllerImpl.java
@@ -1,28 +1,30 @@
-package org.briarproject.android.threaded;
+package org.briarproject.briar.android.threaded;
 
 import android.app.Activity;
 import android.support.annotation.CallSuper;
 
-import org.briarproject.android.api.AndroidNotificationManager;
-import org.briarproject.android.controller.DbControllerImpl;
-import org.briarproject.android.controller.handler.ExceptionHandler;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.android.threaded.ThreadListController.ThreadListListener;
-import org.briarproject.api.clients.NamedGroup;
-import org.briarproject.api.clients.PostHeader;
-import org.briarproject.api.clients.ThreadedMessage;
-import org.briarproject.api.crypto.CryptoExecutor;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.GroupRemovedEvent;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.crypto.CryptoExecutor;
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.android.controller.DbControllerImpl;
+import org.briarproject.briar.android.controller.handler.ExceptionHandler;
+import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.briar.android.threaded.ThreadListController.ThreadListListener;
+import org.briarproject.briar.api.android.AndroidNotificationManager;
+import org.briarproject.briar.api.client.NamedGroup;
+import org.briarproject.briar.api.client.PostHeader;
+import org.briarproject.briar.api.client.ThreadedMessage;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -36,6 +38,8 @@ import java.util.logging.Logger;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends ThreadItem, H extends PostHeader, M extends ThreadedMessage, L extends ThreadListListener<H>>
 		extends DbControllerImpl
 		implements ThreadListController<G, I, H>, EventListener {
diff --git a/briar-android/src/org/briarproject/android/threaded/ThreadPostViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadPostViewHolder.java
similarity index 89%
rename from briar-android/src/org/briarproject/android/threaded/ThreadPostViewHolder.java
rename to briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadPostViewHolder.java
index bffd1d6eaeb5a73f6b30ebedc617a37ded04b06c..87152b0d7c8cc51851ecbe7a6d799639187e9172 100644
--- a/briar-android/src/org/briarproject/android/threaded/ThreadPostViewHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadPostViewHolder.java
@@ -1,12 +1,12 @@
-package org.briarproject.android.threaded;
+package org.briarproject.briar.android.threaded;
 
 import android.support.annotation.UiThread;
 import android.view.View;
 import android.widget.TextView;
 
-import org.briarproject.R;
-import org.briarproject.android.threaded.ThreadItemAdapter.ThreadItemListener;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.threaded.ThreadItemAdapter.ThreadItemListener;
 
 import static android.view.View.GONE;
 import static android.view.View.INVISIBLE;
@@ -49,7 +49,7 @@ public class ThreadPostViewHolder<I extends ThreadItem>
 		}
 		if (item.getLevel() > 5) {
 			lvlText.setVisibility(VISIBLE);
-			lvlText.setText("" + item.getLevel());
+			lvlText.setText(String.valueOf(item.getLevel()));
 		} else {
 			lvlText.setVisibility(GONE);
 		}
diff --git a/briar-android/src/org/briarproject/android/util/BriarAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/util/BriarAdapter.java
similarity index 97%
rename from briar-android/src/org/briarproject/android/util/BriarAdapter.java
rename to briar-android/src/main/java/org/briarproject/briar/android/util/BriarAdapter.java
index 091dcc8a1b4f2a87df741142fd1ea8fbc3cf548e..889fd57f5c0e9669b906a5c7f27aa71696dee028 100644
--- a/briar-android/src/org/briarproject/android/util/BriarAdapter.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/util/BriarAdapter.java
@@ -1,7 +1,6 @@
-package org.briarproject.android.util;
+package org.briarproject.briar.android.util;
 
 import android.content.Context;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.support.v7.util.SortedList;
 import android.support.v7.widget.RecyclerView.Adapter;
@@ -9,6 +8,8 @@ import android.support.v7.widget.RecyclerView.ViewHolder;
 
 import java.util.Collection;
 
+import javax.annotation.Nullable;
+
 import static android.support.v7.util.SortedList.INVALID_POSITION;
 
 public abstract class BriarAdapter<T, V extends ViewHolder>
diff --git a/briar-android/src/org/briarproject/android/util/AndroidUtils.java b/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java
similarity index 61%
rename from briar-android/src/org/briarproject/android/util/AndroidUtils.java
rename to briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java
index 6a0e6b9da30b31ddaabd85af3077b4b18e78589f..3e65fc642146c37e70dd1b961e494b87cc08a7a3 100644
--- a/briar-android/src/org/briarproject/android/util/AndroidUtils.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java
@@ -1,9 +1,6 @@
-package org.briarproject.android.util;
+package org.briarproject.briar.android.util;
 
-import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
-import android.os.Build;
-import android.provider.Settings;
 import android.support.design.widget.TextInputLayout;
 import android.support.v4.app.FragmentManager;
 import android.support.v4.content.ContextCompat;
@@ -20,20 +17,11 @@ import android.text.style.URLSpan;
 import android.view.View;
 import android.widget.TextView;
 
-import org.briarproject.R;
-import org.briarproject.android.view.ArticleMovementMethod;
-import org.briarproject.android.widget.LinkDialogFragment;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.util.IoUtils;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.view.ArticleMovementMethod;
+import org.briarproject.briar.android.widget.LinkDialogFragment;
 
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-import static android.content.Context.MODE_PRIVATE;
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
 import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
 import static android.text.format.DateUtils.FORMAT_ABBREV_RELATIVE;
@@ -42,29 +30,12 @@ import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
 import static android.text.format.DateUtils.WEEK_IN_MILLIS;
 
-public class AndroidUtils {
+public class UiUtils {
 
 	public static final long MIN_RESOLUTION = MINUTE_IN_MILLIS;
 	public static final int TEASER_LENGTH = 320;
 	public static final float GREY_OUT = 0.5f;
 
-	// Fake Bluetooth address returned by BluetoothAdapter on API 23 and later
-	private static final String FAKE_BLUETOOTH_ADDRESS = "02:00:00:00:00:00";
-
-	private static final String STORED_REPORTS = "dev-reports";
-
-	@SuppressWarnings("deprecation")
-	public static Collection<String> getSupportedArchitectures() {
-		List<String> abis = new ArrayList<>();
-		if (Build.VERSION.SDK_INT >= 21) {
-			abis.addAll(Arrays.asList(Build.SUPPORTED_ABIS));
-		} else {
-			abis.add(Build.CPU_ABI);
-			if (Build.CPU_ABI2 != null) abis.add(Build.CPU_ABI2);
-		}
-		return abis;
-	}
-
 	public static void setError(TextInputLayout til, String error,
 			boolean set) {
 		if (set) {
@@ -74,42 +45,6 @@ public class AndroidUtils {
 		}
 	}
 
-	public static String getBluetoothAddress(Context ctx,
-			BluetoothAdapter adapter) {
-		// Return the adapter's address if it's valid and not fake
-		String address = adapter.getAddress();
-		if (isValidBluetoothAddress(address)) return address;
-		// Return the address from settings if it's valid and not fake
-		address = Settings.Secure.getString(ctx.getContentResolver(),
-				"bluetooth_address");
-		if (isValidBluetoothAddress(address)) return address;
-		// Let the caller know we can't find the address
-		return "";
-	}
-
-	private static boolean isValidBluetoothAddress(String address) {
-		return !StringUtils.isNullOrEmpty(address)
-				&& BluetoothAdapter.checkBluetoothAddress(address)
-				&& !address.equals(FAKE_BLUETOOTH_ADDRESS);
-	}
-
-	public static void deleteAppData(Context ctx) {
-		File dataDir = new File(ctx.getApplicationInfo().dataDir);
-		File[] children = dataDir.listFiles();
-		if (children != null) {
-			for (File child : children) {
-				if (!child.getName().equals("lib"))
-					IoUtils.deleteFileOrDir(child);
-			}
-		}
-		// Recreate the cache dir as some OpenGL drivers expect it to exist
-		new File(dataDir, "cache").mkdir();
-	}
-
-	public static File getReportDir(Context ctx) {
-		return ctx.getDir(STORED_REPORTS, MODE_PRIVATE);
-	}
-
 	public static String formatDate(Context ctx, long time) {
 		int flags = FORMAT_ABBREV_RELATIVE |
 				FORMAT_SHOW_DATE | FORMAT_ABBREV_TIME | FORMAT_ABBREV_MONTH;
diff --git a/briar-android/src/org/briarproject/android/util/UserFeedback.java b/briar-android/src/main/java/org/briarproject/briar/android/util/UserFeedback.java
similarity index 52%
rename from briar-android/src/org/briarproject/android/util/UserFeedback.java
rename to briar-android/src/main/java/org/briarproject/briar/android/util/UserFeedback.java
index 3c259458e51afe025ac0f2422e7d17d7b906a38d..c02134a758fef41c071b62febb499cad3e0ed591 100644
--- a/briar-android/src/org/briarproject/android/util/UserFeedback.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/util/UserFeedback.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.util;
+package org.briarproject.briar.android.util;
 
 public class UserFeedback extends Exception {
 
diff --git a/briar-android/src/org/briarproject/android/util/VersionedAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/util/VersionedAdapter.java
similarity index 95%
rename from briar-android/src/org/briarproject/android/util/VersionedAdapter.java
rename to briar-android/src/main/java/org/briarproject/briar/android/util/VersionedAdapter.java
index 26df190cd2e124e96facd474e506f180f0ceb951..de900512bcea342a800fd9acda584474babc925b 100644
--- a/briar-android/src/org/briarproject/android/util/VersionedAdapter.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/util/VersionedAdapter.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.util;
+package org.briarproject.briar.android.util;
 
 import android.support.annotation.UiThread;
 
diff --git a/briar-android/src/org/briarproject/android/view/ArticleMovementMethod.java b/briar-android/src/main/java/org/briarproject/briar/android/view/ArticleMovementMethod.java
similarity index 97%
rename from briar-android/src/org/briarproject/android/view/ArticleMovementMethod.java
rename to briar-android/src/main/java/org/briarproject/briar/android/view/ArticleMovementMethod.java
index d02ca1081e7904d00c7ca0d4c9d24c37e7bd7680..3eebcb05ea65b6731dea3c81ff3d5a235edf3c36 100644
--- a/briar-android/src/org/briarproject/android/view/ArticleMovementMethod.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/view/ArticleMovementMethod.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.briarproject.android.view;
+package org.briarproject.briar.android.view;
 
 import android.text.Layout;
 import android.text.Spannable;
diff --git a/briar-android/src/org/briarproject/android/view/AuthorView.java b/briar-android/src/main/java/org/briarproject/briar/android/view/AuthorView.java
similarity index 89%
rename from briar-android/src/org/briarproject/android/view/AuthorView.java
rename to briar-android/src/main/java/org/briarproject/briar/android/view/AuthorView.java
index 748d48516530a9ba34973a45ca534822b857d93b..4c3ee59442cfcc305bcabbe13d0594fac21be7a3 100644
--- a/briar-android/src/org/briarproject/android/view/AuthorView.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/view/AuthorView.java
@@ -1,11 +1,10 @@
-package org.briarproject.android.view;
+package org.briarproject.briar.android.view;
 
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.TypedArray;
 import android.graphics.Typeface;
 import android.support.annotation.DimenRes;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.support.v4.app.ActivityOptionsCompat;
 import android.support.v4.content.ContextCompat;
@@ -17,12 +16,14 @@ import android.widget.ImageView;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
-import org.briarproject.R;
-import org.briarproject.android.blogs.BlogActivity;
-import org.briarproject.android.util.AndroidUtils;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.Author.Status;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.blog.BlogActivity;
+import org.briarproject.briar.android.util.UiUtils;
+
+import javax.annotation.Nullable;
 
 import de.hdodenhof.circleimageview.CircleImageView;
 import im.delight.android.identicons.IdenticonDrawable;
@@ -32,8 +33,8 @@ import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
 import static android.graphics.Typeface.BOLD;
 import static android.support.v4.app.ActivityOptionsCompat.makeCustomAnimation;
 import static android.util.TypedValue.COMPLEX_UNIT_PX;
-import static org.briarproject.android.BriarActivity.GROUP_ID;
-import static org.briarproject.api.identity.Author.Status.OURSELVES;
+import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
+import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
 
 @UiThread
 public class AuthorView extends RelativeLayout {
@@ -97,7 +98,7 @@ public class AuthorView extends RelativeLayout {
 	}
 
 	public void setDate(long date) {
-		this.date.setText(AndroidUtils.formatDate(getContext(), date));
+		this.date.setText(UiUtils.formatDate(getContext(), date));
 
 		invalidate();
 		requestLayout();
diff --git a/briar-android/src/org/briarproject/android/view/BriarRecyclerView.java b/briar-android/src/main/java/org/briarproject/briar/android/view/BriarRecyclerView.java
similarity index 96%
rename from briar-android/src/org/briarproject/android/view/BriarRecyclerView.java
rename to briar-android/src/main/java/org/briarproject/briar/android/view/BriarRecyclerView.java
index 40f455404d96575b3a5a838361b01c9cf2bb7a81..1f32f5a75f574d260fcb095f2de2ef89c6acd216 100644
--- a/briar-android/src/org/briarproject/android/view/BriarRecyclerView.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/view/BriarRecyclerView.java
@@ -1,8 +1,7 @@
-package org.briarproject.android.view;
+package org.briarproject.briar.android.view;
 
 import android.content.Context;
 import android.content.res.TypedArray;
-import android.support.annotation.Nullable;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.RecyclerView.Adapter;
 import android.util.AttributeSet;
@@ -12,11 +11,13 @@ import android.widget.FrameLayout;
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
-import org.briarproject.R;
+import org.briarproject.briar.R;
 
 import java.util.logging.Logger;
 
-import static org.briarproject.android.util.AndroidUtils.MIN_RESOLUTION;
+import javax.annotation.Nullable;
+
+import static org.briarproject.briar.android.util.UiUtils.MIN_RESOLUTION;
 
 public class BriarRecyclerView extends FrameLayout {
 
diff --git a/briar-android/src/org/briarproject/android/view/BriarRecyclerViewBehavior.java b/briar-android/src/main/java/org/briarproject/briar/android/view/BriarRecyclerViewBehavior.java
similarity index 96%
rename from briar-android/src/org/briarproject/android/view/BriarRecyclerViewBehavior.java
rename to briar-android/src/main/java/org/briarproject/briar/android/view/BriarRecyclerViewBehavior.java
index cfaa352cd430dfa8895f6ebf48a06a61947ecfb4..c2226ec51663da211d861d52b8cbbf8323cf0b00 100644
--- a/briar-android/src/org/briarproject/android/view/BriarRecyclerViewBehavior.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/view/BriarRecyclerViewBehavior.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.view;
+package org.briarproject.briar.android.view;
 
 import android.content.Context;
 import android.support.design.widget.CoordinatorLayout;
diff --git a/briar-android/src/org/briarproject/android/view/LargeTextInputView.java b/briar-android/src/main/java/org/briarproject/briar/android/view/LargeTextInputView.java
similarity index 94%
rename from briar-android/src/org/briarproject/android/view/LargeTextInputView.java
rename to briar-android/src/main/java/org/briarproject/briar/android/view/LargeTextInputView.java
index 124361158bf96c77c589859f997054e3a1b5828d..6b036844932e9f9e15d4eef12ced402dbca34ba7 100644
--- a/briar-android/src/org/briarproject/android/view/LargeTextInputView.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/view/LargeTextInputView.java
@@ -1,17 +1,17 @@
-package org.briarproject.android.view;
+package org.briarproject.briar.android.view;
 
 import android.content.Context;
 import android.content.res.TypedArray;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
-import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
 import android.widget.LinearLayout;
 
-import org.briarproject.R;
+import org.briarproject.briar.R;
+
+import javax.annotation.Nullable;
 
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 
diff --git a/briar-android/src/org/briarproject/android/view/TextAvatarView.java b/briar-android/src/main/java/org/briarproject/briar/android/view/TextAvatarView.java
similarity index 90%
rename from briar-android/src/org/briarproject/android/view/TextAvatarView.java
rename to briar-android/src/main/java/org/briarproject/briar/android/view/TextAvatarView.java
index 2f5a2cfb2c6d486e8a19b40306837bafffc12327..36ee3b4133927f8d52ebc8c0b09f96c22ceb9b4c 100644
--- a/briar-android/src/org/briarproject/android/view/TextAvatarView.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/view/TextAvatarView.java
@@ -1,10 +1,9 @@
-package org.briarproject.android.view;
+package org.briarproject.briar.android.view;
 
 import android.content.Context;
 import android.graphics.Color;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.support.v4.content.ContextCompat;
 import android.support.v7.widget.AppCompatTextView;
@@ -13,8 +12,10 @@ import android.view.LayoutInflater;
 import android.widget.FrameLayout;
 import android.widget.TextView;
 
-import org.briarproject.R;
-import org.briarproject.api.identity.Author;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.briar.R;
+
+import javax.annotation.Nullable;
 
 import de.hdodenhof.circleimageview.CircleImageView;
 import im.delight.android.identicons.IdenticonDrawable;
@@ -22,9 +23,9 @@ import im.delight.android.identicons.IdenticonDrawable;
 @UiThread
 public class TextAvatarView extends FrameLayout {
 
-	final private AppCompatTextView character;
-	final private CircleImageView background;
-	final private TextView badge;
+	private final AppCompatTextView character;
+	private final CircleImageView background;
+	private final TextView badge;
 	private int unreadCount;
 
 	public TextAvatarView(Context context, @Nullable AttributeSet attrs) {
diff --git a/briar-android/src/org/briarproject/android/view/TextInputView.java b/briar-android/src/main/java/org/briarproject/briar/android/view/TextInputView.java
similarity index 98%
rename from briar-android/src/org/briarproject/android/view/TextInputView.java
rename to briar-android/src/main/java/org/briarproject/briar/android/view/TextInputView.java
index 5eda031674a85074fd316381c86d1f8ee9cf7f80..033747179f3cb19cab9d2936f96cf0d887f83d6a 100644
--- a/briar-android/src/org/briarproject/android/view/TextInputView.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/view/TextInputView.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.view;
+package org.briarproject.briar.android.view;
 
 import android.animation.LayoutTransition;
 import android.content.Context;
@@ -6,7 +6,6 @@ import android.content.res.TypedArray;
 import android.graphics.Rect;
 import android.os.IBinder;
 import android.support.annotation.CallSuper;
-import android.support.annotation.Nullable;
 import android.support.annotation.StringRes;
 import android.support.annotation.UiThread;
 import android.text.Editable;
@@ -17,13 +16,15 @@ import android.view.LayoutInflater;
 import android.view.View;
 import android.view.inputmethod.InputMethodManager;
 
-import org.briarproject.R;
+import org.briarproject.briar.R;
 import org.thoughtcrime.securesms.components.KeyboardAwareLinearLayout;
 import org.thoughtcrime.securesms.components.emoji.EmojiDrawer;
 import org.thoughtcrime.securesms.components.emoji.EmojiDrawer.EmojiEventListener;
 import org.thoughtcrime.securesms.components.emoji.EmojiEditText;
 import org.thoughtcrime.securesms.components.emoji.EmojiToggle;
 
+import javax.annotation.Nullable;
+
 import static android.content.Context.INPUT_METHOD_SERVICE;
 import static android.content.Context.LAYOUT_INFLATER_SERVICE;
 import static android.view.KeyEvent.KEYCODE_BACK;
diff --git a/briar-android/src/org/briarproject/android/view/TrustIndicatorView.java b/briar-android/src/main/java/org/briarproject/briar/android/view/TrustIndicatorView.java
similarity index 85%
rename from briar-android/src/org/briarproject/android/view/TrustIndicatorView.java
rename to briar-android/src/main/java/org/briarproject/briar/android/view/TrustIndicatorView.java
index 5a88acdf6850fc5244e1c690e8fb897a60cd9d67..918755eb6c2f0f32cb30dd68c635b1c23d2d68a5 100644
--- a/briar-android/src/org/briarproject/android/view/TrustIndicatorView.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/view/TrustIndicatorView.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.view;
+package org.briarproject.briar.android.view;
 
 import android.content.Context;
 import android.support.annotation.UiThread;
@@ -6,10 +6,8 @@ import android.support.v4.content.ContextCompat;
 import android.util.AttributeSet;
 import android.widget.ImageView;
 
-import org.briarproject.R;
-import org.briarproject.api.identity.Author.Status;
-
-import static org.briarproject.api.identity.Author.Status.OURSELVES;
+import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.briar.R;
 
 @UiThread
 public class TrustIndicatorView extends ImageView {
diff --git a/briar-android/src/org/briarproject/android/widget/LinkDialogFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/widget/LinkDialogFragment.java
similarity index 96%
rename from briar-android/src/org/briarproject/android/widget/LinkDialogFragment.java
rename to briar-android/src/main/java/org/briarproject/briar/android/widget/LinkDialogFragment.java
index ffee887f638c58e8f384c5868cbfde1e03a169f5..1370574f376ef6530b1f2979750d44cb0da062c1 100644
--- a/briar-android/src/org/briarproject/android/widget/LinkDialogFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/widget/LinkDialogFragment.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.widget;
+package org.briarproject.briar.android.widget;
 
 
 import android.content.Intent;
@@ -13,7 +13,7 @@ import android.view.ViewGroup;
 import android.widget.Button;
 import android.widget.TextView;
 
-import org.briarproject.R;
+import org.briarproject.briar.R;
 
 import java.util.List;
 
diff --git a/briar-android/src/org/briarproject/android/widget/PreferenceDividerDecoration.java b/briar-android/src/main/java/org/briarproject/briar/android/widget/PreferenceDividerDecoration.java
similarity index 77%
rename from briar-android/src/org/briarproject/android/widget/PreferenceDividerDecoration.java
rename to briar-android/src/main/java/org/briarproject/briar/android/widget/PreferenceDividerDecoration.java
index a848d3b1c2d2b6c34f188303c46fdb10bd0cf876..50835db2dd8bba9c45bdd0805a5c8a3eea4b90a7 100644
--- a/briar-android/src/org/briarproject/android/widget/PreferenceDividerDecoration.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/widget/PreferenceDividerDecoration.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.widget;
+package org.briarproject.briar.android.widget;
 
 import android.content.Context;
 import android.graphics.Canvas;
@@ -15,7 +15,7 @@ import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.TintTypedArray;
 import android.view.View;
 
-import org.briarproject.R;
+import org.briarproject.briar.R;
 
 /**
  * Use this class to add dividers between {@link Preference} items.
@@ -39,9 +39,11 @@ public class PreferenceDividerDecoration extends RecyclerView.ItemDecoration {
 		mDividerHeight = dividerHeight;
 	}
 
-	public PreferenceDividerDecoration(Context context, @DrawableRes int divider, @DimenRes int dividerHeight) {
+	public PreferenceDividerDecoration(Context context,
+			@DrawableRes int divider, @DimenRes int dividerHeight) {
 		mDivider = ContextCompat.getDrawable(context, divider);
-		mDividerHeight = context.getResources().getDimensionPixelSize(dividerHeight);
+		mDividerHeight =
+				context.getResources().getDimensionPixelSize(dividerHeight);
 	}
 
 	public PreferenceDividerDecoration(Context context) {
@@ -59,9 +61,6 @@ public class PreferenceDividerDecoration extends RecyclerView.ItemDecoration {
 
 	/**
 	 * Controls whether to draw divider above the first item.
-	 *
-	 * @param drawTop
-	 * @return
 	 */
 	public PreferenceDividerDecoration drawTop(boolean drawTop) {
 		mDrawTop = drawTop;
@@ -74,9 +73,6 @@ public class PreferenceDividerDecoration extends RecyclerView.ItemDecoration {
 
 	/**
 	 * Controls whether to draw divider at the bottom of the last item.
-	 *
-	 * @param drawBottom
-	 * @return
 	 */
 	public PreferenceDividerDecoration drawBottom(boolean drawBottom) {
 		mDrawBottom = drawBottom;
@@ -88,12 +84,11 @@ public class PreferenceDividerDecoration extends RecyclerView.ItemDecoration {
 	}
 
 	/**
-	 * Controls whether to draw divider at the bottom of each {@link Preference} and {@link PreferenceScreen} item.
-	 *
-	 * @param drawBetweenItems
-	 * @return
+	 * Controls whether to draw divider at the bottom of each
+	 * {@link Preference} and {@link PreferenceScreen} item.
 	 */
-	public PreferenceDividerDecoration drawBetweenItems(boolean drawBetweenItems) {
+	public PreferenceDividerDecoration drawBetweenItems(
+			boolean drawBetweenItems) {
 		mDrawBetweenItems = drawBetweenItems;
 		return this;
 	}
@@ -103,26 +98,28 @@ public class PreferenceDividerDecoration extends RecyclerView.ItemDecoration {
 	}
 
 	/**
-	 * Controls whether to draw divider above each {@link PreferenceGroup} usually {@link PreferenceCategory}.
-	 *
-	 * @param drawBetweenCategories
-	 * @return
+	 * Controls whether to draw divider above each {@link PreferenceGroup}
+	 * usually {@link PreferenceCategory}.
 	 */
-	public PreferenceDividerDecoration drawBetweenCategories(boolean drawBetweenCategories) {
+	public PreferenceDividerDecoration drawBetweenCategories(
+			boolean drawBetweenCategories) {
 		mDrawBetweenCategories = drawBetweenCategories;
 		return this;
 	}
 
 	@Override
-	public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
+	public void onDrawOver(Canvas c, RecyclerView parent,
+			RecyclerView.State state) {
 		int left = parent.getPaddingLeft();
 		int right = parent.getWidth() - parent.getPaddingRight();
 
-		final PreferenceGroupAdapter adapter = (PreferenceGroupAdapter) parent.getAdapter();
+		final PreferenceGroupAdapter adapter =
+				(PreferenceGroupAdapter) parent.getAdapter();
 		final int adapterCount = adapter.getItemCount();
 
 		boolean wasLastPreferenceGroup = false;
-		for (int i = 0, childCount = parent.getChildCount(); i < childCount; i++) {
+		for (int i = 0, childCount = parent.getChildCount(); i < childCount;
+				i++) {
 			final View child = parent.getChildAt(i);
 
 			final int adapterPosition = parent.getChildAdapterPosition(child);
@@ -164,7 +161,8 @@ public class PreferenceDividerDecoration extends RecyclerView.ItemDecoration {
 	}
 
 	private void drawAbove(Canvas c, int left, int right, View child) {
-		final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
+		final RecyclerView.LayoutParams params =
+				(RecyclerView.LayoutParams) child.getLayoutParams();
 		final int top = child.getTop() - params.topMargin - mDividerHeight;
 		final int bottom = top + mDividerHeight;
 		mDivider.setBounds(left, top, right, bottom);
@@ -172,8 +170,10 @@ public class PreferenceDividerDecoration extends RecyclerView.ItemDecoration {
 	}
 
 	private void drawBottom(Canvas c, int left, int right, View child) {
-		final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
-		final int top = child.getBottom() + params.bottomMargin - mDividerHeight;
+		final RecyclerView.LayoutParams params =
+				(RecyclerView.LayoutParams) child.getLayoutParams();
+		final int top =
+				child.getBottom() + params.bottomMargin - mDividerHeight;
 		final int bottom = top + mDividerHeight;
 		mDivider.setBounds(left, top, right, bottom);
 		mDivider.draw(c);
diff --git a/briar-android/src/org/briarproject/android/api/AndroidNotificationManager.java b/briar-android/src/main/java/org/briarproject/briar/api/android/AndroidNotificationManager.java
similarity index 87%
rename from briar-android/src/org/briarproject/android/api/AndroidNotificationManager.java
rename to briar-android/src/main/java/org/briarproject/briar/api/android/AndroidNotificationManager.java
index 6a199a0feb5c13c5620b62ecdd702bb9c7b6338f..5161fe860d13a8a422187c66d85afeae0e4da210 100644
--- a/briar-android/src/org/briarproject/android/api/AndroidNotificationManager.java
+++ b/briar-android/src/main/java/org/briarproject/briar/api/android/AndroidNotificationManager.java
@@ -1,7 +1,7 @@
-package org.briarproject.android.api;
+package org.briarproject.briar.api.android;
 
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.sync.GroupId;
 
 /**
  * Manages notifications for private messages, forum posts, blog posts and
diff --git a/briar-android/src/org/briarproject/android/api/ReferenceManager.java b/briar-android/src/main/java/org/briarproject/briar/api/android/ReferenceManager.java
similarity index 94%
rename from briar-android/src/org/briarproject/android/api/ReferenceManager.java
rename to briar-android/src/main/java/org/briarproject/briar/api/android/ReferenceManager.java
index 8f1cd93b017b07363c530b2de7be5e6b4ff2f35f..e29b1d95513035c4ae4521f5ba6dbcb77930a0b4 100644
--- a/briar-android/src/org/briarproject/android/api/ReferenceManager.java
+++ b/briar-android/src/main/java/org/briarproject/briar/api/android/ReferenceManager.java
@@ -1,4 +1,4 @@
-package org.briarproject.android.api;
+package org.briarproject.briar.api.android;
 
 /**
  * Manages mappings between object references and serialisable handles. This
diff --git a/briar-android/src/org/thoughtcrime/securesms/LICENSE b/briar-android/src/main/java/org/thoughtcrime/securesms/LICENSE
similarity index 100%
rename from briar-android/src/org/thoughtcrime/securesms/LICENSE
rename to briar-android/src/main/java/org/thoughtcrime/securesms/LICENSE
diff --git a/briar-android/src/org/thoughtcrime/securesms/components/KeyboardAwareLinearLayout.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/KeyboardAwareLinearLayout.java
similarity index 99%
rename from briar-android/src/org/thoughtcrime/securesms/components/KeyboardAwareLinearLayout.java
rename to briar-android/src/main/java/org/thoughtcrime/securesms/components/KeyboardAwareLinearLayout.java
index 096dd0c6917fd1545384dc7e8e23a33b11c1cd48..c3e6050c59d59f364364d56efeb8c329c79cfe9f 100644
--- a/briar-android/src/org/thoughtcrime/securesms/components/KeyboardAwareLinearLayout.java
+++ b/briar-android/src/main/java/org/thoughtcrime/securesms/components/KeyboardAwareLinearLayout.java
@@ -6,20 +6,21 @@ import android.content.SharedPreferences;
 import android.graphics.Rect;
 import android.os.Build;
 import android.preference.PreferenceManager;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.WindowManager;
 import android.widget.LinearLayout;
 
-import org.briarproject.R;
+import org.briarproject.briar.R;
 
 import java.lang.reflect.Field;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
+
 import static android.content.Context.WINDOW_SERVICE;
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
diff --git a/briar-android/src/org/thoughtcrime/securesms/components/RepeatableImageKey.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/RepeatableImageKey.java
similarity index 100%
rename from briar-android/src/org/thoughtcrime/securesms/components/RepeatableImageKey.java
rename to briar-android/src/main/java/org/thoughtcrime/securesms/components/RepeatableImageKey.java
diff --git a/briar-android/src/org/thoughtcrime/securesms/components/emoji/AnimatingImageSpan.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/AnimatingImageSpan.java
similarity index 100%
rename from briar-android/src/org/thoughtcrime/securesms/components/emoji/AnimatingImageSpan.java
rename to briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/AnimatingImageSpan.java
diff --git a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiDrawer.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiDrawer.java
similarity index 98%
rename from briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiDrawer.java
rename to briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiDrawer.java
index 69234600f6b1c5e70799b4cf7b30edf0bc98d791..44c959184d24ab0b7f33f9c2562ebf1607459070 100644
--- a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiDrawer.java
+++ b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiDrawer.java
@@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.components.emoji;
 
 import android.content.Context;
 import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.support.v4.view.PagerAdapter;
 import android.support.v4.view.ViewPager;
@@ -17,7 +16,7 @@ import android.widget.LinearLayout;
 import com.astuetz.PagerSlidingTabStrip;
 import com.astuetz.PagerSlidingTabStrip.CustomTabProvider;
 
-import org.briarproject.R;
+import org.briarproject.briar.R;
 import org.thoughtcrime.securesms.components.RepeatableImageKey;
 import org.thoughtcrime.securesms.components.RepeatableImageKey.KeyEventListener;
 import org.thoughtcrime.securesms.components.emoji.EmojiPageView.EmojiSelectionListener;
@@ -26,6 +25,8 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
+
 import static android.view.KeyEvent.ACTION_DOWN;
 import static android.view.KeyEvent.KEYCODE_DEL;
 import static android.widget.ImageView.ScaleType.CENTER_INSIDE;
diff --git a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiEditText.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiEditText.java
similarity index 95%
rename from briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiEditText.java
rename to briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiEditText.java
index a8a25671ed4821551c53ee4eec5f80063f7061fd..980e29cda61860a46676fcc175922638466b28fe 100644
--- a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiEditText.java
+++ b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiEditText.java
@@ -3,15 +3,16 @@ package org.thoughtcrime.securesms.components.emoji;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.support.v7.widget.AppCompatEditText;
 import android.text.InputFilter;
 import android.util.AttributeSet;
 
-import org.briarproject.R;
+import org.briarproject.briar.R;
 import org.thoughtcrime.securesms.components.emoji.EmojiProvider.EmojiDrawable;
 
+import javax.annotation.Nullable;
+
 @UiThread
 public class EmojiEditText extends AppCompatEditText {
 
diff --git a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiFilter.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiFilter.java
similarity index 91%
rename from briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiFilter.java
rename to briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiFilter.java
index 603544869f954448a22f35059f34b61198853e17..3afc44c2fe6d3a45a66e71d81d15cc3bbff7c7d5 100644
--- a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiFilter.java
+++ b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiFilter.java
@@ -1,6 +1,5 @@
 package org.thoughtcrime.securesms.components.emoji;
 
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.text.InputFilter;
 import android.text.Spannable;
@@ -8,12 +7,14 @@ import android.text.Spanned;
 import android.text.TextUtils;
 import android.widget.TextView;
 
+import javax.annotation.Nullable;
+
 @UiThread
 class EmojiFilter implements InputFilter {
 
 	private final TextView view;
 
-	public EmojiFilter(TextView view) {
+	EmojiFilter(TextView view) {
 		this.view = view;
 	}
 
diff --git a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiPageModel.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPageModel.java
similarity index 87%
rename from briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiPageModel.java
rename to briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPageModel.java
index 2e0b899d54fddb7cb928a081515a018d482469e5..eeaf12409474d64b8833f262ca7905e659086f6e 100644
--- a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiPageModel.java
+++ b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPageModel.java
@@ -2,7 +2,8 @@ package org.thoughtcrime.securesms.components.emoji;
 
 import android.support.annotation.DrawableRes;
 import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
+
+import javax.annotation.Nullable;
 
 interface EmojiPageModel {
 
diff --git a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiPageView.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPageView.java
similarity index 97%
rename from briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiPageView.java
rename to briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPageView.java
index fa5e97c8eef6983e1fda830c524c5eb2ee3345ae..9344319cd264930052129c69e88fe725a3f2186d 100644
--- a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiPageView.java
+++ b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPageView.java
@@ -1,7 +1,6 @@
 package org.thoughtcrime.securesms.components.emoji;
 
 import android.content.Context;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
@@ -14,7 +13,9 @@ import android.widget.BaseAdapter;
 import android.widget.FrameLayout;
 import android.widget.GridView;
 
-import org.briarproject.R;
+import org.briarproject.briar.R;
+
+import javax.annotation.Nullable;
 
 @UiThread
 public class EmojiPageView extends FrameLayout {
diff --git a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiPages.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPages.java
similarity index 98%
rename from briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiPages.java
rename to briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPages.java
index 0544de13af91fd1374ce81b5e0033bb151b4115f..1427b5df98f19216acb8f753cbd04dd40afb95e1 100644
--- a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiPages.java
+++ b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPages.java
@@ -2,7 +2,7 @@ package org.thoughtcrime.securesms.components.emoji;
 
 import android.content.Context;
 
-import org.briarproject.R;
+import org.briarproject.briar.R;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java
similarity index 97%
rename from briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java
rename to briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java
index 2ea99864e9755732f8555d27c481f06fc3436afb..09778df1fa0e5b6bdec758ab47f3d5540a9b0dfc 100644
--- a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java
+++ b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java
@@ -9,15 +9,14 @@ import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
 import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
 import android.text.Spannable;
 import android.text.SpannableStringBuilder;
 import android.util.SparseArray;
 import android.widget.TextView;
 
-import org.briarproject.R;
-import org.briarproject.android.BaseActivity;
-import org.briarproject.android.api.AndroidExecutor;
+import org.briarproject.bramble.api.system.AndroidExecutor;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.BaseActivity;
 import org.thoughtcrime.securesms.components.util.FutureTaskListener;
 import org.thoughtcrime.securesms.components.util.ListenableFutureTask;
 import org.thoughtcrime.securesms.util.BitmapDecodingException;
@@ -31,6 +30,7 @@ import java.util.logging.Logger;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import static android.graphics.PixelFormat.TRANSLUCENT;
diff --git a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiSpan.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiSpan.java
similarity index 97%
rename from briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiSpan.java
rename to briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiSpan.java
index 6168ee2733501703687499453ff3f0725a8679ff..7cab093d85c119ff478ff63dc027cbedaa41da9c 100644
--- a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiSpan.java
+++ b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiSpan.java
@@ -7,7 +7,7 @@ import android.support.annotation.NonNull;
 import android.support.annotation.UiThread;
 import android.widget.TextView;
 
-import org.briarproject.R;
+import org.briarproject.briar.R;
 
 @UiThread
 class EmojiSpan extends AnimatingImageSpan {
diff --git a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiTextView.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiTextView.java
similarity index 98%
rename from briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiTextView.java
rename to briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiTextView.java
index 8cb9ecc09c02cbaf1cb6208505611efe679dc849..024f318c050e6f48c9cc974bf3054fe354811224 100644
--- a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiTextView.java
+++ b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiTextView.java
@@ -4,7 +4,6 @@ import android.content.Context;
 import android.graphics.Paint.FontMetricsInt;
 import android.graphics.drawable.Drawable;
 import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.text.TextUtils;
 import android.util.AttributeSet;
@@ -13,6 +12,8 @@ import android.widget.TextView;
 
 import org.thoughtcrime.securesms.components.emoji.EmojiProvider.EmojiDrawable;
 
+import javax.annotation.Nullable;
+
 import static android.text.TextUtils.TruncateAt.END;
 import static android.view.View.MeasureSpec.AT_MOST;
 import static android.view.View.MeasureSpec.EXACTLY;
diff --git a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiToggle.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiToggle.java
similarity index 94%
rename from briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiToggle.java
rename to briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiToggle.java
index d1f47224320cd306a5a68ab2ed88a0e562f44697..75e79bb271344433ea911d5e78f29bfe91089643 100644
--- a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiToggle.java
+++ b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiToggle.java
@@ -2,15 +2,16 @@ package org.thoughtcrime.securesms.components.emoji;
 
 import android.content.Context;
 import android.graphics.drawable.Drawable;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.support.v4.content.ContextCompat;
 import android.util.AttributeSet;
 import android.widget.ImageButton;
 
-import org.briarproject.R;
+import org.briarproject.briar.R;
 import org.thoughtcrime.securesms.components.emoji.EmojiDrawer.EmojiDrawerListener;
 
+import javax.annotation.Nullable;
+
 @UiThread
 public class EmojiToggle extends ImageButton implements EmojiDrawerListener {
 
diff --git a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiView.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiView.java
similarity index 97%
rename from briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiView.java
rename to briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiView.java
index c4f064d2ad9e5e2300d7730323ceb80934d30202..50217e3b770b43b38dcb523487c1dfd7300aaaee 100644
--- a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiView.java
+++ b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiView.java
@@ -5,13 +5,14 @@ import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.drawable.Drawable;
 import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.support.v4.content.ContextCompat;
 import android.util.AttributeSet;
 import android.view.View;
 
-import org.briarproject.R;
+import org.briarproject.briar.R;
+
+import javax.annotation.Nullable;
 
 import static android.graphics.Paint.ANTI_ALIAS_FLAG;
 import static android.graphics.Paint.Align.CENTER;
diff --git a/briar-android/src/org/thoughtcrime/securesms/components/emoji/RecentEmojiPageModel.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/RecentEmojiPageModel.java
similarity index 87%
rename from briar-android/src/org/thoughtcrime/securesms/components/emoji/RecentEmojiPageModel.java
rename to briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/RecentEmojiPageModel.java
index 1c16d9c87732d8b3c1101f375bcba91fdab2d287..89d086ef790157ad949abcfac7029ddab1abdf89 100644
--- a/briar-android/src/org/thoughtcrime/securesms/components/emoji/RecentEmojiPageModel.java
+++ b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/RecentEmojiPageModel.java
@@ -3,25 +3,25 @@ package org.thoughtcrime.securesms.components.emoji;
 import android.content.Context;
 import android.support.annotation.DrawableRes;
 import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 
-import org.briarproject.R;
-import org.briarproject.android.BaseActivity;
-import org.briarproject.android.controller.DbController;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.settings.Settings;
-import org.briarproject.api.settings.SettingsManager;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.settings.Settings;
+import org.briarproject.bramble.api.settings.SettingsManager;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.BaseActivity;
+import org.briarproject.briar.android.controller.DbController;
 
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.android.fragment.SettingsFragment.SETTINGS_NAMESPACE;
+import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
 
 @UiThread
 public class RecentEmojiPageModel implements EmojiPageModel {
diff --git a/briar-android/src/org/thoughtcrime/securesms/components/emoji/StaticEmojiPageModel.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/StaticEmojiPageModel.java
similarity index 97%
rename from briar-android/src/org/thoughtcrime/securesms/components/emoji/StaticEmojiPageModel.java
rename to briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/StaticEmojiPageModel.java
index 688ee3ae7a4f778c4c79bd30e3b8616679252082..4f9c9b94c66482de567acbe0865dd9c4487e2149 100644
--- a/briar-android/src/org/thoughtcrime/securesms/components/emoji/StaticEmojiPageModel.java
+++ b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/StaticEmojiPageModel.java
@@ -4,9 +4,10 @@ import android.content.Context;
 import android.support.annotation.ArrayRes;
 import android.support.annotation.DrawableRes;
 import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 
+import javax.annotation.Nullable;
+
 @UiThread
 class StaticEmojiPageModel implements EmojiPageModel {
 
diff --git a/briar-android/src/org/thoughtcrime/securesms/components/util/FutureTaskListener.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/util/FutureTaskListener.java
similarity index 100%
rename from briar-android/src/org/thoughtcrime/securesms/components/util/FutureTaskListener.java
rename to briar-android/src/main/java/org/thoughtcrime/securesms/components/util/FutureTaskListener.java
diff --git a/briar-android/src/org/thoughtcrime/securesms/components/util/ListenableFutureTask.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/util/ListenableFutureTask.java
similarity index 98%
rename from briar-android/src/org/thoughtcrime/securesms/components/util/ListenableFutureTask.java
rename to briar-android/src/main/java/org/thoughtcrime/securesms/components/util/ListenableFutureTask.java
index 1283148846464c4e8098a3cca1dc16b0a1eb10ad..d9651770df545155f3958a525e8314ce4549dc50 100644
--- a/briar-android/src/org/thoughtcrime/securesms/components/util/ListenableFutureTask.java
+++ b/briar-android/src/main/java/org/thoughtcrime/securesms/components/util/ListenableFutureTask.java
@@ -16,14 +16,14 @@
  */
 package org.thoughtcrime.securesms.components.util;
 
-import android.support.annotation.Nullable;
-
 import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.FutureTask;
 
+import javax.annotation.Nullable;
+
 public class ListenableFutureTask<V> extends FutureTask<V> {
 
 	private final List<FutureTaskListener<V>> listeners = new LinkedList<>();
diff --git a/briar-android/src/org/thoughtcrime/securesms/util/BitmapDecodingException.java b/briar-android/src/main/java/org/thoughtcrime/securesms/util/BitmapDecodingException.java
similarity index 100%
rename from briar-android/src/org/thoughtcrime/securesms/util/BitmapDecodingException.java
rename to briar-android/src/main/java/org/thoughtcrime/securesms/util/BitmapDecodingException.java
diff --git a/briar-android/src/org/thoughtcrime/securesms/util/BitmapUtil.java b/briar-android/src/main/java/org/thoughtcrime/securesms/util/BitmapUtil.java
similarity index 100%
rename from briar-android/src/org/thoughtcrime/securesms/util/BitmapUtil.java
rename to briar-android/src/main/java/org/thoughtcrime/securesms/util/BitmapUtil.java
diff --git a/briar-android/res/drawable-hdpi/ic_launcher.png b/briar-android/src/main/res/drawable-hdpi/ic_launcher.png
similarity index 100%
rename from briar-android/res/drawable-hdpi/ic_launcher.png
rename to briar-android/src/main/res/drawable-hdpi/ic_launcher.png
diff --git a/briar-android/res/drawable-hdpi/logo.png b/briar-android/src/main/res/drawable-hdpi/logo.png
similarity index 100%
rename from briar-android/res/drawable-hdpi/logo.png
rename to briar-android/src/main/res/drawable-hdpi/logo.png
diff --git a/briar-android/res/drawable-hdpi/msg_in.9.png b/briar-android/src/main/res/drawable-hdpi/msg_in.9.png
similarity index 100%
rename from briar-android/res/drawable-hdpi/msg_in.9.png
rename to briar-android/src/main/res/drawable-hdpi/msg_in.9.png
diff --git a/briar-android/res/drawable-hdpi/msg_in_top.9.png b/briar-android/src/main/res/drawable-hdpi/msg_in_top.9.png
similarity index 100%
rename from briar-android/res/drawable-hdpi/msg_in_top.9.png
rename to briar-android/src/main/res/drawable-hdpi/msg_in_top.9.png
diff --git a/briar-android/res/drawable-hdpi/msg_out.9.png b/briar-android/src/main/res/drawable-hdpi/msg_out.9.png
similarity index 100%
rename from briar-android/res/drawable-hdpi/msg_out.9.png
rename to briar-android/src/main/res/drawable-hdpi/msg_out.9.png
diff --git a/briar-android/res/drawable-hdpi/msg_out_top.9.png b/briar-android/src/main/res/drawable-hdpi/msg_out_top.9.png
similarity index 100%
rename from briar-android/res/drawable-hdpi/msg_out_top.9.png
rename to briar-android/src/main/res/drawable-hdpi/msg_out_top.9.png
diff --git a/briar-android/res/drawable-hdpi/notice_in.9.png b/briar-android/src/main/res/drawable-hdpi/notice_in.9.png
similarity index 100%
rename from briar-android/res/drawable-hdpi/notice_in.9.png
rename to briar-android/src/main/res/drawable-hdpi/notice_in.9.png
diff --git a/briar-android/res/drawable-hdpi/notice_in_bottom.9.png b/briar-android/src/main/res/drawable-hdpi/notice_in_bottom.9.png
similarity index 100%
rename from briar-android/res/drawable-hdpi/notice_in_bottom.9.png
rename to briar-android/src/main/res/drawable-hdpi/notice_in_bottom.9.png
diff --git a/briar-android/res/drawable-hdpi/notice_out.9.png b/briar-android/src/main/res/drawable-hdpi/notice_out.9.png
similarity index 100%
rename from briar-android/res/drawable-hdpi/notice_out.9.png
rename to briar-android/src/main/res/drawable-hdpi/notice_out.9.png
diff --git a/briar-android/res/drawable-hdpi/notice_out_bottom.9.png b/briar-android/src/main/res/drawable-hdpi/notice_out_bottom.9.png
similarity index 100%
rename from briar-android/res/drawable-hdpi/notice_out_bottom.9.png
rename to briar-android/src/main/res/drawable-hdpi/notice_out_bottom.9.png
diff --git a/briar-android/res/drawable-hdpi/ongoing_notification_icon.png b/briar-android/src/main/res/drawable-hdpi/ongoing_notification_icon.png
similarity index 100%
rename from briar-android/res/drawable-hdpi/ongoing_notification_icon.png
rename to briar-android/src/main/res/drawable-hdpi/ongoing_notification_icon.png
diff --git a/briar-android/res/drawable-ldpi/ic_launcher.png b/briar-android/src/main/res/drawable-ldpi/ic_launcher.png
similarity index 100%
rename from briar-android/res/drawable-ldpi/ic_launcher.png
rename to briar-android/src/main/res/drawable-ldpi/ic_launcher.png
diff --git a/briar-android/res/drawable-ldpi/logo.png b/briar-android/src/main/res/drawable-ldpi/logo.png
similarity index 100%
rename from briar-android/res/drawable-ldpi/logo.png
rename to briar-android/src/main/res/drawable-ldpi/logo.png
diff --git a/briar-android/res/drawable-ldpi/ongoing_notification_icon.png b/briar-android/src/main/res/drawable-ldpi/ongoing_notification_icon.png
similarity index 100%
rename from briar-android/res/drawable-ldpi/ongoing_notification_icon.png
rename to briar-android/src/main/res/drawable-ldpi/ongoing_notification_icon.png
diff --git a/briar-android/res/drawable-mdpi/ic_launcher.png b/briar-android/src/main/res/drawable-mdpi/ic_launcher.png
similarity index 100%
rename from briar-android/res/drawable-mdpi/ic_launcher.png
rename to briar-android/src/main/res/drawable-mdpi/ic_launcher.png
diff --git a/briar-android/res/drawable-mdpi/logo.png b/briar-android/src/main/res/drawable-mdpi/logo.png
similarity index 100%
rename from briar-android/res/drawable-mdpi/logo.png
rename to briar-android/src/main/res/drawable-mdpi/logo.png
diff --git a/briar-android/res/drawable-mdpi/msg_in.9.png b/briar-android/src/main/res/drawable-mdpi/msg_in.9.png
similarity index 100%
rename from briar-android/res/drawable-mdpi/msg_in.9.png
rename to briar-android/src/main/res/drawable-mdpi/msg_in.9.png
diff --git a/briar-android/res/drawable-mdpi/msg_in_top.9.png b/briar-android/src/main/res/drawable-mdpi/msg_in_top.9.png
similarity index 100%
rename from briar-android/res/drawable-mdpi/msg_in_top.9.png
rename to briar-android/src/main/res/drawable-mdpi/msg_in_top.9.png
diff --git a/briar-android/res/drawable-mdpi/msg_out.9.png b/briar-android/src/main/res/drawable-mdpi/msg_out.9.png
similarity index 100%
rename from briar-android/res/drawable-mdpi/msg_out.9.png
rename to briar-android/src/main/res/drawable-mdpi/msg_out.9.png
diff --git a/briar-android/res/drawable-mdpi/msg_out_top.9.png b/briar-android/src/main/res/drawable-mdpi/msg_out_top.9.png
similarity index 100%
rename from briar-android/res/drawable-mdpi/msg_out_top.9.png
rename to briar-android/src/main/res/drawable-mdpi/msg_out_top.9.png
diff --git a/briar-android/res/drawable-mdpi/notice_in.9.png b/briar-android/src/main/res/drawable-mdpi/notice_in.9.png
similarity index 100%
rename from briar-android/res/drawable-mdpi/notice_in.9.png
rename to briar-android/src/main/res/drawable-mdpi/notice_in.9.png
diff --git a/briar-android/res/drawable-mdpi/notice_in_bottom.9.png b/briar-android/src/main/res/drawable-mdpi/notice_in_bottom.9.png
similarity index 100%
rename from briar-android/res/drawable-mdpi/notice_in_bottom.9.png
rename to briar-android/src/main/res/drawable-mdpi/notice_in_bottom.9.png
diff --git a/briar-android/res/drawable-mdpi/notice_out.9.png b/briar-android/src/main/res/drawable-mdpi/notice_out.9.png
similarity index 100%
rename from briar-android/res/drawable-mdpi/notice_out.9.png
rename to briar-android/src/main/res/drawable-mdpi/notice_out.9.png
diff --git a/briar-android/res/drawable-mdpi/notice_out_bottom.9.png b/briar-android/src/main/res/drawable-mdpi/notice_out_bottom.9.png
similarity index 100%
rename from briar-android/res/drawable-mdpi/notice_out_bottom.9.png
rename to briar-android/src/main/res/drawable-mdpi/notice_out_bottom.9.png
diff --git a/briar-android/res/drawable-mdpi/ongoing_notification_icon.png b/briar-android/src/main/res/drawable-mdpi/ongoing_notification_icon.png
similarity index 100%
rename from briar-android/res/drawable-mdpi/ongoing_notification_icon.png
rename to briar-android/src/main/res/drawable-mdpi/ongoing_notification_icon.png
diff --git a/briar-android/res/drawable-xhdpi/ic_launcher.png b/briar-android/src/main/res/drawable-xhdpi/ic_launcher.png
similarity index 100%
rename from briar-android/res/drawable-xhdpi/ic_launcher.png
rename to briar-android/src/main/res/drawable-xhdpi/ic_launcher.png
diff --git a/briar-android/res/drawable-xhdpi/logo.png b/briar-android/src/main/res/drawable-xhdpi/logo.png
similarity index 100%
rename from briar-android/res/drawable-xhdpi/logo.png
rename to briar-android/src/main/res/drawable-xhdpi/logo.png
diff --git a/briar-android/res/drawable-xhdpi/msg_in.9.png b/briar-android/src/main/res/drawable-xhdpi/msg_in.9.png
similarity index 100%
rename from briar-android/res/drawable-xhdpi/msg_in.9.png
rename to briar-android/src/main/res/drawable-xhdpi/msg_in.9.png
diff --git a/briar-android/res/drawable-xhdpi/msg_in_top.9.png b/briar-android/src/main/res/drawable-xhdpi/msg_in_top.9.png
similarity index 100%
rename from briar-android/res/drawable-xhdpi/msg_in_top.9.png
rename to briar-android/src/main/res/drawable-xhdpi/msg_in_top.9.png
diff --git a/briar-android/res/drawable-xhdpi/msg_out.9.png b/briar-android/src/main/res/drawable-xhdpi/msg_out.9.png
similarity index 100%
rename from briar-android/res/drawable-xhdpi/msg_out.9.png
rename to briar-android/src/main/res/drawable-xhdpi/msg_out.9.png
diff --git a/briar-android/res/drawable-xhdpi/msg_out_top.9.png b/briar-android/src/main/res/drawable-xhdpi/msg_out_top.9.png
similarity index 100%
rename from briar-android/res/drawable-xhdpi/msg_out_top.9.png
rename to briar-android/src/main/res/drawable-xhdpi/msg_out_top.9.png
diff --git a/briar-android/res/drawable-xhdpi/notice_in.9.png b/briar-android/src/main/res/drawable-xhdpi/notice_in.9.png
similarity index 100%
rename from briar-android/res/drawable-xhdpi/notice_in.9.png
rename to briar-android/src/main/res/drawable-xhdpi/notice_in.9.png
diff --git a/briar-android/res/drawable-xhdpi/notice_in_bottom.9.png b/briar-android/src/main/res/drawable-xhdpi/notice_in_bottom.9.png
similarity index 100%
rename from briar-android/res/drawable-xhdpi/notice_in_bottom.9.png
rename to briar-android/src/main/res/drawable-xhdpi/notice_in_bottom.9.png
diff --git a/briar-android/res/drawable-xhdpi/notice_out.9.png b/briar-android/src/main/res/drawable-xhdpi/notice_out.9.png
similarity index 100%
rename from briar-android/res/drawable-xhdpi/notice_out.9.png
rename to briar-android/src/main/res/drawable-xhdpi/notice_out.9.png
diff --git a/briar-android/res/drawable-xhdpi/notice_out_bottom.9.png b/briar-android/src/main/res/drawable-xhdpi/notice_out_bottom.9.png
similarity index 100%
rename from briar-android/res/drawable-xhdpi/notice_out_bottom.9.png
rename to briar-android/src/main/res/drawable-xhdpi/notice_out_bottom.9.png
diff --git a/briar-android/res/drawable-xhdpi/ongoing_notification_icon.png b/briar-android/src/main/res/drawable-xhdpi/ongoing_notification_icon.png
similarity index 100%
rename from briar-android/res/drawable-xhdpi/ongoing_notification_icon.png
rename to briar-android/src/main/res/drawable-xhdpi/ongoing_notification_icon.png
diff --git a/briar-android/res/drawable-xxhdpi/msg_in.9.png b/briar-android/src/main/res/drawable-xxhdpi/msg_in.9.png
similarity index 100%
rename from briar-android/res/drawable-xxhdpi/msg_in.9.png
rename to briar-android/src/main/res/drawable-xxhdpi/msg_in.9.png
diff --git a/briar-android/res/drawable-xxhdpi/msg_in_top.9.png b/briar-android/src/main/res/drawable-xxhdpi/msg_in_top.9.png
similarity index 100%
rename from briar-android/res/drawable-xxhdpi/msg_in_top.9.png
rename to briar-android/src/main/res/drawable-xxhdpi/msg_in_top.9.png
diff --git a/briar-android/res/drawable-xxhdpi/msg_out.9.png b/briar-android/src/main/res/drawable-xxhdpi/msg_out.9.png
similarity index 100%
rename from briar-android/res/drawable-xxhdpi/msg_out.9.png
rename to briar-android/src/main/res/drawable-xxhdpi/msg_out.9.png
diff --git a/briar-android/res/drawable-xxhdpi/msg_out_top.9.png b/briar-android/src/main/res/drawable-xxhdpi/msg_out_top.9.png
similarity index 100%
rename from briar-android/res/drawable-xxhdpi/msg_out_top.9.png
rename to briar-android/src/main/res/drawable-xxhdpi/msg_out_top.9.png
diff --git a/briar-android/res/drawable-xxhdpi/notice_in.9.png b/briar-android/src/main/res/drawable-xxhdpi/notice_in.9.png
similarity index 100%
rename from briar-android/res/drawable-xxhdpi/notice_in.9.png
rename to briar-android/src/main/res/drawable-xxhdpi/notice_in.9.png
diff --git a/briar-android/res/drawable-xxhdpi/notice_in_bottom.9.png b/briar-android/src/main/res/drawable-xxhdpi/notice_in_bottom.9.png
similarity index 100%
rename from briar-android/res/drawable-xxhdpi/notice_in_bottom.9.png
rename to briar-android/src/main/res/drawable-xxhdpi/notice_in_bottom.9.png
diff --git a/briar-android/res/drawable-xxhdpi/notice_out.9.png b/briar-android/src/main/res/drawable-xxhdpi/notice_out.9.png
similarity index 100%
rename from briar-android/res/drawable-xxhdpi/notice_out.9.png
rename to briar-android/src/main/res/drawable-xxhdpi/notice_out.9.png
diff --git a/briar-android/res/drawable-xxhdpi/notice_out_bottom.9.png b/briar-android/src/main/res/drawable-xxhdpi/notice_out_bottom.9.png
similarity index 100%
rename from briar-android/res/drawable-xxhdpi/notice_out_bottom.9.png
rename to briar-android/src/main/res/drawable-xxhdpi/notice_out_bottom.9.png
diff --git a/briar-android/res/drawable/action_delete_black.xml b/briar-android/src/main/res/drawable/action_delete_black.xml
similarity index 100%
rename from briar-android/res/drawable/action_delete_black.xml
rename to briar-android/src/main/res/drawable/action_delete_black.xml
diff --git a/briar-android/res/drawable/action_delete_white.xml b/briar-android/src/main/res/drawable/action_delete_white.xml
similarity index 100%
rename from briar-android/res/drawable/action_delete_white.xml
rename to briar-android/src/main/res/drawable/action_delete_white.xml
diff --git a/briar-android/res/drawable/alerts_and_states_error.xml b/briar-android/src/main/res/drawable/alerts_and_states_error.xml
similarity index 100%
rename from briar-android/res/drawable/alerts_and_states_error.xml
rename to briar-android/src/main/res/drawable/alerts_and_states_error.xml
diff --git a/briar-android/res/drawable/blogs.xml b/briar-android/src/main/res/drawable/blogs.xml
similarity index 100%
rename from briar-android/res/drawable/blogs.xml
rename to briar-android/src/main/res/drawable/blogs.xml
diff --git a/briar-android/res/drawable/bluetooth.xml b/briar-android/src/main/res/drawable/bluetooth.xml
similarity index 100%
rename from briar-android/res/drawable/bluetooth.xml
rename to briar-android/src/main/res/drawable/bluetooth.xml
diff --git a/briar-android/res/drawable/border_explanation.xml b/briar-android/src/main/res/drawable/border_explanation.xml
similarity index 100%
rename from briar-android/res/drawable/border_explanation.xml
rename to briar-android/src/main/res/drawable/border_explanation.xml
diff --git a/briar-android/res/drawable/border_spinner.xml b/briar-android/src/main/res/drawable/border_spinner.xml
similarity index 100%
rename from briar-android/res/drawable/border_spinner.xml
rename to briar-android/src/main/res/drawable/border_spinner.xml
diff --git a/briar-android/res/drawable/briar_logo_large.png b/briar-android/src/main/res/drawable/briar_logo_large.png
similarity index 100%
rename from briar-android/res/drawable/briar_logo_large.png
rename to briar-android/src/main/res/drawable/briar_logo_large.png
diff --git a/briar-android/res/drawable/bubble.xml b/briar-android/src/main/res/drawable/bubble.xml
similarity index 100%
rename from briar-android/res/drawable/bubble.xml
rename to briar-android/src/main/res/drawable/bubble.xml
diff --git a/briar-android/res/drawable/bubble_problem.xml b/briar-android/src/main/res/drawable/bubble_problem.xml
similarity index 100%
rename from briar-android/res/drawable/bubble_problem.xml
rename to briar-android/src/main/res/drawable/bubble_problem.xml
diff --git a/briar-android/res/drawable/bubble_white.xml b/briar-android/src/main/res/drawable/bubble_white.xml
similarity index 100%
rename from briar-android/res/drawable/bubble_white.xml
rename to briar-android/src/main/res/drawable/bubble_white.xml
diff --git a/briar-android/res/drawable/chevron48dp_down.xml b/briar-android/src/main/res/drawable/chevron48dp_down.xml
similarity index 100%
rename from briar-android/res/drawable/chevron48dp_down.xml
rename to briar-android/src/main/res/drawable/chevron48dp_down.xml
diff --git a/briar-android/res/drawable/chevron48dp_up.xml b/briar-android/src/main/res/drawable/chevron48dp_up.xml
similarity index 100%
rename from briar-android/res/drawable/chevron48dp_up.xml
rename to briar-android/src/main/res/drawable/chevron48dp_up.xml
diff --git a/briar-android/res/drawable/contact_connected.xml b/briar-android/src/main/res/drawable/contact_connected.xml
similarity index 100%
rename from briar-android/res/drawable/contact_connected.xml
rename to briar-android/src/main/res/drawable/contact_connected.xml
diff --git a/briar-android/res/drawable/contact_disconnected.xml b/briar-android/src/main/res/drawable/contact_disconnected.xml
similarity index 100%
rename from briar-android/res/drawable/contact_disconnected.xml
rename to briar-android/src/main/res/drawable/contact_disconnected.xml
diff --git a/briar-android/res/drawable/contact_offline.xml b/briar-android/src/main/res/drawable/contact_offline.xml
similarity index 100%
rename from briar-android/res/drawable/contact_offline.xml
rename to briar-android/src/main/res/drawable/contact_offline.xml
diff --git a/briar-android/res/drawable/contact_online.xml b/briar-android/src/main/res/drawable/contact_online.xml
similarity index 100%
rename from briar-android/res/drawable/contact_online.xml
rename to briar-android/src/main/res/drawable/contact_online.xml
diff --git a/briar-android/res/drawable/forum_item_create_white.xml b/briar-android/src/main/res/drawable/forum_item_create_white.xml
similarity index 100%
rename from briar-android/res/drawable/forum_item_create_white.xml
rename to briar-android/src/main/res/drawable/forum_item_create_white.xml
diff --git a/briar-android/res/drawable/ic_add_white.xml b/briar-android/src/main/res/drawable/ic_add_white.xml
similarity index 100%
rename from briar-android/res/drawable/ic_add_white.xml
rename to briar-android/src/main/res/drawable/ic_add_white.xml
diff --git a/briar-android/res/drawable/ic_backspace_black.xml b/briar-android/src/main/res/drawable/ic_backspace_black.xml
similarity index 100%
rename from briar-android/res/drawable/ic_backspace_black.xml
rename to briar-android/src/main/res/drawable/ic_backspace_black.xml
diff --git a/briar-android/res/drawable/ic_check_white.xml b/briar-android/src/main/res/drawable/ic_check_white.xml
similarity index 100%
rename from briar-android/res/drawable/ic_check_white.xml
rename to briar-android/src/main/res/drawable/ic_check_white.xml
diff --git a/briar-android/res/drawable/ic_contact_introduction.xml b/briar-android/src/main/res/drawable/ic_contact_introduction.xml
similarity index 100%
rename from briar-android/res/drawable/ic_contact_introduction.xml
rename to briar-android/src/main/res/drawable/ic_contact_introduction.xml
diff --git a/briar-android/res/drawable/ic_contacts.xml b/briar-android/src/main/res/drawable/ic_contacts.xml
similarity index 100%
rename from briar-android/res/drawable/ic_contacts.xml
rename to briar-android/src/main/res/drawable/ic_contacts.xml
diff --git a/briar-android/res/drawable/ic_emoji_activity.xml b/briar-android/src/main/res/drawable/ic_emoji_activity.xml
similarity index 100%
rename from briar-android/res/drawable/ic_emoji_activity.xml
rename to briar-android/src/main/res/drawable/ic_emoji_activity.xml
diff --git a/briar-android/res/drawable/ic_emoji_animals_nature.xml b/briar-android/src/main/res/drawable/ic_emoji_animals_nature.xml
similarity index 100%
rename from briar-android/res/drawable/ic_emoji_animals_nature.xml
rename to briar-android/src/main/res/drawable/ic_emoji_animals_nature.xml
diff --git a/briar-android/res/drawable/ic_emoji_emoticons.xml b/briar-android/src/main/res/drawable/ic_emoji_emoticons.xml
similarity index 100%
rename from briar-android/res/drawable/ic_emoji_emoticons.xml
rename to briar-android/src/main/res/drawable/ic_emoji_emoticons.xml
diff --git a/briar-android/res/drawable/ic_emoji_flags.xml b/briar-android/src/main/res/drawable/ic_emoji_flags.xml
similarity index 100%
rename from briar-android/res/drawable/ic_emoji_flags.xml
rename to briar-android/src/main/res/drawable/ic_emoji_flags.xml
diff --git a/briar-android/res/drawable/ic_emoji_food_drink.xml b/briar-android/src/main/res/drawable/ic_emoji_food_drink.xml
similarity index 100%
rename from briar-android/res/drawable/ic_emoji_food_drink.xml
rename to briar-android/src/main/res/drawable/ic_emoji_food_drink.xml
diff --git a/briar-android/res/drawable/ic_emoji_objects.xml b/briar-android/src/main/res/drawable/ic_emoji_objects.xml
similarity index 100%
rename from briar-android/res/drawable/ic_emoji_objects.xml
rename to briar-android/src/main/res/drawable/ic_emoji_objects.xml
diff --git a/briar-android/res/drawable/ic_emoji_recent.xml b/briar-android/src/main/res/drawable/ic_emoji_recent.xml
similarity index 100%
rename from briar-android/res/drawable/ic_emoji_recent.xml
rename to briar-android/src/main/res/drawable/ic_emoji_recent.xml
diff --git a/briar-android/res/drawable/ic_emoji_smiley_people.xml b/briar-android/src/main/res/drawable/ic_emoji_smiley_people.xml
similarity index 100%
rename from briar-android/res/drawable/ic_emoji_smiley_people.xml
rename to briar-android/src/main/res/drawable/ic_emoji_smiley_people.xml
diff --git a/briar-android/res/drawable/ic_emoji_symbols.xml b/briar-android/src/main/res/drawable/ic_emoji_symbols.xml
similarity index 100%
rename from briar-android/res/drawable/ic_emoji_symbols.xml
rename to briar-android/src/main/res/drawable/ic_emoji_symbols.xml
diff --git a/briar-android/res/drawable/ic_emoji_toggle.xml b/briar-android/src/main/res/drawable/ic_emoji_toggle.xml
similarity index 100%
rename from briar-android/res/drawable/ic_emoji_toggle.xml
rename to briar-android/src/main/res/drawable/ic_emoji_toggle.xml
diff --git a/briar-android/res/drawable/ic_emoji_travel_places.xml b/briar-android/src/main/res/drawable/ic_emoji_travel_places.xml
similarity index 100%
rename from briar-android/res/drawable/ic_emoji_travel_places.xml
rename to briar-android/src/main/res/drawable/ic_emoji_travel_places.xml
diff --git a/briar-android/res/drawable/ic_forums_black_24dp.xml b/briar-android/src/main/res/drawable/ic_forums_black_24dp.xml
similarity index 100%
rename from briar-android/res/drawable/ic_forums_black_24dp.xml
rename to briar-android/src/main/res/drawable/ic_forums_black_24dp.xml
diff --git a/briar-android/res/drawable/ic_group.xml b/briar-android/src/main/res/drawable/ic_group.xml
similarity index 100%
rename from briar-android/res/drawable/ic_group.xml
rename to briar-android/src/main/res/drawable/ic_group.xml
diff --git a/briar-android/res/drawable/ic_group_white.xml b/briar-android/src/main/res/drawable/ic_group_white.xml
similarity index 100%
rename from briar-android/res/drawable/ic_group_white.xml
rename to briar-android/src/main/res/drawable/ic_group_white.xml
diff --git a/briar-android/res/drawable/ic_info_white.xml b/briar-android/src/main/res/drawable/ic_info_white.xml
similarity index 100%
rename from briar-android/res/drawable/ic_info_white.xml
rename to briar-android/src/main/res/drawable/ic_info_white.xml
diff --git a/briar-android/res/drawable/ic_keyboard_black.xml b/briar-android/src/main/res/drawable/ic_keyboard_black.xml
similarity index 100%
rename from briar-android/res/drawable/ic_keyboard_black.xml
rename to briar-android/src/main/res/drawable/ic_keyboard_black.xml
diff --git a/briar-android/res/drawable/ic_more_vert_accent.xml b/briar-android/src/main/res/drawable/ic_more_vert_accent.xml
similarity index 100%
rename from briar-android/res/drawable/ic_more_vert_accent.xml
rename to briar-android/src/main/res/drawable/ic_more_vert_accent.xml
diff --git a/briar-android/res/drawable/ic_our_identity_black.xml b/briar-android/src/main/res/drawable/ic_our_identity_black.xml
similarity index 100%
rename from briar-android/res/drawable/ic_our_identity_black.xml
rename to briar-android/src/main/res/drawable/ic_our_identity_black.xml
diff --git a/briar-android/res/drawable/ic_repeat.xml b/briar-android/src/main/res/drawable/ic_repeat.xml
similarity index 100%
rename from briar-android/res/drawable/ic_repeat.xml
rename to briar-android/src/main/res/drawable/ic_repeat.xml
diff --git a/briar-android/res/drawable/ic_settings_black_24dp.xml b/briar-android/src/main/res/drawable/ic_settings_black_24dp.xml
similarity index 100%
rename from briar-android/res/drawable/ic_settings_black_24dp.xml
rename to briar-android/src/main/res/drawable/ic_settings_black_24dp.xml
diff --git a/briar-android/res/drawable/ic_signout_black_24dp.xml b/briar-android/src/main/res/drawable/ic_signout_black_24dp.xml
similarity index 100%
rename from briar-android/res/drawable/ic_signout_black_24dp.xml
rename to briar-android/src/main/res/drawable/ic_signout_black_24dp.xml
diff --git a/briar-android/res/drawable/ic_visibility.xml b/briar-android/src/main/res/drawable/ic_visibility.xml
similarity index 100%
rename from briar-android/res/drawable/ic_visibility.xml
rename to briar-android/src/main/res/drawable/ic_visibility.xml
diff --git a/briar-android/res/drawable/ic_visibility_off.xml b/briar-android/src/main/res/drawable/ic_visibility_off.xml
similarity index 100%
rename from briar-android/res/drawable/ic_visibility_off.xml
rename to briar-android/src/main/res/drawable/ic_visibility_off.xml
diff --git a/briar-android/res/drawable/ic_visibility_white.xml b/briar-android/src/main/res/drawable/ic_visibility_white.xml
similarity index 100%
rename from briar-android/res/drawable/ic_visibility_white.xml
rename to briar-android/src/main/res/drawable/ic_visibility_white.xml
diff --git a/briar-android/res/drawable/introduction_notification.xml b/briar-android/src/main/res/drawable/introduction_notification.xml
similarity index 100%
rename from briar-android/res/drawable/introduction_notification.xml
rename to briar-android/src/main/res/drawable/introduction_notification.xml
diff --git a/briar-android/res/drawable/introduction_white.xml b/briar-android/src/main/res/drawable/introduction_white.xml
similarity index 100%
rename from briar-android/res/drawable/introduction_white.xml
rename to briar-android/src/main/res/drawable/introduction_white.xml
diff --git a/briar-android/res/drawable/level_indicator_circle.xml b/briar-android/src/main/res/drawable/level_indicator_circle.xml
similarity index 100%
rename from briar-android/res/drawable/level_indicator_circle.xml
rename to briar-android/src/main/res/drawable/level_indicator_circle.xml
diff --git a/briar-android/res/drawable/message_delivered.xml b/briar-android/src/main/res/drawable/message_delivered.xml
similarity index 100%
rename from briar-android/res/drawable/message_delivered.xml
rename to briar-android/src/main/res/drawable/message_delivered.xml
diff --git a/briar-android/res/drawable/message_delivered_white.xml b/briar-android/src/main/res/drawable/message_delivered_white.xml
similarity index 100%
rename from briar-android/res/drawable/message_delivered_white.xml
rename to briar-android/src/main/res/drawable/message_delivered_white.xml
diff --git a/briar-android/res/drawable/message_notification_icon.xml b/briar-android/src/main/res/drawable/message_notification_icon.xml
similarity index 100%
rename from briar-android/res/drawable/message_notification_icon.xml
rename to briar-android/src/main/res/drawable/message_notification_icon.xml
diff --git a/briar-android/res/drawable/message_sent.xml b/briar-android/src/main/res/drawable/message_sent.xml
similarity index 100%
rename from briar-android/res/drawable/message_sent.xml
rename to briar-android/src/main/res/drawable/message_sent.xml
diff --git a/briar-android/res/drawable/message_sent_white.xml b/briar-android/src/main/res/drawable/message_sent_white.xml
similarity index 100%
rename from briar-android/res/drawable/message_sent_white.xml
rename to briar-android/src/main/res/drawable/message_sent_white.xml
diff --git a/briar-android/res/drawable/message_stored.xml b/briar-android/src/main/res/drawable/message_stored.xml
similarity index 100%
rename from briar-android/res/drawable/message_stored.xml
rename to briar-android/src/main/res/drawable/message_stored.xml
diff --git a/briar-android/res/drawable/message_stored_white.xml b/briar-android/src/main/res/drawable/message_stored_white.xml
similarity index 100%
rename from briar-android/res/drawable/message_stored_white.xml
rename to briar-android/src/main/res/drawable/message_stored_white.xml
diff --git a/briar-android/res/drawable/navigation_accept.xml b/briar-android/src/main/res/drawable/navigation_accept.xml
similarity index 100%
rename from briar-android/res/drawable/navigation_accept.xml
rename to briar-android/src/main/res/drawable/navigation_accept.xml
diff --git a/briar-android/res/drawable/navigation_drawer_header.png b/briar-android/src/main/res/drawable/navigation_drawer_header.png
similarity index 100%
rename from briar-android/res/drawable/navigation_drawer_header.png
rename to briar-android/src/main/res/drawable/navigation_drawer_header.png
diff --git a/briar-android/res/drawable/qr_code_explanation.xml b/briar-android/src/main/res/drawable/qr_code_explanation.xml
similarity index 100%
rename from briar-android/res/drawable/qr_code_explanation.xml
rename to briar-android/src/main/res/drawable/qr_code_explanation.xml
diff --git a/briar-android/res/drawable/qr_code_intro.xml b/briar-android/src/main/res/drawable/qr_code_intro.xml
similarity index 100%
rename from briar-android/res/drawable/qr_code_intro.xml
rename to briar-android/src/main/res/drawable/qr_code_intro.xml
diff --git a/briar-android/res/drawable/selector_chevron.xml b/briar-android/src/main/res/drawable/selector_chevron.xml
similarity index 100%
rename from briar-android/res/drawable/selector_chevron.xml
rename to briar-android/src/main/res/drawable/selector_chevron.xml
diff --git a/briar-android/res/drawable/social_send_now_white.xml b/briar-android/src/main/res/drawable/social_send_now_white.xml
similarity index 100%
rename from briar-android/res/drawable/social_send_now_white.xml
rename to briar-android/src/main/res/drawable/social_send_now_white.xml
diff --git a/briar-android/res/drawable/social_share_white.xml b/briar-android/src/main/res/drawable/social_share_white.xml
similarity index 100%
rename from briar-android/res/drawable/social_share_white.xml
rename to briar-android/src/main/res/drawable/social_share_white.xml
diff --git a/briar-android/res/drawable/transport_bt.xml b/briar-android/src/main/res/drawable/transport_bt.xml
similarity index 100%
rename from briar-android/res/drawable/transport_bt.xml
rename to briar-android/src/main/res/drawable/transport_bt.xml
diff --git a/briar-android/res/drawable/transport_lan.xml b/briar-android/src/main/res/drawable/transport_lan.xml
similarity index 100%
rename from briar-android/res/drawable/transport_lan.xml
rename to briar-android/src/main/res/drawable/transport_lan.xml
diff --git a/briar-android/res/drawable/transport_tor.xml b/briar-android/src/main/res/drawable/transport_tor.xml
similarity index 100%
rename from briar-android/res/drawable/transport_tor.xml
rename to briar-android/src/main/res/drawable/transport_tor.xml
diff --git a/briar-android/res/drawable/trust_indicator_anonymous.xml b/briar-android/src/main/res/drawable/trust_indicator_anonymous.xml
similarity index 100%
rename from briar-android/res/drawable/trust_indicator_anonymous.xml
rename to briar-android/src/main/res/drawable/trust_indicator_anonymous.xml
diff --git a/briar-android/res/drawable/trust_indicator_unknown.xml b/briar-android/src/main/res/drawable/trust_indicator_unknown.xml
similarity index 100%
rename from briar-android/res/drawable/trust_indicator_unknown.xml
rename to briar-android/src/main/res/drawable/trust_indicator_unknown.xml
diff --git a/briar-android/res/drawable/trust_indicator_unverified.xml b/briar-android/src/main/res/drawable/trust_indicator_unverified.xml
similarity index 100%
rename from briar-android/res/drawable/trust_indicator_unverified.xml
rename to briar-android/src/main/res/drawable/trust_indicator_unverified.xml
diff --git a/briar-android/res/drawable/trust_indicator_verified.xml b/briar-android/src/main/res/drawable/trust_indicator_verified.xml
similarity index 100%
rename from briar-android/res/drawable/trust_indicator_verified.xml
rename to briar-android/src/main/res/drawable/trust_indicator_verified.xml
diff --git a/briar-android/res/layout-land/fragment_keyagreement_id.xml b/briar-android/src/main/res/layout-land/fragment_keyagreement_id.xml
similarity index 100%
rename from briar-android/res/layout-land/fragment_keyagreement_id.xml
rename to briar-android/src/main/res/layout-land/fragment_keyagreement_id.xml
diff --git a/briar-android/res/layout-land/invitation_bluetooth_start.xml b/briar-android/src/main/res/layout-land/invitation_bluetooth_start.xml
similarity index 100%
rename from briar-android/res/layout-land/invitation_bluetooth_start.xml
rename to briar-android/src/main/res/layout-land/invitation_bluetooth_start.xml
diff --git a/briar-android/res/layout/activity_change_password.xml b/briar-android/src/main/res/layout/activity_change_password.xml
similarity index 97%
rename from briar-android/res/layout/activity_change_password.xml
rename to briar-android/src/main/res/layout/activity_change_password.xml
index 6e5887f2bff9c19a72bc64378061d2a92919f53a..e2c54958e82965c45967c0a86d3154b28a88b407 100644
--- a/briar-android/res/layout/activity_change_password.xml
+++ b/briar-android/src/main/res/layout/activity_change_password.xml
@@ -5,7 +5,7 @@
 	xmlns:tools="http://schemas.android.com/tools"
 	android:layout_width="match_parent"
 	android:layout_height="match_parent"
-	tools:context=".android.ChangePasswordActivity">
+	tools:context=".android.login.ChangePasswordActivity">
 
 	<RelativeLayout
 		android:layout_width="match_parent"
@@ -96,7 +96,7 @@
 				android:maxLines="1"/>
 		</android.support.design.widget.TextInputLayout>
 
-		<org.briarproject.android.util.StrengthMeter
+		<org.briarproject.briar.android.login.StrengthMeter
 			android:id="@+id/strength_meter"
 			android:layout_width="match_parent"
 			android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/activity_conversation.xml b/briar-android/src/main/res/layout/activity_conversation.xml
similarity index 94%
rename from briar-android/res/layout/activity_conversation.xml
rename to briar-android/src/main/res/layout/activity_conversation.xml
index cc05097fde4c989f5986e995a8d23f8df1e6729a..1e624c91d6241ff2f83ff2bc8bf0fdfb68f1d655 100644
--- a/briar-android/res/layout/activity_conversation.xml
+++ b/briar-android/src/main/res/layout/activity_conversation.xml
@@ -40,14 +40,14 @@
 
 	</android.support.design.widget.AppBarLayout>
 
-	<org.briarproject.android.view.BriarRecyclerView
+	<org.briarproject.briar.android.view.BriarRecyclerView
 		android:id="@+id/conversationView"
 		android:layout_width="match_parent"
 		android:layout_height="0dp"
 		android:layout_weight="1"
 		android:background="@color/window_background"/>
 
-	<org.briarproject.android.view.TextInputView
+	<org.briarproject.briar.android.view.TextInputView
 		android:id="@+id/text_input_container"
 		android:layout_width="match_parent"
 		android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/activity_create_forum.xml b/briar-android/src/main/res/layout/activity_create_forum.xml
similarity index 100%
rename from briar-android/res/layout/activity_create_forum.xml
rename to briar-android/src/main/res/layout/activity_create_forum.xml
diff --git a/briar-android/res/layout/activity_dev_report.xml b/briar-android/src/main/res/layout/activity_dev_report.xml
similarity index 99%
rename from briar-android/res/layout/activity_dev_report.xml
rename to briar-android/src/main/res/layout/activity_dev_report.xml
index 6670afeffa700af5b30c08f5bb526ec173893bbc..90f52efcf27550e0f129c5852280600cb76b1a07 100644
--- a/briar-android/res/layout/activity_dev_report.xml
+++ b/briar-android/src/main/res/layout/activity_dev_report.xml
@@ -9,7 +9,7 @@
 		android:layout_width="match_parent"
 		android:layout_height="match_parent"
 		android:orientation="vertical"
-		tools:context=".android.report.DevReportActivity">
+		tools:context=".android.reporting.DevReportActivity">
 
 		<android.support.design.widget.AppBarLayout
 			android:layout_width="match_parent"
diff --git a/briar-android/res/layout/activity_expired.xml b/briar-android/src/main/res/layout/activity_expired.xml
similarity index 100%
rename from briar-android/res/layout/activity_expired.xml
rename to briar-android/src/main/res/layout/activity_expired.xml
diff --git a/briar-android/res/layout/activity_forum.xml b/briar-android/src/main/res/layout/activity_forum.xml
similarity index 87%
rename from briar-android/res/layout/activity_forum.xml
rename to briar-android/src/main/res/layout/activity_forum.xml
index 81c7e4a2bb220efd271238321ef1a84d91e4b8b2..3f26d7a0103b77f6e78a694ff7df44ff4419101b 100644
--- a/briar-android/res/layout/activity_forum.xml
+++ b/briar-android/src/main/res/layout/activity_forum.xml
@@ -6,7 +6,7 @@
 	android:layout_height="match_parent"
 	android:orientation="vertical">
 
-	<org.briarproject.android.view.BriarRecyclerView
+	<org.briarproject.briar.android.view.BriarRecyclerView
 		android:id="@+id/list"
 		android:layout_width="match_parent"
 		android:layout_height="0dp"
@@ -14,7 +14,7 @@
 		app:emptyText="@string/no_forum_posts"
 		app:scrollToEnd="false"/>
 
-	<org.briarproject.android.view.TextInputView
+	<org.briarproject.briar.android.view.TextInputView
 		android:id="@+id/text_input_container"
 		android:layout_width="match_parent"
 		android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/activity_fragment_container.xml b/briar-android/src/main/res/layout/activity_fragment_container.xml
similarity index 100%
rename from briar-android/res/layout/activity_fragment_container.xml
rename to briar-android/src/main/res/layout/activity_fragment_container.xml
diff --git a/briar-android/res/layout/activity_nav_drawer.xml b/briar-android/src/main/res/layout/activity_nav_drawer.xml
similarity index 100%
rename from briar-android/res/layout/activity_nav_drawer.xml
rename to briar-android/src/main/res/layout/activity_nav_drawer.xml
diff --git a/briar-android/res/layout/activity_panic_preferences.xml b/briar-android/src/main/res/layout/activity_panic_preferences.xml
similarity index 81%
rename from briar-android/res/layout/activity_panic_preferences.xml
rename to briar-android/src/main/res/layout/activity_panic_preferences.xml
index 78aaeb88da79937717e5f8c0b9b2404e97add599..233f8b1a29a8f7d77142a50bfa728a4a1eece8d7 100644
--- a/briar-android/res/layout/activity_panic_preferences.xml
+++ b/briar-android/src/main/res/layout/activity_panic_preferences.xml
@@ -9,5 +9,5 @@
 		android:id="@+id/fragment"
 		android:layout_width="match_parent"
 		android:layout_height="match_parent"
-		android:name="org.briarproject.android.panic.PanicPreferencesFragment"/>
+		android:name="org.briarproject.briar.android.panic.PanicPreferencesFragment"/>
 </FrameLayout>
\ No newline at end of file
diff --git a/briar-android/res/layout/activity_password.xml b/briar-android/src/main/res/layout/activity_password.xml
similarity index 100%
rename from briar-android/res/layout/activity_password.xml
rename to briar-android/src/main/res/layout/activity_password.xml
diff --git a/briar-android/res/layout/activity_plain.xml b/briar-android/src/main/res/layout/activity_plain.xml
similarity index 100%
rename from briar-android/res/layout/activity_plain.xml
rename to briar-android/src/main/res/layout/activity_plain.xml
diff --git a/briar-android/res/layout/activity_reveal_contacts.xml b/briar-android/src/main/res/layout/activity_reveal_contacts.xml
similarity index 100%
rename from briar-android/res/layout/activity_reveal_contacts.xml
rename to briar-android/src/main/res/layout/activity_reveal_contacts.xml
diff --git a/briar-android/res/layout/activity_rss_feed_import.xml b/briar-android/src/main/res/layout/activity_rss_feed_import.xml
similarity index 100%
rename from briar-android/res/layout/activity_rss_feed_import.xml
rename to briar-android/src/main/res/layout/activity_rss_feed_import.xml
diff --git a/briar-android/res/layout/activity_rss_feed_manage.xml b/briar-android/src/main/res/layout/activity_rss_feed_manage.xml
similarity index 88%
rename from briar-android/res/layout/activity_rss_feed_manage.xml
rename to briar-android/src/main/res/layout/activity_rss_feed_manage.xml
index 8c9a0c468181d7e78c4aa1c33c51476494017d0a..76c14b4aa7f0f7c4d322910c77c9ed3cb11c93fb 100644
--- a/briar-android/res/layout/activity_rss_feed_manage.xml
+++ b/briar-android/src/main/res/layout/activity_rss_feed_manage.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<org.briarproject.android.view.BriarRecyclerView
+<org.briarproject.briar.android.view.BriarRecyclerView
 	xmlns:android="http://schemas.android.com/apk/res/android"
 	xmlns:tools="http://schemas.android.com/tools"
 	xmlns:app="http://schemas.android.com/apk/res-auto"
diff --git a/briar-android/res/layout/activity_settings.xml b/briar-android/src/main/res/layout/activity_settings.xml
similarity index 82%
rename from briar-android/res/layout/activity_settings.xml
rename to briar-android/src/main/res/layout/activity_settings.xml
index 4e629ca51b983b271f6328173203b5f24231ed16..4ef0a41576df4916130ac45ac0219176816fda74 100644
--- a/briar-android/res/layout/activity_settings.xml
+++ b/briar-android/src/main/res/layout/activity_settings.xml
@@ -9,5 +9,5 @@
 		android:id="@+id/fragment"
 		android:layout_width="match_parent"
 		android:layout_height="match_parent"
-		android:name="org.briarproject.android.fragment.SettingsFragment"/>
+		android:name="org.briarproject.briar.android.settings.SettingsFragment"/>
 </FrameLayout>
\ No newline at end of file
diff --git a/briar-android/res/layout/activity_setup.xml b/briar-android/src/main/res/layout/activity_setup.xml
similarity index 97%
rename from briar-android/res/layout/activity_setup.xml
rename to briar-android/src/main/res/layout/activity_setup.xml
index fe77e491df7cb839b089ced9f0a2df4f7ddc0bff..b1120debd9496fb70f4e2c8b4e146afe33304e61 100644
--- a/briar-android/res/layout/activity_setup.xml
+++ b/briar-android/src/main/res/layout/activity_setup.xml
@@ -5,7 +5,7 @@
 	xmlns:tools="http://schemas.android.com/tools"
 	android:layout_width="match_parent"
 	android:layout_height="match_parent"
-	tools:context=".android.SetupActivity">
+	tools:context=".android.login.SetupActivity">
 
 	<RelativeLayout
 		android:layout_width="match_parent"
@@ -61,7 +61,7 @@
 				android:maxLines="1"/>
 		</android.support.design.widget.TextInputLayout>
 
-		<org.briarproject.android.util.StrengthMeter
+		<org.briarproject.briar.android.login.StrengthMeter
 			android:id="@+id/strength_meter"
 			android:layout_width="match_parent"
 			android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/activity_sharing_status.xml b/briar-android/src/main/res/layout/activity_sharing_status.xml
similarity index 92%
rename from briar-android/res/layout/activity_sharing_status.xml
rename to briar-android/src/main/res/layout/activity_sharing_status.xml
index 48d2b7263a2bd3e27d48d5728c7fa43e81f5ebaf..ee9153f477e454e0e787ea45f5ea9b848f55144d 100644
--- a/briar-android/res/layout/activity_sharing_status.xml
+++ b/briar-android/src/main/res/layout/activity_sharing_status.xml
@@ -19,7 +19,7 @@
 
 		<View style="@style/Divider.ForumList"/>
 
-		<org.briarproject.android.view.BriarRecyclerView
+		<org.briarproject.briar.android.view.BriarRecyclerView
 			android:id="@+id/sharedByView"
 			android:layout_width="match_parent"
 			android:layout_height="wrap_content"
@@ -36,7 +36,7 @@
 
 		<View style="@style/Divider.ForumList"/>
 
-		<org.briarproject.android.view.BriarRecyclerView
+		<org.briarproject.briar.android.view.BriarRecyclerView
 			android:id="@+id/sharedWithView"
 			android:layout_width="match_parent"
 			android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/activity_startup_failure.xml b/briar-android/src/main/res/layout/activity_startup_failure.xml
similarity index 100%
rename from briar-android/res/layout/activity_startup_failure.xml
rename to briar-android/src/main/res/layout/activity_startup_failure.xml
diff --git a/briar-android/res/layout/activity_with_loading.xml b/briar-android/src/main/res/layout/activity_with_loading.xml
similarity index 100%
rename from briar-android/res/layout/activity_with_loading.xml
rename to briar-android/src/main/res/layout/activity_with_loading.xml
diff --git a/briar-android/res/layout/activity_write_blog_post.xml b/briar-android/src/main/res/layout/activity_write_blog_post.xml
similarity index 87%
rename from briar-android/res/layout/activity_write_blog_post.xml
rename to briar-android/src/main/res/layout/activity_write_blog_post.xml
index b8e5fe64068efe4a4bc39d5a37b8603c10fb8030..a70a8c31e99da038b808d9573fe954ff4b71da28 100644
--- a/briar-android/res/layout/activity_write_blog_post.xml
+++ b/briar-android/src/main/res/layout/activity_write_blog_post.xml
@@ -5,9 +5,9 @@
 	xmlns:tools="http://schemas.android.com/tools"
 	android:layout_width="match_parent"
 	android:layout_height="match_parent"
-	tools:context=".android.blogs.WriteBlogPostActivity">
+	tools:context=".android.blog.WriteBlogPostActivity">
 
-	<org.briarproject.android.view.LargeTextInputView
+	<org.briarproject.briar.android.view.LargeTextInputView
 		android:id="@+id/bodyInput"
 		android:layout_width="match_parent"
 		android:layout_height="match_parent"
diff --git a/briar-android/res/layout/author_view.xml b/briar-android/src/main/res/layout/author_view.xml
similarity index 97%
rename from briar-android/res/layout/author_view.xml
rename to briar-android/src/main/res/layout/author_view.xml
index 6f389e1de237bb90a63e5ca5c5d3a4cfd779b92e..ad614ab5341d318321796b8a61fa1b009cac0500 100644
--- a/briar-android/res/layout/author_view.xml
+++ b/briar-android/src/main/res/layout/author_view.xml
@@ -36,7 +36,7 @@
 		android:textSize="@dimen/text_size_small"
 		tools:text="Author Name"/>
 
-	<org.briarproject.android.view.TrustIndicatorView
+	<org.briarproject.briar.android.view.TrustIndicatorView
 		android:id="@+id/trustIndicator"
 		android:layout_width="wrap_content"
 		android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/briar_recycler_view.xml b/briar-android/src/main/res/layout/briar_recycler_view.xml
similarity index 100%
rename from briar-android/res/layout/briar_recycler_view.xml
rename to briar-android/src/main/res/layout/briar_recycler_view.xml
diff --git a/briar-android/res/layout/contact_avatar_status.xml b/briar-android/src/main/res/layout/contact_avatar_status.xml
similarity index 100%
rename from briar-android/res/layout/contact_avatar_status.xml
rename to briar-android/src/main/res/layout/contact_avatar_status.xml
diff --git a/briar-android/res/layout/emoji_drawer.xml b/briar-android/src/main/res/layout/emoji_drawer.xml
similarity index 100%
rename from briar-android/res/layout/emoji_drawer.xml
rename to briar-android/src/main/res/layout/emoji_drawer.xml
diff --git a/briar-android/res/layout/emoji_grid_layout.xml b/briar-android/src/main/res/layout/emoji_grid_layout.xml
similarity index 100%
rename from briar-android/res/layout/emoji_grid_layout.xml
rename to briar-android/src/main/res/layout/emoji_grid_layout.xml
diff --git a/briar-android/res/layout/fragment_blog.xml b/briar-android/src/main/res/layout/fragment_blog.xml
similarity index 76%
rename from briar-android/res/layout/fragment_blog.xml
rename to briar-android/src/main/res/layout/fragment_blog.xml
index bfc1c777a24cf170c6addd1cdc0c37b1ebe7e810..df5e36a9e7644598ade8fe29f9fe93c9791f2ff2 100644
--- a/briar-android/res/layout/fragment_blog.xml
+++ b/briar-android/src/main/res/layout/fragment_blog.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<org.briarproject.android.view.BriarRecyclerView
+<org.briarproject.briar.android.view.BriarRecyclerView
 	android:id="@+id/postList"
 	xmlns:android="http://schemas.android.com/apk/res/android"
 	xmlns:app="http://schemas.android.com/apk/res-auto"
@@ -7,4 +7,4 @@
 	android:layout_width="match_parent"
 	android:layout_height="match_parent"
 	app:scrollToEnd="false"
-	tools:context=".android.blogs.BlogActivity"/>
+	tools:context=".android.blog.BlogActivity"/>
diff --git a/briar-android/res/layout/fragment_blog_post.xml b/briar-android/src/main/res/layout/fragment_blog_post.xml
similarity index 100%
rename from briar-android/res/layout/fragment_blog_post.xml
rename to briar-android/src/main/res/layout/fragment_blog_post.xml
diff --git a/briar-android/res/layout/fragment_blog_post_pager.xml b/briar-android/src/main/res/layout/fragment_blog_post_pager.xml
similarity index 100%
rename from briar-android/res/layout/fragment_blog_post_pager.xml
rename to briar-android/src/main/res/layout/fragment_blog_post_pager.xml
diff --git a/briar-android/res/layout/fragment_create_group.xml b/briar-android/src/main/res/layout/fragment_create_group.xml
similarity index 100%
rename from briar-android/res/layout/fragment_create_group.xml
rename to briar-android/src/main/res/layout/fragment_create_group.xml
diff --git a/briar-android/res/layout/fragment_forum_list.xml b/briar-android/src/main/res/layout/fragment_forum_list.xml
similarity index 77%
rename from briar-android/res/layout/fragment_forum_list.xml
rename to briar-android/src/main/res/layout/fragment_forum_list.xml
index ca4fb452052bd7180b1b4c9dc4e9f63a454e97de..6b09a7ff6c8955c60abd2b4257943bddf4af5a6d 100644
--- a/briar-android/res/layout/fragment_forum_list.xml
+++ b/briar-android/src/main/res/layout/fragment_forum_list.xml
@@ -5,11 +5,11 @@
 	android:layout_width="match_parent"
 	android:layout_height="match_parent">
 
-	<org.briarproject.android.view.BriarRecyclerView
+	<org.briarproject.briar.android.view.BriarRecyclerView
 		android:id="@+id/forumList"
 		xmlns:android="http://schemas.android.com/apk/res/android"
 		android:layout_width="match_parent"
 		android:layout_height="match_parent"
-		app:layout_behavior="org.briarproject.android.view.BriarRecyclerViewBehavior"/>
+		app:layout_behavior="org.briarproject.briar.android.view.BriarRecyclerViewBehavior"/>
 
 </android.support.design.widget.CoordinatorLayout>
diff --git a/briar-android/res/layout/fragment_keyagreement_id.xml b/briar-android/src/main/res/layout/fragment_keyagreement_id.xml
similarity index 100%
rename from briar-android/res/layout/fragment_keyagreement_id.xml
rename to briar-android/src/main/res/layout/fragment_keyagreement_id.xml
diff --git a/briar-android/res/layout/fragment_keyagreement_qr.xml b/briar-android/src/main/res/layout/fragment_keyagreement_qr.xml
similarity index 98%
rename from briar-android/res/layout/fragment_keyagreement_qr.xml
rename to briar-android/src/main/res/layout/fragment_keyagreement_qr.xml
index c83c2f3b5fc4773e392b0dd72e55c1f397e53a93..1aaf28183f99d20e5b66f9842d3f68f9aa176336 100644
--- a/briar-android/res/layout/fragment_keyagreement_qr.xml
+++ b/briar-android/src/main/res/layout/fragment_keyagreement_qr.xml
@@ -5,7 +5,7 @@
 	android:layout_width="match_parent"
 	android:layout_height="match_parent">
 
-	<org.briarproject.android.view.CameraView
+	<org.briarproject.briar.android.keyagreement.CameraView
 		android:id="@+id/camera_view"
 		android:layout_width="match_parent"
 		android:layout_height="match_parent"/>
diff --git a/briar-android/res/layout/fragment_link_dialog.xml b/briar-android/src/main/res/layout/fragment_link_dialog.xml
similarity index 100%
rename from briar-android/res/layout/fragment_link_dialog.xml
rename to briar-android/src/main/res/layout/fragment_link_dialog.xml
diff --git a/briar-android/res/layout/fragment_message.xml b/briar-android/src/main/res/layout/fragment_message.xml
similarity index 86%
rename from briar-android/res/layout/fragment_message.xml
rename to briar-android/src/main/res/layout/fragment_message.xml
index 168ff34a4521410e4d828751dca43f489ff1cd3b..7f74c6577e8030ebddfcd9a29658c1c1c1258808 100644
--- a/briar-android/res/layout/fragment_message.xml
+++ b/briar-android/src/main/res/layout/fragment_message.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<org.briarproject.android.view.LargeTextInputView
+<org.briarproject.briar.android.view.LargeTextInputView
 	android:id="@+id/messageView"
 	xmlns:android="http://schemas.android.com/apk/res/android"
 	xmlns:app="http://schemas.android.com/apk/res-auto"
diff --git a/briar-android/res/layout/fragment_reblog.xml b/briar-android/src/main/res/layout/fragment_reblog.xml
similarity index 95%
rename from briar-android/res/layout/fragment_reblog.xml
rename to briar-android/src/main/res/layout/fragment_reblog.xml
index e6f8237cf6b3ad0c0dcd94a0d00a334d1789ba5e..c0305e25035e8f9783bd58802e990cb74f8388b3 100644
--- a/briar-android/res/layout/fragment_reblog.xml
+++ b/briar-android/src/main/res/layout/fragment_reblog.xml
@@ -35,7 +35,7 @@
 
 	</ScrollView>
 
-	<org.briarproject.android.view.LargeTextInputView
+	<org.briarproject.briar.android.view.LargeTextInputView
 		android:id="@+id/inputText"
 		android:layout_width="match_parent"
 		android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/introduction_message.xml b/briar-android/src/main/res/layout/introduction_message.xml
similarity index 98%
rename from briar-android/res/layout/introduction_message.xml
rename to briar-android/src/main/res/layout/introduction_message.xml
index 3240557289461b5623987a530e6a9aebf787887e..61531fd2278c3eacc4a844de7bb647d4f078ebf2 100644
--- a/briar-android/res/layout/introduction_message.xml
+++ b/briar-android/src/main/res/layout/introduction_message.xml
@@ -115,7 +115,7 @@
 
 	</ScrollView>
 
-	<org.briarproject.android.view.LargeTextInputView
+	<org.briarproject.briar.android.view.LargeTextInputView
 		android:id="@+id/introductionMessageView"
 		android:layout_width="match_parent"
 		android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/invitation_bluetooth_confirmation_code.xml b/briar-android/src/main/res/layout/invitation_bluetooth_confirmation_code.xml
similarity index 100%
rename from briar-android/res/layout/invitation_bluetooth_confirmation_code.xml
rename to briar-android/src/main/res/layout/invitation_bluetooth_confirmation_code.xml
diff --git a/briar-android/res/layout/invitation_bluetooth_invitation_code.xml b/briar-android/src/main/res/layout/invitation_bluetooth_invitation_code.xml
similarity index 100%
rename from briar-android/res/layout/invitation_bluetooth_invitation_code.xml
rename to briar-android/src/main/res/layout/invitation_bluetooth_invitation_code.xml
diff --git a/briar-android/res/layout/invitation_bluetooth_start.xml b/briar-android/src/main/res/layout/invitation_bluetooth_start.xml
similarity index 100%
rename from briar-android/res/layout/invitation_bluetooth_start.xml
rename to briar-android/src/main/res/layout/invitation_bluetooth_start.xml
diff --git a/briar-android/res/layout/invitation_error.xml b/briar-android/src/main/res/layout/invitation_error.xml
similarity index 100%
rename from briar-android/res/layout/invitation_error.xml
rename to briar-android/src/main/res/layout/invitation_error.xml
diff --git a/briar-android/res/layout/list.xml b/briar-android/src/main/res/layout/list.xml
similarity index 83%
rename from briar-android/res/layout/list.xml
rename to briar-android/src/main/res/layout/list.xml
index 0fbe7cede515e0b4c9e85998d44d9d2de013e8ce..8f7a01284e69e6cb81b42926358f6329684dde4e 100644
--- a/briar-android/res/layout/list.xml
+++ b/briar-android/src/main/res/layout/list.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<org.briarproject.android.view.BriarRecyclerView
+<org.briarproject.briar.android.view.BriarRecyclerView
 	android:id="@+id/list"
 	xmlns:android="http://schemas.android.com/apk/res/android"
 	xmlns:app="http://schemas.android.com/apk/res-auto"
diff --git a/briar-android/res/layout/list_item_blog.xml b/briar-android/src/main/res/layout/list_item_blog.xml
similarity index 98%
rename from briar-android/res/layout/list_item_blog.xml
rename to briar-android/src/main/res/layout/list_item_blog.xml
index a04a430373568d1e24ca173a6e122d52e28c534f..214056cf4da0c5b4da8c422b374f05ebd6a39104 100644
--- a/briar-android/res/layout/list_item_blog.xml
+++ b/briar-android/src/main/res/layout/list_item_blog.xml
@@ -8,7 +8,7 @@
 	android:layout_marginStart="@dimen/listitem_horizontal_margin"
 	android:background="?attr/selectableItemBackground">
 
-	<org.briarproject.android.view.TextAvatarView
+	<org.briarproject.briar.android.view.TextAvatarView
 		android:id="@+id/avatarView"
 		android:layout_width="@dimen/listitem_picture_frame_size"
 		android:layout_height="@dimen/listitem_picture_frame_size"
diff --git a/briar-android/res/layout/list_item_blog_comment.xml b/briar-android/src/main/res/layout/list_item_blog_comment.xml
similarity index 96%
rename from briar-android/res/layout/list_item_blog_comment.xml
rename to briar-android/src/main/res/layout/list_item_blog_comment.xml
index 4c521522a73ab23f9dfd5aa81078b0f4c2d77f66..3cab8e948b57fa783635c26e4613934e6c78549c 100644
--- a/briar-android/res/layout/list_item_blog_comment.xml
+++ b/briar-android/src/main/res/layout/list_item_blog_comment.xml
@@ -11,7 +11,7 @@
 		android:id="@+id/inputDivider"
 		style="@style/Divider.Horizontal"/>
 
-	<org.briarproject.android.view.AuthorView
+	<org.briarproject.briar.android.view.AuthorView
 		android:id="@+id/authorView"
 		android:layout_width="wrap_content"
 		android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/list_item_blog_post.xml b/briar-android/src/main/res/layout/list_item_blog_post.xml
similarity index 96%
rename from briar-android/res/layout/list_item_blog_post.xml
rename to briar-android/src/main/res/layout/list_item_blog_post.xml
index 96c2033a3fb93ebc746f6ba820c71b585ee92201..a0fef3ea7b3da6bfd10a06cfb037e6502c8dc1e5 100644
--- a/briar-android/res/layout/list_item_blog_post.xml
+++ b/briar-android/src/main/res/layout/list_item_blog_post.xml
@@ -19,7 +19,7 @@
 			android:layout_height="wrap_content"
 			android:padding="@dimen/listitem_vertical_margin">
 
-			<org.briarproject.android.view.AuthorView
+			<org.briarproject.briar.android.view.AuthorView
 				android:id="@+id/rebloggerView"
 				android:layout_width="wrap_content"
 				android:layout_height="wrap_content"
@@ -29,7 +29,7 @@
 				android:layout_toLeftOf="@+id/commentView"
 				app:persona="reblogger"/>
 
-			<org.briarproject.android.view.AuthorView
+			<org.briarproject.briar.android.view.AuthorView
 				android:id="@+id/authorView"
 				android:layout_width="wrap_content"
 				android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/list_item_contact.xml b/briar-android/src/main/res/layout/list_item_contact.xml
similarity index 100%
rename from briar-android/res/layout/list_item_contact.xml
rename to briar-android/src/main/res/layout/list_item_contact.xml
diff --git a/briar-android/res/layout/list_item_contact_small.xml b/briar-android/src/main/res/layout/list_item_contact_small.xml
similarity index 100%
rename from briar-android/res/layout/list_item_contact_small.xml
rename to briar-android/src/main/res/layout/list_item_contact_small.xml
diff --git a/briar-android/res/layout/list_item_conversation_msg_in.xml b/briar-android/src/main/res/layout/list_item_conversation_msg_in.xml
similarity index 100%
rename from briar-android/res/layout/list_item_conversation_msg_in.xml
rename to briar-android/src/main/res/layout/list_item_conversation_msg_in.xml
diff --git a/briar-android/res/layout/list_item_conversation_msg_out.xml b/briar-android/src/main/res/layout/list_item_conversation_msg_out.xml
similarity index 100%
rename from briar-android/res/layout/list_item_conversation_msg_out.xml
rename to briar-android/src/main/res/layout/list_item_conversation_msg_out.xml
diff --git a/briar-android/res/layout/list_item_conversation_notice_in.xml b/briar-android/src/main/res/layout/list_item_conversation_notice_in.xml
similarity index 100%
rename from briar-android/res/layout/list_item_conversation_notice_in.xml
rename to briar-android/src/main/res/layout/list_item_conversation_notice_in.xml
diff --git a/briar-android/res/layout/list_item_conversation_notice_out.xml b/briar-android/src/main/res/layout/list_item_conversation_notice_out.xml
similarity index 100%
rename from briar-android/res/layout/list_item_conversation_notice_out.xml
rename to briar-android/src/main/res/layout/list_item_conversation_notice_out.xml
diff --git a/briar-android/res/layout/list_item_conversation_request.xml b/briar-android/src/main/res/layout/list_item_conversation_request.xml
similarity index 100%
rename from briar-android/res/layout/list_item_conversation_request.xml
rename to briar-android/src/main/res/layout/list_item_conversation_request.xml
diff --git a/briar-android/res/layout/list_item_crash.xml b/briar-android/src/main/res/layout/list_item_crash.xml
similarity index 100%
rename from briar-android/res/layout/list_item_crash.xml
rename to briar-android/src/main/res/layout/list_item_crash.xml
diff --git a/briar-android/res/layout/list_item_forum.xml b/briar-android/src/main/res/layout/list_item_forum.xml
similarity index 98%
rename from briar-android/res/layout/list_item_forum.xml
rename to briar-android/src/main/res/layout/list_item_forum.xml
index 5c4df7bd173ffe09c3142510844775fa50777dcb..50bd1a18aff68639e2a03f6f58817f55e81b0243 100644
--- a/briar-android/res/layout/list_item_forum.xml
+++ b/briar-android/src/main/res/layout/list_item_forum.xml
@@ -8,7 +8,7 @@
 	android:layout_marginStart="@dimen/listitem_horizontal_margin"
 	android:background="?attr/selectableItemBackground">
 
-	<org.briarproject.android.view.TextAvatarView
+	<org.briarproject.briar.android.view.TextAvatarView
 		android:id="@+id/avatarView"
 		android:layout_width="@dimen/listitem_picture_frame_size"
 		android:layout_height="@dimen/listitem_picture_frame_size"
diff --git a/briar-android/res/layout/list_item_group.xml b/briar-android/src/main/res/layout/list_item_group.xml
similarity index 98%
rename from briar-android/res/layout/list_item_group.xml
rename to briar-android/src/main/res/layout/list_item_group.xml
index 20ed6fc9f660e9ba4e820d7323fe6320328bc526..d0b11226487e0d1e4b3866dada0f72ab24fb0794 100644
--- a/briar-android/res/layout/list_item_group.xml
+++ b/briar-android/src/main/res/layout/list_item_group.xml
@@ -8,7 +8,7 @@
 	android:layout_marginStart="@dimen/listitem_horizontal_margin"
 	android:background="?attr/selectableItemBackground">
 
-	<org.briarproject.android.view.TextAvatarView
+	<org.briarproject.briar.android.view.TextAvatarView
 		android:id="@+id/avatarView"
 		android:layout_width="@dimen/listitem_picture_frame_size"
 		android:layout_height="@dimen/listitem_picture_frame_size"
diff --git a/briar-android/res/layout/list_item_group_join_notice.xml b/briar-android/src/main/res/layout/list_item_group_join_notice.xml
similarity index 98%
rename from briar-android/res/layout/list_item_group_join_notice.xml
rename to briar-android/src/main/res/layout/list_item_group_join_notice.xml
index 71d6ceec17f6c855a735bc59b39948a860e146f3..23b7fd283ccdfe6975f61f3a94a7b07b4248b6f4 100644
--- a/briar-android/res/layout/list_item_group_join_notice.xml
+++ b/briar-android/src/main/res/layout/list_item_group_join_notice.xml
@@ -54,7 +54,7 @@
 		android:textStyle="italic"
 		tools:text="@string/groups_reveal_visible_revealed_by_contact"/>
 
-	<org.briarproject.android.view.AuthorView
+	<org.briarproject.briar.android.view.AuthorView
 		android:id="@+id/author"
 		android:layout_width="wrap_content"
 		android:layout_height="@dimen/button_size"
diff --git a/briar-android/res/layout/list_item_group_member.xml b/briar-android/src/main/res/layout/list_item_group_member.xml
similarity index 97%
rename from briar-android/res/layout/list_item_group_member.xml
rename to briar-android/src/main/res/layout/list_item_group_member.xml
index 14640f33875f773a1bb98599519dd65cf120ab3d..f02ed68c7d6e78cd1176399b33de38f3604837ab 100644
--- a/briar-android/res/layout/list_item_group_member.xml
+++ b/briar-android/src/main/res/layout/list_item_group_member.xml
@@ -9,7 +9,7 @@
 	android:layout_marginStart="@dimen/listitem_horizontal_margin"
 	android:paddingTop="@dimen/margin_medium">
 
-	<org.briarproject.android.view.AuthorView
+	<org.briarproject.briar.android.view.AuthorView
 		android:id="@+id/authorView"
 		android:layout_width="wrap_content"
 		android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/list_item_invitations.xml b/briar-android/src/main/res/layout/list_item_invitations.xml
similarity index 98%
rename from briar-android/res/layout/list_item_invitations.xml
rename to briar-android/src/main/res/layout/list_item_invitations.xml
index 6419c14b351aa17fea3b0a7063e26085eeb790cb..ce7afa14770ae968530584d51eb2cadcae59b997 100644
--- a/briar-android/res/layout/list_item_invitations.xml
+++ b/briar-android/src/main/res/layout/list_item_invitations.xml
@@ -9,7 +9,7 @@
 	android:background="?attr/selectableItemBackground"
 	android:paddingTop="@dimen/listitem_horizontal_margin">
 
-	<org.briarproject.android.view.TextAvatarView
+	<org.briarproject.briar.android.view.TextAvatarView
 		android:id="@+id/avatarView"
 		android:layout_width="@dimen/listitem_picture_frame_size"
 		android:layout_height="@dimen/listitem_picture_frame_size"
diff --git a/briar-android/res/layout/list_item_revealable_contact.xml b/briar-android/src/main/res/layout/list_item_revealable_contact.xml
similarity index 100%
rename from briar-android/res/layout/list_item_revealable_contact.xml
rename to briar-android/src/main/res/layout/list_item_revealable_contact.xml
diff --git a/briar-android/res/layout/list_item_rss_feed.xml b/briar-android/src/main/res/layout/list_item_rss_feed.xml
similarity index 100%
rename from briar-android/res/layout/list_item_rss_feed.xml
rename to briar-android/src/main/res/layout/list_item_rss_feed.xml
diff --git a/briar-android/res/layout/list_item_selectable_contact.xml b/briar-android/src/main/res/layout/list_item_selectable_contact.xml
similarity index 100%
rename from briar-android/res/layout/list_item_selectable_contact.xml
rename to briar-android/src/main/res/layout/list_item_selectable_contact.xml
diff --git a/briar-android/res/layout/list_item_thread.xml b/briar-android/src/main/res/layout/list_item_thread.xml
similarity index 98%
rename from briar-android/res/layout/list_item_thread.xml
rename to briar-android/src/main/res/layout/list_item_thread.xml
index 3757cc7e7c9e3335e095ef62a2ad709d906b6487..dbc3cb060afb19cb1c33e2c44dffb874c30fb949 100644
--- a/briar-android/res/layout/list_item_thread.xml
+++ b/briar-android/src/main/res/layout/list_item_thread.xml
@@ -83,7 +83,7 @@
 			android:textSize="@dimen/text_size_medium"
 			tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."/>
 
-		<org.briarproject.android.view.AuthorView
+		<org.briarproject.briar.android.view.AuthorView
 			android:id="@+id/author"
 			android:layout_width="wrap_content"
 			android:layout_height="@dimen/button_size"
diff --git a/briar-android/res/layout/list_item_transport.xml b/briar-android/src/main/res/layout/list_item_transport.xml
similarity index 100%
rename from briar-android/res/layout/list_item_transport.xml
rename to briar-android/src/main/res/layout/list_item_transport.xml
diff --git a/briar-android/res/layout/navigation_header.xml b/briar-android/src/main/res/layout/navigation_header.xml
similarity index 100%
rename from briar-android/res/layout/navigation_header.xml
rename to briar-android/src/main/res/layout/navigation_header.xml
diff --git a/briar-android/res/layout/navigation_menu.xml b/briar-android/src/main/res/layout/navigation_menu.xml
similarity index 100%
rename from briar-android/res/layout/navigation_menu.xml
rename to briar-android/src/main/res/layout/navigation_menu.xml
diff --git a/briar-android/res/layout/splash.xml b/briar-android/src/main/res/layout/splash.xml
similarity index 100%
rename from briar-android/res/layout/splash.xml
rename to briar-android/src/main/res/layout/splash.xml
diff --git a/briar-android/res/layout/text_avatar_view.xml b/briar-android/src/main/res/layout/text_avatar_view.xml
similarity index 100%
rename from briar-android/res/layout/text_avatar_view.xml
rename to briar-android/src/main/res/layout/text_avatar_view.xml
diff --git a/briar-android/res/layout/text_input_view.xml b/briar-android/src/main/res/layout/text_input_view.xml
similarity index 100%
rename from briar-android/res/layout/text_input_view.xml
rename to briar-android/src/main/res/layout/text_input_view.xml
diff --git a/briar-android/res/layout/text_input_view_large.xml b/briar-android/src/main/res/layout/text_input_view_large.xml
similarity index 100%
rename from briar-android/res/layout/text_input_view_large.xml
rename to briar-android/src/main/res/layout/text_input_view_large.xml
diff --git a/briar-android/res/layout/transports_list.xml b/briar-android/src/main/res/layout/transports_list.xml
similarity index 100%
rename from briar-android/res/layout/transports_list.xml
rename to briar-android/src/main/res/layout/transports_list.xml
diff --git a/briar-android/res/layout/view_code_entry.xml b/briar-android/src/main/res/layout/view_code_entry.xml
similarity index 100%
rename from briar-android/res/layout/view_code_entry.xml
rename to briar-android/src/main/res/layout/view_code_entry.xml
diff --git a/briar-android/res/menu/blogs_blog_actions.xml b/briar-android/src/main/res/menu/blogs_blog_actions.xml
similarity index 100%
rename from briar-android/res/menu/blogs_blog_actions.xml
rename to briar-android/src/main/res/menu/blogs_blog_actions.xml
diff --git a/briar-android/res/menu/blogs_feed_actions.xml b/briar-android/src/main/res/menu/blogs_feed_actions.xml
similarity index 100%
rename from briar-android/res/menu/blogs_feed_actions.xml
rename to briar-android/src/main/res/menu/blogs_feed_actions.xml
diff --git a/briar-android/res/menu/contact_list_actions.xml b/briar-android/src/main/res/menu/contact_list_actions.xml
similarity index 100%
rename from briar-android/res/menu/contact_list_actions.xml
rename to briar-android/src/main/res/menu/contact_list_actions.xml
diff --git a/briar-android/res/menu/contact_selection_actions.xml b/briar-android/src/main/res/menu/contact_selection_actions.xml
similarity index 100%
rename from briar-android/res/menu/contact_selection_actions.xml
rename to briar-android/src/main/res/menu/contact_selection_actions.xml
diff --git a/briar-android/res/menu/conversation_actions.xml b/briar-android/src/main/res/menu/conversation_actions.xml
similarity index 100%
rename from briar-android/res/menu/conversation_actions.xml
rename to briar-android/src/main/res/menu/conversation_actions.xml
diff --git a/briar-android/res/menu/dev_report_actions.xml b/briar-android/src/main/res/menu/dev_report_actions.xml
similarity index 100%
rename from briar-android/res/menu/dev_report_actions.xml
rename to briar-android/src/main/res/menu/dev_report_actions.xml
diff --git a/briar-android/res/menu/forum_actions.xml b/briar-android/src/main/res/menu/forum_actions.xml
similarity index 100%
rename from briar-android/res/menu/forum_actions.xml
rename to briar-android/src/main/res/menu/forum_actions.xml
diff --git a/briar-android/res/menu/forum_list_actions.xml b/briar-android/src/main/res/menu/forum_list_actions.xml
similarity index 100%
rename from briar-android/res/menu/forum_list_actions.xml
rename to briar-android/src/main/res/menu/forum_list_actions.xml
diff --git a/briar-android/res/menu/group_actions.xml b/briar-android/src/main/res/menu/group_actions.xml
similarity index 100%
rename from briar-android/res/menu/group_actions.xml
rename to briar-android/src/main/res/menu/group_actions.xml
diff --git a/briar-android/res/menu/group_reveal_actions.xml b/briar-android/src/main/res/menu/group_reveal_actions.xml
similarity index 100%
rename from briar-android/res/menu/group_reveal_actions.xml
rename to briar-android/src/main/res/menu/group_reveal_actions.xml
diff --git a/briar-android/res/menu/groups_list_actions.xml b/briar-android/src/main/res/menu/groups_list_actions.xml
similarity index 100%
rename from briar-android/res/menu/groups_list_actions.xml
rename to briar-android/src/main/res/menu/groups_list_actions.xml
diff --git a/briar-android/res/menu/navigation_drawer.xml b/briar-android/src/main/res/menu/navigation_drawer.xml
similarity index 100%
rename from briar-android/res/menu/navigation_drawer.xml
rename to briar-android/src/main/res/menu/navigation_drawer.xml
diff --git a/briar-android/res/menu/rss_feed_manage_actions.xml b/briar-android/src/main/res/menu/rss_feed_manage_actions.xml
similarity index 100%
rename from briar-android/res/menu/rss_feed_manage_actions.xml
rename to briar-android/src/main/res/menu/rss_feed_manage_actions.xml
diff --git a/briar-android/res/values-de/strings.xml b/briar-android/src/main/res/values-de/strings.xml
similarity index 100%
rename from briar-android/res/values-de/strings.xml
rename to briar-android/src/main/res/values-de/strings.xml
diff --git a/briar-android/res/values-es/strings.xml b/briar-android/src/main/res/values-es/strings.xml
similarity index 100%
rename from briar-android/res/values-es/strings.xml
rename to briar-android/src/main/res/values-es/strings.xml
diff --git a/briar-android/res/values-fr/strings.xml b/briar-android/src/main/res/values-fr/strings.xml
similarity index 100%
rename from briar-android/res/values-fr/strings.xml
rename to briar-android/src/main/res/values-fr/strings.xml
diff --git a/briar-android/res/values-it/strings.xml b/briar-android/src/main/res/values-it/strings.xml
similarity index 100%
rename from briar-android/res/values-it/strings.xml
rename to briar-android/src/main/res/values-it/strings.xml
diff --git a/briar-android/res/values-ms/strings.xml b/briar-android/src/main/res/values-ms/strings.xml
similarity index 100%
rename from briar-android/res/values-ms/strings.xml
rename to briar-android/src/main/res/values-ms/strings.xml
diff --git a/briar-android/res/values-pt-rBR/strings.xml b/briar-android/src/main/res/values-pt-rBR/strings.xml
similarity index 100%
rename from briar-android/res/values-pt-rBR/strings.xml
rename to briar-android/src/main/res/values-pt-rBR/strings.xml
diff --git a/briar-android/res/values-sq/strings.xml b/briar-android/src/main/res/values-sq/strings.xml
similarity index 100%
rename from briar-android/res/values-sq/strings.xml
rename to briar-android/src/main/res/values-sq/strings.xml
diff --git a/briar-android/res/values/arrays.xml b/briar-android/src/main/res/values/arrays.xml
similarity index 100%
rename from briar-android/res/values/arrays.xml
rename to briar-android/src/main/res/values/arrays.xml
diff --git a/briar-android/res/values/attrs.xml b/briar-android/src/main/res/values/attrs.xml
similarity index 100%
rename from briar-android/res/values/attrs.xml
rename to briar-android/src/main/res/values/attrs.xml
diff --git a/briar-android/res/values/color.xml b/briar-android/src/main/res/values/color.xml
similarity index 100%
rename from briar-android/res/values/color.xml
rename to briar-android/src/main/res/values/color.xml
diff --git a/briar-android/res/values/dimens.xml b/briar-android/src/main/res/values/dimens.xml
similarity index 97%
rename from briar-android/res/values/dimens.xml
rename to briar-android/src/main/res/values/dimens.xml
index 0fd1c3aff10f2b4414d8f3e4a6912fd16bab9e7d..d8327da7dacd7befca20ddab2d593631f3a19245 100644
--- a/briar-android/res/values/dimens.xml
+++ b/briar-android/src/main/res/values/dimens.xml
@@ -1,65 +1,65 @@
-<resources>
-
-	<!-- Default screen margins, per the Android Design guidelines. -->
-	<dimen name="margin_activity_horizontal">16dp</dimen>
-	<dimen name="margin_activity_vertical">16dp</dimen>
-
-	<dimen name="margin_separator">1dp</dimen>
-	<dimen name="margin_tiny">2dp</dimen>
-	<dimen name="margin_small">4dp</dimen>
-	<dimen name="margin_medium">8dp</dimen>
-	<dimen name="margin_large">16dp</dimen>
-	<dimen name="margin_xlarge">32dp</dimen>
-	<dimen name="margin_xxlarge">64dp</dimen>
-
-	<!-- v2 dimens -->
-	<dimen name="text_size_tiny">12sp</dimen>
-	<dimen name="text_size_small">14sp</dimen>
-	<dimen name="text_size_medium">16sp</dimen>
-	<dimen name="text_size_large">20sp</dimen>
-	<dimen name="text_size_xlarge">34sp</dimen>
-
-	<dimen name="listitem_horizontal_margin">16dp</dimen>
-	<dimen name="listitem_vertical_margin">10dp</dimen>
-	<dimen name="listitem_height_one_line_avatar">56dp</dimen>
-	<dimen name="listitem_picture_size">48dp</dimen>
-	<dimen name="listitem_picture_size_small">23dp</dimen>
-	<dimen name="listitem_picture_frame_size">51dp</dimen>
-	<dimen name="listitem_picture_frame_offset_horizontal">1dp</dimen>
-	<dimen name="listitem_picture_frame_offset_vertical">2dp</dimen>
-	<dimen name="listitem_selectable_picture_size">40dp</dimen>
-	<dimen name="listitem_group_member_indentation">32dp</dimen>
-	<dimen name="avatar_forum_size">48dp</dimen>
-	<dimen name="avatar_border_width">2dp</dimen>
-	<dimen name="avatar_text_size">30sp</dimen>
-	<dimen name="button_size">48dp</dimen>
-
-	<dimen name="unread_bubble_text_size">12sp</dimen>
-	<dimen name="unread_bubble_padding_horizontal">6dp</dimen>
-	<dimen name="unread_bubble_size">19dp</dimen>
-
-	<dimen name="message_bubble_margin_tail">3dp</dimen>
-	<dimen name="message_bubble_margin_non_tail">30dp</dimen>
-	<dimen name="message_bubble_timestamp_margin">7dp</dimen>
-	<dimen name="forum_nested_line_width">2dp</dimen>
-	<dimen name="forum_nested_indicator">24dp</dimen>
-
-	<dimen name="blogs_avatar_normal_size">30dp</dimen>
-	<dimen name="blogs_avatar_icon_size">15dp</dimen>
-	<dimen name="blogs_avatar_comment_size">20dp</dimen>
-
-	<!-- Emoji -->
-	<dimen name="text_input_height">42dp</dimen>
-	<dimen name="conversation_item_body_text_size">16sp</dimen>
-	<dimen name="emoji_drawer_size">32sp</dimen>
-	<dimen name="emoji_drawer_indicator_height">2dp</dimen>
-	<dimen name="emoji_drawer_item_padding">5dp</dimen>
-	<dimen name="emoji_drawer_left_right_padding">2dp</dimen>
-
-	<!-- Keyboard Sizes -->
-	<dimen name="min_keyboard_size">50dp</dimen>
-	<dimen name="default_custom_keyboard_size">220dp</dimen>
-	<dimen name="min_custom_keyboard_size">110dp</dimen>
-	<dimen name="min_custom_keyboard_top_margin">170dp</dimen>
-
-</resources>
+<resources>
+
+	<!-- Default screen margins, per the Android Design guidelines. -->
+	<dimen name="margin_activity_horizontal">16dp</dimen>
+	<dimen name="margin_activity_vertical">16dp</dimen>
+
+	<dimen name="margin_separator">1dp</dimen>
+	<dimen name="margin_tiny">2dp</dimen>
+	<dimen name="margin_small">4dp</dimen>
+	<dimen name="margin_medium">8dp</dimen>
+	<dimen name="margin_large">16dp</dimen>
+	<dimen name="margin_xlarge">32dp</dimen>
+	<dimen name="margin_xxlarge">64dp</dimen>
+
+	<!-- v2 dimens -->
+	<dimen name="text_size_tiny">12sp</dimen>
+	<dimen name="text_size_small">14sp</dimen>
+	<dimen name="text_size_medium">16sp</dimen>
+	<dimen name="text_size_large">20sp</dimen>
+	<dimen name="text_size_xlarge">34sp</dimen>
+
+	<dimen name="listitem_horizontal_margin">16dp</dimen>
+	<dimen name="listitem_vertical_margin">10dp</dimen>
+	<dimen name="listitem_height_one_line_avatar">56dp</dimen>
+	<dimen name="listitem_picture_size">48dp</dimen>
+	<dimen name="listitem_picture_size_small">23dp</dimen>
+	<dimen name="listitem_picture_frame_size">51dp</dimen>
+	<dimen name="listitem_picture_frame_offset_horizontal">1dp</dimen>
+	<dimen name="listitem_picture_frame_offset_vertical">2dp</dimen>
+	<dimen name="listitem_selectable_picture_size">40dp</dimen>
+	<dimen name="listitem_group_member_indentation">32dp</dimen>
+	<dimen name="avatar_forum_size">48dp</dimen>
+	<dimen name="avatar_border_width">2dp</dimen>
+	<dimen name="avatar_text_size">30sp</dimen>
+	<dimen name="button_size">48dp</dimen>
+
+	<dimen name="unread_bubble_text_size">12sp</dimen>
+	<dimen name="unread_bubble_padding_horizontal">6dp</dimen>
+	<dimen name="unread_bubble_size">19dp</dimen>
+
+	<dimen name="message_bubble_margin_tail">3dp</dimen>
+	<dimen name="message_bubble_margin_non_tail">30dp</dimen>
+	<dimen name="message_bubble_timestamp_margin">7dp</dimen>
+	<dimen name="forum_nested_line_width">2dp</dimen>
+	<dimen name="forum_nested_indicator">24dp</dimen>
+
+	<dimen name="blogs_avatar_normal_size">30dp</dimen>
+	<dimen name="blogs_avatar_icon_size">15dp</dimen>
+	<dimen name="blogs_avatar_comment_size">20dp</dimen>
+
+	<!-- Emoji -->
+	<dimen name="text_input_height">42dp</dimen>
+	<dimen name="conversation_item_body_text_size">16sp</dimen>
+	<dimen name="emoji_drawer_size">32sp</dimen>
+	<dimen name="emoji_drawer_indicator_height">2dp</dimen>
+	<dimen name="emoji_drawer_item_padding">5dp</dimen>
+	<dimen name="emoji_drawer_left_right_padding">2dp</dimen>
+
+	<!-- Keyboard Sizes -->
+	<dimen name="min_keyboard_size">50dp</dimen>
+	<dimen name="default_custom_keyboard_size">220dp</dimen>
+	<dimen name="min_custom_keyboard_size">110dp</dimen>
+	<dimen name="min_custom_keyboard_top_margin">170dp</dimen>
+
+</resources>
diff --git a/briar-android/res/values/emoji.xml b/briar-android/src/main/res/values/emoji.xml
similarity index 100%
rename from briar-android/res/values/emoji.xml
rename to briar-android/src/main/res/values/emoji.xml
diff --git a/briar-android/res/values/strings.xml b/briar-android/src/main/res/values/strings.xml
similarity index 100%
rename from briar-android/res/values/strings.xml
rename to briar-android/src/main/res/values/strings.xml
diff --git a/briar-android/res/values/styles.xml b/briar-android/src/main/res/values/styles.xml
similarity index 100%
rename from briar-android/res/values/styles.xml
rename to briar-android/src/main/res/values/styles.xml
diff --git a/briar-android/res/values/themes.xml b/briar-android/src/main/res/values/themes.xml
similarity index 100%
rename from briar-android/res/values/themes.xml
rename to briar-android/src/main/res/values/themes.xml
diff --git a/briar-android/res/xml/panic_preferences.xml b/briar-android/src/main/res/xml/panic_preferences.xml
similarity index 100%
rename from briar-android/res/xml/panic_preferences.xml
rename to briar-android/src/main/res/xml/panic_preferences.xml
diff --git a/briar-android/res/xml/settings.xml b/briar-android/src/main/res/xml/settings.xml
similarity index 93%
rename from briar-android/res/xml/settings.xml
rename to briar-android/src/main/res/xml/settings.xml
index 32519425808d4c3947b1f18c955b23ea6d9c92e6..5c865755d7e1a6b198c4ac9d44ba43c8cbac45ed 100644
--- a/briar-android/res/xml/settings.xml
+++ b/briar-android/src/main/res/xml/settings.xml
@@ -33,7 +33,7 @@
 			android:title="@string/change_password">
 
 			<intent
-				android:targetClass="org.briarproject.android.ChangePasswordActivity"
+				android:targetClass="org.briarproject.briar.android.login.ChangePasswordActivity"
 				android:targetPackage="@string/app_package"/>
 		</Preference>
 
@@ -47,7 +47,7 @@
 			android:title="@string/panic_setting">
 
 			<intent
-				android:targetClass="org.briarproject.android.panic.PanicPreferencesActivity"
+				android:targetClass="org.briarproject.briar.android.panic.PanicPreferencesActivity"
 				android:targetPackage="@string/app_package"/>
 
 		</Preference>
diff --git a/briar-android/src/org/briarproject/android/ActivityComponent.java b/briar-android/src/org/briarproject/android/ActivityComponent.java
deleted file mode 100644
index 01f39081f52a55dcc041b924a7ea97d134c93da1..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/ActivityComponent.java
+++ /dev/null
@@ -1,184 +0,0 @@
-package org.briarproject.android;
-
-import android.app.Activity;
-
-import org.briarproject.android.blogs.BlogActivity;
-import org.briarproject.android.blogs.BlogFragment;
-import org.briarproject.android.blogs.BlogModule;
-import org.briarproject.android.blogs.BlogPostFragment;
-import org.briarproject.android.blogs.FeedFragment;
-import org.briarproject.android.blogs.FeedPostFragment;
-import org.briarproject.android.blogs.ReblogActivity;
-import org.briarproject.android.blogs.ReblogFragment;
-import org.briarproject.android.blogs.RssFeedImportActivity;
-import org.briarproject.android.blogs.RssFeedManageActivity;
-import org.briarproject.android.blogs.WriteBlogPostActivity;
-import org.briarproject.android.contact.ContactListFragment;
-import org.briarproject.android.contact.ContactModule;
-import org.briarproject.android.contact.ConversationActivity;
-import org.briarproject.android.forum.CreateForumActivity;
-import org.briarproject.android.forum.ForumActivity;
-import org.briarproject.android.forum.ForumListFragment;
-import org.briarproject.android.forum.ForumModule;
-import org.briarproject.android.introduction.ContactChooserFragment;
-import org.briarproject.android.introduction.IntroductionActivity;
-import org.briarproject.android.introduction.IntroductionMessageFragment;
-import org.briarproject.android.invitation.AddContactActivity;
-import org.briarproject.android.keyagreement.IntroFragment;
-import org.briarproject.android.keyagreement.KeyAgreementActivity;
-import org.briarproject.android.keyagreement.ShowQrCodeFragment;
-import org.briarproject.android.panic.PanicPreferencesActivity;
-import org.briarproject.android.panic.PanicResponderActivity;
-import org.briarproject.android.privategroup.conversation.GroupActivity;
-import org.briarproject.android.privategroup.conversation.GroupConversationModule;
-import org.briarproject.android.privategroup.creation.CreateGroupActivity;
-import org.briarproject.android.privategroup.creation.CreateGroupFragment;
-import org.briarproject.android.privategroup.creation.CreateGroupMessageFragment;
-import org.briarproject.android.privategroup.creation.GroupCreateModule;
-import org.briarproject.android.privategroup.creation.GroupInviteActivity;
-import org.briarproject.android.privategroup.creation.GroupInviteFragment;
-import org.briarproject.android.privategroup.invitation.GroupInvitationActivity;
-import org.briarproject.android.privategroup.invitation.GroupInvitationModule;
-import org.briarproject.android.privategroup.list.GroupListFragment;
-import org.briarproject.android.privategroup.list.GroupListModule;
-import org.briarproject.android.privategroup.memberlist.GroupMemberListActivity;
-import org.briarproject.android.privategroup.memberlist.GroupMemberModule;
-import org.briarproject.android.privategroup.reveal.GroupRevealModule;
-import org.briarproject.android.privategroup.reveal.RevealContactsActivity;
-import org.briarproject.android.privategroup.reveal.RevealContactsFragment;
-import org.briarproject.android.sharing.BlogInvitationActivity;
-import org.briarproject.android.sharing.BlogSharingStatusActivity;
-import org.briarproject.android.sharing.ForumInvitationActivity;
-import org.briarproject.android.sharing.ForumSharingStatusActivity;
-import org.briarproject.android.sharing.ShareBlogActivity;
-import org.briarproject.android.sharing.ShareBlogFragment;
-import org.briarproject.android.sharing.ShareBlogMessageFragment;
-import org.briarproject.android.sharing.ShareForumActivity;
-import org.briarproject.android.sharing.ShareForumFragment;
-import org.briarproject.android.sharing.ShareForumMessageFragment;
-import org.briarproject.android.sharing.SharingModule;
-import org.thoughtcrime.securesms.components.emoji.EmojiProvider;
-import org.thoughtcrime.securesms.components.emoji.RecentEmojiPageModel;
-
-import dagger.Component;
-
-@ActivityScope
-@Component(
-		modules = {ActivityModule.class, ForumModule.class, SharingModule.class,
-				BlogModule.class, ContactModule.class, GroupListModule.class,
-				GroupCreateModule.class, GroupInvitationModule.class,
-				GroupConversationModule.class, GroupMemberModule.class,
-				GroupRevealModule.class},
-		dependencies = AndroidComponent.class)
-public interface ActivityComponent {
-
-	Activity activity();
-
-	void inject(SplashScreenActivity activity);
-
-	void inject(SetupActivity activity);
-
-	void inject(NavDrawerActivity activity);
-
-	void inject(PasswordActivity activity);
-
-	void inject(PanicResponderActivity activity);
-
-	void inject(PanicPreferencesActivity activity);
-
-	void inject(AddContactActivity activity);
-
-	void inject(KeyAgreementActivity activity);
-
-	void inject(ConversationActivity activity);
-
-	void inject(ForumInvitationActivity activity);
-
-	void inject(BlogInvitationActivity activity);
-
-	void inject(CreateGroupActivity activity);
-
-	void inject(GroupActivity activity);
-
-	void inject(GroupInviteActivity activity);
-
-	void inject(GroupInvitationActivity activity);
-
-	void inject(GroupMemberListActivity activity);
-
-	void inject(RevealContactsActivity activity);
-
-	void inject(CreateForumActivity activity);
-
-	void inject(ShareForumActivity activity);
-
-	void inject(ShareBlogActivity activity);
-
-	void inject(ForumSharingStatusActivity activity);
-
-	void inject(BlogSharingStatusActivity activity);
-
-	void inject(ForumActivity activity);
-
-	void inject(BlogActivity activity);
-
-	void inject(WriteBlogPostActivity activity);
-
-	void inject(BlogFragment fragment);
-
-	void inject(BlogPostFragment fragment);
-
-	void inject(FeedPostFragment fragment);
-
-	void inject(ReblogFragment fragment);
-
-	void inject(ReblogActivity activity);
-
-	void inject(SettingsActivity activity);
-
-	void inject(ChangePasswordActivity activity);
-
-	void inject(IntroductionActivity activity);
-
-	void inject(RssFeedImportActivity activity);
-
-	void inject(RssFeedManageActivity activity);
-
-	void inject(EmojiProvider emojiProvider);
-
-	void inject(RecentEmojiPageModel recentEmojiPageModel);
-
-	// Fragments
-	void inject(ContactListFragment fragment);
-
-	void inject(CreateGroupFragment fragment);
-
-	void inject(CreateGroupMessageFragment fragment);
-
-	void inject(GroupListFragment fragment);
-
-	void inject(GroupInviteFragment fragment);
-
-	void inject(RevealContactsFragment activity);
-
-	void inject(ForumListFragment fragment);
-
-	void inject(FeedFragment fragment);
-
-	void inject(IntroFragment fragment);
-
-	void inject(ShowQrCodeFragment fragment);
-
-	void inject(ContactChooserFragment fragment);
-
-	void inject(ShareForumFragment fragment);
-
-	void inject(ShareForumMessageFragment fragment);
-
-	void inject(ShareBlogFragment fragment);
-
-	void inject(ShareBlogMessageFragment fragment);
-
-	void inject(IntroductionMessageFragment fragment);
-
-}
diff --git a/briar-android/src/org/briarproject/android/AndroidComponent.java b/briar-android/src/org/briarproject/android/AndroidComponent.java
deleted file mode 100644
index 0a8feb91110a925c60cc88d00cc3319d13d1c844..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/AndroidComponent.java
+++ /dev/null
@@ -1,145 +0,0 @@
-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.report.BriarReportSender;
-import org.briarproject.api.blogs.BlogManager;
-import org.briarproject.api.blogs.BlogPostFactory;
-import org.briarproject.api.blogs.BlogSharingManager;
-import org.briarproject.api.contact.ContactExchangeTask;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.CryptoExecutor;
-import org.briarproject.api.crypto.PasswordStrengthEstimator;
-import org.briarproject.api.db.DatabaseConfig;
-import org.briarproject.api.db.DatabaseExecutor;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.feed.FeedManager;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.forum.ForumSharingManager;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.introduction.IntroductionManager;
-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.ConversationManager;
-import org.briarproject.api.messaging.MessagingManager;
-import org.briarproject.api.messaging.PrivateMessageFactory;
-import org.briarproject.api.plugins.ConnectionRegistry;
-import org.briarproject.api.plugins.PluginManager;
-import org.briarproject.api.privategroup.GroupMessageFactory;
-import org.briarproject.api.privategroup.PrivateGroupFactory;
-import org.briarproject.api.privategroup.PrivateGroupManager;
-import org.briarproject.api.privategroup.invitation.GroupInvitationFactory;
-import org.briarproject.api.privategroup.invitation.GroupInvitationManager;
-import org.briarproject.api.settings.SettingsManager;
-import org.briarproject.api.system.Clock;
-import org.briarproject.plugins.AndroidPluginsModule;
-import org.briarproject.system.AndroidSystemModule;
-
-import java.util.concurrent.Executor;
-
-import javax.inject.Singleton;
-
-import dagger.Component;
-
-@Singleton
-@Component(modules = {
-		CoreModule.class,
-		AppModule.class,
-		AndroidPluginsModule.class,
-		AndroidSystemModule.class
-})
-public interface AndroidComponent extends CoreEagerSingletons {
-
-	// Exposed objects
-	@CryptoExecutor
-	Executor cryptoExecutor();
-
-	PasswordStrengthEstimator passwordStrengthIndicator();
-
-	CryptoComponent cryptoComponent();
-
-	DatabaseConfig databaseConfig();
-
-	ReferenceManager referenceMangager();
-
-	@DatabaseExecutor
-	Executor databaseExecutor();
-
-	LifecycleManager lifecycleManager();
-
-	IdentityManager identityManager();
-
-	PluginManager pluginManager();
-
-	EventBus eventBus();
-
-	InvitationTaskFactory invitationTaskFactory();
-
-	AndroidNotificationManager androidNotificationManager();
-
-	ConnectionRegistry connectionRegistry();
-
-	ContactManager contactManager();
-
-	ConversationManager conversationManager();
-
-	MessagingManager messagingManager();
-
-	PrivateMessageFactory privateMessageFactory();
-
-	PrivateGroupManager privateGroupManager();
-
-	GroupInvitationFactory groupInvitationFactory();
-
-	GroupInvitationManager groupInvitationManager();
-
-	PrivateGroupFactory privateGroupFactory();
-
-	GroupMessageFactory groupMessageFactory();
-
-	ForumManager forumManager();
-
-	ForumSharingManager forumSharingManager();
-
-	BlogSharingManager blogSharingManager();
-
-	BlogManager blogManager();
-
-	BlogPostFactory blogPostFactory();
-
-	SettingsManager settingsManager();
-
-	ContactExchangeTask contactExchangeTask();
-
-	KeyAgreementTaskFactory keyAgreementTaskFactory();
-
-	PayloadEncoder payloadEncoder();
-
-	PayloadParser payloadParser();
-
-	IntroductionManager introductionManager();
-
-	AndroidExecutor androidExecutor();
-
-	FeedManager feedManager();
-
-	Clock clock();
-
-	@IoExecutor
-	Executor ioExecutor();
-
-	void inject(BriarService activity);
-
-	void inject(BriarReportSender briarReportSender);
-
-	// Eager singleton load
-	void inject(AppModule.EagerSingletons init);
-}
diff --git a/briar-android/src/org/briarproject/android/AndroidEagerSingletons.java b/briar-android/src/org/briarproject/android/AndroidEagerSingletons.java
deleted file mode 100644
index 4a6cc4046dae0cafc32dddd36e34dac9e8c3ee48..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/AndroidEagerSingletons.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.briarproject.android;
-
-public class AndroidEagerSingletons {
-
-	public static void initEagerSingletons(AndroidComponent c) {
-		c.inject(new AppModule.EagerSingletons());
-	}
-}
diff --git a/briar-android/src/org/briarproject/android/contactselection/ContactSelectorController.java b/briar-android/src/org/briarproject/android/contactselection/ContactSelectorController.java
deleted file mode 100644
index e0d9cac7abca56232560cd8004791b37d8000fa4..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/contactselection/ContactSelectorController.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.briarproject.android.contactselection;
-
-import org.briarproject.android.controller.DbController;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-
-import java.util.Collection;
-
-@NotNullByDefault
-public interface ContactSelectorController<I extends SelectableContactItem>
-		extends DbController {
-
-	void loadContacts(GroupId g, Collection<ContactId> selection,
-			ResultExceptionHandler<Collection<I>, DbException> handler);
-
-}
diff --git a/briar-android/src/org/briarproject/android/controller/DbController.java b/briar-android/src/org/briarproject/android/controller/DbController.java
deleted file mode 100644
index f0c186bf3485f062e3cc1fa93f7d60bf213d0d1b..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/controller/DbController.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.briarproject.android.controller;
-
-public interface DbController {
-
-	void runOnDbThread(Runnable task);
-}
diff --git a/briar-android/src/org/briarproject/android/controller/NavDrawerController.java b/briar-android/src/org/briarproject/android/controller/NavDrawerController.java
deleted file mode 100644
index 869ec8bc0950597ab6aae2e5ae202d78aa0740cb..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/controller/NavDrawerController.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.briarproject.android.controller;
-
-import org.briarproject.api.TransportId;
-
-public interface NavDrawerController extends ActivityLifecycleController {
-
-	boolean isTransportRunning(TransportId transportId);
-
-}
diff --git a/briar-android/src/org/briarproject/android/controller/PasswordController.java b/briar-android/src/org/briarproject/android/controller/PasswordController.java
deleted file mode 100644
index 64e4d4df001876405057913e5a6d561ae860b42e..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/controller/PasswordController.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.briarproject.android.controller;
-
-import org.briarproject.android.controller.handler.ResultHandler;
-
-public interface PasswordController extends ConfigController {
-
-	void validatePassword(String password,
-			ResultHandler<Boolean> resultHandler);
-
-	void changePassword(String password, String newPassword,
-			ResultHandler<Boolean> resultHandler);
-}
diff --git a/briar-android/src/org/briarproject/android/controller/SetupController.java b/briar-android/src/org/briarproject/android/controller/SetupController.java
deleted file mode 100644
index 947d6991ab946f09a686dca664bd35a8aeec34ac..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/controller/SetupController.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.briarproject.android.controller;
-
-import org.briarproject.android.controller.handler.ResultHandler;
-
-public interface SetupController {
-
-	float estimatePasswordStrength(String password);
-
-	void storeAuthorInfo(String nickname, String password,
-			ResultHandler<Void> resultHandler);
-
-}
diff --git a/briar-android/src/org/briarproject/android/controller/TransportStateListener.java b/briar-android/src/org/briarproject/android/controller/TransportStateListener.java
deleted file mode 100644
index 3bb1c0a883e31cc25facdd157de8d44752b4a7b5..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/controller/TransportStateListener.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.briarproject.android.controller;
-
-import org.briarproject.android.DestroyableContext;
-import org.briarproject.api.TransportId;
-
-public interface TransportStateListener extends DestroyableContext {
-
-	void stateUpdate(TransportId id, boolean enabled);
-}
diff --git a/briar-android/src/org/briarproject/android/forum/ForumController.java b/briar-android/src/org/briarproject/android/forum/ForumController.java
deleted file mode 100644
index 9b1fba5641b032c862b4fb9ba1ffcf254b773fd6..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/forum/ForumController.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.briarproject.android.forum;
-
-import org.briarproject.android.threaded.ThreadListController;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumPostHeader;
-
-public interface ForumController
-		extends ThreadListController<Forum, ForumItem, ForumPostHeader> {
-
-}
diff --git a/briar-android/src/org/briarproject/android/forum/ForumItem.java b/briar-android/src/org/briarproject/android/forum/ForumItem.java
deleted file mode 100644
index 9c64f4ebf37012946e0b84d2c549ede534b48eba..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/forum/ForumItem.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.briarproject.android.forum;
-
-import org.briarproject.android.threaded.ThreadItem;
-import org.briarproject.api.forum.ForumPostHeader;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.Author.Status;
-import org.briarproject.api.sync.MessageId;
-
-import javax.annotation.concurrent.NotThreadSafe;
-
-@NotThreadSafe
-class ForumItem extends ThreadItem {
-
-	ForumItem(ForumPostHeader h, String body) {
-		super(h.getId(), h.getParentId(), body, h.getTimestamp(), h.getAuthor(),
-				h.getAuthorStatus(), h.isRead());
-	}
-
-	ForumItem(MessageId messageId, MessageId parentId, String text,
-			long timestamp, Author author, Status status) {
-		super(messageId, parentId, text, timestamp, author, status, true);
-	}
-
-}
diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupController.java b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupController.java
deleted file mode 100644
index 523abc1b9b7b62c9e2d61df072fd57b54274edf5..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupController.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.briarproject.android.privategroup.conversation;
-
-import android.support.annotation.UiThread;
-
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.android.threaded.ThreadListController;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.privategroup.GroupMessageHeader;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.privategroup.Visibility;
-
-public interface GroupController
-		extends
-		ThreadListController<PrivateGroup, GroupMessageItem, GroupMessageHeader> {
-
-	void loadLocalAuthor(
-			ResultExceptionHandler<LocalAuthor, DbException> handler);
-
-	void isDissolved(
-			ResultExceptionHandler<Boolean, DbException> handler);
-
-	interface GroupListener extends ThreadListListener<GroupMessageHeader> {
-		@UiThread
-		void onContactRelationshipRevealed(AuthorId memberId, Visibility v);
-
-		@UiThread
-		void onGroupDissolved();
-	}
-
-}
diff --git a/briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupController.java b/briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupController.java
deleted file mode 100644
index 2434ccd7d2a9da11add41888d7ee992ec84cc7d9..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupController.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.briarproject.android.privategroup.creation;
-
-import org.briarproject.android.contactselection.ContactSelectorController;
-import org.briarproject.android.contactselection.SelectableContactItem;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-
-import java.util.Collection;
-
-@NotNullByDefault
-public interface CreateGroupController
-		extends ContactSelectorController<SelectableContactItem> {
-
-	void createGroup(String name,
-			ResultExceptionHandler<GroupId, DbException> result);
-
-	void sendInvitation(GroupId g, Collection<ContactId> contacts,
-			String message, ResultExceptionHandler<Void, DbException> result);
-
-}
diff --git a/briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationController.java b/briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationController.java
deleted file mode 100644
index 54318f31b2dc5b96e4852e1650d8cd27696e556b..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationController.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.briarproject.android.privategroup.invitation;
-
-import org.briarproject.android.sharing.InvitationController;
-import org.briarproject.api.privategroup.invitation.GroupInvitationItem;
-
-public interface GroupInvitationController
-		extends InvitationController<GroupInvitationItem> {
-}
diff --git a/briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationViewHolder.java b/briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationViewHolder.java
deleted file mode 100644
index 25aef8ce8d2df68022ee0c7dd4e0286b85347c99..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationViewHolder.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.briarproject.android.privategroup.invitation;
-
-import android.support.annotation.Nullable;
-import android.view.View;
-
-import org.briarproject.R;
-import org.briarproject.android.sharing.InvitationAdapter.InvitationClickListener;
-import org.briarproject.android.sharing.InvitationViewHolder;
-import org.briarproject.api.privategroup.invitation.GroupInvitationItem;
-
-public class GroupInvitationViewHolder extends InvitationViewHolder<GroupInvitationItem> {
-
-	public GroupInvitationViewHolder(View v) {
-		super(v);
-	}
-
-	@Override
-	public void onBind(@Nullable final GroupInvitationItem item,
-			final InvitationClickListener<GroupInvitationItem> listener) {
-		super.onBind(item, listener);
-		if (item == null) return;
-
-		sharedBy.setText(
-				sharedBy.getContext().getString(R.string.groups_created_by,
-						item.getCreator().getAuthor().getName()));
-	}
-
-}
\ No newline at end of file
diff --git a/briar-android/src/org/briarproject/android/privategroup/memberlist/GroupMemberListController.java b/briar-android/src/org/briarproject/android/privategroup/memberlist/GroupMemberListController.java
deleted file mode 100644
index 0f657d2d9c634f73f8d26afc2d19bec239989390..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/privategroup/memberlist/GroupMemberListController.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.briarproject.android.privategroup.memberlist;
-
-import org.briarproject.android.controller.DbController;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.sync.GroupId;
-
-import java.util.Collection;
-
-public interface GroupMemberListController extends DbController {
-
-	void loadMembers(GroupId groupId,
-			ResultExceptionHandler<Collection<MemberListItem>, DbException> handler);
-
-}
diff --git a/briar-android/src/org/briarproject/android/privategroup/memberlist/MemberListItem.java b/briar-android/src/org/briarproject/android/privategroup/memberlist/MemberListItem.java
deleted file mode 100644
index 42b001db73f457354c635d4ec48cb87893c1a2e9..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/privategroup/memberlist/MemberListItem.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.briarproject.android.privategroup.memberlist;
-
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.Author.Status;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.privategroup.GroupMember;
-import org.briarproject.api.privategroup.Visibility;
-
-import javax.annotation.concurrent.Immutable;
-
-import static org.briarproject.api.privategroup.Visibility.INVISIBLE;
-
-@Immutable
-@NotNullByDefault
-class MemberListItem {
-
-	private final Author member;
-	private final Status status;
-	private final Visibility visibility;
-
-	public MemberListItem(GroupMember groupMember) {
-		this.member = groupMember.getAuthor();
-		this.visibility = groupMember.getVisibility();
-		this.status = groupMember.getStatus();
-	}
-
-	public Author getMember() {
-		return member;
-	}
-
-	public Visibility getVisibility() {
-		return visibility;
-	}
-
-	public Status getStatus() {
-		return status;
-	}
-
-}
diff --git a/briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsController.java b/briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsController.java
deleted file mode 100644
index dcc67f6aabb01344049418903a300d1592eef6bb..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsController.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.briarproject.android.privategroup.reveal;
-
-import org.briarproject.android.contactselection.ContactSelectorController;
-import org.briarproject.android.controller.handler.ExceptionHandler;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-
-import java.util.Collection;
-
-@NotNullByDefault
-public interface RevealContactsController
-		extends ContactSelectorController<RevealableContactItem> {
-
-	void isOnboardingNeeded(
-			ResultExceptionHandler<Boolean, DbException> handler);
-
-	void onboardingShown(ExceptionHandler<DbException> handler);
-
-	void reveal(GroupId g, Collection<ContactId> contacts,
-			ExceptionHandler<DbException> handler);
-
-}
diff --git a/briar-android/src/org/briarproject/android/privategroup/reveal/RevealableContactItem.java b/briar-android/src/org/briarproject/android/privategroup/reveal/RevealableContactItem.java
deleted file mode 100644
index 493fbda2e519d0dca4f3cd88b798433443a6d4a0..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/privategroup/reveal/RevealableContactItem.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.briarproject.android.privategroup.reveal;
-
-import org.briarproject.android.contactselection.SelectableContactItem;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.privategroup.Visibility;
-
-import javax.annotation.concurrent.NotThreadSafe;
-
-@NotThreadSafe
-@NotNullByDefault
-public class RevealableContactItem extends SelectableContactItem {
-
-	private final Visibility visibility;
-
-	public RevealableContactItem(Contact contact, boolean selected,
-			boolean disabled, Visibility visibility) {
-		super(contact, selected, disabled);
-		this.visibility = visibility;
-	}
-
-	public Visibility getVisibility() {
-		return visibility;
-	}
-
-}
diff --git a/briar-android/src/org/briarproject/android/sharing/BlogInvitationController.java b/briar-android/src/org/briarproject/android/sharing/BlogInvitationController.java
deleted file mode 100644
index ebd447369e9ea28e1a22be632729a546ddf29430..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/sharing/BlogInvitationController.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.briarproject.android.sharing;
-
-import org.briarproject.api.sharing.SharingInvitationItem;
-
-public interface BlogInvitationController
-		extends InvitationController<SharingInvitationItem> {
-}
diff --git a/briar-android/src/org/briarproject/android/sharing/ForumInvitationController.java b/briar-android/src/org/briarproject/android/sharing/ForumInvitationController.java
deleted file mode 100644
index 74ee19ee27f25a5ab6c0c0320861d3028378aa01..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/sharing/ForumInvitationController.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.briarproject.android.sharing;
-
-import org.briarproject.api.sharing.SharingInvitationItem;
-
-public interface ForumInvitationController
-		extends InvitationController<SharingInvitationItem> {
-}
diff --git a/briar-android/src/org/briarproject/android/sharing/InvitationController.java b/briar-android/src/org/briarproject/android/sharing/InvitationController.java
deleted file mode 100644
index a79d0347ad1b14439a7ccf3c0f8f6e0be92bfe9a..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/sharing/InvitationController.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.briarproject.android.sharing;
-
-import org.briarproject.android.controller.ActivityLifecycleController;
-import org.briarproject.android.controller.handler.ExceptionHandler;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sharing.InvitationItem;
-
-import java.util.Collection;
-
-@NotNullByDefault
-public interface InvitationController<I extends InvitationItem>
-		extends ActivityLifecycleController {
-
-	void loadInvitations(boolean clear,
-			ResultExceptionHandler<Collection<I>, DbException> handler);
-
-	void respondToInvitation(I item, boolean accept,
-			ExceptionHandler<DbException> handler);
-
-	interface InvitationListener {
-
-		void loadInvitations(boolean clear);
-
-	}
-
-}
diff --git a/briar-android/src/org/briarproject/android/sharing/ShareBlogController.java b/briar-android/src/org/briarproject/android/sharing/ShareBlogController.java
deleted file mode 100644
index 7e51d99fed7eb394b5f22cebb66fd5442583aa40..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/sharing/ShareBlogController.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.briarproject.android.sharing;
-
-import org.briarproject.android.contactselection.ContactSelectorController;
-import org.briarproject.android.contactselection.SelectableContactItem;
-import org.briarproject.android.controller.handler.ExceptionHandler;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.sync.GroupId;
-
-import java.util.Collection;
-
-public interface ShareBlogController
-		extends ContactSelectorController<SelectableContactItem> {
-
-	void share(GroupId g, Collection<ContactId> contacts, String msg,
-			ExceptionHandler<DbException> handler);
-
-}
diff --git a/briar-android/src/org/briarproject/android/sharing/ShareForumController.java b/briar-android/src/org/briarproject/android/sharing/ShareForumController.java
deleted file mode 100644
index 1ad94416a3996adfdadabf6bc86c5a57a695ea60..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/sharing/ShareForumController.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.briarproject.android.sharing;
-
-import org.briarproject.android.contactselection.ContactSelectorController;
-import org.briarproject.android.contactselection.SelectableContactItem;
-import org.briarproject.android.controller.handler.ExceptionHandler;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.sync.GroupId;
-
-import java.util.Collection;
-
-public interface ShareForumController
-		extends ContactSelectorController<SelectableContactItem> {
-
-	void share(GroupId g, Collection<ContactId> contacts, String msg,
-			ExceptionHandler<DbException> handler);
-
-}
diff --git a/briar-android/src/org/briarproject/system/AndroidSystemModule.java b/briar-android/src/org/briarproject/system/AndroidSystemModule.java
deleted file mode 100644
index 99ca8fb7abf5a18feb793e9dbf1dd3ddeda1929f..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/system/AndroidSystemModule.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.briarproject.system;
-
-import android.app.Application;
-
-import org.briarproject.android.api.AndroidExecutor;
-import org.briarproject.api.system.LocationUtils;
-import org.briarproject.api.system.SeedProvider;
-
-import javax.inject.Singleton;
-
-import dagger.Module;
-import dagger.Provides;
-
-@Module
-public class AndroidSystemModule {
-
-	@Provides
-	@Singleton
-	public SeedProvider provideSeedProvider(Application app) {
-		return new AndroidSeedProvider(app);
-	}
-
-	@Provides
-	public LocationUtils provideLocationUtils(Application app) {
-		return new AndroidLocationUtils(app);
-	}
-
-	@Provides
-	@Singleton
-	public AndroidExecutor provideAndroidExecutor(Application app) {
-		return new AndroidExecutorImpl(app);
-	}
-}
diff --git a/briar-android/test/java/android/net/http/AndroidHttpClient.java b/briar-android/src/test/java/android/net/http/AndroidHttpClient.java
similarity index 71%
rename from briar-android/test/java/android/net/http/AndroidHttpClient.java
rename to briar-android/src/test/java/android/net/http/AndroidHttpClient.java
index f2cf7a34632bbf4e3a5ef2220ac8a9d01e0da1da..e83fb8177a3feb5317a9ff82c7edf079f08c4575 100644
--- a/briar-android/test/java/android/net/http/AndroidHttpClient.java
+++ b/briar-android/src/test/java/android/net/http/AndroidHttpClient.java
@@ -2,6 +2,6 @@ package android.net.http;
 
 // This class is here to fix an issue with Robolectric.
 // https://github.com/robolectric/robolectric/issues/1862
-// TODO Check if this class can be removed on next Robolectric update
+// TODO: Check if this class can be removed on next Robolectric update
 public class AndroidHttpClient {
 }
\ No newline at end of file
diff --git a/briar-android/test/java/org/briarproject/android/SetupActivityTest.java b/briar-android/src/test/java/org/briarproject/briar/android/SetupActivityTest.java
similarity index 90%
rename from briar-android/test/java/org/briarproject/android/SetupActivityTest.java
rename to briar-android/src/test/java/org/briarproject/briar/android/SetupActivityTest.java
index 05a57f9ee14a7e0d4c9a2972572fab0fd4fc73dc..d6c445eb85f72cdcc9b44b25ebcae1fd10d37126 100644
--- a/briar-android/test/java/org/briarproject/android/SetupActivityTest.java
+++ b/briar-android/src/test/java/org/briarproject/briar/android/SetupActivityTest.java
@@ -1,4 +1,4 @@
-package org.briarproject.android;
+package org.briarproject.briar.android;
 
 import android.content.Context;
 import android.content.Intent;
@@ -9,12 +9,13 @@ import android.widget.EditText;
 
 import com.google.common.base.Strings;
 
-import org.briarproject.BuildConfig;
-import org.briarproject.R;
-import org.briarproject.android.controller.SetupController;
-import org.briarproject.android.controller.handler.ResultHandler;
-import org.briarproject.android.util.StrengthMeter;
-import org.briarproject.api.identity.AuthorConstants;
+import org.briarproject.bramble.api.identity.AuthorConstants;
+import org.briarproject.briar.BuildConfig;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.controller.handler.ResultHandler;
+import org.briarproject.briar.android.login.SetupController;
+import org.briarproject.briar.android.login.StrengthMeter;
+import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -30,11 +31,11 @@ import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowActivity;
 
 import static junit.framework.Assert.assertEquals;
-import static org.briarproject.api.crypto.PasswordStrengthEstimator.NONE;
-import static org.briarproject.api.crypto.PasswordStrengthEstimator.QUITE_STRONG;
-import static org.briarproject.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
-import static org.briarproject.api.crypto.PasswordStrengthEstimator.STRONG;
-import static org.briarproject.api.crypto.PasswordStrengthEstimator.WEAK;
+import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.NONE;
+import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_STRONG;
+import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
+import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.STRONG;
+import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.WEAK;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
diff --git a/briar-android/test/java/org/briarproject/android/TestBriarApplication.java b/briar-android/src/test/java/org/briarproject/briar/android/TestBriarApplication.java
similarity index 75%
rename from briar-android/test/java/org/briarproject/android/TestBriarApplication.java
rename to briar-android/src/test/java/org/briarproject/briar/android/TestBriarApplication.java
index 6250040a19b4964190b81147d38e84ee1d6cd262..bc6016caaaa37fa395bf55a847f8e834525d936b 100644
--- a/briar-android/test/java/org/briarproject/android/TestBriarApplication.java
+++ b/briar-android/src/test/java/org/briarproject/briar/android/TestBriarApplication.java
@@ -1,8 +1,9 @@
-package org.briarproject.android;
+package org.briarproject.briar.android;
 
 import android.app.Application;
 
-import org.briarproject.CoreModule;
+import org.briarproject.bramble.BrambleCoreModule;
+import org.briarproject.briar.BriarCoreModule;
 
 import java.util.logging.Logger;
 
@@ -28,7 +29,8 @@ public class TestBriarApplication extends Application
 
 		// We need to load the eager singletons directly after making the
 		// dependency graphs
-		CoreModule.initEagerSingletons(applicationComponent);
+		BrambleCoreModule.initEagerSingletons(applicationComponent);
+		BriarCoreModule.initEagerSingletons(applicationComponent);
 		AndroidEagerSingletons.initEagerSingletons(applicationComponent);
 	}
 
diff --git a/briar-android/test/java/org/briarproject/android/TestSetupActivity.java b/briar-android/src/test/java/org/briarproject/briar/android/TestSetupActivity.java
similarity index 67%
rename from briar-android/test/java/org/briarproject/android/TestSetupActivity.java
rename to briar-android/src/test/java/org/briarproject/briar/android/TestSetupActivity.java
index bb4598752b3794a3c837261bf82d2efb236f98e5..d9c78c800405d3beb8775814f8cb353fba0fbf09 100644
--- a/briar-android/test/java/org/briarproject/android/TestSetupActivity.java
+++ b/briar-android/src/test/java/org/briarproject/briar/android/TestSetupActivity.java
@@ -1,6 +1,7 @@
-package org.briarproject.android;
+package org.briarproject.briar.android;
 
-import org.briarproject.android.controller.SetupController;
+import org.briarproject.briar.android.login.SetupActivity;
+import org.briarproject.briar.android.login.SetupController;
 
 /**
  * This class exposes the SetupController and offers the possibility to
diff --git a/briar-android/test/java/org/briarproject/android/forum/ForumActivityTest.java b/briar-android/src/test/java/org/briarproject/briar/android/forum/ForumActivityTest.java
similarity index 85%
rename from briar-android/test/java/org/briarproject/android/forum/ForumActivityTest.java
rename to briar-android/src/test/java/org/briarproject/briar/android/forum/ForumActivityTest.java
index cedacc77d08850c7dc891bd4647f215150bb9f5f..6b4d135b4b032bbbb14045a0cc2f109df6c98ee2 100644
--- a/briar-android/test/java/org/briarproject/android/forum/ForumActivityTest.java
+++ b/briar-android/src/test/java/org/briarproject/briar/android/forum/ForumActivityTest.java
@@ -1,18 +1,18 @@
-package org.briarproject.android.forum;
+package org.briarproject.briar.android.forum;
 
 import android.content.Intent;
 
 import junit.framework.Assert;
 
-import org.briarproject.BuildConfig;
 import org.briarproject.TestUtils;
-import org.briarproject.android.TestBriarApplication;
-import org.briarproject.android.controller.handler.UiResultExceptionHandler;
-import org.briarproject.android.threaded.ThreadItemAdapter;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.BuildConfig;
+import org.briarproject.briar.android.TestBriarApplication;
+import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
+import org.briarproject.briar.android.threaded.ThreadItemAdapter;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -30,8 +30,8 @@ import java.util.List;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertTrue;
-import static org.briarproject.api.identity.Author.Status.UNKNOWN;
-import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.bramble.api.identity.Author.Status.UNKNOWN;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
diff --git a/briar-android/test/java/org/briarproject/android/forum/TestForumActivity.java b/briar-android/src/test/java/org/briarproject/briar/android/forum/TestForumActivity.java
similarity index 61%
rename from briar-android/test/java/org/briarproject/android/forum/TestForumActivity.java
rename to briar-android/src/test/java/org/briarproject/briar/android/forum/TestForumActivity.java
index 7d4ff2f7d27dcedd92e14bbf1c8d5e4d67f3b58c..faa4faa10d27133d705ef935512e88040ba7c013 100644
--- a/briar-android/test/java/org/briarproject/android/forum/TestForumActivity.java
+++ b/briar-android/src/test/java/org/briarproject/briar/android/forum/TestForumActivity.java
@@ -1,18 +1,23 @@
-package org.briarproject.android.forum;
-
-import org.briarproject.android.ActivityModule;
-import org.briarproject.android.BaseActivity;
-import org.briarproject.android.controller.BriarController;
-import org.briarproject.android.controller.BriarControllerImpl;
-import org.briarproject.android.threaded.ThreadItemAdapter;
+package org.briarproject.briar.android.forum;
+
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.briar.android.activity.ActivityModule;
+import org.briarproject.briar.android.activity.BaseActivity;
+import org.briarproject.briar.android.controller.BriarController;
+import org.briarproject.briar.android.controller.BriarControllerImpl;
+import org.briarproject.briar.android.threaded.ThreadItemAdapter;
 import org.mockito.Mockito;
 
 /**
  * This class exposes the ForumController and offers the possibility to
  * override it.
  */
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 public class TestForumActivity extends ForumActivity {
 
+	@Override
 	public ForumController getController() {
 		return forumController;
 	}
diff --git a/briar-android/test/java/org/briarproject/android/ChangePasswordActivityTest.java b/briar-android/src/test/java/org/briarproject/briar/android/login/ChangePasswordActivityTest.java
similarity index 92%
rename from briar-android/test/java/org/briarproject/android/ChangePasswordActivityTest.java
rename to briar-android/src/test/java/org/briarproject/briar/android/login/ChangePasswordActivityTest.java
index 54ea446e82a9d118819d2f66190ff5800b486fb8..d163c8c509ff14700ab80d7f959b785f7976d0ac 100644
--- a/briar-android/test/java/org/briarproject/android/ChangePasswordActivityTest.java
+++ b/briar-android/src/test/java/org/briarproject/briar/android/login/ChangePasswordActivityTest.java
@@ -1,4 +1,4 @@
-package org.briarproject.android;
+package org.briarproject.briar.android.login;
 
 import android.content.Context;
 import android.content.SharedPreferences;
@@ -6,12 +6,10 @@ import android.support.design.widget.TextInputLayout;
 import android.widget.Button;
 import android.widget.EditText;
 
-import org.briarproject.BuildConfig;
-import org.briarproject.R;
-import org.briarproject.android.controller.PasswordController;
-import org.briarproject.android.controller.SetupController;
-import org.briarproject.android.controller.handler.ResultHandler;
-import org.briarproject.android.util.StrengthMeter;
+import org.briarproject.briar.BuildConfig;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.TestBriarApplication;
+import org.briarproject.briar.android.controller.handler.ResultHandler;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -26,11 +24,11 @@ import org.robolectric.RobolectricGradleTestRunner;
 import org.robolectric.annotation.Config;
 
 import static junit.framework.Assert.assertEquals;
-import static org.briarproject.api.crypto.PasswordStrengthEstimator.NONE;
-import static org.briarproject.api.crypto.PasswordStrengthEstimator.QUITE_STRONG;
-import static org.briarproject.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
-import static org.briarproject.api.crypto.PasswordStrengthEstimator.STRONG;
-import static org.briarproject.api.crypto.PasswordStrengthEstimator.WEAK;
+import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.NONE;
+import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_STRONG;
+import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
+import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.STRONG;
+import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.WEAK;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.anyString;
diff --git a/briar-android/test/java/org/briarproject/android/TestChangePasswordActivity.java b/briar-android/src/test/java/org/briarproject/briar/android/login/TestChangePasswordActivity.java
similarity index 79%
rename from briar-android/test/java/org/briarproject/android/TestChangePasswordActivity.java
rename to briar-android/src/test/java/org/briarproject/briar/android/login/TestChangePasswordActivity.java
index 21d57e4fb3fd6133a9e2201ae83ca5265e2714dc..3298c0e9be8d50c5707cc6635f39fb230b02f559 100644
--- a/briar-android/test/java/org/briarproject/android/TestChangePasswordActivity.java
+++ b/briar-android/src/test/java/org/briarproject/briar/android/login/TestChangePasswordActivity.java
@@ -1,7 +1,4 @@
-package org.briarproject.android;
-
-import org.briarproject.android.controller.PasswordController;
-import org.briarproject.android.controller.SetupController;
+package org.briarproject.briar.android.login;
 
 /**
  * This class exposes the PasswordController and SetupController and offers the
diff --git a/briar-api/build.gradle b/briar-api/build.gradle
index 18e5784e8a51ef6516de211aaf0e9993fdd21f47..f3f2257c0d960623647ba090938d3606d3550cde 100644
--- a/briar-api/build.gradle
+++ b/briar-api/build.gradle
@@ -5,25 +5,5 @@ targetCompatibility = 1.6
 apply plugin: 'witness'
 
 dependencies {
-	compile "com.google.dagger:dagger:2.0.2"
-	compile 'com.google.dagger:dagger-compiler:2.0.2'
-	compile 'org.jetbrains:annotations-java5:15.0'
-	compile 'com.google.code.findbugs:jsr305:3.0.1'
-}
-
-dependencyVerification {
-	verify = [
-			'com.google.dagger:dagger:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
-			'com.google.dagger:dagger-compiler:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
-			'org.jetbrains:annotations-java5:c84e6e9947f802ec2183bdc415dd496df02a749cac92e805f697e60f628a1e24',
-			'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
-			'com.google.dagger:dagger-producers:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
-			'com.google.guava:guava:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
-			'com.google.code.findbugs:jsr305:c885ce34249682bc0236b4a7d56efcc12048e6135a5baf7a9cde8ad8cda13fcd'
-	]
-}
-
-sourceSets {
-	main.java.srcDirs = ['src']
-	main.resources.srcDirs = ['src']
+	compile project(':bramble-api')
 }
diff --git a/briar-api/src/org/briarproject/api/blogs/Blog.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/Blog.java
similarity index 64%
rename from briar-api/src/org/briarproject/api/blogs/Blog.java
rename to briar-api/src/main/java/org/briarproject/briar/api/blog/Blog.java
index 3de97f5ea8706eb98f1d7482ec16d36518d79fb5..b7e1d240fea96c14eed901a1fff18c2c9424dac9 100644
--- a/briar-api/src/org/briarproject/api/blogs/Blog.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/Blog.java
@@ -1,10 +1,10 @@
-package org.briarproject.api.blogs;
+package org.briarproject.briar.api.blog;
 
-import org.briarproject.api.clients.BaseGroup;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sharing.Shareable;
-import org.briarproject.api.sync.Group;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.briar.api.client.BaseGroup;
+import org.briarproject.briar.api.sharing.Shareable;
 
 import javax.annotation.concurrent.Immutable;
 
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogCommentHeader.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogCommentHeader.java
new file mode 100644
index 0000000000000000000000000000000000000000..70fded28135d661b93bcb7500bb42082cefe6b15
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogCommentHeader.java
@@ -0,0 +1,46 @@
+package org.briarproject.briar.api.blog;
+
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+import static org.briarproject.briar.api.blog.MessageType.COMMENT;
+import static org.briarproject.briar.api.blog.MessageType.WRAPPED_COMMENT;
+
+@Immutable
+@NotNullByDefault
+public class BlogCommentHeader extends BlogPostHeader {
+
+	@Nullable
+	private final String comment;
+	private final BlogPostHeader parent;
+
+	public BlogCommentHeader(MessageType type, GroupId groupId,
+			@Nullable String comment, BlogPostHeader parent, MessageId id,
+			long timestamp, long timeReceived, Author author,
+			Status authorStatus, boolean read) {
+
+		super(type, groupId, id, parent.getId(), timestamp,
+				timeReceived, author, authorStatus, read);
+
+		if (type != COMMENT && type != WRAPPED_COMMENT)
+			throw new IllegalArgumentException("Incompatible Message Type");
+
+		this.comment = comment;
+		this.parent = parent;
+	}
+
+	@Nullable
+	public String getComment() {
+		return comment;
+	}
+
+	public BlogPostHeader getParent() {
+		return parent;
+	}
+}
diff --git a/briar-api/src/org/briarproject/api/blogs/BlogConstants.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogConstants.java
similarity index 72%
rename from briar-api/src/org/briarproject/api/blogs/BlogConstants.java
rename to briar-api/src/main/java/org/briarproject/briar/api/blog/BlogConstants.java
index 19adcefbddc354e7baff2d42e59d923dc6b76bff..28df61f7451d8f74267d610005ca110503579aa5 100644
--- a/briar-api/src/org/briarproject/api/blogs/BlogConstants.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogConstants.java
@@ -1,19 +1,27 @@
-package org.briarproject.api.blogs;
+package org.briarproject.briar.api.blog;
 
-import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
 
 public interface BlogConstants {
 
-	/** The maximum length of a blogs's name in UTF-8 bytes. */
+	/**
+	 * The maximum length of a blogs's name in UTF-8 bytes.
+	 */
 	int MAX_BLOG_TITLE_LENGTH = 100;
 
-	/** The length of a blogs's description in UTF-8 bytes. */
+	/**
+	 * The length of a blogs's description in UTF-8 bytes.
+	 */
 	int MAX_BLOG_DESC_LENGTH = 240;
 
-	/** The maximum length of a blog post's body in bytes. */
+	/**
+	 * The maximum length of a blog post's body in bytes.
+	 */
 	int MAX_BLOG_POST_BODY_LENGTH = MAX_MESSAGE_BODY_LENGTH - 1024;
 
-	/** The maximum length of a blog comment in bytes. */
+	/**
+	 * The maximum length of a blog comment in bytes.
+	 */
 	int MAX_BLOG_COMMENT_LENGTH = MAX_BLOG_POST_BODY_LENGTH;
 
 	/* Blog Sharing Constants */
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogFactory.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..4b0a89cf377b3f8c036cd206e1f15a8c78e9be4b
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogFactory.java
@@ -0,0 +1,21 @@
+package org.briarproject.briar.api.blog;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+
+@NotNullByDefault
+public interface BlogFactory {
+
+	/**
+	 * Creates a personal blog for a given author.
+	 */
+	Blog createBlog(Author author);
+
+	/**
+	 * Parses a blog with the given Group
+	 */
+	Blog parseBlog(Group g) throws FormatException;
+
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogInvitationRequest.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogInvitationRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..505a5a064b90d087e99d21c804da48e510ecc6d8
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogInvitationRequest.java
@@ -0,0 +1,31 @@
+package org.briarproject.briar.api.blog;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.sharing.InvitationRequest;
+
+import javax.annotation.Nullable;
+
+@NotNullByDefault
+public class BlogInvitationRequest extends InvitationRequest {
+
+	private final String blogAuthorName;
+
+	public BlogInvitationRequest(MessageId id, SessionId sessionId,
+			GroupId groupId, ContactId contactId, String blogAuthorName,
+			@Nullable String message, boolean available, long time,
+			boolean local, boolean sent, boolean seen, boolean read) {
+
+		super(id, sessionId, groupId, contactId, message, available, time,
+				local, sent, seen, read);
+		this.blogAuthorName = blogAuthorName;
+	}
+
+	public String getBlogAuthorName() {
+		return blogAuthorName;
+	}
+
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogInvitationResponse.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogInvitationResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..664126aba9eb75a60dc35ae34394fefd974616e8
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogInvitationResponse.java
@@ -0,0 +1,21 @@
+package org.briarproject.briar.api.blog;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.sharing.InvitationResponse;
+
+@NotNullByDefault
+public class BlogInvitationResponse extends InvitationResponse {
+
+	public BlogInvitationResponse(MessageId id, SessionId sessionId,
+			GroupId groupId, ContactId contactId, boolean accept, long time,
+			boolean local, boolean sent, boolean seen, boolean read) {
+
+		super(id, sessionId, groupId, contactId, accept, time, local, sent,
+				seen, read);
+	}
+
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogManager.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..8b596d6b65128599d494037ece1c1e30cd787dc4
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogManager.java
@@ -0,0 +1,105 @@
+package org.briarproject.briar.api.blog;
+
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+
+import java.util.Collection;
+
+import javax.annotation.Nullable;
+
+@NotNullByDefault
+public interface BlogManager {
+
+	/**
+	 * Unique ID of the blog client.
+	 */
+	ClientId CLIENT_ID = new ClientId("org.briarproject.briar.blog");
+
+	/**
+	 * Returns true if a blog can be removed.
+	 */
+	boolean canBeRemoved(GroupId g) throws DbException;
+
+	/**
+	 * Removes and deletes a blog.
+	 */
+	void removeBlog(Blog b) throws DbException;
+
+	/**
+	 * Stores a local blog post.
+	 */
+	void addLocalPost(BlogPost p) throws DbException;
+
+	/**
+	 * Stores a local blog post.
+	 */
+	void addLocalPost(Transaction txn, BlogPost p) throws DbException;
+
+	/**
+	 * Adds a comment to an existing blog post or reblogs it.
+	 */
+	void addLocalComment(LocalAuthor author, GroupId groupId,
+			@Nullable String comment, BlogPostHeader wHeader)
+			throws DbException;
+
+	/**
+	 * Returns the blog with the given ID.
+	 */
+	Blog getBlog(GroupId g) throws DbException;
+
+	/**
+	 * Returns the blog with the given ID.
+	 */
+	Blog getBlog(Transaction txn, GroupId g) throws DbException;
+
+	/**
+	 * Returns all blogs owned by the given localAuthor.
+	 */
+	Collection<Blog> getBlogs(LocalAuthor localAuthor) throws DbException;
+
+	/**
+	 * Returns only the personal blog of the given author.
+	 */
+	Blog getPersonalBlog(Author author);
+
+	/**
+	 * Returns all blogs to which the user subscribes.
+	 */
+	Collection<Blog> getBlogs() throws DbException;
+
+	/**
+	 * Returns the header of the blog post with the given ID.
+	 */
+	BlogPostHeader getPostHeader(GroupId g, MessageId m) throws DbException;
+
+	/**
+	 * Returns the body of the blog post with the given ID.
+	 */
+	String getPostBody(MessageId m) throws DbException;
+
+	/**
+	 * Returns the headers of all posts in the given blog.
+	 */
+	Collection<BlogPostHeader> getPostHeaders(GroupId g) throws DbException;
+
+	/**
+	 * Marks a blog post as read or unread.
+	 */
+	void setReadFlag(MessageId m, boolean read) throws DbException;
+
+	/**
+	 * Registers a hook to be called whenever a blog is removed.
+	 */
+	void registerRemoveBlogHook(RemoveBlogHook hook);
+
+	interface RemoveBlogHook {
+		void removingBlog(Transaction txn, Blog b) throws DbException;
+	}
+
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogPost.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogPost.java
new file mode 100644
index 0000000000000000000000000000000000000000..53037b732cbf7658b57ba04f49727d1786a596c1
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogPost.java
@@ -0,0 +1,20 @@
+package org.briarproject.briar.api.blog;
+
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.forum.ForumPost;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public class BlogPost extends ForumPost {
+
+	public BlogPost(Message message, @Nullable MessageId parent,
+			Author author) {
+		super(message, parent, author);
+	}
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogPostFactory.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogPostFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..4a64c27323232acff7bf2d957ecbdc4c2f4432f8
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogPostFactory.java
@@ -0,0 +1,54 @@
+package org.briarproject.briar.api.blog;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+
+import java.security.GeneralSecurityException;
+
+import javax.annotation.Nullable;
+
+import static org.briarproject.briar.api.blog.BlogManager.CLIENT_ID;
+
+@NotNullByDefault
+public interface BlogPostFactory {
+
+	String SIGNING_LABEL_POST = CLIENT_ID + "/POST";
+	String SIGNING_LABEL_COMMENT = CLIENT_ID + "/COMMENT";
+
+	BlogPost createBlogPost(GroupId groupId, long timestamp,
+			@Nullable MessageId parent, LocalAuthor author, String body)
+			throws FormatException, GeneralSecurityException;
+
+	Message createBlogComment(GroupId groupId, LocalAuthor author,
+			@Nullable String comment, MessageId originalId, MessageId wrappedId)
+			throws FormatException, GeneralSecurityException;
+
+	/**
+	 * Wraps a blog post
+	 */
+	Message wrapPost(GroupId groupId, byte[] descriptor, long timestamp,
+			BdfList body) throws FormatException;
+
+	/**
+	 * Re-wraps a previously wrapped post
+	 */
+	Message rewrapWrappedPost(GroupId groupId, BdfList body)
+			throws FormatException;
+
+	/**
+	 * Wraps a blog comment
+	 */
+	Message wrapComment(GroupId groupId, byte[] descriptor, long timestamp,
+			BdfList body, MessageId currentId) throws FormatException;
+
+	/**
+	 * Re-wraps a previously wrapped comment
+	 */
+	Message rewrapWrappedComment(GroupId groupId, BdfList body,
+			MessageId currentId) throws FormatException;
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogPostHeader.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogPostHeader.java
new file mode 100644
index 0000000000000000000000000000000000000000..cf01dfc57117deb72e48df2ba304dd16f90d9162
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogPostHeader.java
@@ -0,0 +1,48 @@
+package org.briarproject.briar.api.blog;
+
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.PostHeader;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public class BlogPostHeader extends PostHeader {
+
+	private final MessageType type;
+	private final GroupId groupId;
+	private final long timeReceived;
+
+	public BlogPostHeader(MessageType type, GroupId groupId, MessageId id,
+			@Nullable MessageId parentId, long timestamp, long timeReceived,
+			Author author, Status authorStatus, boolean read) {
+		super(id, parentId, timestamp, author, authorStatus, read);
+		this.type = type;
+		this.groupId = groupId;
+		this.timeReceived = timeReceived;
+	}
+
+	public BlogPostHeader(MessageType type, GroupId groupId, MessageId id,
+			long timestamp, long timeReceived, Author author,
+			Status authorStatus, boolean read) {
+		this(type, groupId, id, null, timestamp, timeReceived, author,
+				authorStatus, read);
+	}
+
+	public MessageType getType() {
+		return type;
+	}
+
+	public GroupId getGroupId() {
+		return groupId;
+	}
+
+	public long getTimeReceived() {
+		return timeReceived;
+	}
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogSharingManager.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogSharingManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..87f669bef0099f4f255b8a45fde8fbe60b78059c
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogSharingManager.java
@@ -0,0 +1,10 @@
+package org.briarproject.briar.api.blog;
+
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.briar.api.sharing.SharingManager;
+
+public interface BlogSharingManager extends SharingManager<Blog> {
+
+	ClientId CLIENT_ID = new ClientId("org.briarproject.briar.blog.sharing");
+
+}
diff --git a/briar-api/src/org/briarproject/api/blogs/BlogSharingMessage.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogSharingMessage.java
similarity index 62%
rename from briar-api/src/org/briarproject/api/blogs/BlogSharingMessage.java
rename to briar-api/src/main/java/org/briarproject/briar/api/blog/BlogSharingMessage.java
index f97799ac530946d0085f199758870d5db5b79915..811bf32e850bf339465f2c6775c1d334feca040f 100644
--- a/briar-api/src/org/briarproject/api/blogs/BlogSharingMessage.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogSharingMessage.java
@@ -1,18 +1,22 @@
-package org.briarproject.api.blogs;
+package org.briarproject.briar.api.blog;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.sharing.SharingMessage.Invitation;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.sharing.SharingMessage.Invitation;
 
-import static org.briarproject.api.blogs.BlogConstants.BLOG_AUTHOR_NAME;
-import static org.briarproject.api.blogs.BlogConstants.BLOG_PUBLIC_KEY;
-import static org.briarproject.api.sharing.SharingConstants.INVITATION_MSG;
-import static org.briarproject.api.sharing.SharingConstants.SESSION_ID;
-import static org.briarproject.api.sharing.SharingConstants.TIME;
+import javax.annotation.Nullable;
 
+import static org.briarproject.briar.api.blog.BlogConstants.BLOG_AUTHOR_NAME;
+import static org.briarproject.briar.api.blog.BlogConstants.BLOG_PUBLIC_KEY;
+import static org.briarproject.briar.api.sharing.SharingConstants.INVITATION_MSG;
+import static org.briarproject.briar.api.sharing.SharingConstants.SESSION_ID;
+import static org.briarproject.briar.api.sharing.SharingConstants.TIME;
+
+@NotNullByDefault
 public interface BlogSharingMessage {
 
 	class BlogInvitation extends Invitation {
@@ -22,7 +26,7 @@ public interface BlogSharingMessage {
 
 		public BlogInvitation(GroupId groupId, SessionId sessionId,
 				String blogAuthorName, byte[] blogPublicKey, long time,
-				String message) {
+				@Nullable String message) {
 			super(groupId, sessionId, time, message);
 
 			this.blogAuthorName = blogAuthorName;
diff --git a/briar-api/src/org/briarproject/api/blogs/MessageType.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/MessageType.java
similarity index 91%
rename from briar-api/src/org/briarproject/api/blogs/MessageType.java
rename to briar-api/src/main/java/org/briarproject/briar/api/blog/MessageType.java
index 9be155679cfc83ea0c7113565d9656e00154884b..e717886b76e6406d664f1e320986f5676f04ec43 100644
--- a/briar-api/src/org/briarproject/api/blogs/MessageType.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/MessageType.java
@@ -1,6 +1,7 @@
-package org.briarproject.api.blogs;
+package org.briarproject.briar.api.blog;
 
 public enum MessageType {
+
 	POST(0),
 	COMMENT(1),
 	WRAPPED_POST(2),
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/blog/event/BlogInvitationRequestReceivedEvent.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/event/BlogInvitationRequestReceivedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..957daaf7de489b380697df29a905b339643e467e
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/event/BlogInvitationRequestReceivedEvent.java
@@ -0,0 +1,21 @@
+package org.briarproject.briar.api.blog.event;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.api.blog.Blog;
+import org.briarproject.briar.api.sharing.InvitationRequest;
+import org.briarproject.briar.api.sharing.event.InvitationRequestReceivedEvent;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public class BlogInvitationRequestReceivedEvent extends
+		InvitationRequestReceivedEvent<Blog> {
+
+	public BlogInvitationRequestReceivedEvent(Blog blog, ContactId contactId,
+			InvitationRequest request) {
+		super(blog, contactId, request);
+	}
+
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/blog/event/BlogInvitationResponseReceivedEvent.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/event/BlogInvitationResponseReceivedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..0b9ae90051e395864605a1dd98dbebba02ef6662
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/event/BlogInvitationResponseReceivedEvent.java
@@ -0,0 +1,20 @@
+package org.briarproject.briar.api.blog.event;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.api.blog.BlogInvitationResponse;
+import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public class BlogInvitationResponseReceivedEvent
+		extends InvitationResponseReceivedEvent {
+
+	public BlogInvitationResponseReceivedEvent(ContactId contactId,
+			BlogInvitationResponse response) {
+		super(contactId, response);
+	}
+
+}
diff --git a/briar-api/src/org/briarproject/api/event/BlogPostAddedEvent.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/event/BlogPostAddedEvent.java
similarity index 52%
rename from briar-api/src/org/briarproject/api/event/BlogPostAddedEvent.java
rename to briar-api/src/main/java/org/briarproject/briar/api/blog/event/BlogPostAddedEvent.java
index c00e4efbff7e80d117cbcb2787a366a0a5988f50..77d9892cb801f060a51129311705fb4da9f20d4a 100644
--- a/briar-api/src/org/briarproject/api/event/BlogPostAddedEvent.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/event/BlogPostAddedEvent.java
@@ -1,9 +1,17 @@
-package org.briarproject.api.event;
+package org.briarproject.briar.api.blog.event;
 
-import org.briarproject.api.blogs.BlogPostHeader;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.api.blog.BlogPostHeader;
 
-/** An event that is broadcast when a blog post was added to the database. */
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when a blog post is added to the database.
+ */
+@Immutable
+@NotNullByDefault
 public class BlogPostAddedEvent extends Event {
 
 	private final GroupId groupId;
diff --git a/briar-api/src/org/briarproject/api/clients/BaseGroup.java b/briar-api/src/main/java/org/briarproject/briar/api/client/BaseGroup.java
similarity index 71%
rename from briar-api/src/org/briarproject/api/clients/BaseGroup.java
rename to briar-api/src/main/java/org/briarproject/briar/api/client/BaseGroup.java
index f4f7636e1444770012f0b8f35b7386b2e62d6f17..d26b8190f41abb6293db13ef7a44efb1a1cc9e76 100644
--- a/briar-api/src/org/briarproject/api/clients/BaseGroup.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/client/BaseGroup.java
@@ -1,8 +1,8 @@
-package org.briarproject.api.clients;
+package org.briarproject.briar.api.client;
 
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
 
 import javax.annotation.concurrent.Immutable;
 
diff --git a/briar-api/src/org/briarproject/api/clients/BaseMessageHeader.java b/briar-api/src/main/java/org/briarproject/briar/api/client/BaseMessageHeader.java
similarity index 61%
rename from briar-api/src/org/briarproject/api/clients/BaseMessageHeader.java
rename to briar-api/src/main/java/org/briarproject/briar/api/client/BaseMessageHeader.java
index b77ac908d4fa7a98a850f17ef5a67bcae7cbbda7..4707ba8caae827b560ceeb733def586de35f31fc 100644
--- a/briar-api/src/org/briarproject/api/clients/BaseMessageHeader.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/client/BaseMessageHeader.java
@@ -1,9 +1,13 @@
-package org.briarproject.api.clients;
+package org.briarproject.briar.api.client;
 
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.NotNull;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
 
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 public abstract class BaseMessageHeader {
 
 	private final MessageId id;
@@ -11,9 +15,8 @@ public abstract class BaseMessageHeader {
 	private final long timestamp;
 	private final boolean local, read, sent, seen;
 
-	public BaseMessageHeader(@NotNull MessageId id, @NotNull GroupId groupId,
-			long timestamp, boolean local, boolean read, boolean sent,
-			boolean seen) {
+	public BaseMessageHeader(MessageId id, GroupId groupId, long timestamp,
+			boolean local, boolean read, boolean sent, boolean seen) {
 
 		this.id = id;
 		this.groupId = groupId;
@@ -24,12 +27,10 @@ public abstract class BaseMessageHeader {
 		this.seen = seen;
 	}
 
-	@NotNull
 	public MessageId getId() {
 		return id;
 	}
 
-	@NotNull
 	public GroupId getGroupId() {
 		return groupId;
 	}
diff --git a/briar-api/src/org/briarproject/api/clients/MessageQueueManager.java b/briar-api/src/main/java/org/briarproject/briar/api/client/MessageQueueManager.java
similarity index 78%
rename from briar-api/src/org/briarproject/api/clients/MessageQueueManager.java
rename to briar-api/src/main/java/org/briarproject/briar/api/client/MessageQueueManager.java
index 0766e5e4be1adfaed44267f08b2b3f1804aa39bf..75418bf7c27afd1375a2156d6ac6b1f15388805e 100644
--- a/briar-api/src/org/briarproject/api/clients/MessageQueueManager.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/client/MessageQueueManager.java
@@ -1,14 +1,15 @@
-package org.briarproject.api.clients;
+package org.briarproject.briar.api.client;
 
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.InvalidMessageException;
-import org.briarproject.api.sync.MessageContext;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.InvalidMessageException;
+import org.briarproject.bramble.api.sync.MessageContext;
 
+@Deprecated
 @NotNullByDefault
 public interface MessageQueueManager {
 
@@ -35,6 +36,7 @@ public interface MessageQueueManager {
 	 */
 	void registerIncomingMessageHook(ClientId c, IncomingQueueMessageHook hook);
 
+	@Deprecated
 	interface QueueMessageValidator {
 
 		/**
@@ -45,6 +47,7 @@ public interface MessageQueueManager {
 				throws InvalidMessageException;
 	}
 
+	@Deprecated
 	interface IncomingQueueMessageHook {
 
 		/**
diff --git a/briar-api/src/org/briarproject/api/clients/MessageTracker.java b/briar-api/src/main/java/org/briarproject/briar/api/client/MessageTracker.java
similarity index 79%
rename from briar-api/src/org/briarproject/api/clients/MessageTracker.java
rename to briar-api/src/main/java/org/briarproject/briar/api/client/MessageTracker.java
index 6351491c74742bc1e0f50eab04ce368bc02089b1..44c26fef4d583fc947e5e59e35954513c5ec3d98 100644
--- a/briar-api/src/org/briarproject/api/clients/MessageTracker.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/client/MessageTracker.java
@@ -1,11 +1,11 @@
-package org.briarproject.api.clients;
+package org.briarproject.briar.api.client;
 
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
 
 @NotNullByDefault
 public interface MessageTracker {
@@ -36,7 +36,7 @@ public interface MessageTracker {
 	 * Updates the group count for the given message.
 	 */
 	void trackMessage(Transaction txn, GroupId g, long timestamp, boolean read)
-		throws DbException;
+			throws DbException;
 
 	/**
 	 * Marks a message as read or unread and updates the group count.
diff --git a/briar-api/src/org/briarproject/api/clients/MessageTree.java b/briar-api/src/main/java/org/briarproject/briar/api/client/MessageTree.java
similarity index 64%
rename from briar-api/src/org/briarproject/api/clients/MessageTree.java
rename to briar-api/src/main/java/org/briarproject/briar/api/client/MessageTree.java
index 14481f2a563486cfcf222abda0ed4229eabd93d8..cca70884e3577278b96541fb17ef3049fe5dc79d 100644
--- a/briar-api/src/org/briarproject/api/clients/MessageTree.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/client/MessageTree.java
@@ -1,23 +1,38 @@
-package org.briarproject.api.clients;
+package org.briarproject.briar.api.client;
 
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.MessageId;
 
 import java.util.Collection;
 import java.util.Comparator;
 
+import javax.annotation.Nullable;
+
+@NotNullByDefault
 public interface MessageTree<T extends MessageTree.MessageNode> {
 
 	void add(Collection<T> nodes);
+
 	void add(T node);
+
 	void setComparator(Comparator<T> comparator);
+
 	void clear();
+
 	Collection<T> depthFirstOrder();
 
+	@NotNullByDefault
 	interface MessageNode {
+
 		MessageId getId();
+
+		@Nullable
 		MessageId getParentId();
+
 		void setLevel(int level);
+
 		void setDescendantCount(int descendantCount);
+
 		long getTimestamp();
 	}
 
diff --git a/briar-api/src/org/briarproject/api/clients/NamedGroup.java b/briar-api/src/main/java/org/briarproject/briar/api/client/NamedGroup.java
similarity index 76%
rename from briar-api/src/org/briarproject/api/clients/NamedGroup.java
rename to briar-api/src/main/java/org/briarproject/briar/api/client/NamedGroup.java
index 176a50858dba2492f3f17368517d60b995655002..2bd0a066806f63fdb84bd3ef7145655b7f4b6c8d 100644
--- a/briar-api/src/org/briarproject/api/clients/NamedGroup.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/client/NamedGroup.java
@@ -1,7 +1,7 @@
-package org.briarproject.api.clients;
+package org.briarproject.briar.api.client;
 
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.Group;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
 
 import javax.annotation.concurrent.Immutable;
 
diff --git a/briar-api/src/org/briarproject/api/clients/PostHeader.java b/briar-api/src/main/java/org/briarproject/briar/api/client/PostHeader.java
similarity index 56%
rename from briar-api/src/org/briarproject/api/clients/PostHeader.java
rename to briar-api/src/main/java/org/briarproject/briar/api/client/PostHeader.java
index 7ffed63645bb5a057712cdb30b389a86a17e50dd..1935e27f6471fd8f0651bd4e1acfb0646f62840e 100644
--- a/briar-api/src/org/briarproject/api/clients/PostHeader.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/client/PostHeader.java
@@ -1,20 +1,27 @@
-package org.briarproject.api.clients;
+package org.briarproject.briar.api.client;
 
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.Author.Status;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.MessageId;
 
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 public abstract class PostHeader {
 
 	private final MessageId id;
+	@Nullable
 	private final MessageId parentId;
 	private final long timestamp;
 	private final Author author;
 	private final Status authorStatus;
 	private final boolean read;
 
-	public PostHeader(MessageId id, MessageId parentId, long timestamp,
-			Author author, Status authorStatus, boolean read) {
+	public PostHeader(MessageId id, @Nullable MessageId parentId,
+			long timestamp, Author author, Status authorStatus, boolean read) {
 		this.id = id;
 		this.parentId = parentId;
 		this.timestamp = timestamp;
@@ -43,6 +50,7 @@ public abstract class PostHeader {
 		return read;
 	}
 
+	@Nullable
 	public MessageId getParentId() {
 		return parentId;
 	}
diff --git a/briar-api/src/org/briarproject/api/clients/ProtocolEngine.java b/briar-api/src/main/java/org/briarproject/briar/api/client/ProtocolEngine.java
similarity index 64%
rename from briar-api/src/org/briarproject/api/clients/ProtocolEngine.java
rename to briar-api/src/main/java/org/briarproject/briar/api/client/ProtocolEngine.java
index 1958deaf0d6fcf02a1d29eef32afae69e037d3e3..281d9af86ff4b2d642a08d0854860cf46a626db3 100644
--- a/briar-api/src/org/briarproject/api/clients/ProtocolEngine.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/client/ProtocolEngine.java
@@ -1,10 +1,14 @@
-package org.briarproject.api.clients;
+package org.briarproject.briar.api.client;
 
-import org.briarproject.api.event.Event;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.util.List;
 
+@Deprecated
+@NotNullByDefault
 public interface ProtocolEngine<A, S, M> {
+
 	StateUpdate<S, M> onLocalAction(S localState, A action);
 
 	StateUpdate<S, M> onMessageReceived(S localState, M received);
@@ -23,11 +27,15 @@ public interface ProtocolEngine<A, S, M> {
 		 * It only shows how the state should be updated,
 		 * but does not carry out the updates on its own.
 		 *
-		 * @param deleteMessage whether to delete the message that triggered the state update. This will be ignored for {@link ProtocolEngine#onLocalAction}.
-		 * @param deleteState   whether to delete the localState {@link S}
-		 * @param localState    the new local state
-		 * @param toSend        a list of messages to be sent as part of the state update
-		 * @param toBroadcast   a list of events to broadcast as result of the state update
+		 * @param deleteMessage whether to delete the message that triggered
+		 * the state update. This will be ignored for
+		 * {@link ProtocolEngine#onLocalAction}.
+		 * @param deleteState whether to delete the localState {@link S}
+		 * @param localState the new local state
+		 * @param toSend a list of messages to be sent as part of the
+		 * state update
+		 * @param toBroadcast a list of events to broadcast as result of the
+		 * state update
 		 */
 		public StateUpdate(boolean deleteMessage, boolean deleteState,
 				S localState, List<M> toSend, List<Event> toBroadcast) {
diff --git a/briar-api/src/org/briarproject/api/clients/ProtocolStateException.java b/briar-api/src/main/java/org/briarproject/briar/api/client/ProtocolStateException.java
similarity index 51%
rename from briar-api/src/org/briarproject/api/clients/ProtocolStateException.java
rename to briar-api/src/main/java/org/briarproject/briar/api/client/ProtocolStateException.java
index f7b072abfc620b9a46357645066605358530946e..a879e912d8ede480ba1a37127e59f3b1713ded66 100644
--- a/briar-api/src/org/briarproject/api/clients/ProtocolStateException.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/client/ProtocolStateException.java
@@ -1,11 +1,12 @@
-package org.briarproject.api.clients;
+package org.briarproject.briar.api.client;
 
-import org.briarproject.api.db.DbException;
+import org.briarproject.bramble.api.db.DbException;
 
 /**
  * Thrown when a database operation is attempted as part of a protocol session
- * and the operation is not applicable to the current protocol state.
+ * and the operation is not applicable to the current protocol state. This
+ * exception may occur due to concurrent updates and does not indicate a
+ * database error.
  */
 public class ProtocolStateException extends DbException {
-
 }
diff --git a/briar-api/src/org/briarproject/api/clients/QueueMessage.java b/briar-api/src/main/java/org/briarproject/briar/api/client/QueueMessage.java
similarity index 52%
rename from briar-api/src/org/briarproject/api/clients/QueueMessage.java
rename to briar-api/src/main/java/org/briarproject/briar/api/client/QueueMessage.java
index 0979c3d19493d663292cbda98020b53ee3cb3ebe..c41b6da2b665dfc2dbc5b0c939c81f7917c80543 100644
--- a/briar-api/src/org/briarproject/api/clients/QueueMessage.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/client/QueueMessage.java
@@ -1,12 +1,15 @@
-package org.briarproject.api.clients;
+package org.briarproject.briar.api.client;
 
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
 
-import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
-import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
 
+@Deprecated
+@NotNullByDefault
 public class QueueMessage extends Message {
 
 	public static final int QUEUE_MESSAGE_HEADER_LENGTH =
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/client/QueueMessageFactory.java b/briar-api/src/main/java/org/briarproject/briar/api/client/QueueMessageFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..ac458a8a89494536aab35ba09fffc68e0a80b182
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/client/QueueMessageFactory.java
@@ -0,0 +1,15 @@
+package org.briarproject.briar.api.client;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+
+@Deprecated
+@NotNullByDefault
+public interface QueueMessageFactory {
+
+	QueueMessage createMessage(GroupId groupId, long timestamp,
+			long queuePosition, byte[] body);
+
+	QueueMessage createMessage(MessageId id, byte[] raw);
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/client/SessionId.java b/briar-api/src/main/java/org/briarproject/briar/api/client/SessionId.java
new file mode 100644
index 0000000000000000000000000000000000000000..d569bdfec8c2e8d941fdf92b41df9c58df8b903b
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/client/SessionId.java
@@ -0,0 +1,24 @@
+package org.briarproject.briar.api.client;
+
+import org.briarproject.bramble.api.UniqueId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.ThreadSafe;
+
+/**
+ * Type-safe wrapper for a byte array that uniquely identifies a protocol
+ * session.
+ */
+@ThreadSafe
+@NotNullByDefault
+public class SessionId extends UniqueId {
+
+	public SessionId(byte[] id) {
+		super(id);
+	}
+
+	@Override
+	public boolean equals(Object o) {
+		return o instanceof SessionId && super.equals(o);
+	}
+}
diff --git a/briar-api/src/org/briarproject/api/clients/ThreadedMessage.java b/briar-api/src/main/java/org/briarproject/briar/api/client/ThreadedMessage.java
similarity index 57%
rename from briar-api/src/org/briarproject/api/clients/ThreadedMessage.java
rename to briar-api/src/main/java/org/briarproject/briar/api/client/ThreadedMessage.java
index 34cd35a2bf49d794de8d2151f93b8d524bd5d4a9..37b0dc86f23766fd2913c46dc3142f615063d6fe 100644
--- a/briar-api/src/org/briarproject/api/clients/ThreadedMessage.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/client/ThreadedMessage.java
@@ -1,12 +1,12 @@
-package org.briarproject.api.clients;
+package org.briarproject.briar.api.client;
 
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.messaging.PrivateMessage;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.messaging.PrivateMessage;
 
+import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
 
 @Immutable
diff --git a/briar-api/src/org/briarproject/api/feed/Feed.java b/briar-api/src/main/java/org/briarproject/briar/api/feed/Feed.java
similarity index 65%
rename from briar-api/src/org/briarproject/api/feed/Feed.java
rename to briar-api/src/main/java/org/briarproject/briar/api/feed/Feed.java
index 502923c4b037ab99d07654280cd378f99d32629f..b36a8a70b113a395aa58f213e3214b840c194a7c 100644
--- a/briar-api/src/org/briarproject/api/feed/Feed.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/feed/Feed.java
@@ -1,26 +1,32 @@
-package org.briarproject.api.feed;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.sync.GroupId;
-import org.jetbrains.annotations.Nullable;
-
-import static org.briarproject.api.feed.FeedConstants.KEY_BLOG_GROUP_ID;
-import static org.briarproject.api.feed.FeedConstants.KEY_FEED_ADDED;
-import static org.briarproject.api.feed.FeedConstants.KEY_FEED_AUTHOR;
-import static org.briarproject.api.feed.FeedConstants.KEY_FEED_DESC;
-import static org.briarproject.api.feed.FeedConstants.KEY_FEED_LAST_ENTRY;
-import static org.briarproject.api.feed.FeedConstants.KEY_FEED_TITLE;
-import static org.briarproject.api.feed.FeedConstants.KEY_FEED_UPDATED;
-import static org.briarproject.api.feed.FeedConstants.KEY_FEED_URL;
-
+package org.briarproject.briar.api.feed;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+import static org.briarproject.briar.api.feed.FeedConstants.KEY_BLOG_GROUP_ID;
+import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_ADDED;
+import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_AUTHOR;
+import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_DESC;
+import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_LAST_ENTRY;
+import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_TITLE;
+import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_UPDATED;
+import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_URL;
+
+@Immutable
+@NotNullByDefault
 public class Feed {
 
-	final private String url;
-	final private GroupId blogId;
-	final private String title, description, author;
-	final private long added, updated, lastEntryTime;
+	private final String url;
+	private final GroupId blogId;
+	@Nullable
+	private final String title, description, author;
+	private final long added, updated, lastEntryTime;
 
 	public Feed(String url, GroupId blogId, @Nullable String title,
 			@Nullable String description, @Nullable String author,
@@ -37,14 +43,11 @@ public class Feed {
 	}
 
 	public Feed(String url, GroupId blogId, @Nullable String title,
-			@Nullable String description, @Nullable String author,
-			long added) {
-
+			@Nullable String description, @Nullable String author, long added) {
 		this(url, blogId, title, description, author, added, 0L, 0L);
 	}
 
 	public Feed(String url, GroupId blogId, long added) {
-
 		this(url, blogId, null, null, null, added, 0L, 0L);
 	}
 
@@ -126,9 +129,9 @@ public class Feed {
 		return false;
 	}
 
-	private boolean equalsWithNull(Object a, Object b) {
+	private boolean equalsWithNull(@Nullable Object a, @Nullable Object b) {
 		if (a == b) return true;
-		if (a == null || b==null) return false;
+		if (a == null || b == null) return false;
 		return a.equals(b);
 	}
 }
diff --git a/briar-api/src/org/briarproject/api/feed/FeedConstants.java b/briar-api/src/main/java/org/briarproject/briar/api/feed/FeedConstants.java
similarity index 94%
rename from briar-api/src/org/briarproject/api/feed/FeedConstants.java
rename to briar-api/src/main/java/org/briarproject/briar/api/feed/FeedConstants.java
index bc98ad7eeace3ffa0274608161925786e7117d5c..8be05d5681fb7b1db2c26d71a484b4d5d69f2515 100644
--- a/briar-api/src/org/briarproject/api/feed/FeedConstants.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/feed/FeedConstants.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.feed;
+package org.briarproject.briar.api.feed;
 
 import java.util.concurrent.TimeUnit;
 
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/feed/FeedManager.java b/briar-api/src/main/java/org/briarproject/briar/api/feed/FeedManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..5d31b448a04295a369317b3601af005132dce707
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/feed/FeedManager.java
@@ -0,0 +1,34 @@
+package org.briarproject.briar.api.feed;
+
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.GroupId;
+
+import java.io.IOException;
+import java.util.List;
+
+@NotNullByDefault
+public interface FeedManager {
+
+	/**
+	 * The unique ID of the RSS feed client.
+	 */
+	ClientId CLIENT_ID = new ClientId("org.briarproject.briar.feed");
+
+	/**
+	 * Adds an RSS feed.
+	 */
+	void addFeed(String url, GroupId g) throws DbException, IOException;
+
+	/**
+	 * Removes an RSS feed.
+	 */
+	void removeFeed(String url) throws DbException;
+
+	/**
+	 * Returns a list of all added RSS feeds
+	 */
+	List<Feed> getFeeds() throws DbException;
+
+}
diff --git a/briar-api/src/org/briarproject/api/forum/Forum.java b/briar-api/src/main/java/org/briarproject/briar/api/forum/Forum.java
similarity index 55%
rename from briar-api/src/org/briarproject/api/forum/Forum.java
rename to briar-api/src/main/java/org/briarproject/briar/api/forum/Forum.java
index f73cd049afff86ea54c15bb905b9dd9bb4ccdd0f..98cabde3e158a85b9e7ff690c68aadce4c979a6c 100644
--- a/briar-api/src/org/briarproject/api/forum/Forum.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/forum/Forum.java
@@ -1,9 +1,9 @@
-package org.briarproject.api.forum;
+package org.briarproject.briar.api.forum;
 
-import org.briarproject.api.clients.NamedGroup;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sharing.Shareable;
-import org.briarproject.api.sync.Group;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.briar.api.client.NamedGroup;
+import org.briarproject.briar.api.sharing.Shareable;
 
 import javax.annotation.concurrent.Immutable;
 
diff --git a/briar-api/src/org/briarproject/api/forum/ForumConstants.java b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumConstants.java
similarity index 57%
rename from briar-api/src/org/briarproject/api/forum/ForumConstants.java
rename to briar-api/src/main/java/org/briarproject/briar/api/forum/ForumConstants.java
index 048f6c3c714935161da35ef05bd28ddb85ed0356..cca6c913e1ba94ce4740fa5347787f2c381b7b4a 100644
--- a/briar-api/src/org/briarproject/api/forum/ForumConstants.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumConstants.java
@@ -1,19 +1,27 @@
-package org.briarproject.api.forum;
+package org.briarproject.briar.api.forum;
 
-import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
 
 public interface ForumConstants {
 
-	/** The maximum length of a forum's name in UTF-8 bytes. */
+	/**
+	 * The maximum length of a forum's name in UTF-8 bytes.
+	 */
 	int MAX_FORUM_NAME_LENGTH = 100;
 
-	/** The length of a forum's random salt in bytes. */
+	/**
+	 * The length of a forum's random salt in bytes.
+	 */
 	int FORUM_SALT_LENGTH = 32;
 
-	/** The maximum length of a forum post's content type in UTF-8 bytes. */
+	/**
+	 * The maximum length of a forum post's content type in UTF-8 bytes.
+	 */
 	int MAX_CONTENT_TYPE_LENGTH = 50;
 
-	/** The maximum length of a forum post's body in bytes. */
+	/**
+	 * The maximum length of a forum post's body in bytes.
+	 */
 	int MAX_FORUM_POST_BODY_LENGTH = MAX_MESSAGE_BODY_LENGTH - 1024;
 
 	/* Forum Sharing Constants */
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumFactory.java b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..1b14a06bef733312a4f3735f2868088f260a0ac1
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumFactory.java
@@ -0,0 +1,18 @@
+package org.briarproject.briar.api.forum;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+public interface ForumFactory {
+
+	/**
+	 * Creates a forum with the given name.
+	 */
+	Forum createForum(String name);
+
+	/**
+	 * Creates a forum with the given name and salt.
+	 */
+	Forum createForum(String name, byte[] salt);
+
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumInvitationRequest.java b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumInvitationRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..25a544510d36f37d1f1bbd3f6f84e17ca4320d4a
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumInvitationRequest.java
@@ -0,0 +1,33 @@
+package org.briarproject.briar.api.forum;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.sharing.InvitationRequest;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public class ForumInvitationRequest extends InvitationRequest {
+
+	private final String forumName;
+
+	public ForumInvitationRequest(MessageId id, SessionId sessionId,
+			GroupId groupId, ContactId contactId, String forumName,
+			@Nullable String message, boolean available, long time,
+			boolean local, boolean sent, boolean seen, boolean read) {
+
+		super(id, sessionId, groupId, contactId, message, available, time,
+				local, sent, seen, read);
+		this.forumName = forumName;
+	}
+
+	public String getForumName() {
+		return forumName;
+	}
+
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumInvitationResponse.java b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumInvitationResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..4d65cf1c4ed245da69c1a301afaaa704a135a09e
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumInvitationResponse.java
@@ -0,0 +1,24 @@
+package org.briarproject.briar.api.forum;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.sharing.InvitationResponse;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public class ForumInvitationResponse extends InvitationResponse {
+
+	public ForumInvitationResponse(MessageId id, SessionId sessionId,
+			GroupId groupId, ContactId contactId, boolean accept, long time,
+			boolean local, boolean sent, boolean seen, boolean read) {
+
+		super(id, sessionId, groupId, contactId, accept, time, local, sent,
+				seen, read);
+	}
+
+}
diff --git a/briar-api/src/org/briarproject/api/forum/ForumManager.java b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumManager.java
similarity index 75%
rename from briar-api/src/org/briarproject/api/forum/ForumManager.java
rename to briar-api/src/main/java/org/briarproject/briar/api/forum/ForumManager.java
index 75c9b9eafc912f12561144834bf240e65700c256..f00a926af45f21464641057b5199c68876c72bd8 100644
--- a/briar-api/src/org/briarproject/api/forum/ForumManager.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumManager.java
@@ -1,18 +1,19 @@
-package org.briarproject.api.forum;
-
-import org.briarproject.api.clients.MessageTracker.GroupCount;
-import org.briarproject.api.crypto.CryptoExecutor;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.Nullable;
+package org.briarproject.briar.api.forum;
+
+import org.briarproject.bramble.api.crypto.CryptoExecutor;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.MessageTracker.GroupCount;
 
 import java.util.Collection;
 
+import javax.annotation.Nullable;
+
 @NotNullByDefault
 public interface ForumManager {
 
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumPost.java b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumPost.java
new file mode 100644
index 0000000000000000000000000000000000000000..fe35ca6ddc34c782fa0746c4e5cc148748cb7a36
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumPost.java
@@ -0,0 +1,21 @@
+package org.briarproject.briar.api.forum;
+
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.ThreadedMessage;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public class ForumPost extends ThreadedMessage {
+
+	public ForumPost(Message message, @Nullable MessageId parent,
+			Author author) {
+		super(message, parent, author);
+	}
+
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumPostFactory.java b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumPostFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..a6ff14554ebedfc8b58f9f83fc4a01083a66900c
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumPostFactory.java
@@ -0,0 +1,26 @@
+package org.briarproject.briar.api.forum;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.crypto.CryptoExecutor;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+
+import java.security.GeneralSecurityException;
+
+import javax.annotation.Nullable;
+
+import static org.briarproject.briar.api.forum.ForumManager.CLIENT_ID;
+
+@NotNullByDefault
+public interface ForumPostFactory {
+
+	String SIGNING_LABEL_POST = CLIENT_ID + "/POST";
+
+	@CryptoExecutor
+	ForumPost createPost(GroupId groupId, long timestamp,
+			@Nullable MessageId parent, LocalAuthor author, String body)
+			throws FormatException, GeneralSecurityException;
+
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumPostHeader.java b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumPostHeader.java
new file mode 100644
index 0000000000000000000000000000000000000000..01c76a5e7735f1c7d3663ac58d656b5f27e96ae7
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumPostHeader.java
@@ -0,0 +1,21 @@
+package org.briarproject.briar.api.forum;
+
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.PostHeader;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public class ForumPostHeader extends PostHeader {
+
+	public ForumPostHeader(MessageId id, @Nullable MessageId parentId,
+			long timestamp, Author author, Author.Status authorStatus,
+			boolean read) {
+		super(id, parentId, timestamp, author, authorStatus, read);
+	}
+
+}
diff --git a/briar-api/src/org/briarproject/api/forum/ForumSharingManager.java b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumSharingManager.java
similarity index 50%
rename from briar-api/src/org/briarproject/api/forum/ForumSharingManager.java
rename to briar-api/src/main/java/org/briarproject/briar/api/forum/ForumSharingManager.java
index b2f99acf6186b881d4e1d9a5b8bc2c46c96fa94a..85bdf53da858e17ccecba833e23c2655f7c6ea47 100644
--- a/briar-api/src/org/briarproject/api/forum/ForumSharingManager.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumSharingManager.java
@@ -1,7 +1,7 @@
-package org.briarproject.api.forum;
+package org.briarproject.briar.api.forum;
 
-import org.briarproject.api.sharing.SharingManager;
-import org.briarproject.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.briar.api.sharing.SharingManager;
 
 public interface ForumSharingManager extends SharingManager<Forum> {
 
diff --git a/briar-api/src/org/briarproject/api/forum/ForumSharingMessage.java b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumSharingMessage.java
similarity index 56%
rename from briar-api/src/org/briarproject/api/forum/ForumSharingMessage.java
rename to briar-api/src/main/java/org/briarproject/briar/api/forum/ForumSharingMessage.java
index e93a39c6b84b782c5806f773cf83991fdc7ec974..c8a08752e5652af0acb3eeec3de1f1ab98ab79a8 100644
--- a/briar-api/src/org/briarproject/api/forum/ForumSharingMessage.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumSharingMessage.java
@@ -1,27 +1,35 @@
-package org.briarproject.api.forum;
+package org.briarproject.briar.api.forum;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.sharing.SharingMessage.Invitation;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.sharing.SharingMessage.Invitation;
 
-import static org.briarproject.api.forum.ForumConstants.FORUM_NAME;
-import static org.briarproject.api.forum.ForumConstants.FORUM_SALT;
-import static org.briarproject.api.sharing.SharingConstants.INVITATION_MSG;
-import static org.briarproject.api.sharing.SharingConstants.SESSION_ID;
-import static org.briarproject.api.sharing.SharingConstants.TIME;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
 
+import static org.briarproject.briar.api.forum.ForumConstants.FORUM_NAME;
+import static org.briarproject.briar.api.forum.ForumConstants.FORUM_SALT;
+import static org.briarproject.briar.api.sharing.SharingConstants.INVITATION_MSG;
+import static org.briarproject.briar.api.sharing.SharingConstants.SESSION_ID;
+import static org.briarproject.briar.api.sharing.SharingConstants.TIME;
+
+@NotNullByDefault
 public interface ForumSharingMessage {
 
+	@Immutable
+	@NotNullByDefault
 	class ForumInvitation extends Invitation {
 
 		private final String forumName;
 		private final byte[] forumSalt;
 
 		public ForumInvitation(GroupId groupId, SessionId sessionId,
-				String forumName, byte[] forumSalt, long time, String message) {
+				String forumName, byte[] forumSalt, long time,
+				@Nullable String message) {
 
 			super(groupId, sessionId, time, message);
 
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/forum/event/ForumInvitationRequestReceivedEvent.java b/briar-api/src/main/java/org/briarproject/briar/api/forum/event/ForumInvitationRequestReceivedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..a737e1a443de675adda8742ed8284a4c2f752139
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/forum/event/ForumInvitationRequestReceivedEvent.java
@@ -0,0 +1,21 @@
+package org.briarproject.briar.api.forum.event;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.api.forum.Forum;
+import org.briarproject.briar.api.forum.ForumInvitationRequest;
+import org.briarproject.briar.api.sharing.event.InvitationRequestReceivedEvent;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public class ForumInvitationRequestReceivedEvent extends
+		InvitationRequestReceivedEvent<Forum> {
+
+	public ForumInvitationRequestReceivedEvent(Forum forum, ContactId contactId,
+			ForumInvitationRequest request) {
+		super(forum, contactId, request);
+	}
+
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/forum/event/ForumInvitationResponseReceivedEvent.java b/briar-api/src/main/java/org/briarproject/briar/api/forum/event/ForumInvitationResponseReceivedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..60567907a19efa601d933126f2f187c09c07caa7
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/forum/event/ForumInvitationResponseReceivedEvent.java
@@ -0,0 +1,21 @@
+package org.briarproject.briar.api.forum.event;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.briar.api.forum.ForumInvitationResponse;
+import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent;
+
+public class ForumInvitationResponseReceivedEvent extends
+		InvitationResponseReceivedEvent {
+
+	private final String forumName;
+
+	public ForumInvitationResponseReceivedEvent(String forumName,
+			ContactId contactId, ForumInvitationResponse response) {
+		super(contactId, response);
+		this.forumName = forumName;
+	}
+
+	public String getForumName() {
+		return forumName;
+	}
+}
diff --git a/briar-api/src/org/briarproject/api/event/ForumPostReceivedEvent.java b/briar-api/src/main/java/org/briarproject/briar/api/forum/event/ForumPostReceivedEvent.java
similarity index 51%
rename from briar-api/src/org/briarproject/api/event/ForumPostReceivedEvent.java
rename to briar-api/src/main/java/org/briarproject/briar/api/forum/event/ForumPostReceivedEvent.java
index b300f9ee276f063e6dd4c63de6e607b05907ea30..0aef3a23f522b2612d4d640452ba181d346e7425 100644
--- a/briar-api/src/org/briarproject/api/event/ForumPostReceivedEvent.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/forum/event/ForumPostReceivedEvent.java
@@ -1,12 +1,17 @@
-package org.briarproject.api.event;
+package org.briarproject.briar.api.forum.event;
 
-import org.briarproject.api.forum.ForumPostHeader;
-import org.briarproject.api.messaging.PrivateMessageHeader;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.api.forum.ForumPostHeader;
+
+import javax.annotation.concurrent.Immutable;
 
 /**
- * An event that is broadcast when a new forum post was received.
+ * An event that is broadcast when a new forum post is received.
  */
+@Immutable
+@NotNullByDefault
 public class ForumPostReceivedEvent extends Event {
 
 	private final ForumPostHeader forumPostHeader;
diff --git a/briar-api/src/org/briarproject/api/introduction/IntroduceeAction.java b/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroduceeAction.java
similarity index 62%
rename from briar-api/src/org/briarproject/api/introduction/IntroduceeAction.java
rename to briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroduceeAction.java
index 324ba5bb613d7cb902af9aed0bff813c71669370..68881b9dc0d57e5993afb38e35943652141629a5 100644
--- a/briar-api/src/org/briarproject/api/introduction/IntroduceeAction.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroduceeAction.java
@@ -1,10 +1,15 @@
-package org.briarproject.api.introduction;
+package org.briarproject.briar.api.introduction;
 
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ABORT;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
+import javax.annotation.Nullable;
+
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_ABORT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_ACK;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_REQUEST;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_RESPONSE;
+
+@NotNullByDefault
 public enum IntroduceeAction {
 
 	LOCAL_ACCEPT,
@@ -16,6 +21,7 @@ public enum IntroduceeAction {
 	REMOTE_ABORT,
 	ACK;
 
+	@Nullable
 	public static IntroduceeAction getRemote(int type, boolean accept) {
 		if (type == TYPE_REQUEST) return REMOTE_REQUEST;
 		if (type == TYPE_RESPONSE && accept) return REMOTE_ACCEPT;
@@ -25,10 +31,12 @@ public enum IntroduceeAction {
 		return null;
 	}
 
+	@Nullable
 	public static IntroduceeAction getRemote(int type) {
 		return getRemote(type, true);
 	}
 
+	@Nullable
 	public static IntroduceeAction getLocal(int type, boolean accept) {
 		if (type == TYPE_RESPONSE && accept) return LOCAL_ACCEPT;
 		if (type == TYPE_RESPONSE) return LOCAL_DECLINE;
@@ -37,6 +45,7 @@ public enum IntroduceeAction {
 		return null;
 	}
 
+	@Nullable
 	public static IntroduceeAction getLocal(int type) {
 		return getLocal(type, true);
 	}
diff --git a/briar-api/src/org/briarproject/api/introduction/IntroduceeProtocolState.java b/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroduceeProtocolState.java
similarity index 68%
rename from briar-api/src/org/briarproject/api/introduction/IntroduceeProtocolState.java
rename to briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroduceeProtocolState.java
index 8b46a0c1f6168b86b02cdd3c7520d262fe520384..e696181a01715261bd2d58b697ce03ff61907d67 100644
--- a/briar-api/src/org/briarproject/api/introduction/IntroduceeProtocolState.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroduceeProtocolState.java
@@ -1,12 +1,18 @@
-package org.briarproject.api.introduction;
+package org.briarproject.briar.api.introduction;
 
-import static org.briarproject.api.introduction.IntroduceeAction.ACK;
-import static org.briarproject.api.introduction.IntroduceeAction.LOCAL_ACCEPT;
-import static org.briarproject.api.introduction.IntroduceeAction.LOCAL_DECLINE;
-import static org.briarproject.api.introduction.IntroduceeAction.REMOTE_ACCEPT;
-import static org.briarproject.api.introduction.IntroduceeAction.REMOTE_DECLINE;
-import static org.briarproject.api.introduction.IntroduceeAction.REMOTE_REQUEST;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
+import javax.annotation.concurrent.Immutable;
+
+import static org.briarproject.briar.api.introduction.IntroduceeAction.ACK;
+import static org.briarproject.briar.api.introduction.IntroduceeAction.LOCAL_ACCEPT;
+import static org.briarproject.briar.api.introduction.IntroduceeAction.LOCAL_DECLINE;
+import static org.briarproject.briar.api.introduction.IntroduceeAction.REMOTE_ACCEPT;
+import static org.briarproject.briar.api.introduction.IntroduceeAction.REMOTE_DECLINE;
+import static org.briarproject.briar.api.introduction.IntroduceeAction.REMOTE_REQUEST;
+
+@Immutable
+@NotNullByDefault
 public enum IntroduceeProtocolState {
 
 	ERROR(0),
diff --git a/briar-api/src/org/briarproject/api/introduction/IntroducerAction.java b/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroducerAction.java
similarity index 62%
rename from briar-api/src/org/briarproject/api/introduction/IntroducerAction.java
rename to briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroducerAction.java
index d20433876aec53c41c3ce361807137668292bceb..7123c7eb26f8abf6f9c455307253aaaf04f59c75 100644
--- a/briar-api/src/org/briarproject/api/introduction/IntroducerAction.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroducerAction.java
@@ -1,10 +1,15 @@
-package org.briarproject.api.introduction;
+package org.briarproject.briar.api.introduction;
 
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ABORT;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
+import javax.annotation.Nullable;
+
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_ABORT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_ACK;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_REQUEST;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_RESPONSE;
+
+@NotNullByDefault
 public enum IntroducerAction {
 
 	LOCAL_REQUEST,
@@ -17,12 +22,14 @@ public enum IntroducerAction {
 	ACK_1,
 	ACK_2;
 
+	@Nullable
 	public static IntroducerAction getLocal(int type) {
 		if (type == TYPE_REQUEST) return LOCAL_REQUEST;
 		if (type == TYPE_ABORT) return LOCAL_ABORT;
 		return null;
 	}
 
+	@Nullable
 	public static IntroducerAction getRemote(int type, boolean one,
 			boolean accept) {
 
@@ -39,6 +46,7 @@ public enum IntroducerAction {
 		return null;
 	}
 
+	@Nullable
 	public static IntroducerAction getRemote(int type, boolean one) {
 		return getRemote(type, one, true);
 	}
diff --git a/briar-api/src/org/briarproject/api/introduction/IntroducerProtocolState.java b/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroducerProtocolState.java
similarity index 70%
rename from briar-api/src/org/briarproject/api/introduction/IntroducerProtocolState.java
rename to briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroducerProtocolState.java
index 61bcf383274c6b5e6fee7f2bcf5d0c4c60350c25..b3d89864e421b60853111c67e43fdbe9a2c6a6f3 100644
--- a/briar-api/src/org/briarproject/api/introduction/IntroducerProtocolState.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroducerProtocolState.java
@@ -1,14 +1,20 @@
-package org.briarproject.api.introduction;
+package org.briarproject.briar.api.introduction;
 
-import static org.briarproject.api.introduction.IntroducerAction.ACK_1;
-import static org.briarproject.api.introduction.IntroducerAction.ACK_2;
-import static org.briarproject.api.introduction.IntroducerAction.LOCAL_REQUEST;
-import static org.briarproject.api.introduction.IntroducerAction.REMOTE_ABORT;
-import static org.briarproject.api.introduction.IntroducerAction.REMOTE_ACCEPT_1;
-import static org.briarproject.api.introduction.IntroducerAction.REMOTE_ACCEPT_2;
-import static org.briarproject.api.introduction.IntroducerAction.REMOTE_DECLINE_1;
-import static org.briarproject.api.introduction.IntroducerAction.REMOTE_DECLINE_2;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
+import javax.annotation.concurrent.Immutable;
+
+import static org.briarproject.briar.api.introduction.IntroducerAction.ACK_1;
+import static org.briarproject.briar.api.introduction.IntroducerAction.ACK_2;
+import static org.briarproject.briar.api.introduction.IntroducerAction.LOCAL_REQUEST;
+import static org.briarproject.briar.api.introduction.IntroducerAction.REMOTE_ABORT;
+import static org.briarproject.briar.api.introduction.IntroducerAction.REMOTE_ACCEPT_1;
+import static org.briarproject.briar.api.introduction.IntroducerAction.REMOTE_ACCEPT_2;
+import static org.briarproject.briar.api.introduction.IntroducerAction.REMOTE_DECLINE_1;
+import static org.briarproject.briar.api.introduction.IntroducerAction.REMOTE_DECLINE_2;
+
+@Immutable
+@NotNullByDefault
 public enum IntroducerProtocolState {
 
 	ERROR(0),
@@ -30,6 +36,7 @@ public enum IntroducerProtocolState {
 		}
 	},
 	AWAIT_RESPONSE_1(3) {
+		@Override
 		public IntroducerProtocolState next(IntroducerAction a) {
 			if (a == REMOTE_ACCEPT_1) return AWAIT_ACKS;
 			if (a == REMOTE_DECLINE_1) return FINISHED;
diff --git a/briar-api/src/org/briarproject/api/introduction/IntroductionConstants.java b/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionConstants.java
similarity index 94%
rename from briar-api/src/org/briarproject/api/introduction/IntroductionConstants.java
rename to briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionConstants.java
index 4e0e0582836364bd721f3914746fabce09f4f836..a0ee65e00b072c7e5439389d99353d15b69d6f0b 100644
--- a/briar-api/src/org/briarproject/api/introduction/IntroductionConstants.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionConstants.java
@@ -1,6 +1,6 @@
-package org.briarproject.api.introduction;
+package org.briarproject.briar.api.introduction;
 
-import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
 
 public interface IntroductionConstants {
 
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionManager.java b/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..2b707d9f182e81f98cc3f01115c054479fc0f3ff
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionManager.java
@@ -0,0 +1,50 @@
+package org.briarproject.briar.api.introduction;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.messaging.ConversationManager.ConversationClient;
+
+import java.util.Collection;
+
+import javax.annotation.Nullable;
+
+@NotNullByDefault
+public interface IntroductionManager extends ConversationClient {
+
+	/**
+	 * The unique ID of the introduction client.
+	 */
+	ClientId CLIENT_ID = new ClientId("org.briarproject.briar.introduction");
+
+	/**
+	 * Sends two initial introduction messages.
+	 */
+	void makeIntroduction(Contact c1, Contact c2, @Nullable String msg,
+			final long timestamp) throws DbException, FormatException;
+
+	/**
+	 * Accepts an introduction.
+	 */
+	void acceptIntroduction(final ContactId contactId,
+			final SessionId sessionId, final long timestamp)
+			throws DbException, FormatException;
+
+	/**
+	 * Declines an introduction.
+	 */
+	void declineIntroduction(final ContactId contactId,
+			final SessionId sessionId, final long timestamp)
+			throws DbException, FormatException;
+
+	/**
+	 * Returns all introduction messages for the given contact.
+	 */
+	Collection<IntroductionMessage> getIntroductionMessages(ContactId contactId)
+			throws DbException;
+
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionMessage.java b/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionMessage.java
new file mode 100644
index 0000000000000000000000000000000000000000..680a955ff144a92c48e9f455f5f81c8444146b49
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionMessage.java
@@ -0,0 +1,43 @@
+package org.briarproject.briar.api.introduction;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.BaseMessageHeader;
+import org.briarproject.briar.api.client.SessionId;
+
+import javax.annotation.concurrent.Immutable;
+
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ROLE_INTRODUCER;
+
+@Immutable
+@NotNullByDefault
+public class IntroductionMessage extends BaseMessageHeader {
+
+	private final SessionId sessionId;
+	private final MessageId messageId;
+	private final int role;
+
+	IntroductionMessage(SessionId sessionId, MessageId messageId,
+			GroupId groupId, int role, long time, boolean local, boolean sent,
+			boolean seen, boolean read) {
+
+		super(messageId, groupId, time, local, read, sent, seen);
+		this.sessionId = sessionId;
+		this.messageId = messageId;
+		this.role = role;
+	}
+
+	public SessionId getSessionId() {
+		return sessionId;
+	}
+
+	public MessageId getMessageId() {
+		return messageId;
+	}
+
+	public boolean isIntroducer() {
+		return role == ROLE_INTRODUCER;
+	}
+
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionRequest.java b/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..428528260c6a4f11dbd88983e78f55183f9b1614
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionRequest.java
@@ -0,0 +1,51 @@
+package org.briarproject.briar.api.introduction;
+
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.SessionId;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public class IntroductionRequest extends IntroductionResponse {
+
+	@Nullable
+	private final String message;
+	private final boolean answered, exists, introducesOtherIdentity;
+
+	public IntroductionRequest(SessionId sessionId, MessageId messageId,
+			GroupId groupId, int role, long time, boolean local, boolean sent,
+			boolean seen, boolean read, AuthorId authorId, String name,
+			boolean accepted, @Nullable String message, boolean answered,
+			boolean exists, boolean introducesOtherIdentity) {
+
+		super(sessionId, messageId, groupId, role, time, local, sent, seen,
+				read, authorId, name, accepted);
+
+		this.message = message;
+		this.answered = answered;
+		this.exists = exists;
+		this.introducesOtherIdentity = introducesOtherIdentity;
+	}
+
+	@Nullable
+	public String getMessage() {
+		return message;
+	}
+
+	public boolean wasAnswered() {
+		return answered;
+	}
+
+	public boolean contactExists() {
+		return exists;
+	}
+
+	public boolean doesIntroduceOtherIdentity() {
+		return introducesOtherIdentity;
+	}
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionResponse.java b/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..22df6eba89e2e44d38fb15cdd94bd75dfacd3cb4
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionResponse.java
@@ -0,0 +1,43 @@
+package org.briarproject.briar.api.introduction;
+
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.SessionId;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public class IntroductionResponse extends IntroductionMessage {
+
+	private final AuthorId remoteAuthorId;
+	private final String name;
+	private final boolean accepted;
+
+	public IntroductionResponse(SessionId sessionId, MessageId messageId,
+			GroupId groupId, int role, long time, boolean local, boolean sent,
+			boolean seen, boolean read, AuthorId remoteAuthorId, String name,
+			boolean accepted) {
+
+		super(sessionId, messageId, groupId, role, time, local, sent, seen,
+				read);
+
+		this.remoteAuthorId = remoteAuthorId;
+		this.name = name;
+		this.accepted = accepted;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public boolean wasAccepted() {
+		return accepted;
+	}
+
+	public AuthorId getRemoteAuthorId() {
+		return remoteAuthorId;
+	}
+}
diff --git a/briar-api/src/org/briarproject/api/event/IntroductionAbortedEvent.java b/briar-api/src/main/java/org/briarproject/briar/api/introduction/event/IntroductionAbortedEvent.java
similarity index 52%
rename from briar-api/src/org/briarproject/api/event/IntroductionAbortedEvent.java
rename to briar-api/src/main/java/org/briarproject/briar/api/introduction/event/IntroductionAbortedEvent.java
index b5d821655a4ec8c7103281ef360f3ad23dd72671..5855275918a6001dbabf6211183d5aad40d4b9a5 100644
--- a/briar-api/src/org/briarproject/api/event/IntroductionAbortedEvent.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/introduction/event/IntroductionAbortedEvent.java
@@ -1,8 +1,14 @@
-package org.briarproject.api.event;
+package org.briarproject.briar.api.introduction.event;
 
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.clients.SessionId;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.api.client.SessionId;
 
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 public class IntroductionAbortedEvent extends Event {
 
 	private final ContactId contactId;
diff --git a/briar-api/src/org/briarproject/api/event/IntroductionRequestReceivedEvent.java b/briar-api/src/main/java/org/briarproject/briar/api/introduction/event/IntroductionRequestReceivedEvent.java
similarity index 57%
rename from briar-api/src/org/briarproject/api/event/IntroductionRequestReceivedEvent.java
rename to briar-api/src/main/java/org/briarproject/briar/api/introduction/event/IntroductionRequestReceivedEvent.java
index 58473e08c81326327670b71cb5d25e54301a5014..9fe4871e22d7019d64bced199f787a2f3f53e086 100644
--- a/briar-api/src/org/briarproject/api/event/IntroductionRequestReceivedEvent.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/introduction/event/IntroductionRequestReceivedEvent.java
@@ -1,8 +1,14 @@
-package org.briarproject.api.event;
+package org.briarproject.briar.api.introduction.event;
 
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.introduction.IntroductionRequest;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.api.introduction.IntroductionRequest;
 
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 public class IntroductionRequestReceivedEvent extends Event {
 
 	private final ContactId contactId;
diff --git a/briar-api/src/org/briarproject/api/event/IntroductionResponseReceivedEvent.java b/briar-api/src/main/java/org/briarproject/briar/api/introduction/event/IntroductionResponseReceivedEvent.java
similarity index 58%
rename from briar-api/src/org/briarproject/api/event/IntroductionResponseReceivedEvent.java
rename to briar-api/src/main/java/org/briarproject/briar/api/introduction/event/IntroductionResponseReceivedEvent.java
index 2938c40db6423f4683de5956d9fa372a3fd58be1..2cd3d1c29d14649129f9b8dde4ae6553eb12fcdd 100644
--- a/briar-api/src/org/briarproject/api/event/IntroductionResponseReceivedEvent.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/introduction/event/IntroductionResponseReceivedEvent.java
@@ -1,8 +1,14 @@
-package org.briarproject.api.event;
+package org.briarproject.briar.api.introduction.event;
 
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.introduction.IntroductionResponse;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.api.introduction.IntroductionResponse;
 
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 public class IntroductionResponseReceivedEvent extends Event {
 
 	private final ContactId contactId;
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/introduction/event/IntroductionSucceededEvent.java b/briar-api/src/main/java/org/briarproject/briar/api/introduction/event/IntroductionSucceededEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..88998789c201b3ea1a5d4a788d3651904f91b4aa
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/introduction/event/IntroductionSucceededEvent.java
@@ -0,0 +1,22 @@
+package org.briarproject.briar.api.introduction.event;
+
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public class IntroductionSucceededEvent extends Event {
+
+	private final Contact contact;
+
+	public IntroductionSucceededEvent(Contact contact) {
+		this.contact = contact;
+	}
+
+	public Contact getContact() {
+		return contact;
+	}
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/messaging/ConversationManager.java b/briar-api/src/main/java/org/briarproject/briar/api/messaging/ConversationManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..8e8ddac0dde60762d41e6e688a7ae4b080574f3c
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/messaging/ConversationManager.java
@@ -0,0 +1,39 @@
+package org.briarproject.briar.api.messaging;
+
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.MessageTracker.GroupCount;
+
+@NotNullByDefault
+public interface ConversationManager {
+
+	/**
+	 * Clients that present messages in a private conversation need to
+	 * register themselves here.
+	 */
+	void registerConversationClient(ConversationClient client);
+
+	/**
+	 * Returns the unified group count for all private conversation messages.
+	 */
+	GroupCount getGroupCount(ContactId c) throws DbException;
+
+	@NotNullByDefault
+	interface ConversationClient {
+
+		Group getContactGroup(Contact c);
+
+		GroupCount getGroupCount(Transaction txn, ContactId c)
+				throws DbException;
+
+		void setReadFlag(GroupId g, MessageId m, boolean read)
+				throws DbException;
+	}
+
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/messaging/MessagingConstants.java b/briar-api/src/main/java/org/briarproject/briar/api/messaging/MessagingConstants.java
new file mode 100644
index 0000000000000000000000000000000000000000..f515e60e6af719fbddbd938b17d7972428b88d1d
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/messaging/MessagingConstants.java
@@ -0,0 +1,11 @@
+package org.briarproject.briar.api.messaging;
+
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
+
+public interface MessagingConstants {
+
+	/**
+	 * The maximum length of a private message's body in bytes.
+	 */
+	int MAX_PRIVATE_MESSAGE_BODY_LENGTH = MAX_MESSAGE_BODY_LENGTH - 1024;
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/messaging/MessagingManager.java b/briar-api/src/main/java/org/briarproject/briar/api/messaging/MessagingManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..c2b80fc4625b4c87159f9c6aec881c72b239a74a
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/messaging/MessagingManager.java
@@ -0,0 +1,47 @@
+package org.briarproject.briar.api.messaging;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.messaging.ConversationManager.ConversationClient;
+
+import java.util.Collection;
+
+@NotNullByDefault
+public interface MessagingManager extends ConversationClient {
+
+	/**
+	 * The unique ID of the messaging client.
+	 */
+	ClientId CLIENT_ID = new ClientId("org.briarproject.briar.messaging");
+
+	/**
+	 * Stores a local private message.
+	 */
+	void addLocalMessage(PrivateMessage m) throws DbException;
+
+	/**
+	 * Returns the ID of the contact with the given private conversation.
+	 */
+	ContactId getContactId(GroupId g) throws DbException;
+
+	/**
+	 * Returns the ID of the private conversation with the given contact.
+	 */
+	GroupId getConversationId(ContactId c) throws DbException;
+
+	/**
+	 * Returns the headers of all messages in the given private conversation.
+	 */
+	Collection<PrivateMessageHeader> getMessageHeaders(ContactId c)
+			throws DbException;
+
+	/**
+	 * Returns the body of the private message with the given ID.
+	 */
+	String getMessageBody(MessageId m) throws DbException;
+
+}
diff --git a/briar-api/src/org/briarproject/api/messaging/PrivateMessage.java b/briar-api/src/main/java/org/briarproject/briar/api/messaging/PrivateMessage.java
similarity index 62%
rename from briar-api/src/org/briarproject/api/messaging/PrivateMessage.java
rename to briar-api/src/main/java/org/briarproject/briar/api/messaging/PrivateMessage.java
index 90c14e54adcbb49673bbf38f792d8bfafb027db0..2fe86deab9c39d5250348cf2d11606389e9364d7 100644
--- a/briar-api/src/org/briarproject/api/messaging/PrivateMessage.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/messaging/PrivateMessage.java
@@ -1,7 +1,7 @@
-package org.briarproject.api.messaging;
+package org.briarproject.briar.api.messaging;
 
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.Message;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Message;
 
 import javax.annotation.concurrent.Immutable;
 
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/messaging/PrivateMessageFactory.java b/briar-api/src/main/java/org/briarproject/briar/api/messaging/PrivateMessageFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..95db155f10465c0a462dd2dab5fd411b2bd919c2
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/messaging/PrivateMessageFactory.java
@@ -0,0 +1,13 @@
+package org.briarproject.briar.api.messaging;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+
+@NotNullByDefault
+public interface PrivateMessageFactory {
+
+	PrivateMessage createPrivateMessage(GroupId groupId, long timestamp,
+			String body) throws FormatException;
+
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/messaging/PrivateMessageHeader.java b/briar-api/src/main/java/org/briarproject/briar/api/messaging/PrivateMessageHeader.java
new file mode 100644
index 0000000000000000000000000000000000000000..bc0003177f986b71878fa1df82f808d59410719a
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/messaging/PrivateMessageHeader.java
@@ -0,0 +1,20 @@
+package org.briarproject.briar.api.messaging;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.BaseMessageHeader;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public class PrivateMessageHeader extends BaseMessageHeader {
+
+	public PrivateMessageHeader(MessageId id, GroupId groupId, long timestamp,
+			boolean local, boolean read, boolean sent, boolean seen) {
+
+		super(id, groupId, timestamp, local, read, sent, seen);
+	}
+
+}
diff --git a/briar-api/src/org/briarproject/api/event/PrivateMessageReceivedEvent.java b/briar-api/src/main/java/org/briarproject/briar/api/messaging/event/PrivateMessageReceivedEvent.java
similarity index 55%
rename from briar-api/src/org/briarproject/api/event/PrivateMessageReceivedEvent.java
rename to briar-api/src/main/java/org/briarproject/briar/api/messaging/event/PrivateMessageReceivedEvent.java
index e1ddbfd1942494e2a3079ff4f28148142ecf62f1..d82bff8f6c3f3a015b8c936ece49d5a722e97ecc 100644
--- a/briar-api/src/org/briarproject/api/event/PrivateMessageReceivedEvent.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/messaging/event/PrivateMessageReceivedEvent.java
@@ -1,12 +1,18 @@
-package org.briarproject.api.event;
+package org.briarproject.briar.api.messaging.event;
 
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.messaging.PrivateMessageHeader;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.api.messaging.PrivateMessageHeader;
+
+import javax.annotation.concurrent.Immutable;
 
 /**
- * An event that is broadcast when a new private message was received.
+ * An event that is broadcast when a new private message is received.
  */
+@Immutable
+@NotNullByDefault
 public class PrivateMessageReceivedEvent extends Event {
 
 	private final PrivateMessageHeader messageHeader;
diff --git a/briar-api/src/org/briarproject/api/privategroup/GroupMember.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMember.java
similarity index 69%
rename from briar-api/src/org/briarproject/api/privategroup/GroupMember.java
rename to briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMember.java
index 2638dfe706b6e37b4006e45fb6f335d776825714..fca0a05814d913ab88dd7c09f653dfbc3569a6f3 100644
--- a/briar-api/src/org/briarproject/api/privategroup/GroupMember.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMember.java
@@ -1,8 +1,8 @@
-package org.briarproject.api.privategroup;
+package org.briarproject.briar.api.privategroup;
 
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.Author.Status;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import javax.annotation.concurrent.Immutable;
 
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMessage.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMessage.java
new file mode 100644
index 0000000000000000000000000000000000000000..7f57e1c1245a8e33178b15fcbb1079d5871f784b
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMessage.java
@@ -0,0 +1,25 @@
+package org.briarproject.briar.api.privategroup;
+
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.ThreadedMessage;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public class GroupMessage extends ThreadedMessage {
+
+	public GroupMessage(Message message, @Nullable MessageId parent,
+			Author member) {
+		super(message, parent, member);
+	}
+
+	public Author getMember() {
+		return super.getAuthor();
+	}
+
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMessageFactory.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMessageFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..0de8ada8730a59e6a805eee4f29bd62bd9eb15ee
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMessageFactory.java
@@ -0,0 +1,63 @@
+package org.briarproject.briar.api.privategroup;
+
+import org.briarproject.bramble.api.crypto.CryptoExecutor;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+
+import javax.annotation.Nullable;
+
+import static org.briarproject.briar.api.privategroup.PrivateGroupManager.CLIENT_ID;
+
+@NotNullByDefault
+public interface GroupMessageFactory {
+
+	String SIGNING_LABEL_JOIN = CLIENT_ID + "/JOIN";
+	String SIGNING_LABEL_POST = CLIENT_ID + "/POST";
+
+	/**
+	 * Creates a join announcement message for the creator of a group.
+	 *
+	 * @param groupId The ID of the private group that is being joined
+	 * @param timestamp The timestamp to be used in the join announcement
+	 * @param creator The creator's identity
+	 */
+	@CryptoExecutor
+	GroupMessage createJoinMessage(GroupId groupId, long timestamp,
+			LocalAuthor creator);
+
+	/**
+	 * Creates a join announcement message for a joining member.
+	 *
+	 * @param groupId The ID of the private group that is being joined
+	 * @param timestamp The timestamp to be used in the join announcement,
+	 * which must be greater than the timestamp of the invitation message
+	 * @param member The member's identity
+	 * @param inviteTimestamp The timestamp of the invitation message
+	 * @param creatorSignature The creator's signature from the invitation
+	 * message
+	 */
+	@CryptoExecutor
+	GroupMessage createJoinMessage(GroupId groupId, long timestamp,
+			LocalAuthor member, long inviteTimestamp, byte[] creatorSignature);
+
+	/**
+	 * Creates a private group post.
+	 *
+	 * @param groupId The ID of the private group
+	 * @param timestamp Must be greater than the timestamps of the parent
+	 * post, if any, and the member's previous message
+	 * @param parentId The ID of the parent post, or null if the post has no
+	 * parent
+	 * @param author The author of the post
+	 * @param body The content of the post
+	 * @param previousMsgId The ID of the author's previous message
+	 * in this group
+	 */
+	@CryptoExecutor
+	GroupMessage createGroupMessage(GroupId groupId, long timestamp,
+			@Nullable MessageId parentId, LocalAuthor author, String body,
+			MessageId previousMsgId);
+
+}
diff --git a/briar-api/src/org/briarproject/api/privategroup/GroupMessageHeader.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMessageHeader.java
similarity index 52%
rename from briar-api/src/org/briarproject/api/privategroup/GroupMessageHeader.java
rename to briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMessageHeader.java
index 9789a59e0ac2e31ddd1e46a7ad7bb69c1fe78bbe..f75183010f68b26e34d24a7297976b85941485cd 100644
--- a/briar-api/src/org/briarproject/api/privategroup/GroupMessageHeader.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMessageHeader.java
@@ -1,14 +1,13 @@
-package org.briarproject.api.privategroup;
+package org.briarproject.briar.api.privategroup;
 
-import org.briarproject.api.clients.PostHeader;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.Author.Status;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.PostHeader;
 
+import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
 
 @Immutable
@@ -24,7 +23,6 @@ public class GroupMessageHeader extends PostHeader {
 		this.groupId = groupId;
 	}
 
-	@NotNull
 	public GroupId getGroupId() {
 		return groupId;
 	}
diff --git a/briar-api/src/org/briarproject/api/privategroup/JoinMessageHeader.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/JoinMessageHeader.java
similarity index 80%
rename from briar-api/src/org/briarproject/api/privategroup/JoinMessageHeader.java
rename to briar-api/src/main/java/org/briarproject/briar/api/privategroup/JoinMessageHeader.java
index ae83be9327ae6555b9128487760296ff692ebb5a..74619a80c14690c580d9f00261aca7a406681d24 100644
--- a/briar-api/src/org/briarproject/api/privategroup/JoinMessageHeader.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/JoinMessageHeader.java
@@ -1,6 +1,6 @@
-package org.briarproject.api.privategroup;
+package org.briarproject.briar.api.privategroup;
 
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import javax.annotation.concurrent.Immutable;
 
@@ -11,7 +11,8 @@ public class JoinMessageHeader extends GroupMessageHeader {
 	private final Visibility visibility;
 	private final boolean isInitial;
 
-	public JoinMessageHeader(GroupMessageHeader h, Visibility visibility, boolean isInitial) {
+	public JoinMessageHeader(GroupMessageHeader h, Visibility visibility,
+			boolean isInitial) {
 		super(h.getGroupId(), h.getId(), h.getParentId(), h.getTimestamp(),
 				h.getAuthor(), h.getAuthorStatus(), h.isRead());
 		this.visibility = visibility;
diff --git a/briar-api/src/org/briarproject/api/privategroup/MessageType.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/MessageType.java
similarity index 58%
rename from briar-api/src/org/briarproject/api/privategroup/MessageType.java
rename to briar-api/src/main/java/org/briarproject/briar/api/privategroup/MessageType.java
index 8b5cf7d578dff9631d0a6e8dabe126b0b7a88932..9927ae4f2dd3be80853db0c174472d8967d9c95a 100644
--- a/briar-api/src/org/briarproject/api/privategroup/MessageType.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/MessageType.java
@@ -1,10 +1,17 @@
-package org.briarproject.api.privategroup;
+package org.briarproject.briar.api.privategroup;
 
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 public enum MessageType {
+
 	JOIN(0),
 	POST(1);
 
-	int value;
+	private final int value;
 
 	MessageType(int value) {
 		this.value = value;
diff --git a/briar-api/src/org/briarproject/api/privategroup/PrivateGroup.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/PrivateGroup.java
similarity index 52%
rename from briar-api/src/org/briarproject/api/privategroup/PrivateGroup.java
rename to briar-api/src/main/java/org/briarproject/briar/api/privategroup/PrivateGroup.java
index 6bb6fdbe9eefb5cbb6ad24426ba9d3443960e7bb..37303c868e06882f103a7c0df8950727cb6798f4 100644
--- a/briar-api/src/org/briarproject/api/privategroup/PrivateGroup.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/PrivateGroup.java
@@ -1,10 +1,10 @@
-package org.briarproject.api.privategroup;
+package org.briarproject.briar.api.privategroup;
 
-import org.briarproject.api.clients.NamedGroup;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sharing.Shareable;
-import org.briarproject.api.sync.Group;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.briar.api.client.NamedGroup;
+import org.briarproject.briar.api.sharing.Shareable;
 
 import javax.annotation.concurrent.Immutable;
 
@@ -25,7 +25,7 @@ public class PrivateGroup extends NamedGroup implements Shareable {
 
 	@Override
 	public boolean equals(Object o) {
-		return o instanceof PrivateGroup &&	super.equals(o);
+		return o instanceof PrivateGroup && super.equals(o);
 	}
 
 }
diff --git a/briar-api/src/org/briarproject/api/privategroup/PrivateGroupConstants.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/PrivateGroupConstants.java
similarity index 79%
rename from briar-api/src/org/briarproject/api/privategroup/PrivateGroupConstants.java
rename to briar-api/src/main/java/org/briarproject/briar/api/privategroup/PrivateGroupConstants.java
index def6c3f69bc660707c6ed088532dc7dab5908d29..c9496a1b3f9521b1d0cafa1d8c989012e72a3247 100644
--- a/briar-api/src/org/briarproject/api/privategroup/PrivateGroupConstants.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/PrivateGroupConstants.java
@@ -1,6 +1,6 @@
-package org.briarproject.api.privategroup;
+package org.briarproject.briar.api.privategroup;
 
-import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
 
 public interface PrivateGroupConstants {
 
diff --git a/briar-api/src/org/briarproject/api/privategroup/PrivateGroupFactory.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/PrivateGroupFactory.java
similarity index 64%
rename from briar-api/src/org/briarproject/api/privategroup/PrivateGroupFactory.java
rename to briar-api/src/main/java/org/briarproject/briar/api/privategroup/PrivateGroupFactory.java
index e4a13eeb789976b066193bbafec8af0ed26c520a..8413f0d1f9a02f08d83bea3d5266ec21cefcbe80 100644
--- a/briar-api/src/org/briarproject/api/privategroup/PrivateGroupFactory.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/PrivateGroupFactory.java
@@ -1,9 +1,9 @@
-package org.briarproject.api.privategroup;
+package org.briarproject.briar.api.privategroup;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.Group;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
 
 @NotNullByDefault
 public interface PrivateGroupFactory {
diff --git a/briar-api/src/org/briarproject/api/privategroup/PrivateGroupManager.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/PrivateGroupManager.java
similarity index 59%
rename from briar-api/src/org/briarproject/api/privategroup/PrivateGroupManager.java
rename to briar-api/src/main/java/org/briarproject/briar/api/privategroup/PrivateGroupManager.java
index b5665dc23fcb720692a403b7fbada1f24a0b526d..aa4b7d45828d2a3d6e279a66f87801a940a5036c 100644
--- a/briar-api/src/org/briarproject/api/privategroup/PrivateGroupManager.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/PrivateGroupManager.java
@@ -1,15 +1,15 @@
-package org.briarproject.api.privategroup;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.MessageTracker.GroupCount;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+package org.briarproject.briar.api.privategroup;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.MessageTracker.GroupCount;
 
 import java.util.Collection;
 
@@ -24,8 +24,8 @@ public interface PrivateGroupManager {
 	/**
 	 * Adds a new private group and joins it.
 	 *
-	 * @param group   The private group to add
-	 * @param joinMsg The creators's join message
+	 * @param group The private group to add
+	 * @param joinMsg The new member's join message
 	 * @param creator True if the group is added by its creator
 	 */
 	void addPrivateGroup(PrivateGroup group, GroupMessage joinMsg,
@@ -34,7 +34,7 @@ public interface PrivateGroupManager {
 	/**
 	 * Adds a new private group and joins it.
 	 *
-	 * @param group   The private group to add
+	 * @param group The private group to add
 	 * @param joinMsg The new member's join message
 	 * @param creator True if the group is added by its creator
 	 */
@@ -47,22 +47,22 @@ public interface PrivateGroupManager {
 	void removePrivateGroup(GroupId g) throws DbException;
 
 	/**
-	 * Gets the MessageId of the user's previous message sent to the group
+	 * Returns the ID of the user's previous message sent to the group
 	 */
 	MessageId getPreviousMsgId(GroupId g) throws DbException;
 
 	/**
-	 * Marks the group with GroupId g as resolved
+	 * Marks the given private group as dissolved.
 	 */
 	void markGroupDissolved(Transaction txn, GroupId g) throws DbException;
 
 	/**
-	 * Returns true if the private group has been dissolved.
+	 * Returns true if the given private group has been dissolved.
 	 */
 	boolean isDissolved(GroupId g) throws DbException;
 
 	/**
-	 * Stores (and sends) a local group message.
+	 * Stores and sends a local private group message.
 	 */
 	GroupMessageHeader addLocalMessage(GroupMessage p) throws DbException;
 
@@ -72,7 +72,7 @@ public interface PrivateGroupManager {
 	PrivateGroup getPrivateGroup(GroupId g) throws DbException;
 
 	/**
-	 * Returns the private group with the given ID within the given transaction.
+	 * Returns the private group with the given ID.
 	 */
 	PrivateGroup getPrivateGroup(Transaction txn, GroupId g) throws DbException;
 
@@ -82,27 +82,27 @@ public interface PrivateGroupManager {
 	Collection<PrivateGroup> getPrivateGroups() throws DbException;
 
 	/**
-	 * Returns the body of the group message with the given ID.
+	 * Returns the body of the private group message with the given ID.
 	 */
 	String getMessageBody(MessageId m) throws DbException;
 
 	/**
-	 * Returns the headers of all group messages in the given group.
+	 * Returns the headers of all messages in the given private group.
 	 */
 	Collection<GroupMessageHeader> getHeaders(GroupId g) throws DbException;
 
 	/**
-	 * Returns all members of the group with ID g
+	 * Returns all members of the given private group.
 	 */
 	Collection<GroupMember> getMembers(GroupId g) throws DbException;
 
 	/**
-	 * Returns true if the given Author a is member of the group with ID g
+	 * Returns true if the given author is a member of the given private group.
 	 */
 	boolean isMember(Transaction txn, GroupId g, Author a) throws DbException;
 
 	/**
-	 * Returns the group count for the given group.
+	 * Returns the group count for the given private group.
 	 */
 	GroupCount getGroupCount(GroupId g) throws DbException;
 
@@ -112,19 +112,18 @@ public interface PrivateGroupManager {
 	void setReadFlag(GroupId g, MessageId m, boolean read) throws DbException;
 
 	/**
-	 * This method needs to be called when a contact relationship
-	 * has been revealed between the user and the Author with AuthorId a
-	 * in the Group identified by the GroupId g.
+	 * Called when a contact relationship has been revealed between the user
+	 * and the given author in the given private group.
 	 *
-	 * @param byContact true if the remote contact has revealed
-	 *                  the relationship first. Otherwise false.
+	 * @param byContact True if the contact revealed the relationship first,
+	 * otherwise false.
 	 */
 	void relationshipRevealed(Transaction txn, GroupId g, AuthorId a,
 			boolean byContact) throws FormatException, DbException;
 
 	/**
-	 * Registers a hook to be called when members are added
-	 * or groups are removed.
+	 * Registers a hook to be called when members are added or private groups
+	 * are removed.
 	 */
 	void registerPrivateGroupHook(PrivateGroupHook hook);
 
diff --git a/briar-api/src/org/briarproject/api/privategroup/Visibility.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/Visibility.java
similarity index 57%
rename from briar-api/src/org/briarproject/api/privategroup/Visibility.java
rename to briar-api/src/main/java/org/briarproject/briar/api/privategroup/Visibility.java
index 4ff09c3ed49eee9c318f64711b5e30a889f43ca3..c8c97c1bad2deb1e0103a3a1694111d035346bc0 100644
--- a/briar-api/src/org/briarproject/api/privategroup/Visibility.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/Visibility.java
@@ -1,7 +1,12 @@
-package org.briarproject.api.privategroup;
+package org.briarproject.briar.api.privategroup;
 
-import org.briarproject.api.FormatException;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 public enum Visibility {
 
 	INVISIBLE(0),
@@ -9,7 +14,7 @@ public enum Visibility {
 	REVEALED_BY_US(2),
 	REVEALED_BY_CONTACT(3);
 
-	int value;
+	private final int value;
 
 	Visibility(int value) {
 		this.value = value;
diff --git a/briar-api/src/org/briarproject/api/privategroup/ContactRelationshipRevealedEvent.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/event/ContactRelationshipRevealedEvent.java
similarity index 64%
rename from briar-api/src/org/briarproject/api/privategroup/ContactRelationshipRevealedEvent.java
rename to briar-api/src/main/java/org/briarproject/briar/api/privategroup/event/ContactRelationshipRevealedEvent.java
index 2fd120315844edf27ab8a67818086c4e8815c75d..08fd42b3d8bc4dd8850903def3e601604a7757e6 100644
--- a/briar-api/src/org/briarproject/api/privategroup/ContactRelationshipRevealedEvent.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/event/ContactRelationshipRevealedEvent.java
@@ -1,9 +1,10 @@
-package org.briarproject.api.privategroup;
+package org.briarproject.briar.api.privategroup.event;
 
-import org.briarproject.api.event.Event;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.api.privategroup.Visibility;
 
 import javax.annotation.concurrent.Immutable;
 
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/event/GroupDissolvedEvent.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/event/GroupDissolvedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..030bd266fa15a02450102c503cba2682561e4f8e
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/event/GroupDissolvedEvent.java
@@ -0,0 +1,27 @@
+package org.briarproject.briar.api.privategroup.event;
+
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when a private group is dissolved by a remote
+ * creator.
+ */
+@Immutable
+@NotNullByDefault
+public class GroupDissolvedEvent extends Event {
+
+	private final GroupId groupId;
+
+	public GroupDissolvedEvent(GroupId groupId) {
+		this.groupId = groupId;
+	}
+
+	public GroupId getGroupId() {
+		return groupId;
+	}
+
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/event/GroupInvitationRequestReceivedEvent.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/event/GroupInvitationRequestReceivedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..6ce0ff1accf5972ec23585777da96e90d0af1548
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/event/GroupInvitationRequestReceivedEvent.java
@@ -0,0 +1,21 @@
+package org.briarproject.briar.api.privategroup.event;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest;
+import org.briarproject.briar.api.sharing.event.InvitationRequestReceivedEvent;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public class GroupInvitationRequestReceivedEvent extends
+		InvitationRequestReceivedEvent<PrivateGroup> {
+
+	public GroupInvitationRequestReceivedEvent(PrivateGroup group,
+			ContactId contactId, GroupInvitationRequest request) {
+		super(group, contactId, request);
+	}
+
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/event/GroupInvitationResponseReceivedEvent.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/event/GroupInvitationResponseReceivedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..705c93074d43c5a84b21487edcaefb2162309548
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/event/GroupInvitationResponseReceivedEvent.java
@@ -0,0 +1,19 @@
+package org.briarproject.briar.api.privategroup.event;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.api.sharing.InvitationResponse;
+import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public class GroupInvitationResponseReceivedEvent
+		extends InvitationResponseReceivedEvent {
+
+	public GroupInvitationResponseReceivedEvent(ContactId contactId,
+			InvitationResponse response) {
+		super(contactId, response);
+	}
+}
diff --git a/briar-api/src/org/briarproject/api/event/GroupMessageAddedEvent.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/event/GroupMessageAddedEvent.java
similarity index 62%
rename from briar-api/src/org/briarproject/api/event/GroupMessageAddedEvent.java
rename to briar-api/src/main/java/org/briarproject/briar/api/privategroup/event/GroupMessageAddedEvent.java
index d0c05c105a315a1b2d3e9d1a0ef420f948de010c..91d363779ba62cad9bd83728ea4aef29e17e7b4a 100644
--- a/briar-api/src/org/briarproject/api/event/GroupMessageAddedEvent.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/event/GroupMessageAddedEvent.java
@@ -1,12 +1,18 @@
-package org.briarproject.api.event;
+package org.briarproject.briar.api.privategroup.event;
 
-import org.briarproject.api.privategroup.GroupMessageHeader;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.api.privategroup.GroupMessageHeader;
+
+import javax.annotation.concurrent.Immutable;
 
 /**
  * An event that is broadcast when a private group message was added
  * to the database.
  */
+@Immutable
+@NotNullByDefault
 public class GroupMessageAddedEvent extends Event {
 
 	private final GroupId groupId;
diff --git a/briar-api/src/org/briarproject/api/privategroup/invitation/GroupInvitationFactory.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationFactory.java
similarity index 59%
rename from briar-api/src/org/briarproject/api/privategroup/invitation/GroupInvitationFactory.java
rename to briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationFactory.java
index fdde77abe33e8c6003b60e14790d659cdbd28fe1..f539a04124b605dccdcd9bcb6ada2d7fc9fa1cad 100644
--- a/briar-api/src/org/briarproject/api/privategroup/invitation/GroupInvitationFactory.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationFactory.java
@@ -1,13 +1,15 @@
-package org.briarproject.api.privategroup.invitation;
+package org.briarproject.briar.api.privategroup.invitation;
 
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.crypto.CryptoExecutor;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.crypto.CryptoExecutor;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
 
-import static org.briarproject.api.privategroup.invitation.GroupInvitationManager.CLIENT_ID;
+import static org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager.CLIENT_ID;
 
+@NotNullByDefault
 public interface GroupInvitationFactory {
 
 	String SIGNING_LABEL_INVITE = CLIENT_ID + "/INVITE";
diff --git a/briar-api/src/org/briarproject/api/privategroup/invitation/GroupInvitationItem.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationItem.java
similarity index 55%
rename from briar-api/src/org/briarproject/api/privategroup/invitation/GroupInvitationItem.java
rename to briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationItem.java
index 7fb91d6acd6689d80c9bdecc717d97ff423e1f51..215e3b756d66aaa6ba303653f5eb547406d4231f 100644
--- a/briar-api/src/org/briarproject/api/privategroup/invitation/GroupInvitationItem.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationItem.java
@@ -1,9 +1,9 @@
-package org.briarproject.api.privategroup.invitation;
+package org.briarproject.briar.api.privategroup.invitation;
 
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.sharing.InvitationItem;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.sharing.InvitationItem;
 
 import javax.annotation.concurrent.Immutable;
 
diff --git a/briar-api/src/org/briarproject/api/privategroup/invitation/GroupInvitationManager.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationManager.java
similarity index 75%
rename from briar-api/src/org/briarproject/api/privategroup/invitation/GroupInvitationManager.java
rename to briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationManager.java
index 21a25e5933d3e1712c4729ffb4c55290d7e4ba71..6fc4c57e440e0210515b106fbd5fa9897d5fb090 100644
--- a/briar-api/src/org/briarproject/api/privategroup/invitation/GroupInvitationManager.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationManager.java
@@ -1,16 +1,16 @@
-package org.briarproject.api.privategroup.invitation;
+package org.briarproject.briar.api.privategroup.invitation;
 
-import org.briarproject.api.clients.ProtocolStateException;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.messaging.ConversationManager.ConversationClient;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.sharing.InvitationMessage;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.api.client.ProtocolStateException;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.messaging.ConversationManager.ConversationClient;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.sharing.InvitationMessage;
 
 import java.util.Collection;
 
diff --git a/briar-api/src/org/briarproject/api/privategroup/invitation/GroupInvitationRequest.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationRequest.java
similarity index 63%
rename from briar-api/src/org/briarproject/api/privategroup/invitation/GroupInvitationRequest.java
rename to briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationRequest.java
index d98bcad2e187deefa1214ebebe2ead758ea53890..bf8110c6b383521ece7f5d87242ac58f10ba6b95 100644
--- a/briar-api/src/org/briarproject/api/privategroup/invitation/GroupInvitationRequest.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationRequest.java
@@ -1,12 +1,12 @@
-package org.briarproject.api.privategroup.invitation;
-
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sharing.InvitationRequest;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+package org.briarproject.briar.api.privategroup.invitation;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.sharing.InvitationRequest;
 
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
diff --git a/briar-api/src/org/briarproject/api/privategroup/invitation/GroupInvitationResponse.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationResponse.java
similarity index 52%
rename from briar-api/src/org/briarproject/api/privategroup/invitation/GroupInvitationResponse.java
rename to briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationResponse.java
index ba41a8b25ef0c67f581630c94ff6dcb2a18aa0d4..3a72271560354b27f707459ca6f7a4fd75f28690 100644
--- a/briar-api/src/org/briarproject/api/privategroup/invitation/GroupInvitationResponse.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationResponse.java
@@ -1,11 +1,11 @@
-package org.briarproject.api.privategroup.invitation;
+package org.briarproject.briar.api.privategroup.invitation;
 
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sharing.InvitationResponse;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.sharing.InvitationResponse;
 
 import javax.annotation.concurrent.Immutable;
 
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationFactory.java b/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..eab12f74142f15539b4f8f9a2dae4c5fa93a0a9f
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationFactory.java
@@ -0,0 +1,10 @@
+package org.briarproject.briar.api.sharing;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.sync.GroupId;
+
+public interface InvitationFactory<I extends SharingMessage.Invitation> {
+
+	I build(GroupId groupId, BdfDictionary d) throws FormatException;
+}
diff --git a/briar-api/src/org/briarproject/api/sharing/InvitationItem.java b/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationItem.java
similarity index 77%
rename from briar-api/src/org/briarproject/api/sharing/InvitationItem.java
rename to briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationItem.java
index c81a4730d87bd00faf9acab6e481f0fcfbc325ec..34735e7940d4543004b78645ca8650ef6a876775 100644
--- a/briar-api/src/org/briarproject/api/sharing/InvitationItem.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationItem.java
@@ -1,7 +1,7 @@
-package org.briarproject.api.sharing;
+package org.briarproject.briar.api.sharing;
 
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
 
 import javax.annotation.concurrent.Immutable;
 
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationMessage.java b/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationMessage.java
new file mode 100644
index 0000000000000000000000000000000000000000..495e9d489c3bf507c874cc074331266e9082cfe4
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationMessage.java
@@ -0,0 +1,36 @@
+package org.briarproject.briar.api.sharing;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.BaseMessageHeader;
+import org.briarproject.briar.api.client.SessionId;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public abstract class InvitationMessage extends BaseMessageHeader {
+
+	private final SessionId sessionId;
+	private final ContactId contactId;
+
+	public InvitationMessage(MessageId id, SessionId sessionId, GroupId groupId,
+			ContactId contactId, long time, boolean local, boolean sent,
+			boolean seen, boolean read) {
+
+		super(id, groupId, time, local, read, sent, seen);
+		this.sessionId = sessionId;
+		this.contactId = contactId;
+	}
+
+	public SessionId getSessionId() {
+		return sessionId;
+	}
+
+	public ContactId getContactId() {
+		return contactId;
+	}
+
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationRequest.java b/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9d961f9058754f2e9f39eb81a9247b9bdccd6717
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationRequest.java
@@ -0,0 +1,39 @@
+package org.briarproject.briar.api.sharing;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.SessionId;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public abstract class InvitationRequest extends InvitationMessage {
+
+	@Nullable
+	private final String message;
+	private final boolean available;
+
+	public InvitationRequest(MessageId id, SessionId sessionId, GroupId groupId,
+			ContactId contactId, @Nullable String message, boolean available,
+			long time, boolean local, boolean sent, boolean seen,
+			boolean read) {
+
+		super(id, sessionId, groupId, contactId, time, local, sent, seen, read);
+		this.message = message;
+		this.available = available;
+	}
+
+	@Nullable
+	public String getMessage() {
+		return message;
+	}
+
+	public boolean isAvailable() {
+		return available;
+	}
+
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationResponse.java b/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..ce94524c5686f9bcfc1f3a8d411a747b5560c275
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationResponse.java
@@ -0,0 +1,28 @@
+package org.briarproject.briar.api.sharing;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.SessionId;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public abstract class InvitationResponse extends InvitationMessage {
+
+	private final boolean accept;
+
+	public InvitationResponse(MessageId id, SessionId sessionId,
+			GroupId groupId, ContactId contactId, boolean accept, long time,
+			boolean local, boolean sent, boolean seen, boolean read) {
+
+		super(id, sessionId, groupId, contactId, time, local, sent, seen, read);
+		this.accept = accept;
+	}
+
+	public boolean wasAccepted() {
+		return accept;
+	}
+}
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/sharing/Shareable.java b/briar-api/src/main/java/org/briarproject/briar/api/sharing/Shareable.java
new file mode 100644
index 0000000000000000000000000000000000000000..409e4ba21889ff2fbb061ddfcb384448dbc0fe82
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/sharing/Shareable.java
@@ -0,0 +1,16 @@
+package org.briarproject.briar.api.sharing;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+
+@NotNullByDefault
+public interface Shareable {
+
+	GroupId getId();
+
+	Group getGroup();
+
+	String getName();
+
+}
diff --git a/briar-api/src/org/briarproject/api/sharing/SharingConstants.java b/briar-api/src/main/java/org/briarproject/briar/api/sharing/SharingConstants.java
similarity index 91%
rename from briar-api/src/org/briarproject/api/sharing/SharingConstants.java
rename to briar-api/src/main/java/org/briarproject/briar/api/sharing/SharingConstants.java
index de49d674a94d855bc71e06fe09f1af4461da0d46..53f4557e45e3ff86702d55fb0d6aba2ad6d84986 100644
--- a/briar-api/src/org/briarproject/api/sharing/SharingConstants.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/sharing/SharingConstants.java
@@ -1,6 +1,6 @@
-package org.briarproject.api.sharing;
+package org.briarproject.briar.api.sharing;
 
-import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
 
 public interface SharingConstants {
 
diff --git a/briar-api/src/org/briarproject/api/sharing/SharingInvitationItem.java b/briar-api/src/main/java/org/briarproject/briar/api/sharing/SharingInvitationItem.java
similarity index 74%
rename from briar-api/src/org/briarproject/api/sharing/SharingInvitationItem.java
rename to briar-api/src/main/java/org/briarproject/briar/api/sharing/SharingInvitationItem.java
index 04b69f49e9cd4a65be8afd3805edcd42069a03f0..e04a38cf25cd6cc79b9605cdaef9c364f2ddf2c1 100644
--- a/briar-api/src/org/briarproject/api/sharing/SharingInvitationItem.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/sharing/SharingInvitationItem.java
@@ -1,7 +1,7 @@
-package org.briarproject.api.sharing;
+package org.briarproject.briar.api.sharing;
 
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.util.Collection;
 
diff --git a/briar-api/src/org/briarproject/api/sharing/SharingManager.java b/briar-api/src/main/java/org/briarproject/briar/api/sharing/SharingManager.java
similarity index 73%
rename from briar-api/src/org/briarproject/api/sharing/SharingManager.java
rename to briar-api/src/main/java/org/briarproject/briar/api/sharing/SharingManager.java
index 783e3ba3eba6c8c072516d9f92fe62a6f3d162f6..e4cff4876ead3adfe3448cbd2237d0629bcd4d0b 100644
--- a/briar-api/src/org/briarproject/api/sharing/SharingManager.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/sharing/SharingManager.java
@@ -1,16 +1,17 @@
-package org.briarproject.api.sharing;
+package org.briarproject.briar.api.sharing;
 
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.messaging.ConversationManager.ConversationClient;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.messaging.ConversationManager.ConversationClient;
 
 import java.util.Collection;
 
+import javax.annotation.Nullable;
+
 @NotNullByDefault
 public interface SharingManager<S extends Shareable>
 		extends ConversationClient {
diff --git a/briar-api/src/org/briarproject/api/sharing/SharingMessage.java b/briar-api/src/main/java/org/briarproject/briar/api/sharing/SharingMessage.java
similarity index 62%
rename from briar-api/src/org/briarproject/api/sharing/SharingMessage.java
rename to briar-api/src/main/java/org/briarproject/briar/api/sharing/SharingMessage.java
index 3078d86b4ef208e0d233d0e9c19c6717d25d6090..23340ac1c012f35a61407bfbc8db4e06279b8865 100644
--- a/briar-api/src/org/briarproject/api/sharing/SharingMessage.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/sharing/SharingMessage.java
@@ -1,25 +1,33 @@
-package org.briarproject.api.sharing;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.sync.GroupId;
-
-import static org.briarproject.api.sharing.SharingConstants.GROUP_ID;
-import static org.briarproject.api.sharing.SharingConstants.SESSION_ID;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ACCEPT;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_DECLINE;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE;
-import static org.briarproject.api.sharing.SharingConstants.TIME;
-import static org.briarproject.api.sharing.SharingConstants.TYPE;
-
+package org.briarproject.briar.api.sharing;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.api.client.SessionId;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+import static org.briarproject.briar.api.sharing.SharingConstants.GROUP_ID;
+import static org.briarproject.briar.api.sharing.SharingConstants.SESSION_ID;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_ACCEPT;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_DECLINE;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE;
+import static org.briarproject.briar.api.sharing.SharingConstants.TIME;
+import static org.briarproject.briar.api.sharing.SharingConstants.TYPE;
+
+@NotNullByDefault
 public interface SharingMessage {
 
+	@Immutable
+	@NotNullByDefault
 	abstract class BaseMessage {
+
 		private final GroupId groupId;
 		private final SessionId sessionId;
 		private final long time;
@@ -71,12 +79,15 @@ public interface SharingMessage {
 		}
 	}
 
+	@Immutable
+	@NotNullByDefault
 	abstract class Invitation extends BaseMessage {
 
+		@Nullable
 		protected final String message;
 
 		public Invitation(GroupId groupId, SessionId sessionId, long time,
-				String message) {
+				@Nullable String message) {
 
 			super(groupId, sessionId, time);
 
@@ -88,11 +99,14 @@ public interface SharingMessage {
 			return SHARE_MSG_TYPE_INVITATION;
 		}
 
+		@Nullable
 		public String getMessage() {
 			return message;
 		}
 	}
 
+	@Immutable
+	@NotNullByDefault
 	class SimpleMessage extends BaseMessage {
 
 		private final long type;
diff --git a/briar-api/src/org/briarproject/api/event/InvitationRequestReceivedEvent.java b/briar-api/src/main/java/org/briarproject/briar/api/sharing/event/InvitationRequestReceivedEvent.java
similarity index 50%
rename from briar-api/src/org/briarproject/api/event/InvitationRequestReceivedEvent.java
rename to briar-api/src/main/java/org/briarproject/briar/api/sharing/event/InvitationRequestReceivedEvent.java
index f9bcfe1a5c792b2e9b6ef2490c53730224aa4e0a..1491240136ead21e264b08392ea4dd92ac155566 100644
--- a/briar-api/src/org/briarproject/api/event/InvitationRequestReceivedEvent.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/sharing/event/InvitationRequestReceivedEvent.java
@@ -1,9 +1,15 @@
-package org.briarproject.api.event;
+package org.briarproject.briar.api.sharing.event;
 
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.sharing.InvitationRequest;
-import org.briarproject.api.sharing.Shareable;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.api.sharing.InvitationRequest;
+import org.briarproject.briar.api.sharing.Shareable;
 
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 public abstract class InvitationRequestReceivedEvent<S extends Shareable>
 		extends Event {
 
@@ -11,7 +17,7 @@ public abstract class InvitationRequestReceivedEvent<S extends Shareable>
 	private final ContactId contactId;
 	private final InvitationRequest request;
 
-	InvitationRequestReceivedEvent(S shareable, ContactId contactId,
+	protected InvitationRequestReceivedEvent(S shareable, ContactId contactId,
 			InvitationRequest request) {
 		this.shareable = shareable;
 		this.contactId = contactId;
diff --git a/briar-api/src/org/briarproject/api/event/InvitationResponseReceivedEvent.java b/briar-api/src/main/java/org/briarproject/briar/api/sharing/event/InvitationResponseReceivedEvent.java
similarity index 55%
rename from briar-api/src/org/briarproject/api/event/InvitationResponseReceivedEvent.java
rename to briar-api/src/main/java/org/briarproject/briar/api/sharing/event/InvitationResponseReceivedEvent.java
index 63f41be02d538503e37521386609fcfd94ce6eb9..ac9ebce868fc1aab1e233c429b309347b8eba747 100644
--- a/briar-api/src/org/briarproject/api/event/InvitationResponseReceivedEvent.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/sharing/event/InvitationResponseReceivedEvent.java
@@ -1,8 +1,14 @@
-package org.briarproject.api.event;
+package org.briarproject.briar.api.sharing.event;
 
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.sharing.InvitationResponse;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.api.sharing.InvitationResponse;
 
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 public abstract class InvitationResponseReceivedEvent extends Event {
 
 	private final ContactId contactId;
diff --git a/briar-api/src/org/briarproject/api/FormatException.java b/briar-api/src/org/briarproject/api/FormatException.java
deleted file mode 100644
index 0cbbb8535de0663468c23b1548615109d869f033..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/FormatException.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.briarproject.api;
-
-import java.io.IOException;
-
-/** An exception that indicates an unrecoverable formatting error. */
-public class FormatException extends IOException {
-
-	private static final long serialVersionUID = 2274966775687766337L;
-}
diff --git a/briar-api/src/org/briarproject/api/UniqueId.java b/briar-api/src/org/briarproject/api/UniqueId.java
deleted file mode 100644
index 72c78d103272a42784aef24f8404cccbac9626d3..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/UniqueId.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.briarproject.api;
-
-public abstract class UniqueId extends Bytes {
-
-	/** The length of a unique identifier in bytes. */
-	public static final int LENGTH = 32;
-
-	protected UniqueId(byte[] id) {
-		super(id);
-		if (id.length != LENGTH) throw new IllegalArgumentException();
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/blogs/BlogCommentHeader.java b/briar-api/src/org/briarproject/api/blogs/BlogCommentHeader.java
deleted file mode 100644
index a5d2e4e9df68def851974bb3a896e03c21aefb1f..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/blogs/BlogCommentHeader.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.briarproject.api.blogs;
-
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.Author.Status;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import static org.briarproject.api.blogs.MessageType.COMMENT;
-import static org.briarproject.api.blogs.MessageType.WRAPPED_COMMENT;
-
-public class BlogCommentHeader extends BlogPostHeader {
-
-	private final String comment;
-	private final BlogPostHeader parent;
-
-	public BlogCommentHeader(@NotNull MessageType type,
-			@NotNull GroupId groupId, @Nullable String comment,
-			@NotNull BlogPostHeader parent, @NotNull MessageId id,
-			long timestamp, long timeReceived, @NotNull Author author,
-			@NotNull Status authorStatus, boolean read) {
-
-		super(type, groupId, id, parent.getId(), timestamp,
-				timeReceived, author, authorStatus, read);
-
-		if (type != COMMENT && type != WRAPPED_COMMENT)
-			throw new IllegalArgumentException("Incompatible Message Type");
-
-		this.comment = comment;
-		this.parent = parent;
-	}
-
-	@Nullable
-	public String getComment() {
-		return comment;
-	}
-
-	public BlogPostHeader getParent() {
-		return parent;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/blogs/BlogFactory.java b/briar-api/src/org/briarproject/api/blogs/BlogFactory.java
deleted file mode 100644
index f730f4367417bcb400f9e2adbe4bbb82ce9ca9e2..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/blogs/BlogFactory.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.briarproject.api.blogs;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.Group;
-import org.jetbrains.annotations.NotNull;
-
-@NotNullByDefault
-public interface BlogFactory {
-
-	/** Creates a personal blog for a given author. */
-	Blog createBlog(Author author);
-
-	/** Parses a blog with the given Group */
-	Blog parseBlog(@NotNull Group g) throws FormatException;
-
-}
diff --git a/briar-api/src/org/briarproject/api/blogs/BlogInvitationRequest.java b/briar-api/src/org/briarproject/api/blogs/BlogInvitationRequest.java
deleted file mode 100644
index 3fc41b9ddc1c67af73565aa7be09bea9cf3bec7d..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/blogs/BlogInvitationRequest.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.briarproject.api.blogs;
-
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.sharing.InvitationRequest;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-
-public class BlogInvitationRequest extends InvitationRequest {
-
-	private final String blogAuthorName;
-
-	public BlogInvitationRequest(MessageId id, SessionId sessionId,
-			GroupId groupId, ContactId contactId, String blogAuthorName,
-			String message, boolean available, long time, boolean local,
-			boolean sent, boolean seen, boolean read) {
-
-		super(id, sessionId, groupId, contactId, message, available, time,
-				local, sent, seen, read);
-		this.blogAuthorName = blogAuthorName;
-	}
-
-	public String getBlogAuthorName() {
-		return blogAuthorName;
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/blogs/BlogInvitationResponse.java b/briar-api/src/org/briarproject/api/blogs/BlogInvitationResponse.java
deleted file mode 100644
index 3798ea75e29b2282cfe236ea40db1c9d9b5229ad..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/blogs/BlogInvitationResponse.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.briarproject.api.blogs;
-
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.sharing.InvitationResponse;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.NotNull;
-
-public class BlogInvitationResponse extends InvitationResponse {
-
-	public BlogInvitationResponse(@NotNull MessageId id, SessionId sessionId,
-			GroupId groupId, ContactId contactId, boolean accept, long time,
-			boolean local, boolean sent, boolean seen, boolean read) {
-
-		super(id, sessionId, groupId, contactId, accept, time, local, sent,
-				seen, read);
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/blogs/BlogManager.java b/briar-api/src/org/briarproject/api/blogs/BlogManager.java
deleted file mode 100644
index 6b0f28ec16d6ae1e4855e5c8ee279e832827a29b..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/blogs/BlogManager.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package org.briarproject.api.blogs;
-
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.Collection;
-
-public interface BlogManager {
-
-	/** Unique ID of the blog client. */
-	ClientId CLIENT_ID = new ClientId("org.briarproject.briar.blogs");
-
-	/** Returns true if a blog can be removed. */
-	boolean canBeRemoved(GroupId g) throws DbException;
-
-	/** Removes and deletes a blog. */
-	void removeBlog(Blog b) throws DbException;
-
-	/** Stores a local blog post. */
-	void addLocalPost(BlogPost p) throws DbException;
-
-	/** Stores a local blog post. */
-	void addLocalPost(Transaction txn, BlogPost p) throws DbException;
-
-	/** Add a comment to an existing blog post or reblog it. */
-	void addLocalComment(LocalAuthor author, GroupId groupId,
-			@Nullable String comment, BlogPostHeader wHeader)
-			throws DbException;
-
-	/** Returns the blog with the given ID. */
-	Blog getBlog(GroupId g) throws DbException;
-
-	/** Returns the blog with the given ID. */
-	Blog getBlog(Transaction txn, GroupId g) throws DbException;
-
-	/** Returns all blogs owned by the given localAuthor. */
-	Collection<Blog> getBlogs(LocalAuthor localAuthor) throws DbException;
-
-	/** Returns only the personal blog of the given author. */
-	Blog getPersonalBlog(Author author);
-
-	/** Returns all blogs to which the user subscribes. */
-	Collection<Blog> getBlogs() throws DbException;
-
-	/** Returns the header of the blog post with the given ID. */
-	BlogPostHeader getPostHeader(GroupId g, MessageId m) throws DbException;
-
-	/** Returns the body of the blog post with the given ID. */
-	String getPostBody(MessageId m) throws DbException;
-
-	/** Returns the headers of all posts in the given blog. */
-	Collection<BlogPostHeader> getPostHeaders(GroupId g) throws DbException;
-
-	/** Marks a blog post as read or unread. */
-	void setReadFlag(MessageId m, boolean read) throws DbException;
-
-	/** Registers a hook to be called whenever a blog is removed. */
-	void registerRemoveBlogHook(RemoveBlogHook hook);
-
-	interface RemoveBlogHook {
-		void removingBlog(Transaction txn, Blog b) throws DbException;
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/blogs/BlogPost.java b/briar-api/src/org/briarproject/api/blogs/BlogPost.java
deleted file mode 100644
index 73c787b29dbd1776b9bf0eff9e75db144411a69c..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/blogs/BlogPost.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.briarproject.api.blogs;
-
-import org.briarproject.api.forum.ForumPost;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-public class BlogPost extends ForumPost {
-
-	public BlogPost(@NotNull Message message, @Nullable MessageId parent,
-			@NotNull Author author) {
-		super(message, parent, author);
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/blogs/BlogPostFactory.java b/briar-api/src/org/briarproject/api/blogs/BlogPostFactory.java
deleted file mode 100644
index 4f8292720ad203b1f87af6afcedb190ac5c4591d..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/blogs/BlogPostFactory.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.briarproject.api.blogs;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.security.GeneralSecurityException;
-
-import static org.briarproject.api.blogs.BlogManager.CLIENT_ID;
-
-public interface BlogPostFactory {
-
-	String SIGNING_LABEL_POST = CLIENT_ID + "/POST";
-	String SIGNING_LABEL_COMMENT = CLIENT_ID + "/COMMENT";
-
-	BlogPost createBlogPost(@NotNull GroupId groupId, long timestamp,
-			@Nullable MessageId parent, @NotNull LocalAuthor author,
-			@NotNull String body)
-			throws FormatException, GeneralSecurityException;
-
-	Message createBlogComment(GroupId groupId, LocalAuthor author,
-			@Nullable String comment, MessageId originalId, MessageId wrappedId)
-			throws FormatException, GeneralSecurityException;
-
-	/** Wraps a blog post */
-	Message wrapPost(GroupId groupId, byte[] descriptor,
-			long timestamp, BdfList body)
-			throws FormatException;
-
-	/** Re-wraps a previously wrapped post */
-	Message rewrapWrappedPost(GroupId groupId, BdfList body)
-			throws FormatException;
-
-	/** Wraps a blog comment */
-	Message wrapComment(GroupId groupId, byte[] descriptor,
-			long timestamp, BdfList body, MessageId currentId)
-			throws FormatException;
-
-	/** Re-wraps a previously wrapped comment */
-	Message rewrapWrappedComment(GroupId groupId, BdfList body,
-			MessageId currentId) throws FormatException;
-}
diff --git a/briar-api/src/org/briarproject/api/blogs/BlogPostHeader.java b/briar-api/src/org/briarproject/api/blogs/BlogPostHeader.java
deleted file mode 100644
index dc191078dfa8af7cd0bbfc44ff81544c00cc718a..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/blogs/BlogPostHeader.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.briarproject.api.blogs;
-
-import org.briarproject.api.clients.PostHeader;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.Author.Status;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-public class BlogPostHeader extends PostHeader {
-
-	private final MessageType type;
-	private final GroupId groupId;
-	private final long timeReceived;
-
-	public BlogPostHeader(@NotNull MessageType type, @NotNull GroupId groupId,
-			@NotNull MessageId id, @Nullable MessageId parentId, long timestamp,
-			long timeReceived, @NotNull Author author,
-			@NotNull Status authorStatus, boolean read) {
-		super(id, parentId, timestamp, author, authorStatus, read);
-
-		this.type = type;
-		this.groupId = groupId;
-		this.timeReceived = timeReceived;
-	}
-
-	public BlogPostHeader(@NotNull MessageType type, @NotNull GroupId groupId,
-			@NotNull MessageId id, long timestamp, long timeReceived,
-			@NotNull Author author, @NotNull Status authorStatus,
-			boolean read) {
-		this(type, groupId, id, null, timestamp, timeReceived, author,
-				authorStatus, read);
-	}
-
-	public MessageType getType() {
-		return type;
-	}
-
-	public GroupId getGroupId() {
-		return groupId;
-	}
-
-	public long getTimeReceived() {
-		return timeReceived;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/blogs/BlogSharingManager.java b/briar-api/src/org/briarproject/api/blogs/BlogSharingManager.java
deleted file mode 100644
index 10ee0ff84217c61a62021d4f0441165dd785016c..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/blogs/BlogSharingManager.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.briarproject.api.blogs;
-
-import org.briarproject.api.sharing.SharingManager;
-import org.briarproject.api.sync.ClientId;
-
-public interface BlogSharingManager extends SharingManager<Blog> {
-
-	ClientId CLIENT_ID = new ClientId("org.briarproject.briar.blogs.sharing");
-
-}
diff --git a/briar-api/src/org/briarproject/api/clients/Client.java b/briar-api/src/org/briarproject/api/clients/Client.java
deleted file mode 100644
index 28954c238a7768e0c2b8109d1c5f5fa0f5036703..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/clients/Client.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.briarproject.api.clients;
-
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-
-public interface Client {
-
-	/**
-	 * Called at startup to create any local state needed by the client.
-	 */
-	void createLocalState(Transaction txn) throws DbException;
-}
diff --git a/briar-api/src/org/briarproject/api/clients/ContactGroupFactory.java b/briar-api/src/org/briarproject/api/clients/ContactGroupFactory.java
deleted file mode 100644
index 705934de6db3e79626d7682275a5f9a2f459f92a..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/clients/ContactGroupFactory.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.briarproject.api.clients;
-
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-
-public interface ContactGroupFactory {
-
-	/** Creates a group that is not shared with any contacts. */
-	Group createLocalGroup(ClientId clientId);
-
-	/** Creates a group for the given client to share with the given contact. */
-	Group createContactGroup(ClientId clientId, Contact contact);
-
-	/**
-	 * Creates a group for the given client to share between the given authors
-	 * identified by their AuthorIds.
-	 */
-	Group createContactGroup(ClientId clientId, AuthorId authorId1,
-			AuthorId authorId2);
-
-}
diff --git a/briar-api/src/org/briarproject/api/clients/QueueMessageFactory.java b/briar-api/src/org/briarproject/api/clients/QueueMessageFactory.java
deleted file mode 100644
index cea02f230f7c9b3a42657a4eb80c894e086d597d..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/clients/QueueMessageFactory.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.briarproject.api.clients;
-
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-
-public interface QueueMessageFactory {
-
-	QueueMessage createMessage(GroupId groupId, long timestamp,
-			long queuePosition, byte[] body);
-
-	QueueMessage createMessage(MessageId id, byte[] raw);
-}
diff --git a/briar-api/src/org/briarproject/api/clients/SessionId.java b/briar-api/src/org/briarproject/api/clients/SessionId.java
deleted file mode 100644
index c9730730bf52cfdc8be7a80f95daba27c1143584..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/clients/SessionId.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.briarproject.api.clients;
-
-import org.briarproject.api.sync.MessageId;
-
-/**
- * Type-safe wrapper for a byte array
- * that uniquely identifies a protocol session.
- */
-public class SessionId extends MessageId {
-
-	public SessionId(byte[] id) {
-		super(id);
-	}
-
-	@Override
-	public boolean equals(Object o) {
-		return o instanceof SessionId && super.equals(o);
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/contact/ContactExchangeListener.java b/briar-api/src/org/briarproject/api/contact/ContactExchangeListener.java
deleted file mode 100644
index 50bf543c71c26607f6c041cbff59c23df152e85b..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/contact/ContactExchangeListener.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.briarproject.api.contact;
-
-import org.briarproject.api.identity.Author;
-
-public interface ContactExchangeListener {
-
-	void contactExchangeSucceeded(Author remoteAuthor);
-
-	/** The exchange failed because the contact already exists. */
-	void duplicateContact(Author remoteAuthor);
-
-	/** A general failure. */
-	void contactExchangeFailed();
-}
diff --git a/briar-api/src/org/briarproject/api/contact/ContactExchangeTask.java b/briar-api/src/org/briarproject/api/contact/ContactExchangeTask.java
deleted file mode 100644
index 0d85850f6fa8a67b9401396854652ce3bec47c02..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/contact/ContactExchangeTask.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.briarproject.api.contact;
-
-import org.briarproject.api.TransportId;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
-
-/**
- * A task for conducting a contact information exchange with a remote peer.
- */
-public interface ContactExchangeTask {
-
-	/**
-	 * Exchange contact information with a remote peer.
-	 */
-	void startExchange(ContactExchangeListener listener,
-			LocalAuthor localAuthor, SecretKey masterSecret,
-			DuplexTransportConnection conn, TransportId transportId,
-			boolean alice);
-}
diff --git a/briar-api/src/org/briarproject/api/crypto/MessageDigest.java b/briar-api/src/org/briarproject/api/crypto/MessageDigest.java
deleted file mode 100644
index 342733c2d8e20e2a5939fec22013f03d346d85e6..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/crypto/MessageDigest.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.briarproject.api.crypto;
-
-public interface MessageDigest {
-
-	/** @see {@link java.security.MessageDigest#digest()} */
-	byte[] digest();
-
-	/** @see {@link java.security.MessageDigest#digest(byte[])} */
-	byte[] digest(byte[] input);
-
-	/** @see {@link java.security.MessageDigest#digest(byte[], int, int)} */
-	int digest(byte[] buf, int offset, int len);
-
-	/** @see {@link java.security.MessageDigest#getDigestLength()} */
-	int getDigestLength();
-
-	/** @see {@link java.security.MessageDigest#reset()} */
-	void reset();
-
-	/** @see {@link java.security.MessageDigest#update(byte)} */
-	void update(byte input);
-
-	/** @see {@link java.security.MessageDigest#update(byte[])} */
-	void update(byte[] input);
-
-	/** @see {@link java.security.MessageDigest#update(byte[], int, int)} */
-	void update(byte[] input, int offset, int len);
-}
diff --git a/briar-api/src/org/briarproject/api/crypto/PrivateKey.java b/briar-api/src/org/briarproject/api/crypto/PrivateKey.java
deleted file mode 100644
index 0fd491e1e61d8abdaea78c3708f47aa6038678d2..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/crypto/PrivateKey.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.briarproject.api.crypto;
-
-/** The private half of a public/private {@link KeyPair}. */
-public interface PrivateKey {
-
-	/** Returns the encoded representation of this key. */
-	byte[] getEncoded();
-}
diff --git a/briar-api/src/org/briarproject/api/crypto/PseudoRandom.java b/briar-api/src/org/briarproject/api/crypto/PseudoRandom.java
deleted file mode 100644
index 1edaa2b2587792712b2ea753ba4701f09ec86ff4..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/crypto/PseudoRandom.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.briarproject.api.crypto;
-
-/** A deterministic PRNG. */
-public interface PseudoRandom {
-
-	byte[] nextBytes(int bytes);
-}
diff --git a/briar-api/src/org/briarproject/api/crypto/PublicKey.java b/briar-api/src/org/briarproject/api/crypto/PublicKey.java
deleted file mode 100644
index f192be90f442463b3025ba62fc137a141683ae8d..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/crypto/PublicKey.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.briarproject.api.crypto;
-
-/** The public half of a public/private {@link KeyPair}. */
-public interface PublicKey {
-
-	/** Returns the encoded representation of this key. */
-	byte[] getEncoded();
-}
diff --git a/briar-api/src/org/briarproject/api/crypto/StreamEncrypter.java b/briar-api/src/org/briarproject/api/crypto/StreamEncrypter.java
deleted file mode 100644
index a332743bb1924fbca5dbb90b22ec6bbbd2b8eeee..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/crypto/StreamEncrypter.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.briarproject.api.crypto;
-
-import java.io.IOException;
-
-public interface StreamEncrypter {
-
-	/** Encrypts the given frame and writes it to the stream. */
-	void writeFrame(byte[] payload, int payloadLength, int paddingLength,
-			boolean finalFrame) throws IOException;
-
-	/** Flushes the stream. */
-	void flush() throws IOException;
-}
diff --git a/briar-api/src/org/briarproject/api/data/BdfWriterFactory.java b/briar-api/src/org/briarproject/api/data/BdfWriterFactory.java
deleted file mode 100644
index f7ede1890837278dd928547264434cde3bdc224a..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/data/BdfWriterFactory.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.briarproject.api.data;
-
-import java.io.OutputStream;
-
-public interface BdfWriterFactory {
-
-	BdfWriter createWriter(OutputStream out);
-}
diff --git a/briar-api/src/org/briarproject/api/data/MetadataEncoder.java b/briar-api/src/org/briarproject/api/data/MetadataEncoder.java
deleted file mode 100644
index 4b2e3ab8e41f59ff35a41e682661f155a49b5130..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/data/MetadataEncoder.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.briarproject.api.data;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.db.Metadata;
-
-public interface MetadataEncoder {
-
-	Metadata encode(BdfDictionary d) throws FormatException;
-}
diff --git a/briar-api/src/org/briarproject/api/data/MetadataParser.java b/briar-api/src/org/briarproject/api/data/MetadataParser.java
deleted file mode 100644
index 798ad5df9c4a21067214e5d2d71fb98340be7455..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/data/MetadataParser.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.briarproject.api.data;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.db.Metadata;
-
-public interface MetadataParser {
-
-	BdfDictionary parse(Metadata m) throws FormatException;
-}
diff --git a/briar-api/src/org/briarproject/api/data/ObjectReader.java b/briar-api/src/org/briarproject/api/data/ObjectReader.java
deleted file mode 100644
index 81f02902c1a6e9f4377be30e5a690014d069053d..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/data/ObjectReader.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.briarproject.api.data;
-
-import java.io.IOException;
-
-public interface ObjectReader<T> {
-
-	T readObject(BdfReader r) throws IOException;
-}
diff --git a/briar-api/src/org/briarproject/api/event/BlogInvitationReceivedEvent.java b/briar-api/src/org/briarproject/api/event/BlogInvitationReceivedEvent.java
deleted file mode 100644
index 2089e6c5d03c388c5bf8960bd5861eceddfadd60..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/BlogInvitationReceivedEvent.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.blogs.Blog;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.sharing.InvitationRequest;
-
-public class BlogInvitationReceivedEvent extends
-		InvitationRequestReceivedEvent<Blog> {
-
-	public BlogInvitationReceivedEvent(Blog blog, ContactId contactId,
-			InvitationRequest request) {
-		super(blog, contactId, request);
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/event/BlogInvitationResponseReceivedEvent.java b/briar-api/src/org/briarproject/api/event/BlogInvitationResponseReceivedEvent.java
deleted file mode 100644
index 6043885ada8f3055b47ec7c0992038d96ea63201..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/BlogInvitationResponseReceivedEvent.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.blogs.BlogInvitationResponse;
-import org.briarproject.api.contact.ContactId;
-
-public class BlogInvitationResponseReceivedEvent
-		extends InvitationResponseReceivedEvent {
-
-	public BlogInvitationResponseReceivedEvent(ContactId contactId,
-			BlogInvitationResponse response) {
-		super(contactId, response);
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/event/ContactAddedEvent.java b/briar-api/src/org/briarproject/api/event/ContactAddedEvent.java
deleted file mode 100644
index 0b2e5017cc88f8bacc762ed97d132773fe4b4093..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/ContactAddedEvent.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.contact.ContactId;
-
-/** An event that is broadcast when a contact is added. */
-public class ContactAddedEvent extends Event {
-
-	private final ContactId contactId;
-	private final boolean active;
-
-	public ContactAddedEvent(ContactId contactId, boolean active) {
-		this.contactId = contactId;
-		this.active = active;
-	}
-
-	public ContactId getContactId() {
-		return contactId;
-	}
-
-	public boolean isActive() {
-		return active;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/event/ContactRemovedEvent.java b/briar-api/src/org/briarproject/api/event/ContactRemovedEvent.java
deleted file mode 100644
index f76c9a7ecacb6e80928afe16848d57ddab842c25..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/ContactRemovedEvent.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.contact.ContactId;
-
-/** An event that is broadcast when a contact is removed. */
-public class ContactRemovedEvent extends Event {
-
-	private final ContactId contactId;
-
-	public ContactRemovedEvent(ContactId contactId) {
-		this.contactId = contactId;
-	}
-
-	public ContactId getContactId() {
-		return contactId;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/event/ContactStatusChangedEvent.java b/briar-api/src/org/briarproject/api/event/ContactStatusChangedEvent.java
deleted file mode 100644
index ddbdbd5db0514defee7ecb5203405efd4c1d2454..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/ContactStatusChangedEvent.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.contact.ContactId;
-
-/** An event that is broadcast when a contact is marked active or inactive. */
-public class ContactStatusChangedEvent extends Event {
-
-	private final ContactId contactId;
-	private final boolean active;
-
-	public ContactStatusChangedEvent(ContactId contactId, boolean active) {
-		this.contactId = contactId;
-		this.active = active;
-	}
-
-	public ContactId getContactId() {
-		return contactId;
-	}
-
-	public boolean isActive() {
-		return active;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/event/ContactVerifiedEvent.java b/briar-api/src/org/briarproject/api/event/ContactVerifiedEvent.java
deleted file mode 100644
index 2507dee4ef9b91757a551f21934e80c2313c5825..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/ContactVerifiedEvent.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.contact.ContactId;
-
-/** An event that is broadcast when a contact is verified. */
-public class ContactVerifiedEvent extends Event {
-
-	private final ContactId contactId;
-
-	public ContactVerifiedEvent(ContactId contactId) {
-		this.contactId = contactId;
-	}
-
-	public ContactId getContactId() {
-		return contactId;
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/event/Event.java b/briar-api/src/org/briarproject/api/event/Event.java
deleted file mode 100644
index 9a7a8b64842e1a0e371750355c3c259e127f6d66..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/Event.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.briarproject.api.event;
-
-/** An abstract superclass for events. */
-public abstract class Event {
-
-}
diff --git a/briar-api/src/org/briarproject/api/event/EventBus.java b/briar-api/src/org/briarproject/api/event/EventBus.java
deleted file mode 100644
index 0b49d81e6da09b7358820c69dda7dd70aa1381ad..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/EventBus.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.briarproject.api.event;
-
-public interface EventBus {
-
-	/** Adds a listener to be notified when events occur. */
-	void addListener(EventListener l);
-
-	/** Removes a listener. */
-	void removeListener(EventListener l);
-
-	/** Notifies all listeners of an event. */
-	void broadcast(Event e);
-}
diff --git a/briar-api/src/org/briarproject/api/event/EventListener.java b/briar-api/src/org/briarproject/api/event/EventListener.java
deleted file mode 100644
index 89598d79e1e4bbdccf702da3edc35feed070acb5..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/EventListener.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.briarproject.api.event;
-
-/** An interface for receiving notifications when events occur. */
-public interface EventListener {
-
-	/**
-	 * Called when an event is broadcast. Implementations of this method must
-	 * not block.
-	 */
-	void eventOccurred(Event e);
-}
diff --git a/briar-api/src/org/briarproject/api/event/ForumInvitationReceivedEvent.java b/briar-api/src/org/briarproject/api/event/ForumInvitationReceivedEvent.java
deleted file mode 100644
index 416979d2e400017a22adc914aafee71d992fb704..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/ForumInvitationReceivedEvent.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumInvitationRequest;
-
-public class ForumInvitationReceivedEvent extends
-		InvitationRequestReceivedEvent<Forum> {
-
-	public ForumInvitationReceivedEvent(Forum forum, ContactId contactId,
-			ForumInvitationRequest request) {
-		super(forum, contactId, request);
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/event/ForumInvitationResponseReceivedEvent.java b/briar-api/src/org/briarproject/api/event/ForumInvitationResponseReceivedEvent.java
deleted file mode 100644
index f4669f94620328c6ad4fcd15647c5c6ca5148624..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/ForumInvitationResponseReceivedEvent.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.forum.ForumInvitationResponse;
-
-public class ForumInvitationResponseReceivedEvent extends InvitationResponseReceivedEvent {
-
-	private final String forumName;
-
-	public ForumInvitationResponseReceivedEvent(String forumName,
-			ContactId contactId, ForumInvitationResponse response) {
-		super(contactId, response);
-		this.forumName = forumName;
-	}
-
-	public String getForumName() {
-		return forumName;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/event/GroupAddedEvent.java b/briar-api/src/org/briarproject/api/event/GroupAddedEvent.java
deleted file mode 100644
index d900388bc451bb3662bd44ebc798a7735b3b656b..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/GroupAddedEvent.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.sync.Group;
-
-/** An event that is broadcast when a group is added. */
-public class GroupAddedEvent extends Event {
-
-	private final Group group;
-
-	public GroupAddedEvent(Group group) {
-		this.group = group;
-	}
-
-	public Group getGroup() {
-		return group;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/event/GroupDissolvedEvent.java b/briar-api/src/org/briarproject/api/event/GroupDissolvedEvent.java
deleted file mode 100644
index 5b8a3224d36643f7139b0425e05fb938cc27cf7c..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/GroupDissolvedEvent.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * An event that is broadcast when a private group was dissolved
- * by a remote creator.
- */
-@Immutable
-@NotNullByDefault
-public class GroupDissolvedEvent extends Event {
-
-	private final GroupId groupId;
-
-	public GroupDissolvedEvent(GroupId groupId) {
-		this.groupId = groupId;
-	}
-
-	public GroupId getGroupId() {
-		return groupId;
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/event/GroupInvitationRequestReceivedEvent.java b/briar-api/src/org/briarproject/api/event/GroupInvitationRequestReceivedEvent.java
deleted file mode 100644
index 1fc2599c22f77ee4183c7da1836caa31b5a57af8..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/GroupInvitationRequestReceivedEvent.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.privategroup.invitation.GroupInvitationRequest;
-
-public class GroupInvitationRequestReceivedEvent extends
-		InvitationRequestReceivedEvent<PrivateGroup> {
-
-	public GroupInvitationRequestReceivedEvent(PrivateGroup group,
-			ContactId contactId, GroupInvitationRequest request) {
-		super(group, contactId, request);
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/event/GroupInvitationResponseReceivedEvent.java b/briar-api/src/org/briarproject/api/event/GroupInvitationResponseReceivedEvent.java
deleted file mode 100644
index a72fd313af7b3899b85fc7539b756270456f99cd..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/GroupInvitationResponseReceivedEvent.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.sharing.InvitationResponse;
-
-public class GroupInvitationResponseReceivedEvent
-		extends InvitationResponseReceivedEvent {
-
-	public GroupInvitationResponseReceivedEvent(ContactId contactId,
-			InvitationResponse response) {
-		super(contactId, response);
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/event/GroupRemovedEvent.java b/briar-api/src/org/briarproject/api/event/GroupRemovedEvent.java
deleted file mode 100644
index 25838e610140469d870b99b48087c64c49163b59..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/GroupRemovedEvent.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.sync.Group;
-
-/** An event that is broadcast when a group is removed. */
-public class GroupRemovedEvent extends Event {
-
-	private final Group group;
-
-	public GroupRemovedEvent(Group group) {
-		this.group = group;
-	}
-
-	public Group getGroup() {
-		return group;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/event/GroupVisibilityUpdatedEvent.java b/briar-api/src/org/briarproject/api/event/GroupVisibilityUpdatedEvent.java
deleted file mode 100644
index 368865217c487ef898e32dbfbc81ccf0e6500d86..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/GroupVisibilityUpdatedEvent.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.contact.ContactId;
-
-import java.util.Collection;
-
-/** An event that is broadcast when the visibility of a group is updated. */
-public class GroupVisibilityUpdatedEvent extends Event {
-
-	private final Collection<ContactId> affected;
-
-	public GroupVisibilityUpdatedEvent(Collection<ContactId> affected) {
-		this.affected = affected;
-	}
-
-	/** Returns the contacts affected by the update. */
-	public Collection<ContactId> getAffectedContacts() {
-		return affected;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/event/IntroductionSucceededEvent.java b/briar-api/src/org/briarproject/api/event/IntroductionSucceededEvent.java
deleted file mode 100644
index dfbf3a3193748403a90d0455b7cc394fff4d479e..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/IntroductionSucceededEvent.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.contact.Contact;
-
-public class IntroductionSucceededEvent extends Event {
-
-	private final Contact contact;
-
-	public IntroductionSucceededEvent(Contact contact) {
-		this.contact = contact;
-	}
-
-	public Contact getContact() {
-		return contact;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/event/KeyAgreementAbortedEvent.java b/briar-api/src/org/briarproject/api/event/KeyAgreementAbortedEvent.java
deleted file mode 100644
index 5e217f7f4d2752f09ae68d7e0ee9b9cbc68f9d46..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/KeyAgreementAbortedEvent.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.briarproject.api.event;
-
-/** An event that is broadcast when a BQP protocol aborts. */
-public class KeyAgreementAbortedEvent extends Event {
-
-	private final boolean remoteAborted;
-
-	public KeyAgreementAbortedEvent(boolean remoteAborted) {
-		this.remoteAborted = remoteAborted;
-	}
-
-	public boolean didRemoteAbort() {
-		return remoteAborted;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/event/KeyAgreementFailedEvent.java b/briar-api/src/org/briarproject/api/event/KeyAgreementFailedEvent.java
deleted file mode 100644
index 97313a276b0bf19f582e4177b3680753ac09568f..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/KeyAgreementFailedEvent.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.briarproject.api.event;
-
-/** An event that is broadcast when a BQP connection cannot be created. */
-public class KeyAgreementFailedEvent extends Event {
-
-}
diff --git a/briar-api/src/org/briarproject/api/event/KeyAgreementFinishedEvent.java b/briar-api/src/org/briarproject/api/event/KeyAgreementFinishedEvent.java
deleted file mode 100644
index f2afe349ebb23c6a9c63d33d518660f7b84e036b..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/KeyAgreementFinishedEvent.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.keyagreement.KeyAgreementResult;
-
-/** An event that is broadcast when a BQP protocol completes. */
-public class KeyAgreementFinishedEvent extends Event {
-
-	private final KeyAgreementResult result;
-
-	public KeyAgreementFinishedEvent(KeyAgreementResult result) {
-		this.result = result;
-	}
-
-	public KeyAgreementResult getResult() {
-		return result;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/event/KeyAgreementListeningEvent.java b/briar-api/src/org/briarproject/api/event/KeyAgreementListeningEvent.java
deleted file mode 100644
index df3b2cbac5fc6ced89e43a37cee90766a7a2e70b..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/KeyAgreementListeningEvent.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.keyagreement.Payload;
-
-/** An event that is broadcast when a BQP task is listening. */
-public class KeyAgreementListeningEvent extends Event {
-
-	private final Payload localPayload;
-
-	public KeyAgreementListeningEvent(Payload localPayload) {
-		this.localPayload = localPayload;
-	}
-
-	public Payload getLocalPayload() {
-		return localPayload;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/event/KeyAgreementStartedEvent.java b/briar-api/src/org/briarproject/api/event/KeyAgreementStartedEvent.java
deleted file mode 100644
index a12a9c459a38c3b1131bb605f1b9eb857a13d2f2..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/KeyAgreementStartedEvent.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.briarproject.api.event;
-
-/** An event that is broadcast when a BQP protocol completes. */
-public class KeyAgreementStartedEvent extends Event {
-
-}
diff --git a/briar-api/src/org/briarproject/api/event/LocalAuthorAddedEvent.java b/briar-api/src/org/briarproject/api/event/LocalAuthorAddedEvent.java
deleted file mode 100644
index 5f0aeb3cd4ea2107c9a3f755a7e851085ce71cad..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/LocalAuthorAddedEvent.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.identity.AuthorId;
-
-/** An event that is broadcast when a local pseudonym is added. */
-public class LocalAuthorAddedEvent extends Event {
-
-	private final AuthorId authorId;
-
-	public LocalAuthorAddedEvent(AuthorId authorId) {
-		this.authorId = authorId;
-	}
-
-	public AuthorId getAuthorId() {
-		return authorId;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/event/LocalAuthorRemovedEvent.java b/briar-api/src/org/briarproject/api/event/LocalAuthorRemovedEvent.java
deleted file mode 100644
index 5e69ccf7a2c13bb3fcf7aa8a1f7ec0d2860ea914..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/LocalAuthorRemovedEvent.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.identity.AuthorId;
-
-/** An event that is broadcast when a local pseudonym is removed. */
-public class LocalAuthorRemovedEvent extends Event {
-
-	private final AuthorId authorId;
-
-	public LocalAuthorRemovedEvent(AuthorId authorId) {
-		this.authorId = authorId;
-	}
-
-	public AuthorId getAuthorId() {
-		return authorId;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/event/MessageAddedEvent.java b/briar-api/src/org/briarproject/api/event/MessageAddedEvent.java
deleted file mode 100644
index dca0212fdc53d2009b2f1e1f09ccb0b82cf4cd46..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/MessageAddedEvent.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-
-/** An event that is broadcast when a message is added to the database. */
-public class MessageAddedEvent extends Event {
-
-	private final Message message;
-	private final ContactId contactId;
-
-	public MessageAddedEvent(Message message, ContactId contactId) {
-		this.message = message;
-		this.contactId = contactId;
-	}
-
-	/** Returns the message that was added. */
-	public Message getMessage() {
-		return message;
-	}
-
-	/** Returns the ID of the group to which the message belongs. */
-	public GroupId getGroupId() {
-		return message.getGroupId();
-	}
-
-	/**
-	 * Returns the ID of the contact from which the message was received, or
-	 * null if the message was locally generated.
-	 */
-	public ContactId getContactId() {
-		return contactId;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/event/MessageRequestedEvent.java b/briar-api/src/org/briarproject/api/event/MessageRequestedEvent.java
deleted file mode 100644
index f2dd84be0b95224eacade2ddffd8e9cb833c881d..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/MessageRequestedEvent.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.contact.ContactId;
-
-/** An event that is broadcast when a message is requested by a contact. */
-public class MessageRequestedEvent extends Event {
-
-	private final ContactId contactId;
-
-	public MessageRequestedEvent(ContactId contactId) {
-		this.contactId = contactId;
-	}
-
-	public ContactId getContactId() {
-		return contactId;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/event/MessageSharedEvent.java b/briar-api/src/org/briarproject/api/event/MessageSharedEvent.java
deleted file mode 100644
index 840c7cc42d6808497f98bea0cbde985e008ccbb5..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/MessageSharedEvent.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.sync.MessageId;
-
-/** An event that is broadcast when a message is shared. */
-public class MessageSharedEvent extends Event {
-
-	private final MessageId messageId;
-
-	public MessageSharedEvent(MessageId message) {
-		this.messageId = message;
-	}
-
-	public MessageId getMessageId() {
-		return messageId;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/event/MessageToAckEvent.java b/briar-api/src/org/briarproject/api/event/MessageToAckEvent.java
deleted file mode 100644
index 8afaed4e749f33e2854560bb69157853f524b7df..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/MessageToAckEvent.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.contact.ContactId;
-
-/**
- * An event that is broadcast when a message is received from or offered by a
- * contact and needs to be acknowledged.
- */
-public class MessageToAckEvent extends Event {
-
-	private final ContactId contactId;
-
-	public MessageToAckEvent(ContactId contactId) {
-		this.contactId = contactId;
-	}
-
-	public ContactId getContactId() {
-		return contactId;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/event/MessagesAckedEvent.java b/briar-api/src/org/briarproject/api/event/MessagesAckedEvent.java
deleted file mode 100644
index fc6a7fca30180a4804f332b3302cbcd4e499db27..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/MessagesAckedEvent.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.sync.MessageId;
-
-import java.util.Collection;
-
-/** An event that is broadcast when messages are acked by a contact. */
-public class MessagesAckedEvent extends Event {
-
-	private final ContactId contactId;
-	private final Collection<MessageId> acked;
-
-	public MessagesAckedEvent(ContactId contactId,
-			Collection<MessageId> acked ) {
-		this.contactId = contactId;
-		this.acked = acked;
-	}
-
-	public ContactId getContactId() {
-		return contactId;
-	}
-
-	public Collection<MessageId> getMessageIds() {
-		return acked;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/event/SettingsUpdatedEvent.java b/briar-api/src/org/briarproject/api/event/SettingsUpdatedEvent.java
deleted file mode 100644
index ef25719aaaebe87e58bc9182bd57ea6e6b9ea6d0..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/SettingsUpdatedEvent.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.briarproject.api.event;
-
-/** An event that is broadcast when one or more settings are updated. */
-public class SettingsUpdatedEvent extends Event {
-
-	private final String namespace;
-
-	public SettingsUpdatedEvent(String namespace) {
-		this.namespace = namespace;
-	}
-
-	public String getNamespace() {
-		return namespace;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/event/ShutdownEvent.java b/briar-api/src/org/briarproject/api/event/ShutdownEvent.java
deleted file mode 100644
index b4d65fbb69e2765ed712063e18829598a1bb0401..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/ShutdownEvent.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.briarproject.api.event;
-
-/** An event that is broadcast when the app is shutting down. */
-public class ShutdownEvent extends Event {
-
-}
diff --git a/briar-api/src/org/briarproject/api/event/TransportDisabledEvent.java b/briar-api/src/org/briarproject/api/event/TransportDisabledEvent.java
deleted file mode 100644
index 1efb575fdfc576f0527982d6b53dba69c0fefb23..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/TransportDisabledEvent.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.TransportId;
-
-/** An event that is broadcast when a transport is disabled. */
-public class TransportDisabledEvent extends Event {
-
-	private final TransportId transportId;
-
-	public TransportDisabledEvent(TransportId transportId) {
-		this.transportId = transportId;
-	}
-
-	public TransportId getTransportId() {
-		return transportId;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/event/TransportEnabledEvent.java b/briar-api/src/org/briarproject/api/event/TransportEnabledEvent.java
deleted file mode 100644
index 7a72d83587250bb21ebe7a90f52365c27330a908..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/TransportEnabledEvent.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.TransportId;
-
-/** An event that is broadcast when a transport is enabled. */
-public class TransportEnabledEvent extends Event {
-
-	private final TransportId transportId;
-
-	public TransportEnabledEvent(TransportId transportId) {
-		this.transportId = transportId;
-	}
-
-	public TransportId getTransportId() {
-		return transportId;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/feed/FeedManager.java b/briar-api/src/org/briarproject/api/feed/FeedManager.java
deleted file mode 100644
index a643cc429b32d0ebf48f2813241e4efa5e6f8557..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/feed/FeedManager.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.briarproject.api.feed;
-
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.GroupId;
-
-import java.io.IOException;
-import java.util.List;
-
-public interface FeedManager {
-
-	/** The unique ID of the RSS feed client. */
-	ClientId CLIENT_ID = new ClientId("org.briarproject.briar.feed");
-
-	/** Adds a RSS feed. */
-	void addFeed(String url, GroupId g) throws DbException, IOException;
-
-	/** Removes a RSS feed. */
-	void removeFeed(String url) throws DbException;
-
-	/** Gets a list of all added RSS feeds */
-	List<Feed> getFeeds() throws DbException;
-
-}
diff --git a/briar-api/src/org/briarproject/api/forum/ForumFactory.java b/briar-api/src/org/briarproject/api/forum/ForumFactory.java
deleted file mode 100644
index ee3b716cc9a2e9b7c57245dc5764f5a57a250732..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/forum/ForumFactory.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.briarproject.api.forum;
-
-public interface ForumFactory {
-
-	/** Creates a forum with the given name. */
-	Forum createForum(String name);
-
-	/** Creates a forum with the given name and salt. */
-	Forum createForum(String name, byte[] salt);
-
-}
diff --git a/briar-api/src/org/briarproject/api/forum/ForumInvitationRequest.java b/briar-api/src/org/briarproject/api/forum/ForumInvitationRequest.java
deleted file mode 100644
index 5d4c8d5542d29e2f2c6397fe71063f8938cee7db..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/forum/ForumInvitationRequest.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.briarproject.api.forum;
-
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.sharing.InvitationRequest;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-
-public class ForumInvitationRequest extends InvitationRequest {
-
-	private final String forumName;
-
-	public ForumInvitationRequest(MessageId id, SessionId sessionId,
-			GroupId groupId, ContactId contactId, String forumName,
-			String message, boolean available, long time, boolean local,
-			boolean sent, boolean seen, boolean read) {
-
-		super(id, sessionId, groupId, contactId, message, available, time,
-				local, sent, seen, read);
-		this.forumName = forumName;
-	}
-
-	public String getForumName() {
-		return forumName;
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/forum/ForumInvitationResponse.java b/briar-api/src/org/briarproject/api/forum/ForumInvitationResponse.java
deleted file mode 100644
index 54969d97cb870fe3947e3e718333f484a9eef856..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/forum/ForumInvitationResponse.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.briarproject.api.forum;
-
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.sharing.InvitationResponse;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.NotNull;
-
-public class ForumInvitationResponse extends InvitationResponse {
-
-	public ForumInvitationResponse(@NotNull MessageId id, SessionId sessionId,
-			GroupId groupId, ContactId contactId, boolean accept, long time,
-			boolean local, boolean sent, boolean seen, boolean read) {
-
-		super(id, sessionId, groupId, contactId, accept, time, local, sent,
-				seen, read);
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/forum/ForumPost.java b/briar-api/src/org/briarproject/api/forum/ForumPost.java
deleted file mode 100644
index 205b4c6ecd53dd13c4ca7e62d38e07ab5b95472b..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/forum/ForumPost.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.briarproject.api.forum;
-
-import org.briarproject.api.clients.ThreadedMessage;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.Nullable;
-
-import javax.annotation.concurrent.Immutable;
-
-@Immutable
-@NotNullByDefault
-public class ForumPost extends ThreadedMessage {
-
-	public ForumPost(Message message, @Nullable MessageId parent,
-			Author author) {
-		super(message, parent, author);
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/forum/ForumPostFactory.java b/briar-api/src/org/briarproject/api/forum/ForumPostFactory.java
deleted file mode 100644
index d5b8d9b35614555678a7c67848cad529e3606fee..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/forum/ForumPostFactory.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.briarproject.api.forum;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.crypto.CryptoExecutor;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-
-import java.security.GeneralSecurityException;
-
-import static org.briarproject.api.forum.ForumManager.CLIENT_ID;
-
-public interface ForumPostFactory {
-
-	String SIGNING_LABEL_POST = CLIENT_ID + "/POST";
-
-	@CryptoExecutor
-	ForumPost createPost(GroupId groupId, long timestamp, MessageId parent,
-			LocalAuthor author, String body)
-			throws FormatException, GeneralSecurityException;
-
-}
diff --git a/briar-api/src/org/briarproject/api/forum/ForumPostHeader.java b/briar-api/src/org/briarproject/api/forum/ForumPostHeader.java
deleted file mode 100644
index b98d23448ce6dd4ec3c43b164082b0e00e7c3d3a..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/forum/ForumPostHeader.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.briarproject.api.forum;
-
-import org.briarproject.api.clients.PostHeader;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.sync.MessageId;
-
-public class ForumPostHeader extends PostHeader {
-
-	public ForumPostHeader(MessageId id, MessageId parentId, long timestamp,
-			Author author, Author.Status authorStatus, boolean read) {
-		super(id, parentId, timestamp, author, authorStatus, read);
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/identity/IdentityManager.java b/briar-api/src/org/briarproject/api/identity/IdentityManager.java
deleted file mode 100644
index 9a27c3e38be419b30ca1f60e85721691254b9308..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/identity/IdentityManager.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.briarproject.api.identity;
-
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.identity.Author.Status;
-
-public interface IdentityManager {
-
-	/** Stores the local pseudonym. */
-	void registerLocalAuthor(LocalAuthor a) throws DbException;
-
-	/** Returns the cached main local identity, non-blocking, or loads it from
-	 * the db, blocking*/
-	LocalAuthor getLocalAuthor() throws DbException;
-
-	/** Returns the cached main local identity, non-blocking, or loads it from
-	 * the db, blocking, within the given Transaction. */
-	LocalAuthor getLocalAuthor(Transaction txn) throws DbException;
-
-	/** Returns the trust-level status of the author */
-	Status getAuthorStatus(AuthorId a) throws DbException;
-
-	/** Returns the trust-level status of the author */
-	Status getAuthorStatus(Transaction txn, AuthorId a) throws DbException;
-
-}
diff --git a/briar-api/src/org/briarproject/api/introduction/IntroductionManager.java b/briar-api/src/org/briarproject/api/introduction/IntroductionManager.java
deleted file mode 100644
index a7e7e3db73dc4c56373b620665340c8216889ce7..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/introduction/IntroductionManager.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.briarproject.api.introduction;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.messaging.ConversationManager.ConversationClient;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.ClientId;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.Collection;
-
-@NotNullByDefault
-public interface IntroductionManager extends ConversationClient {
-
-	/** The unique ID of the introduction client. */
-	ClientId CLIENT_ID = new ClientId("org.briarproject.briar.introduction");
-
-	/**
-	 * sends two initial introduction messages
-	 */
-	void makeIntroduction(Contact c1, Contact c2, @Nullable String msg,
-			final long timestamp)
-			throws DbException, FormatException;
-
-	/**
-	 * Accept an introduction that had been made
-	 */
-	void acceptIntroduction(final ContactId contactId,
-			final SessionId sessionId, final long timestamp)
-			throws DbException, FormatException;
-
-	/**
-	 * Decline an introduction that had been made
-	 */
-	void declineIntroduction(final ContactId contactId,
-			final SessionId sessionId, final long timestamp)
-			throws DbException, FormatException;
-
-	/**
-	 * Get all introduction messages for the contact with this contactId
-	 */
-	Collection<IntroductionMessage> getIntroductionMessages(ContactId contactId)
-			throws DbException;
-
-}
diff --git a/briar-api/src/org/briarproject/api/introduction/IntroductionMessage.java b/briar-api/src/org/briarproject/api/introduction/IntroductionMessage.java
deleted file mode 100644
index e2d968bfa119feb813900876df126b0a84b8f85c..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/introduction/IntroductionMessage.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.briarproject.api.introduction;
-
-import org.briarproject.api.clients.BaseMessageHeader;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.NotNull;
-
-import static org.briarproject.api.introduction.IntroductionConstants.ROLE_INTRODUCER;
-
-public class IntroductionMessage extends BaseMessageHeader {
-
-	private final SessionId sessionId;
-	private final MessageId messageId;
-	private final int role;
-
-	public IntroductionMessage(@NotNull SessionId sessionId,
-			@NotNull MessageId messageId, @NotNull GroupId groupId, int role,
-			long time, boolean local, boolean sent, boolean seen,
-			boolean read) {
-
-		super(messageId, groupId, time, local, read, sent, seen);
-		this.sessionId = sessionId;
-		this.messageId = messageId;
-		this.role = role;
-	}
-
-	@NotNull
-	public SessionId getSessionId() {
-		return sessionId;
-	}
-
-	@NotNull
-	public MessageId getMessageId() {
-		return messageId;
-	}
-
-	public boolean isIntroducer() {
-		return role == ROLE_INTRODUCER;
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/introduction/IntroductionRequest.java b/briar-api/src/org/briarproject/api/introduction/IntroductionRequest.java
deleted file mode 100644
index 4a2910dc238092a2240e513acd16944af07734e1..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/introduction/IntroductionRequest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.briarproject.api.introduction;
-
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-public class IntroductionRequest extends IntroductionResponse {
-
-	private final String message;
-	private final boolean answered, exists, introducesOtherIdentity;
-
-	public IntroductionRequest(@NotNull SessionId sessionId,
-			@NotNull MessageId messageId, @NotNull GroupId groupId, int role,
-			long time, boolean local, boolean sent, boolean seen, boolean read,
-			AuthorId authorId, String name, boolean accepted,
-			@Nullable String message, boolean answered, boolean exists,
-			boolean introducesOtherIdentity) {
-
-		super(sessionId, messageId, groupId, role, time, local, sent, seen,
-				read, authorId, name, accepted);
-
-		this.message = message;
-		this.answered = answered;
-		this.exists = exists;
-		this.introducesOtherIdentity = introducesOtherIdentity;
-	}
-
-	@Nullable
-	public String getMessage() {
-		return message;
-	}
-
-	public boolean wasAnswered() {
-		return answered;
-	}
-
-	public boolean contactExists() {
-		return exists;
-	}
-
-	public boolean doesIntroduceOtherIdentity() {
-		return introducesOtherIdentity;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/introduction/IntroductionResponse.java b/briar-api/src/org/briarproject/api/introduction/IntroductionResponse.java
deleted file mode 100644
index bcb2ce3349e1fd7b02b506d78651156e20d8d753..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/introduction/IntroductionResponse.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.briarproject.api.introduction;
-
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.NotNull;
-
-public class IntroductionResponse extends IntroductionMessage {
-
-	private final AuthorId remoteAuthorId;
-	private final String name;
-	private final boolean accepted;
-
-	public IntroductionResponse(@NotNull SessionId sessionId,
-			@NotNull MessageId messageId, @NotNull GroupId groupId, int role,
-			long time, boolean local, boolean sent, boolean seen, boolean read,
-			AuthorId remoteAuthorId, String name, boolean accepted) {
-
-		super(sessionId, messageId, groupId, role, time, local, sent, seen,
-				read);
-
-		this.remoteAuthorId = remoteAuthorId;
-		this.name = name;
-		this.accepted = accepted;
-	}
-
-	public String getName() {
-		return name;
-	}
-
-	public boolean wasAccepted() {
-		return accepted;
-	}
-
-	public AuthorId getRemoteAuthorId() {
-		return remoteAuthorId;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/invitation/InvitationConstants.java b/briar-api/src/org/briarproject/api/invitation/InvitationConstants.java
deleted file mode 100644
index fda0ab037a8b89d35affd88e2757ff68e6396146..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/invitation/InvitationConstants.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.briarproject.api.invitation;
-
-
-public interface InvitationConstants {
-
-	long CONNECTION_TIMEOUT = 60 * 1000; // Milliseconds
-
-	long CONFIRMATION_TIMEOUT = 60 * 1000; // Milliseconds
-
-	int CODE_BITS = 19; // Codes must fit into six decimal digits
-}
diff --git a/briar-api/src/org/briarproject/api/invitation/InvitationTaskFactory.java b/briar-api/src/org/briarproject/api/invitation/InvitationTaskFactory.java
deleted file mode 100644
index feea2d8126a7d63152655bc486dfd147a1962fe9..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/invitation/InvitationTaskFactory.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.briarproject.api.invitation;
-
-/** Creates tasks for exchanging invitations with remote peers. */
-public interface InvitationTaskFactory {
-
-	/** Creates a task using the local author and invitation codes. */
-	InvitationTask createTask(int localCode, int remoteCode);
-}
diff --git a/briar-api/src/org/briarproject/api/keyagreement/KeyAgreementConstants.java b/briar-api/src/org/briarproject/api/keyagreement/KeyAgreementConstants.java
deleted file mode 100644
index 9961a2b9949a74dde7ec7b6ff1fc3d645518347d..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/keyagreement/KeyAgreementConstants.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.briarproject.api.keyagreement;
-
-
-public interface KeyAgreementConstants {
-
-	/** The current version of the BQP protocol. */
-	byte PROTOCOL_VERSION = 2;
-
-	/** The length of the record header in bytes. */
-	int RECORD_HEADER_LENGTH = 4;
-
-	/** The offset of the payload length in the record header, in bytes. */
-	int RECORD_HEADER_PAYLOAD_LENGTH_OFFSET = 2;
-
-	/** The length of the BQP key commitment in bytes. */
-	int COMMIT_LENGTH = 16;
-
-	long CONNECTION_TIMEOUT = 20 * 1000; // Milliseconds
-
-	/** The transport identifier for Bluetooth. */
-	int TRANSPORT_ID_BLUETOOTH = 0;
-
-	/** The transport identifier for LAN. */
-	int TRANSPORT_ID_LAN = 1;
-}
diff --git a/briar-api/src/org/briarproject/api/keyagreement/KeyAgreementTaskFactory.java b/briar-api/src/org/briarproject/api/keyagreement/KeyAgreementTaskFactory.java
deleted file mode 100644
index f823fcacdbfe44898399ad5851f62a86c542e06e..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/keyagreement/KeyAgreementTaskFactory.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.briarproject.api.keyagreement;
-
-/** Manages tasks for conducting key agreements with remote peers. */
-public interface KeyAgreementTaskFactory {
-
-	/** Gets the current key agreement task. */
-	KeyAgreementTask getTask();
-}
diff --git a/briar-api/src/org/briarproject/api/keyagreement/KeyAgreementTaskId.java b/briar-api/src/org/briarproject/api/keyagreement/KeyAgreementTaskId.java
deleted file mode 100644
index 434f9cb71ac2ea2bd746fd6dd225d294b1f854bb..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/keyagreement/KeyAgreementTaskId.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.briarproject.api.keyagreement;
-
-import org.briarproject.api.UniqueId;
-
-/**
- * Type-safe wrapper for a byte array that uniquely identifies a BQP task.
- */
-public class KeyAgreementTaskId extends UniqueId {
-
-	public KeyAgreementTaskId(byte[] id) {
-		super(id);
-	}
-
-	@Override
-	public boolean equals(Object o) {
-		return o instanceof KeyAgreementTaskId && super.equals(o);
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/keyagreement/PayloadEncoder.java b/briar-api/src/org/briarproject/api/keyagreement/PayloadEncoder.java
deleted file mode 100644
index 31876c10271146fe99de491bd6d3f1053ad769da..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/keyagreement/PayloadEncoder.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.briarproject.api.keyagreement;
-
-public interface PayloadEncoder {
-
-	byte[] encode(Payload p);
-}
diff --git a/briar-api/src/org/briarproject/api/lifecycle/LifecycleManager.java b/briar-api/src/org/briarproject/api/lifecycle/LifecycleManager.java
deleted file mode 100644
index c0795ccdeb35b0c07a6ad87a6364bfda34ea70a9..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/lifecycle/LifecycleManager.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.briarproject.api.lifecycle;
-
-import org.briarproject.api.clients.Client;
-
-import java.util.concurrent.ExecutorService;
-
-import javax.annotation.Nullable;
-
-/**
- * Manages the lifecycle of the app, starting {@link
- * org.briarproject.api.clients.Client Clients}, starting and stopping {@link
- * Service Services}, shutting down {@link java.util.concurrent.ExecutorService
- * ExecutorServices}, and opening and closing the {@link
- * org.briarproject.api.db.DatabaseComponent DatabaseComponent}.
- */
-public interface LifecycleManager {
-
-	/**
-	 * The result of calling {@link LifecycleManager#startServices(String)}.
-	 */
-	enum StartResult {
-		ALREADY_RUNNING, DB_ERROR, SERVICE_ERROR, SUCCESS
-	}
-
-	/**
-	 * Registers a {@link Service} to be started and stopped.
-	 */
-	void registerService(Service s);
-
-	/**
-	 * Registers a {@link org.briarproject.api.clients.Client Client} to be
-	 * started.
-	 */
-	void registerClient(Client c);
-
-	/**
-	 * Registers an {@link java.util.concurrent.ExecutorService ExecutorService}
-	 * to be shut down.
-	 */
-	void registerForShutdown(ExecutorService e);
-
-	/**
-	 * Opens the {@link org.briarproject.api.db.DatabaseComponent
-	 * DatabaseComponent}, creates a local author with the provided nickname,
-	 * and starts any registered {@link org.briarproject.api.clients.Client
-	 * Clients} and {@link Service Services}.
-	 */
-	StartResult startServices(@Nullable String nickname);
-
-	/**
-	 * Stops any registered {@link Service Services}, shuts down any
-	 * registered {@link java.util.concurrent.ExecutorService ExecutorServices},
-	 * and closes the {@link org.briarproject.api.db.DatabaseComponent
-	 * DatabaseComponent}.
-	 */
-	void stopServices();
-
-	/**
-	 * Waits for the {@link org.briarproject.api.db.DatabaseComponent
-	 * DatabaseComponent} to be opened before returning.
-	 */
-	void waitForDatabase() throws InterruptedException;
-
-	/**
-	 * Waits for the {@link org.briarproject.api.db.DatabaseComponent
-	 * DatabaseComponent} to be opened and all registered {@link
-	 * org.briarproject.api.clients.Client Clients} and {@link Service
-	 * Services} to start before returning.
-	 */
-	void waitForStartup() throws InterruptedException;
-
-	/**
-	 * Waits for all registered {@link Service Services} to stop, all
-	 * registered {@link java.util.concurrent.ExecutorService ExecutorServices}
-	 * to shut down, and the {@link org.briarproject.api.db.DatabaseComponent
-	 * DatabaseComponent} to be closed before returning.
-	 */
-	void waitForShutdown() throws InterruptedException;
-}
\ No newline at end of file
diff --git a/briar-api/src/org/briarproject/api/messaging/ConversationManager.java b/briar-api/src/org/briarproject/api/messaging/ConversationManager.java
deleted file mode 100644
index 69ecc3016a7bdddc60f1ff35969f9816bae72f98..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/messaging/ConversationManager.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.briarproject.api.messaging;
-
-import org.briarproject.api.clients.MessageTracker.GroupCount;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-
-@NotNullByDefault
-public interface ConversationManager {
-
-	/**
-	 * Clients that present messages in a private conversation need to
-	 * register themselves here.
-	 */
-	void registerConversationClient(ConversationClient client);
-
-	/**
-	 * Get the unified group count for all private conversation messages.
-	 */
-	GroupCount getGroupCount(ContactId c) throws DbException;
-
-	interface ConversationClient {
-
-		Group getContactGroup(Contact c);
-
-		GroupCount getGroupCount(Transaction txn, ContactId c)
-				throws DbException;
-
-		void setReadFlag(GroupId g, MessageId m, boolean read)
-				throws DbException;
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/messaging/MessagingConstants.java b/briar-api/src/org/briarproject/api/messaging/MessagingConstants.java
deleted file mode 100644
index 98750b5518c58a0b487b62d2a8d416dd7903588c..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/messaging/MessagingConstants.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.briarproject.api.messaging;
-
-import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
-
-public interface MessagingConstants {
-
-	/** The maximum length of a private message's content type in bytes. */
-	int MAX_CONTENT_TYPE_LENGTH = 50;
-
-	/** The maximum length of a private message's body in bytes. */
-	int MAX_PRIVATE_MESSAGE_BODY_LENGTH = MAX_MESSAGE_BODY_LENGTH - 1024;
-}
diff --git a/briar-api/src/org/briarproject/api/messaging/MessagingManager.java b/briar-api/src/org/briarproject/api/messaging/MessagingManager.java
deleted file mode 100644
index 78c7c4a7593d6e8f7135c404ae5bee961198d0b8..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/messaging/MessagingManager.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package org.briarproject.api.messaging;
-
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.messaging.ConversationManager.ConversationClient;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-
-import java.util.Collection;
-
-@NotNullByDefault
-public interface MessagingManager extends ConversationClient {
-
-	/** The unique ID of the messaging client. */
-	ClientId CLIENT_ID = new ClientId("org.briarproject.briar.messaging");
-
-	/** Stores a local private message. */
-	void addLocalMessage(PrivateMessage m) throws DbException;
-
-	/** Returns the ID of the contact with the given private conversation. */
-	ContactId getContactId(GroupId g) throws DbException;
-
-	/** Returns the ID of the private conversation with the given contact. */
-	GroupId getConversationId(ContactId c) throws DbException;
-
-	/**
-	 * Returns the headers of all messages in the given private conversation.
-	 */
-	Collection<PrivateMessageHeader> getMessageHeaders(ContactId c)
-			throws DbException;
-
-	/** Returns the body of the private message with the given ID. */
-	String getMessageBody(MessageId m) throws DbException;
-
-}
diff --git a/briar-api/src/org/briarproject/api/messaging/PrivateMessageFactory.java b/briar-api/src/org/briarproject/api/messaging/PrivateMessageFactory.java
deleted file mode 100644
index 0191ce61a67d74d8c1137c403a7373e78409218f..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/messaging/PrivateMessageFactory.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.briarproject.api.messaging;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-
-@NotNullByDefault
-public interface PrivateMessageFactory {
-
-	PrivateMessage createPrivateMessage(GroupId groupId, long timestamp,
-			String body) throws FormatException;
-
-}
diff --git a/briar-api/src/org/briarproject/api/messaging/PrivateMessageHeader.java b/briar-api/src/org/briarproject/api/messaging/PrivateMessageHeader.java
deleted file mode 100644
index 706e453732f214f7a1b9c2eb84dbafe1533d6c38..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/messaging/PrivateMessageHeader.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.briarproject.api.messaging;
-
-import org.briarproject.api.clients.BaseMessageHeader;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-
-public class PrivateMessageHeader extends BaseMessageHeader {
-
-	public PrivateMessageHeader(MessageId id, GroupId groupId, long timestamp,
-			boolean local, boolean read, boolean sent, boolean seen) {
-
-		super(id, groupId, timestamp, local, read, sent, seen);
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/plugins/PluginConfig.java b/briar-api/src/org/briarproject/api/plugins/PluginConfig.java
deleted file mode 100644
index 7fda14476e8b3c900d1755e1bf948a5420fce46b..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/plugins/PluginConfig.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.briarproject.api.plugins;
-
-import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
-import org.briarproject.api.plugins.simplex.SimplexPluginFactory;
-
-import java.util.Collection;
-
-public interface PluginConfig {
-
-	Collection<DuplexPluginFactory> getDuplexFactories();
-
-	Collection<SimplexPluginFactory> getSimplexFactories();
-}
diff --git a/briar-api/src/org/briarproject/api/plugins/duplex/DuplexTransportConnection.java b/briar-api/src/org/briarproject/api/plugins/duplex/DuplexTransportConnection.java
deleted file mode 100644
index 8440fe4add593c36820d53262e8aa712f8260ce7..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/plugins/duplex/DuplexTransportConnection.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.briarproject.api.plugins.duplex;
-
-import org.briarproject.api.plugins.TransportConnectionReader;
-import org.briarproject.api.plugins.TransportConnectionWriter;
-
-/**
- * An interface for reading and writing data over a duplex transport. The
- * connection is not responsible for encrypting/decrypting or authenticating
- * the data.
- */
-public interface DuplexTransportConnection {
-
-	/** Returns a {@link org.briarproject.api.plugins.TransportConnectionReader
-	 * TransportConnectionReader} for reading from the connection. */
-	TransportConnectionReader getReader();
-
-	/** Returns a {@link org.briarproject.api.plugins.TransportConnectionWriter
-	 * TransportConnectionWriter} for writing to the connection. */
-	TransportConnectionWriter getWriter();
-}
diff --git a/briar-api/src/org/briarproject/api/plugins/simplex/SimplexPluginCallback.java b/briar-api/src/org/briarproject/api/plugins/simplex/SimplexPluginCallback.java
deleted file mode 100644
index 51f15da58b5f594d9b16f0116d66df3cc511c9c5..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/plugins/simplex/SimplexPluginCallback.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.briarproject.api.plugins.simplex;
-
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.plugins.PluginCallback;
-import org.briarproject.api.plugins.TransportConnectionReader;
-import org.briarproject.api.plugins.TransportConnectionWriter;
-
-/**
- * An interface for handling readers and writers created by a simplex transport
- * plugin.
- */
-public interface SimplexPluginCallback extends PluginCallback {
-
-	void readerCreated(TransportConnectionReader r);
-
-	void writerCreated(ContactId c, TransportConnectionWriter w);
-}
diff --git a/briar-api/src/org/briarproject/api/privategroup/GroupMessage.java b/briar-api/src/org/briarproject/api/privategroup/GroupMessage.java
deleted file mode 100644
index 513f80c7be3214981d9f54f034b997851273b5ee..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/privategroup/GroupMessage.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.briarproject.api.privategroup;
-
-import org.briarproject.api.clients.ThreadedMessage;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.Nullable;
-
-import javax.annotation.concurrent.Immutable;
-
-@Immutable
-@NotNullByDefault
-public class GroupMessage extends ThreadedMessage {
-
-	public GroupMessage(Message message, @Nullable MessageId parent,
-			Author member) {
-		super(message, parent, member);
-	}
-
-	public Author getMember() {
-		return super.getAuthor();
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/privategroup/GroupMessageFactory.java b/briar-api/src/org/briarproject/api/privategroup/GroupMessageFactory.java
deleted file mode 100644
index 220e958fc07f3339e2a13c804a0f3daa794e65d5..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/privategroup/GroupMessageFactory.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package org.briarproject.api.privategroup;
-
-import org.briarproject.api.crypto.CryptoExecutor;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.Nullable;
-
-import static org.briarproject.api.privategroup.PrivateGroupManager.CLIENT_ID;
-
-@NotNullByDefault
-public interface GroupMessageFactory {
-
-	String SIGNING_LABEL_JOIN = CLIENT_ID + "/JOIN";
-	String SIGNING_LABEL_POST = CLIENT_ID + "/POST";
-
-	/**
-	 * Creates a join announcement message for the creator of a group.
-	 *
-	 * @param groupId     The ID of the Group that is being joined
-	 * @param timestamp   Must be greater than the timestamp of the invitation message
-	 * @param creator     The creator's LocalAuthor
-	 */
-	@CryptoExecutor
-	GroupMessage createJoinMessage(GroupId groupId, long timestamp,
-			LocalAuthor creator);
-
-	/**
-	 * Creates a join announcement message for a joining member.
-	 *
-	 * @param groupId          The ID of the Group that is being joined
-	 * @param timestamp        Must be greater than the timestamp of the
-	 *                         invitation message
-	 * @param member           The member's LocalAuthor
-	 * @param inviteTimestamp  The timestamp of the group invitation message
-	 * @param creatorSignature The creator's signature from the group invitation
-	 */
-	@CryptoExecutor
-	GroupMessage createJoinMessage(GroupId groupId, long timestamp,
-			LocalAuthor member, long inviteTimestamp, byte[] creatorSignature);
-
-	/**
-	 * Creates a group message
-	 *
-	 * @param groupId       The ID of the Group that is posted in
-	 * @param timestamp     Must be greater than the timestamps of the parentId
-	 *                      post, if any, and the member's previous message
-	 * @param parentId      The ID of the message that is replied to
-	 * @param author        The author of the group message
-	 * @param body          The content of the group message
-	 * @param previousMsgId The ID of the author's previous message
-	 *                      in this group
-	 */
-	@CryptoExecutor
-	GroupMessage createGroupMessage(GroupId groupId, long timestamp,
-			@Nullable MessageId parentId, LocalAuthor author, String body,
-			MessageId previousMsgId);
-
-}
diff --git a/briar-api/src/org/briarproject/api/properties/TransportPropertyConstants.java b/briar-api/src/org/briarproject/api/properties/TransportPropertyConstants.java
deleted file mode 100644
index fd0171094b7c6eca5140cd6937467625fb09f165..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/properties/TransportPropertyConstants.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.briarproject.api.properties;
-
-public interface TransportPropertyConstants {
-
-	/** The maximum number of properties per transport. */
-	int MAX_PROPERTIES_PER_TRANSPORT = 100;
-
-	/** The maximum length of a property's key or value in UTF-8 bytes. */
-	int MAX_PROPERTY_LENGTH = 100;
-}
diff --git a/briar-api/src/org/briarproject/api/reliability/ReadHandler.java b/briar-api/src/org/briarproject/api/reliability/ReadHandler.java
deleted file mode 100644
index 44b7b3344c2c86b54c595a04afefbc0c899f35b7..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/reliability/ReadHandler.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.briarproject.api.reliability;
-
-import java.io.IOException;
-
-public interface ReadHandler {
-
-	void handleRead(byte[] b) throws IOException;
-}
diff --git a/briar-api/src/org/briarproject/api/reliability/ReliabilityLayerFactory.java b/briar-api/src/org/briarproject/api/reliability/ReliabilityLayerFactory.java
deleted file mode 100644
index f98e87f13a5483d6859338cc461c0a472249f67d..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/reliability/ReliabilityLayerFactory.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.briarproject.api.reliability;
-
-public interface ReliabilityLayerFactory {
-
-	/** Returns a reliability layer that writes to the given lower layer. */
-	ReliabilityLayer createReliabilityLayer(WriteHandler writeHandler);
-}
diff --git a/briar-api/src/org/briarproject/api/reliability/WriteHandler.java b/briar-api/src/org/briarproject/api/reliability/WriteHandler.java
deleted file mode 100644
index 22bdbe0d99eeb2612fd34c378fb98c4136d211fb..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/reliability/WriteHandler.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.briarproject.api.reliability;
-
-import java.io.IOException;
-
-public interface WriteHandler {
-
-	void handleWrite(byte[] b) throws IOException;
-}
diff --git a/briar-api/src/org/briarproject/api/reporting/DevConfig.java b/briar-api/src/org/briarproject/api/reporting/DevConfig.java
deleted file mode 100644
index b6f4ccbf898a8795e95cd8d93065ad317ab026cc..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/reporting/DevConfig.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.briarproject.api.reporting;
-
-import org.briarproject.api.crypto.PublicKey;
-
-public interface DevConfig {
-
-	PublicKey getDevPublicKey();
-
-	String getDevOnionAddress();
-}
diff --git a/briar-api/src/org/briarproject/api/reporting/DevReporter.java b/briar-api/src/org/briarproject/api/reporting/DevReporter.java
deleted file mode 100644
index dfcbb9c1a96ff7bfe08fb6f0b5a80655981e94ee..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/reporting/DevReporter.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.briarproject.api.reporting;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-
-/**
- * A task for reporting back to the developers.
- */
-public interface DevReporter {
-
-	/**
-	 * Store a report encrypted on-disk to be sent later.
-	 *
-	 * @param reportDir the directory where reports are stored.
-	 * @param report    the report in the form expected by the server.
-	 * @throws FileNotFoundException if the report could not be written.
-	 */
-	void encryptReportToFile(File reportDir, String filename,
-			String report) throws FileNotFoundException;
-
-	/**
-	 * Send reports previously stored on-disk.
-	 *
-	 * @param reportDir the directory where reports are stored.
-	 */
-	void sendReports(File reportDir);
-}
diff --git a/briar-api/src/org/briarproject/api/settings/Settings.java b/briar-api/src/org/briarproject/api/settings/Settings.java
deleted file mode 100644
index 43fe1e56663002948000023d058e5600bab179c7..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/settings/Settings.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.briarproject.api.settings;
-
-import org.briarproject.api.StringMap;
-
-public class Settings extends StringMap {
-
-	private static final long serialVersionUID = 8439364293077111359L;
-}
diff --git a/briar-api/src/org/briarproject/api/settings/SettingsManager.java b/briar-api/src/org/briarproject/api/settings/SettingsManager.java
deleted file mode 100644
index 05166529b71984d59b83e488ab51db4a2fc40ee4..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/settings/SettingsManager.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.briarproject.api.settings;
-
-import org.briarproject.api.db.DbException;
-
-public interface SettingsManager {
-
-	/** Returns all settings in the given namespace. */
-	Settings getSettings(String namespace) throws DbException;
-
-	/**
-	 * Merges the given settings with the existing settings in the given
-	 * namespace.
-	 */
-	void mergeSettings(Settings s, String namespace) throws DbException;
-}
diff --git a/briar-api/src/org/briarproject/api/sharing/InvitationFactory.java b/briar-api/src/org/briarproject/api/sharing/InvitationFactory.java
deleted file mode 100644
index 1f8548d38433666d25719ce8ed3a799eabe19ba9..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/sharing/InvitationFactory.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.briarproject.api.sharing;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.sync.GroupId;
-
-public interface InvitationFactory<I extends SharingMessage.Invitation> {
-
-	I build(GroupId groupId, BdfDictionary d) throws FormatException;
-}
diff --git a/briar-api/src/org/briarproject/api/sharing/InvitationMessage.java b/briar-api/src/org/briarproject/api/sharing/InvitationMessage.java
deleted file mode 100644
index 4e6e4858f0a370f530b50f896e17ec3cafbaf8cb..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/sharing/InvitationMessage.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.briarproject.api.sharing;
-
-import org.briarproject.api.clients.BaseMessageHeader;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.NotNull;
-
-public abstract class InvitationMessage extends BaseMessageHeader {
-
-	private final SessionId sessionId;
-	private final ContactId contactId;
-
-	public InvitationMessage(@NotNull MessageId id,
-			@NotNull SessionId sessionId, @NotNull GroupId groupId,
-			@NotNull ContactId contactId, long time, boolean local,
-			boolean sent, boolean seen, boolean read) {
-
-		super(id, groupId, time, local, read, sent, seen);
-		this.sessionId = sessionId;
-		this.contactId = contactId;
-	}
-
-	@NotNull
-	public SessionId getSessionId() {
-		return sessionId;
-	}
-
-	@NotNull
-	public ContactId getContactId() {
-		return contactId;
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/sharing/InvitationRequest.java b/briar-api/src/org/briarproject/api/sharing/InvitationRequest.java
deleted file mode 100644
index 23ed952b96d43829fa72a5149cec284bc6526e8d..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/sharing/InvitationRequest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.briarproject.api.sharing;
-
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-public abstract class InvitationRequest extends InvitationMessage {
-
-	private final String message;
-	private final boolean available;
-
-	public InvitationRequest(@NotNull MessageId id,
-			@NotNull SessionId sessionId, @NotNull GroupId groupId,
-			@NotNull ContactId contactId, @Nullable String message,
-			boolean available, long time, boolean local, boolean sent,
-			boolean seen, boolean read) {
-
-		super(id, sessionId, groupId, contactId, time, local, sent, seen, read);
-		this.message = message;
-		this.available = available;
-	}
-
-	@Nullable
-	public String getMessage() {
-		return message;
-	}
-
-	public boolean isAvailable() {
-		return available;
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/sharing/InvitationResponse.java b/briar-api/src/org/briarproject/api/sharing/InvitationResponse.java
deleted file mode 100644
index 0e2d24ee65f00e1ca5f76a1108138d5c0ed9d69c..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/sharing/InvitationResponse.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.briarproject.api.sharing;
-
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.NotNull;
-
-public abstract class InvitationResponse extends InvitationMessage {
-
-	private final boolean accept;
-
-	public InvitationResponse(@NotNull MessageId id, SessionId sessionId,
-			GroupId groupId, ContactId contactId, boolean accept, long time,
-			boolean local, boolean sent, boolean seen, boolean read) {
-
-		super(id, sessionId, groupId, contactId, time, local, sent, seen, read);
-		this.accept = accept;
-	}
-
-	public boolean wasAccepted() {
-		return accept;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/sharing/Shareable.java b/briar-api/src/org/briarproject/api/sharing/Shareable.java
deleted file mode 100644
index 144b06dde1db37991a3258b4970d91dfbbfa7443..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/sharing/Shareable.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.briarproject.api.sharing;
-
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-
-public interface Shareable {
-
-	GroupId getId();
-
-	Group getGroup();
-
-	String getName();
-
-}
diff --git a/briar-api/src/org/briarproject/api/sync/GroupFactory.java b/briar-api/src/org/briarproject/api/sync/GroupFactory.java
deleted file mode 100644
index 02187cb8f58155356797569c4539bf57708ce099..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/sync/GroupFactory.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.briarproject.api.sync;
-
-public interface GroupFactory {
-
-	/** Creates a group with the given client ID and descriptor. */
-	Group createGroup(ClientId c, byte[] descriptor);
-}
diff --git a/briar-api/src/org/briarproject/api/sync/PacketReaderFactory.java b/briar-api/src/org/briarproject/api/sync/PacketReaderFactory.java
deleted file mode 100644
index 5e48269d2ff636e6da6c77ffb02914c3008226d0..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/sync/PacketReaderFactory.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.briarproject.api.sync;
-
-import java.io.InputStream;
-
-public interface PacketReaderFactory {
-
-	PacketReader createPacketReader(InputStream in);
-}
diff --git a/briar-api/src/org/briarproject/api/sync/PacketWriterFactory.java b/briar-api/src/org/briarproject/api/sync/PacketWriterFactory.java
deleted file mode 100644
index 51befe31fe53715de89149f4e9260f5579254236..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/sync/PacketWriterFactory.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.briarproject.api.sync;
-
-import java.io.OutputStream;
-
-public interface PacketWriterFactory {
-
-	PacketWriter createPacketWriter(OutputStream out);
-}
diff --git a/briar-api/src/org/briarproject/api/sync/Request.java b/briar-api/src/org/briarproject/api/sync/Request.java
deleted file mode 100644
index af6d2321f8b1f7dcafe8c77dfc54197adc32209d..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/sync/Request.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.briarproject.api.sync;
-
-import java.util.Collection;
-
-/**
- * A packet requesting one or more {@link Message Messages} from the recipient.
- */
-public class Request {
-
-	private final Collection<org.briarproject.api.sync.MessageId> requested;
-
-	public Request(Collection<org.briarproject.api.sync.MessageId> requested) {
-		this.requested = requested;
-	}
-
-	/** Returns the identifiers of the requested messages. */
-	public Collection<org.briarproject.api.sync.MessageId> getMessageIds() {
-		return requested;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/sync/SyncConstants.java b/briar-api/src/org/briarproject/api/sync/SyncConstants.java
deleted file mode 100644
index 78229ef2020bc757ce564f59c846b75ab41320dd..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/sync/SyncConstants.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.briarproject.api.sync;
-
-import org.briarproject.api.UniqueId;
-
-public interface SyncConstants {
-
-	/** The current version of the sync protocol. */
-	byte PROTOCOL_VERSION = 0;
-
-	/** The length of the packet header in bytes. */
-	int PACKET_HEADER_LENGTH = 4;
-
-	/** The maximum length of the packet payload in bytes. */
-	int MAX_PACKET_PAYLOAD_LENGTH = 32 * 1024; // 32 KiB
-
-	/** The maximum length of a message in bytes. */
-	int MAX_MESSAGE_LENGTH = MAX_PACKET_PAYLOAD_LENGTH - PACKET_HEADER_LENGTH;
-
-	/** The length of the message header in bytes. */
-	int MESSAGE_HEADER_LENGTH = UniqueId.LENGTH + 8;
-
-	/** The maximum length of a message body in bytes. */
-	int MAX_MESSAGE_BODY_LENGTH = MAX_MESSAGE_LENGTH - MESSAGE_HEADER_LENGTH;
-
-	/** The maximum number of message IDs in an ack, offer or request packet. */
-	int MAX_MESSAGE_IDS = MAX_PACKET_PAYLOAD_LENGTH / UniqueId.LENGTH;
-}
diff --git a/briar-api/src/org/briarproject/api/transport/StreamReaderFactory.java b/briar-api/src/org/briarproject/api/transport/StreamReaderFactory.java
deleted file mode 100644
index 8e8544b525dac332e0a9ec7b69c30fad7830ad99..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/transport/StreamReaderFactory.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.briarproject.api.transport;
-
-import java.io.InputStream;
-
-import org.briarproject.api.crypto.SecretKey;
-
-public interface StreamReaderFactory {
-
-	/**
-	 * Creates an {@link java.io.InputStream InputStream} for reading from a
-	 * transport stream.
-	 */
-	InputStream createStreamReader(InputStream in, StreamContext ctx);
-
-	/**
-	 * Creates an {@link java.io.InputStream InputStream} for reading from an
-	 * invitation stream.
-	 */
-	InputStream createInvitationStreamReader(InputStream in,
-			SecretKey headerKey);
-}
diff --git a/briar-api/src/org/briarproject/api/transport/StreamWriterFactory.java b/briar-api/src/org/briarproject/api/transport/StreamWriterFactory.java
deleted file mode 100644
index 7a23fa6e9a9809744ea3f9c5f4b5f061509d6c0f..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/transport/StreamWriterFactory.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.briarproject.api.transport;
-
-import java.io.OutputStream;
-
-import org.briarproject.api.crypto.SecretKey;
-
-public interface StreamWriterFactory {
-
-	/**
-	 * Creates an {@link java.io.OutputStream OutputStream} for writing to a
-	 * transport stream
-	 */
-	OutputStream createStreamWriter(OutputStream out, StreamContext ctx);
-
-	/**
-	 * Creates an {@link java.io.OutputStream OutputStream} for writing to an
-	 * invitation stream.
-	 */
-	OutputStream createInvitationStreamWriter(OutputStream out,
-			SecretKey headerKey);
-}
diff --git a/briar-core/build.gradle b/briar-core/build.gradle
index 9ffd0987f5189ed0d0a45e5cc781933b3866c93a..f4b3040f1764e782ccd8b5ebf5716968374ae866 100644
--- a/briar-core/build.gradle
+++ b/briar-core/build.gradle
@@ -7,30 +7,21 @@ apply plugin: 'witness'
 dependencies {
 	compile project(':briar-api')
 	compile fileTree(dir: 'libs', include: '*.jar')
-	compile "com.madgag.spongycastle:core:1.54.0.0"
-	compile "com.h2database:h2:1.4.190"
 	compile 'com.rometools:rome:1.7.0'
 	compile 'org.jdom:jdom2:2.0.6'
-	compile 'org.slf4j:slf4j-api:1.7.21'
 	compile 'com.squareup.okhttp3:okhttp:3.3.1'
 	compile 'org.jsoup:jsoup:1.9.2'
 }
 
 dependencyVerification {
 	verify = [
-			'com.madgag.spongycastle:core:1e7fa4b19ccccd1011364ab838d0b4702470c178bbbdd94c5c90b2d4d749ea1e',
-			'com.h2database:h2:23ba495a07bbbb3bd6c3084d10a96dad7a23741b8b6d64b213459a784195a98c',
 			'com.rometools:rome:3096b7a36c0e54f59b8193c431d28494c6bfa85c72ef3c5f341cdf09eae815e6',
 			'org.jdom:jdom2:1345f11ba606d15603d6740551a8c21947c0215640770ec67271fe78bea97cf5',
-			'org.slf4j:slf4j-api:1d5aeb6bd98b0fdd151269eae941c05f6468a791ea0f1e68d8e7fe518af3e7df',
 			'com.squareup.okhttp3:okhttp:a47f4efa166551cd5acc04f1071d82dafbf05638c21f9ca13068bc6633e3bff6',
 			'com.rometools:rome-utils:2be18a1edc601c31fe49c2000bb5484dd75182309270c2a2561d71888d81587a',
 			'com.squareup.okio:okio:5cfea5afe6c6e441a4dbf6053a07a733b1249d1009382eb44ac2255ccedd0c15',
 			'org.jsoup:jsoup:9c1885f1b182256e06f1e30b8451caed0c0dee96299d6348f968d18b54d0a46a',
+			'org.slf4j:slf4j-api:e56288031f5e60652c06e7bb6e9fa410a61231ab54890f7b708fc6adc4107c5b'
 	]
 }
 
-sourceSets {
-	main.java.srcDirs = ['src']
-	main.resources.srcDirs = ['src']
-}
diff --git a/briar-core/src/main/java/org/briarproject/briar/BriarCoreEagerSingletons.java b/briar-core/src/main/java/org/briarproject/briar/BriarCoreEagerSingletons.java
new file mode 100644
index 0000000000000000000000000000000000000000..b8980daa2d009862926b623791b1094a69556327
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/BriarCoreEagerSingletons.java
@@ -0,0 +1,29 @@
+package org.briarproject.briar;
+
+import org.briarproject.briar.blog.BlogModule;
+import org.briarproject.briar.feed.FeedModule;
+import org.briarproject.briar.forum.ForumModule;
+import org.briarproject.briar.introduction.IntroductionModule;
+import org.briarproject.briar.messaging.MessagingModule;
+import org.briarproject.briar.privategroup.PrivateGroupModule;
+import org.briarproject.briar.privategroup.invitation.GroupInvitationModule;
+import org.briarproject.briar.sharing.SharingModule;
+
+public interface BriarCoreEagerSingletons {
+
+	void inject(BlogModule.EagerSingletons init);
+
+	void inject(FeedModule.EagerSingletons init);
+
+	void inject(ForumModule.EagerSingletons init);
+
+	void inject(GroupInvitationModule.EagerSingletons init);
+
+	void inject(IntroductionModule.EagerSingletons init);
+
+	void inject(MessagingModule.EagerSingletons init);
+
+	void inject(PrivateGroupModule.EagerSingletons init);
+
+	void inject(SharingModule.EagerSingletons init);
+}
diff --git a/briar-core/src/main/java/org/briarproject/briar/BriarCoreModule.java b/briar-core/src/main/java/org/briarproject/briar/BriarCoreModule.java
new file mode 100644
index 0000000000000000000000000000000000000000..a9a7bfc506e344f4e400919327e29083d4e96c53
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/BriarCoreModule.java
@@ -0,0 +1,38 @@
+package org.briarproject.briar;
+
+import org.briarproject.briar.blog.BlogModule;
+import org.briarproject.briar.client.BriarClientModule;
+import org.briarproject.briar.feed.FeedModule;
+import org.briarproject.briar.forum.ForumModule;
+import org.briarproject.briar.introduction.IntroductionModule;
+import org.briarproject.briar.messaging.MessagingModule;
+import org.briarproject.briar.privategroup.PrivateGroupModule;
+import org.briarproject.briar.privategroup.invitation.GroupInvitationModule;
+import org.briarproject.briar.sharing.SharingModule;
+
+import dagger.Module;
+
+@Module(includes = {
+		BlogModule.class,
+		BriarClientModule.class,
+		FeedModule.class,
+		ForumModule.class,
+		GroupInvitationModule.class,
+		IntroductionModule.class,
+		MessagingModule.class,
+		PrivateGroupModule.class,
+		SharingModule.class
+})
+public class BriarCoreModule {
+
+	public static void initEagerSingletons(BriarCoreEagerSingletons c) {
+		c.inject(new BlogModule.EagerSingletons());
+		c.inject(new FeedModule.EagerSingletons());
+		c.inject(new ForumModule.EagerSingletons());
+		c.inject(new GroupInvitationModule.EagerSingletons());
+		c.inject(new MessagingModule.EagerSingletons());
+		c.inject(new PrivateGroupModule.EagerSingletons());
+		c.inject(new SharingModule.EagerSingletons());
+		c.inject(new IntroductionModule.EagerSingletons());
+	}
+}
diff --git a/briar-core/src/org/briarproject/blogs/BlogFactoryImpl.java b/briar-core/src/main/java/org/briarproject/briar/blog/BlogFactoryImpl.java
similarity index 60%
rename from briar-core/src/org/briarproject/blogs/BlogFactoryImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/blog/BlogFactoryImpl.java
index aed543f5334dc5f112ac24185d2c7d428f80ecb8..26c1eb108c0f9e75301e3e2a8f854adb6bc91660 100644
--- a/briar-core/src/org/briarproject/blogs/BlogFactoryImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/blog/BlogFactoryImpl.java
@@ -1,19 +1,20 @@
-package org.briarproject.blogs;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.blogs.Blog;
-import org.briarproject.api.blogs.BlogFactory;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupFactory;
-import org.jetbrains.annotations.NotNull;
-
+package org.briarproject.briar.blog;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupFactory;
+import org.briarproject.briar.api.blog.Blog;
+import org.briarproject.briar.api.blog.BlogFactory;
+
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
+@Immutable
 @NotNullByDefault
 class BlogFactoryImpl implements BlogFactory {
 
@@ -47,7 +48,7 @@ class BlogFactoryImpl implements BlogFactory {
 	}
 
 	@Override
-	public Blog parseBlog(@NotNull Group g) throws FormatException {
+	public Blog parseBlog(Group g) throws FormatException {
 		byte[] descriptor = g.getDescriptor();
 		// Author Name, Public Key
 		BdfList blog = clientHelper.toList(descriptor);
diff --git a/briar-core/src/org/briarproject/blogs/BlogManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/blog/BlogManagerImpl.java
similarity index 82%
rename from briar-core/src/org/briarproject/blogs/BlogManagerImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/blog/BlogManagerImpl.java
index ecc5991fa3001a0fb39fad70d9f380449082f18d..deab371d7948475bff8492596863ac849f924656 100644
--- a/briar-core/src/org/briarproject/blogs/BlogManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/blog/BlogManagerImpl.java
@@ -1,38 +1,37 @@
-package org.briarproject.blogs;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.blogs.Blog;
-import org.briarproject.api.blogs.BlogCommentHeader;
-import org.briarproject.api.blogs.BlogFactory;
-import org.briarproject.api.blogs.BlogManager;
-import org.briarproject.api.blogs.BlogPost;
-import org.briarproject.api.blogs.BlogPostFactory;
-import org.briarproject.api.blogs.BlogPostHeader;
-import org.briarproject.api.blogs.MessageType;
-import org.briarproject.api.clients.Client;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataParser;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.BlogPostAddedEvent;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.Author.Status;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.clients.BdfIncomingMessageHook;
-import org.jetbrains.annotations.Nullable;
+package org.briarproject.briar.blog;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataParser;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Client;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.blog.Blog;
+import org.briarproject.briar.api.blog.BlogCommentHeader;
+import org.briarproject.briar.api.blog.BlogFactory;
+import org.briarproject.briar.api.blog.BlogManager;
+import org.briarproject.briar.api.blog.BlogPost;
+import org.briarproject.briar.api.blog.BlogPostFactory;
+import org.briarproject.briar.api.blog.BlogPostHeader;
+import org.briarproject.briar.api.blog.MessageType;
+import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
+import org.briarproject.briar.client.BdfIncomingMessageHook;
 
 import java.security.GeneralSecurityException;
 import java.util.ArrayList;
@@ -47,28 +46,29 @@ import java.util.Map.Entry;
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
-import static org.briarproject.api.blogs.BlogConstants.KEY_AUTHOR;
-import static org.briarproject.api.blogs.BlogConstants.KEY_AUTHOR_ID;
-import static org.briarproject.api.blogs.BlogConstants.KEY_AUTHOR_NAME;
-import static org.briarproject.api.blogs.BlogConstants.KEY_COMMENT;
-import static org.briarproject.api.blogs.BlogConstants.KEY_ORIGINAL_MSG_ID;
-import static org.briarproject.api.blogs.BlogConstants.KEY_ORIGINAL_PARENT_MSG_ID;
-import static org.briarproject.api.blogs.BlogConstants.KEY_PARENT_MSG_ID;
-import static org.briarproject.api.blogs.BlogConstants.KEY_PUBLIC_KEY;
-import static org.briarproject.api.blogs.BlogConstants.KEY_READ;
-import static org.briarproject.api.blogs.BlogConstants.KEY_TIMESTAMP;
-import static org.briarproject.api.blogs.BlogConstants.KEY_TIME_RECEIVED;
-import static org.briarproject.api.blogs.BlogConstants.KEY_TYPE;
-import static org.briarproject.api.blogs.MessageType.COMMENT;
-import static org.briarproject.api.blogs.MessageType.POST;
-import static org.briarproject.api.blogs.MessageType.WRAPPED_COMMENT;
-import static org.briarproject.api.blogs.MessageType.WRAPPED_POST;
-import static org.briarproject.api.contact.ContactManager.AddContactHook;
-import static org.briarproject.api.contact.ContactManager.RemoveContactHook;
-import static org.briarproject.api.sync.Group.Visibility.SHARED;
-import static org.briarproject.blogs.BlogPostValidator.authorToBdfDictionary;
+import static org.briarproject.bramble.api.contact.ContactManager.AddContactHook;
+import static org.briarproject.bramble.api.contact.ContactManager.RemoveContactHook;
+import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_ID;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_NAME;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_COMMENT;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_MSG_ID;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_PARENT_MSG_ID;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_PARENT_MSG_ID;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_PUBLIC_KEY;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_READ;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_TIMESTAMP;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_TIME_RECEIVED;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_TYPE;
+import static org.briarproject.briar.api.blog.MessageType.COMMENT;
+import static org.briarproject.briar.api.blog.MessageType.POST;
+import static org.briarproject.briar.api.blog.MessageType.WRAPPED_COMMENT;
+import static org.briarproject.briar.api.blog.MessageType.WRAPPED_POST;
+import static org.briarproject.briar.blog.BlogPostValidator.authorToBdfDictionary;
 
 @NotNullByDefault
 class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
@@ -135,8 +135,10 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
 
 			// check that original message IDs match
 			if (type == COMMENT) {
+				MessageId parentId = h.getParentId();
+				if (parentId == null) throw new FormatException();
 				BdfDictionary d = clientHelper
-						.getMessageMetadataAsDictionary(txn, h.getParentId());
+						.getMessageMetadataAsDictionary(txn, parentId);
 				byte[] original1 = d.getRaw(KEY_ORIGINAL_MSG_ID);
 				byte[] original2 = meta.getRaw(KEY_ORIGINAL_PARENT_MSG_ID);
 				if (!Arrays.equals(original1, original2)) {
@@ -307,6 +309,7 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
 		// Get body of message to be wrapped
 		BdfList body =
 				clientHelper.getMessageAsList(txn, pOriginalHeader.getId());
+		if (body == null) throw new DbException();
 		long wTimestamp = pOriginalHeader.getTimestamp();
 		Message wMessage;
 
@@ -330,7 +333,7 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
 					.wrapComment(groupId, wDescriptor, wTimestamp,
 							body, wrappedId);
 			meta.put(KEY_TYPE, WRAPPED_COMMENT.getInt());
-			if(wComment.getComment() != null)
+			if (wComment.getComment() != null)
 				meta.put(KEY_COMMENT, wComment.getComment());
 			meta.put(KEY_PARENT_MSG_ID, wrappedId);
 		} else if (type == WRAPPED_POST) {
@@ -345,7 +348,7 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
 			wMessage = blogPostFactory
 					.rewrapWrappedComment(groupId, body, wrappedId);
 			meta.put(KEY_TYPE, WRAPPED_COMMENT.getInt());
-			if(wComment.getComment() != null)
+			if (wComment.getComment() != null)
 				meta.put(KEY_COMMENT, wComment.getComment());
 			meta.put(KEY_PARENT_MSG_ID, wrappedId);
 		} else {
@@ -353,7 +356,8 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
 					"Unknown Message Type: " + type);
 		}
 		meta.put(KEY_ORIGINAL_MSG_ID, pOriginalHeader.getId());
-		meta.put(KEY_AUTHOR, authorToBdfDictionary(pOriginalHeader.getAuthor()));
+		meta.put(KEY_AUTHOR,
+				authorToBdfDictionary(pOriginalHeader.getAuthor()));
 		meta.put(KEY_TIMESTAMP, pOriginalHeader.getTimestamp());
 		meta.put(KEY_TIME_RECEIVED, pOriginalHeader.getTimeReceived());
 
diff --git a/briar-core/src/org/briarproject/blogs/BlogsModule.java b/briar-core/src/main/java/org/briarproject/briar/blog/BlogModule.java
similarity index 66%
rename from briar-core/src/org/briarproject/blogs/BlogsModule.java
rename to briar-core/src/main/java/org/briarproject/briar/blog/BlogModule.java
index 0ba7eaa0d51362543aae7615ccd37204c4c08fe6..4a6fde080658dddcf11be60cb2fdae1a6eeeddb1 100644
--- a/briar-core/src/org/briarproject/blogs/BlogsModule.java
+++ b/briar-core/src/main/java/org/briarproject/briar/blog/BlogModule.java
@@ -1,17 +1,17 @@
-package org.briarproject.blogs;
+package org.briarproject.briar.blog;
 
-import org.briarproject.api.blogs.BlogFactory;
-import org.briarproject.api.blogs.BlogManager;
-import org.briarproject.api.blogs.BlogPostFactory;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.sync.GroupFactory;
-import org.briarproject.api.sync.MessageFactory;
-import org.briarproject.api.sync.ValidationManager;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.sync.GroupFactory;
+import org.briarproject.bramble.api.sync.MessageFactory;
+import org.briarproject.bramble.api.sync.ValidationManager;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.blog.BlogFactory;
+import org.briarproject.briar.api.blog.BlogManager;
+import org.briarproject.briar.api.blog.BlogPostFactory;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -19,10 +19,10 @@ import javax.inject.Singleton;
 import dagger.Module;
 import dagger.Provides;
 
-import static org.briarproject.blogs.BlogManagerImpl.CLIENT_ID;
+import static org.briarproject.briar.blog.BlogManagerImpl.CLIENT_ID;
 
 @Module
-public class BlogsModule {
+public class BlogModule {
 
 	public static class EagerSingletons {
 		@Inject
diff --git a/briar-core/src/org/briarproject/blogs/BlogPostFactoryImpl.java b/briar-core/src/main/java/org/briarproject/briar/blog/BlogPostFactoryImpl.java
similarity index 76%
rename from briar-core/src/org/briarproject/blogs/BlogPostFactoryImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/blog/BlogPostFactoryImpl.java
index 52cbc72a76e3e6db71ed4471c24bf7626f408734..b8fd8b7e32e85c816ec766921d043dcbd4b58b08 100644
--- a/briar-core/src/org/briarproject/blogs/BlogPostFactoryImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/blog/BlogPostFactoryImpl.java
@@ -1,31 +1,34 @@
-package org.briarproject.blogs;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.blogs.BlogPost;
-import org.briarproject.api.blogs.BlogPostFactory;
-import org.briarproject.api.blogs.MessageType;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.system.Clock;
-import org.briarproject.util.StringUtils;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+package org.briarproject.briar.blog;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.api.blog.BlogPost;
+import org.briarproject.briar.api.blog.BlogPostFactory;
+import org.briarproject.briar.api.blog.MessageType;
 
 import java.security.GeneralSecurityException;
 
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_COMMENT_LENGTH;
-import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_POST_BODY_LENGTH;
-import static org.briarproject.api.blogs.MessageType.COMMENT;
-import static org.briarproject.api.blogs.MessageType.POST;
-import static org.briarproject.api.blogs.MessageType.WRAPPED_COMMENT;
-import static org.briarproject.api.blogs.MessageType.WRAPPED_POST;
+import static org.briarproject.briar.api.blog.BlogConstants.MAX_BLOG_COMMENT_LENGTH;
+import static org.briarproject.briar.api.blog.BlogConstants.MAX_BLOG_POST_BODY_LENGTH;
+import static org.briarproject.briar.api.blog.MessageType.COMMENT;
+import static org.briarproject.briar.api.blog.MessageType.POST;
+import static org.briarproject.briar.api.blog.MessageType.WRAPPED_COMMENT;
+import static org.briarproject.briar.api.blog.MessageType.WRAPPED_POST;
 
+@Immutable
+@NotNullByDefault
 class BlogPostFactoryImpl implements BlogPostFactory {
 
 	private final ClientHelper clientHelper;
@@ -38,9 +41,8 @@ class BlogPostFactoryImpl implements BlogPostFactory {
 	}
 
 	@Override
-	public BlogPost createBlogPost(@NotNull GroupId groupId, long timestamp,
-			@Nullable MessageId parent, @NotNull LocalAuthor author,
-			@NotNull String body)
+	public BlogPost createBlogPost(GroupId groupId, long timestamp,
+			@Nullable MessageId parent, LocalAuthor author, String body)
 			throws FormatException, GeneralSecurityException {
 
 		// Validate the arguments
diff --git a/briar-core/src/org/briarproject/blogs/BlogPostValidator.java b/briar-core/src/main/java/org/briarproject/briar/blog/BlogPostValidator.java
similarity index 74%
rename from briar-core/src/org/briarproject/blogs/BlogPostValidator.java
rename to briar-core/src/main/java/org/briarproject/briar/blog/BlogPostValidator.java
index 4b7dd148e39197e64f86a63084075895896dc19c..33fb0bddf76a4736df6bff337c7892f65520afca 100644
--- a/briar-core/src/org/briarproject/blogs/BlogPostValidator.java
+++ b/briar-core/src/main/java/org/briarproject/briar/blog/BlogPostValidator.java
@@ -1,50 +1,55 @@
-package org.briarproject.blogs;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.blogs.Blog;
-import org.briarproject.api.blogs.BlogFactory;
-import org.briarproject.api.blogs.MessageType;
-import org.briarproject.api.clients.BdfMessageContext;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupFactory;
-import org.briarproject.api.sync.InvalidMessageException;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageFactory;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.system.Clock;
-import org.briarproject.clients.BdfMessageValidator;
+package org.briarproject.briar.blog;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.BdfMessageContext;
+import org.briarproject.bramble.api.client.BdfMessageValidator;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupFactory;
+import org.briarproject.bramble.api.sync.InvalidMessageException;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageFactory;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.blog.Blog;
+import org.briarproject.briar.api.blog.BlogFactory;
+import org.briarproject.briar.api.blog.MessageType;
 
 import java.security.GeneralSecurityException;
 import java.util.Collection;
 import java.util.Collections;
 
-import static org.briarproject.api.blogs.BlogConstants.KEY_AUTHOR;
-import static org.briarproject.api.blogs.BlogConstants.KEY_AUTHOR_ID;
-import static org.briarproject.api.blogs.BlogConstants.KEY_AUTHOR_NAME;
-import static org.briarproject.api.blogs.BlogConstants.KEY_COMMENT;
-import static org.briarproject.api.blogs.BlogConstants.KEY_ORIGINAL_MSG_ID;
-import static org.briarproject.api.blogs.BlogConstants.KEY_ORIGINAL_PARENT_MSG_ID;
-import static org.briarproject.api.blogs.BlogConstants.KEY_PARENT_MSG_ID;
-import static org.briarproject.api.blogs.BlogConstants.KEY_PUBLIC_KEY;
-import static org.briarproject.api.blogs.BlogConstants.KEY_READ;
-import static org.briarproject.api.blogs.BlogConstants.KEY_TIMESTAMP;
-import static org.briarproject.api.blogs.BlogConstants.KEY_TIME_RECEIVED;
-import static org.briarproject.api.blogs.BlogConstants.KEY_TYPE;
-import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_COMMENT_LENGTH;
-import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_POST_BODY_LENGTH;
-import static org.briarproject.api.blogs.BlogPostFactory.SIGNING_LABEL_COMMENT;
-import static org.briarproject.api.blogs.BlogPostFactory.SIGNING_LABEL_POST;
-import static org.briarproject.api.blogs.MessageType.COMMENT;
-import static org.briarproject.api.blogs.MessageType.POST;
-import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
-
+import javax.annotation.concurrent.Immutable;
+
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
+import static org.briarproject.bramble.util.ValidationUtils.checkLength;
+import static org.briarproject.bramble.util.ValidationUtils.checkSize;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_ID;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_NAME;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_COMMENT;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_MSG_ID;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_PARENT_MSG_ID;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_PARENT_MSG_ID;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_PUBLIC_KEY;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_READ;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_TIMESTAMP;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_TIME_RECEIVED;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_TYPE;
+import static org.briarproject.briar.api.blog.BlogConstants.MAX_BLOG_COMMENT_LENGTH;
+import static org.briarproject.briar.api.blog.BlogConstants.MAX_BLOG_POST_BODY_LENGTH;
+import static org.briarproject.briar.api.blog.BlogPostFactory.SIGNING_LABEL_COMMENT;
+import static org.briarproject.briar.api.blog.BlogPostFactory.SIGNING_LABEL_POST;
+import static org.briarproject.briar.api.blog.MessageType.COMMENT;
+import static org.briarproject.briar.api.blog.MessageType.POST;
+
+@Immutable
 @NotNullByDefault
 class BlogPostValidator extends BdfMessageValidator {
 
@@ -255,7 +260,7 @@ class BlogPostValidator extends BdfMessageValidator {
 		// Get and Validate the Wrapped Comment
 		Group wGroup = groupFactory
 				.createGroup(BlogManagerImpl.CLIENT_ID, descriptor);
-		BdfList wBodyList =	BdfList.of(COMMENT.getInt(), comment, pOriginalId,
+		BdfList wBodyList = BdfList.of(COMMENT.getInt(), comment, pOriginalId,
 				oldId, signature);
 		byte[] wBody = clientHelper.toByteArray(wBodyList);
 		Message wMessage =
diff --git a/briar-core/src/org/briarproject/clients/BdfIncomingMessageHook.java b/briar-core/src/main/java/org/briarproject/briar/client/BdfIncomingMessageHook.java
similarity index 66%
rename from briar-core/src/org/briarproject/clients/BdfIncomingMessageHook.java
rename to briar-core/src/main/java/org/briarproject/briar/client/BdfIncomingMessageHook.java
index 41c402133433d3006acc34346d81b0fd28cbed60..19d8142c1a6c2f8e99d378ffea4a8f769e5d3cc3 100644
--- a/briar-core/src/org/briarproject/clients/BdfIncomingMessageHook.java
+++ b/briar-core/src/main/java/org/briarproject/briar/client/BdfIncomingMessageHook.java
@@ -1,24 +1,27 @@
-package org.briarproject.clients;
+package org.briarproject.briar.client;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageQueueManager.IncomingQueueMessageHook;
-import org.briarproject.api.clients.QueueMessage;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataParser;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.InvalidMessageException;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.ValidationManager.IncomingMessageHook;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataParser;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.InvalidMessageException;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.ValidationManager.IncomingMessageHook;
+import org.briarproject.briar.api.client.MessageQueueManager.IncomingQueueMessageHook;
+import org.briarproject.briar.api.client.QueueMessage;
 
-import static org.briarproject.api.clients.QueueMessage.QUEUE_MESSAGE_HEADER_LENGTH;
-import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
+import javax.annotation.concurrent.Immutable;
 
+import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
+import static org.briarproject.briar.api.client.QueueMessage.QUEUE_MESSAGE_HEADER_LENGTH;
+
+@Immutable
 @NotNullByDefault
 public abstract class BdfIncomingMessageHook implements IncomingMessageHook,
 		IncomingQueueMessageHook {
diff --git a/briar-core/src/main/java/org/briarproject/briar/client/BdfQueueMessageValidator.java b/briar-core/src/main/java/org/briarproject/briar/client/BdfQueueMessageValidator.java
new file mode 100644
index 0000000000000000000000000000000000000000..48fd665a10f17cd77c2fc446da96ccf5a39d3181
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/client/BdfQueueMessageValidator.java
@@ -0,0 +1,71 @@
+package org.briarproject.briar.client;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.BdfMessageContext;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.InvalidMessageException;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageContext;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.client.MessageQueueManager.QueueMessageValidator;
+import org.briarproject.briar.api.client.QueueMessage;
+
+import java.util.logging.Logger;
+
+import javax.annotation.concurrent.Immutable;
+
+import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
+import static org.briarproject.briar.api.client.QueueMessage.QUEUE_MESSAGE_HEADER_LENGTH;
+
+@Deprecated
+@Immutable
+@NotNullByDefault
+public abstract class BdfQueueMessageValidator
+		implements QueueMessageValidator {
+
+	protected static final Logger LOG =
+			Logger.getLogger(BdfQueueMessageValidator.class.getName());
+
+	protected final ClientHelper clientHelper;
+	protected final MetadataEncoder metadataEncoder;
+	protected final Clock clock;
+
+	protected BdfQueueMessageValidator(ClientHelper clientHelper,
+			MetadataEncoder metadataEncoder, Clock clock) {
+		this.clientHelper = clientHelper;
+		this.metadataEncoder = metadataEncoder;
+		this.clock = clock;
+	}
+
+	protected abstract BdfMessageContext validateMessage(Message m, Group g,
+			BdfList body) throws InvalidMessageException, FormatException;
+
+	@Override
+	public MessageContext validateMessage(QueueMessage q, Group g)
+			throws InvalidMessageException {
+		// Reject the message if it's too far in the future
+		long now = clock.currentTimeMillis();
+		if (q.getTimestamp() - now > MAX_CLOCK_DIFFERENCE) {
+			throw new InvalidMessageException(
+					"Timestamp is too far in the future");
+		}
+		byte[] raw = q.getRaw();
+		if (raw.length <= QUEUE_MESSAGE_HEADER_LENGTH) {
+			throw new InvalidMessageException("Message is too short");
+		}
+		try {
+			BdfList body = clientHelper.toList(raw, QUEUE_MESSAGE_HEADER_LENGTH,
+					raw.length - QUEUE_MESSAGE_HEADER_LENGTH);
+			BdfMessageContext result = validateMessage(q, g, body);
+			Metadata meta = metadataEncoder.encode(result.getDictionary());
+			return new MessageContext(meta, result.getDependencies());
+		} catch (FormatException e) {
+			throw new InvalidMessageException(e);
+		}
+	}
+}
diff --git a/briar-core/src/main/java/org/briarproject/briar/client/BriarClientModule.java b/briar-core/src/main/java/org/briarproject/briar/client/BriarClientModule.java
new file mode 100644
index 0000000000000000000000000000000000000000..52ecdb50aabe262d5f06a6c3e70c187f1d1266a7
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/client/BriarClientModule.java
@@ -0,0 +1,37 @@
+package org.briarproject.briar.client;
+
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.sync.ValidationManager;
+import org.briarproject.briar.api.client.MessageQueueManager;
+import org.briarproject.briar.api.client.MessageTracker;
+import org.briarproject.briar.api.client.QueueMessageFactory;
+
+import javax.inject.Singleton;
+
+import dagger.Module;
+import dagger.Provides;
+
+@Module
+public class BriarClientModule {
+
+	@Provides
+	@Singleton
+	MessageQueueManager provideMessageQueueManager(DatabaseComponent db,
+			ClientHelper clientHelper, QueueMessageFactory queueMessageFactory,
+			ValidationManager validationManager) {
+		return new MessageQueueManagerImpl(db, clientHelper,
+				queueMessageFactory, validationManager);
+	}
+
+	@Provides
+	QueueMessageFactory provideQueueMessageFactory(CryptoComponent crypto) {
+		return new QueueMessageFactoryImpl(crypto);
+	}
+
+	@Provides
+	MessageTracker provideMessageTracker(MessageTrackerImpl messageTracker) {
+		return messageTracker;
+	}
+}
diff --git a/briar-core/src/main/java/org/briarproject/briar/client/ConversationClientImpl.java b/briar-core/src/main/java/org/briarproject/briar/client/ConversationClientImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..9e47fa3a3fd786b077ed382bcb662f15a5abe01e
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/client/ConversationClientImpl.java
@@ -0,0 +1,46 @@
+package org.briarproject.briar.client;
+
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.data.MetadataParser;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.MessageTracker;
+import org.briarproject.briar.api.client.MessageTracker.GroupCount;
+import org.briarproject.briar.api.messaging.ConversationManager.ConversationClient;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public abstract class ConversationClientImpl extends BdfIncomingMessageHook
+		implements ConversationClient {
+
+	protected final MessageTracker messageTracker;
+
+	protected ConversationClientImpl(DatabaseComponent db,
+			ClientHelper clientHelper, MetadataParser metadataParser,
+			MessageTracker messageTracker) {
+		super(db, clientHelper, metadataParser);
+		this.messageTracker = messageTracker;
+	}
+
+	@Override
+	public GroupCount getGroupCount(Transaction txn, ContactId contactId)
+			throws DbException {
+		Contact contact = db.getContact(txn, contactId);
+		GroupId groupId = getContactGroup(contact).getId();
+		return messageTracker.getGroupCount(txn, groupId);
+	}
+
+	@Override
+	public void setReadFlag(GroupId g, MessageId m, boolean read)
+			throws DbException {
+		messageTracker.setReadFlag(g, m, read);
+	}
+}
diff --git a/briar-core/src/org/briarproject/clients/MessageQueueManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/client/MessageQueueManagerImpl.java
similarity index 83%
rename from briar-core/src/org/briarproject/clients/MessageQueueManagerImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/client/MessageQueueManagerImpl.java
index d666598509dd68f5ff2f43e70d26e529d68f0e00..5e68e713c2ff84498e107621546106afcdb37193 100644
--- a/briar-core/src/org/briarproject/clients/MessageQueueManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/client/MessageQueueManagerImpl.java
@@ -1,28 +1,28 @@
-package org.briarproject.clients;
+package org.briarproject.briar.client;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageQueueManager;
-import org.briarproject.api.clients.QueueMessage;
-import org.briarproject.api.clients.QueueMessageFactory;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.InvalidMessageException;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageContext;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.sync.ValidationManager;
-import org.briarproject.api.sync.ValidationManager.IncomingMessageHook;
-import org.briarproject.api.sync.ValidationManager.MessageValidator;
-import org.briarproject.util.ByteUtils;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.InvalidMessageException;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageContext;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.ValidationManager;
+import org.briarproject.bramble.api.sync.ValidationManager.IncomingMessageHook;
+import org.briarproject.bramble.api.sync.ValidationManager.MessageValidator;
+import org.briarproject.bramble.util.ByteUtils;
+import org.briarproject.briar.api.client.MessageQueueManager;
+import org.briarproject.briar.api.client.QueueMessage;
+import org.briarproject.briar.api.client.QueueMessageFactory;
 
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -32,12 +32,14 @@ import java.util.TreeMap;
 import java.util.logging.Logger;
 
 import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
 import static java.util.logging.Level.INFO;
-import static org.briarproject.api.clients.QueueMessage.QUEUE_MESSAGE_HEADER_LENGTH;
-import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
+import static org.briarproject.briar.api.client.QueueMessage.QUEUE_MESSAGE_HEADER_LENGTH;
 
+@Immutable
 @NotNullByDefault
 class MessageQueueManagerImpl implements MessageQueueManager {
 
@@ -239,6 +241,7 @@ class MessageQueueManagerImpl implements MessageQueueManager {
 				delegate.incomingMessage(txn, q, meta);
 				for (MessageId id : consecutive) {
 					byte[] raw = db.getRawMessage(txn, id);
+					if (raw == null) throw new DbException();
 					meta = db.getMessageMetadata(txn, id);
 					q = queueMessageFactory.createMessage(id, raw);
 					if (LOG.isLoggable(INFO)) {
diff --git a/briar-core/src/org/briarproject/clients/BdfConstants.java b/briar-core/src/main/java/org/briarproject/briar/client/MessageTrackerConstants.java
similarity index 69%
rename from briar-core/src/org/briarproject/clients/BdfConstants.java
rename to briar-core/src/main/java/org/briarproject/briar/client/MessageTrackerConstants.java
index 6f81491854f140965c20799ba3480cbf5174c7d0..ca689fc1ca2543ecb6ae80e922831233a9daf319 100644
--- a/briar-core/src/org/briarproject/clients/BdfConstants.java
+++ b/briar-core/src/main/java/org/briarproject/briar/client/MessageTrackerConstants.java
@@ -1,6 +1,6 @@
-package org.briarproject.clients;
+package org.briarproject.briar.client;
 
-public interface BdfConstants {
+public interface MessageTrackerConstants {
 
 	String GROUP_KEY_MSG_COUNT = "messageCount";
 	String GROUP_KEY_UNREAD_COUNT = "unreadCount";
diff --git a/briar-core/src/org/briarproject/clients/MessageTrackerImpl.java b/briar-core/src/main/java/org/briarproject/briar/client/MessageTrackerImpl.java
similarity index 74%
rename from briar-core/src/org/briarproject/clients/MessageTrackerImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/client/MessageTrackerImpl.java
index 0d5328eee6f4e1db77942bcf3d206785be25804f..bd230dca8ea0ab8efda10cc9f1c6744a0186bbda 100644
--- a/briar-core/src/org/briarproject/clients/MessageTrackerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/client/MessageTrackerImpl.java
@@ -1,25 +1,27 @@
-package org.briarproject.clients;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageTracker;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-
+package org.briarproject.briar.client;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.MessageTracker;
+
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-import static org.briarproject.clients.BdfConstants.GROUP_KEY_LATEST_MSG;
-import static org.briarproject.clients.BdfConstants.GROUP_KEY_MSG_COUNT;
-import static org.briarproject.clients.BdfConstants.GROUP_KEY_UNREAD_COUNT;
-import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
+import static org.briarproject.briar.client.MessageTrackerConstants.GROUP_KEY_LATEST_MSG;
+import static org.briarproject.briar.client.MessageTrackerConstants.GROUP_KEY_MSG_COUNT;
+import static org.briarproject.briar.client.MessageTrackerConstants.GROUP_KEY_UNREAD_COUNT;
+import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
 
+@Immutable
 @NotNullByDefault
 class MessageTrackerImpl implements MessageTracker {
 
diff --git a/briar-core/src/org/briarproject/clients/MessageTreeImpl.java b/briar-core/src/main/java/org/briarproject/briar/client/MessageTreeImpl.java
similarity index 78%
rename from briar-core/src/org/briarproject/clients/MessageTreeImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/client/MessageTreeImpl.java
index 0ef7c230ab6bbc2fabc317a3a8df87b65e9178e4..982bcd2e765218dbaa1673e959ea70bea2653d63 100644
--- a/briar-core/src/org/briarproject/clients/MessageTreeImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/client/MessageTreeImpl.java
@@ -1,7 +1,8 @@
-package org.briarproject.clients;
+package org.briarproject.briar.client;
 
-import org.briarproject.api.clients.MessageTree;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.MessageTree;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -11,10 +12,15 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import javax.annotation.concurrent.ThreadSafe;
+
+@ThreadSafe
+@NotNullByDefault
 public class MessageTreeImpl<T extends MessageTree.MessageNode>
 		implements MessageTree<T> {
 
-	private final Map<MessageId, List<T>> nodeMap = new HashMap<MessageId, List<T>>();
+	private final Map<MessageId, List<T>> nodeMap =
+			new HashMap<MessageId, List<T>>();
 	private final List<T> roots = new ArrayList<T>();
 	private final List<List<T>> unsortedLists = new ArrayList<List<T>>();
 
@@ -67,23 +73,19 @@ public class MessageTreeImpl<T extends MessageTree.MessageNode>
 	}
 
 	private void sortUnsorted() {
-		// leave unsorted if there is no comparator
-		if (comparator != null) {
-			for (List<T> list : unsortedLists) {
-				Collections.sort(list, comparator);
-			}
-			unsortedLists.clear();
+		for (List<T> list : unsortedLists) {
+			Collections.sort(list, comparator);
 		}
+		unsortedLists.clear();
 	}
 
-
 	private void traverse(List<T> list, T node, int level) {
 		list.add(node);
 		List<T> children = nodeMap.get(node.getId());
 		node.setLevel(level);
 		node.setDescendantCount(children.size());
 		for (T child : children) {
-			traverse(list, child, level+1);
+			traverse(list, child, level + 1);
 		}
 	}
 
@@ -92,7 +94,7 @@ public class MessageTreeImpl<T extends MessageTree.MessageNode>
 		this.comparator = comparator;
 		// Sort all lists with the new comparator
 		Collections.sort(roots, comparator);
-		for (Map.Entry<MessageId, List<T>> entry: nodeMap.entrySet()) {
+		for (Map.Entry<MessageId, List<T>> entry : nodeMap.entrySet()) {
 			Collections.sort(entry.getValue(), comparator);
 		}
 	}
diff --git a/briar-core/src/org/briarproject/clients/QueueMessageFactoryImpl.java b/briar-core/src/main/java/org/briarproject/briar/client/QueueMessageFactoryImpl.java
similarity index 63%
rename from briar-core/src/org/briarproject/clients/QueueMessageFactoryImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/client/QueueMessageFactoryImpl.java
index d64cbb5713f548c846941397c659d856ebdef15a..9b207cbaa310a0924dba34e7581ed667e1c7e0ef 100644
--- a/briar-core/src/org/briarproject/clients/QueueMessageFactoryImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/client/QueueMessageFactoryImpl.java
@@ -1,20 +1,24 @@
-package org.briarproject.clients;
-
-import org.briarproject.api.UniqueId;
-import org.briarproject.api.clients.QueueMessage;
-import org.briarproject.api.clients.QueueMessageFactory;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.util.ByteUtils;
-
+package org.briarproject.briar.client;
+
+import org.briarproject.bramble.api.UniqueId;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.util.ByteUtils;
+import org.briarproject.briar.api.client.QueueMessage;
+import org.briarproject.briar.api.client.QueueMessageFactory;
+
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-import static org.briarproject.api.clients.QueueMessage.MAX_QUEUE_MESSAGE_BODY_LENGTH;
-import static org.briarproject.api.clients.QueueMessage.QUEUE_MESSAGE_HEADER_LENGTH;
-import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_LENGTH;
-import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
+import static org.briarproject.briar.api.client.QueueMessage.MAX_QUEUE_MESSAGE_BODY_LENGTH;
+import static org.briarproject.briar.api.client.QueueMessage.QUEUE_MESSAGE_HEADER_LENGTH;
 
+@Immutable
+@NotNullByDefault
 class QueueMessageFactoryImpl implements QueueMessageFactory {
 
 	private final CryptoComponent crypto;
diff --git a/briar-core/src/org/briarproject/feed/FeedManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/feed/FeedManagerImpl.java
similarity index 81%
rename from briar-core/src/org/briarproject/feed/FeedManagerImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/feed/FeedManagerImpl.java
index 55a413cde3cb174c7832d73cb717f24809bfdccc..1cbc8e677fdd392813fb3b8c6fbaaf89211814e2 100644
--- a/briar-core/src/org/briarproject/feed/FeedManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/feed/FeedManagerImpl.java
@@ -1,4 +1,4 @@
-package org.briarproject.feed;
+package org.briarproject.briar.feed;
 
 import com.rometools.rome.feed.synd.SyndContent;
 import com.rometools.rome.feed.synd.SyndEntry;
@@ -7,34 +7,35 @@ import com.rometools.rome.io.FeedException;
 import com.rometools.rome.io.SyndFeedInput;
 import com.rometools.rome.io.XmlReader;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.blogs.BlogManager;
-import org.briarproject.api.blogs.BlogPost;
-import org.briarproject.api.blogs.BlogPostFactory;
-import org.briarproject.api.clients.Client;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.ContactGroupFactory;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.TransportEnabledEvent;
-import org.briarproject.api.feed.Feed;
-import org.briarproject.api.feed.FeedManager;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.lifecycle.IoExecutor;
-import org.briarproject.api.system.Scheduler;
-import org.briarproject.api.plugins.TorConstants;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.system.Clock;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.client.ContactGroupFactory;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.event.EventListener;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.lifecycle.IoExecutor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TorConstants;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.event.TransportEnabledEvent;
+import org.briarproject.bramble.api.sync.Client;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.bramble.api.system.Scheduler;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.api.blog.BlogManager;
+import org.briarproject.briar.api.blog.BlogPost;
+import org.briarproject.briar.api.blog.BlogPostFactory;
+import org.briarproject.briar.api.feed.Feed;
+import org.briarproject.briar.api.feed.FeedManager;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -49,6 +50,8 @@ import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
 import javax.inject.Inject;
 import javax.net.SocketFactory;
 
@@ -59,15 +62,17 @@ import okhttp3.Response;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_POST_BODY_LENGTH;
-import static org.briarproject.api.feed.FeedConstants.FETCH_DELAY_INITIAL;
-import static org.briarproject.api.feed.FeedConstants.FETCH_INTERVAL;
-import static org.briarproject.api.feed.FeedConstants.FETCH_UNIT;
-import static org.briarproject.api.feed.FeedConstants.KEY_FEEDS;
-import static org.briarproject.util.HtmlUtils.article;
-import static org.briarproject.util.HtmlUtils.clean;
-import static org.briarproject.util.HtmlUtils.stripAll;
-
+import static org.briarproject.briar.api.blog.BlogConstants.MAX_BLOG_POST_BODY_LENGTH;
+import static org.briarproject.briar.api.feed.FeedConstants.FETCH_DELAY_INITIAL;
+import static org.briarproject.briar.api.feed.FeedConstants.FETCH_INTERVAL;
+import static org.briarproject.briar.api.feed.FeedConstants.FETCH_UNIT;
+import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEEDS;
+import static org.briarproject.briar.util.HtmlUtils.ARTICLE;
+import static org.briarproject.briar.util.HtmlUtils.STRIP_ALL;
+import static org.briarproject.briar.util.HtmlUtils.clean;
+
+@ThreadSafe
+@NotNullByDefault
 class FeedManagerImpl implements FeedManager, Client, EventListener {
 
 	private static final Logger LOG =
@@ -82,22 +87,18 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
 	private final ClientHelper clientHelper;
 	private final IdentityManager identityManager;
 	private final BlogManager blogManager;
+	private final BlogPostFactory blogPostFactory;
 	private final SocketFactory torSocketFactory;
+	private final Clock clock;
 	private final AtomicBoolean fetcherStarted = new AtomicBoolean(false);
 
-	@Inject
-	@SuppressWarnings("WeakerAccess")
-	BlogPostFactory blogPostFactory;
-	@Inject
-	@SuppressWarnings("WeakerAccess")
-	Clock clock;
-
 	@Inject
 	FeedManagerImpl(@Scheduler ScheduledExecutorService scheduler,
 			@IoExecutor Executor ioExecutor, DatabaseComponent db,
 			ContactGroupFactory contactGroupFactory, ClientHelper clientHelper,
 			IdentityManager identityManager, BlogManager blogManager,
-			SocketFactory torSocketFactory) {
+			BlogPostFactory blogPostFactory, SocketFactory torSocketFactory,
+			Clock clock) {
 
 		this.scheduler = scheduler;
 		this.ioExecutor = ioExecutor;
@@ -106,7 +107,9 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
 		this.clientHelper = clientHelper;
 		this.identityManager = identityManager;
 		this.blogManager = blogManager;
+		this.blogPostFactory = blogPostFactory;
 		this.torSocketFactory = torSocketFactory;
+		this.clock = clock;
 	}
 
 	@Override
@@ -248,7 +251,7 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
 		return feeds;
 	}
 
-	private void storeFeeds(Transaction txn, List<Feed> feeds)
+	private void storeFeeds(@Nullable Transaction txn, List<Feed> feeds)
 			throws DbException {
 
 		BdfList feedList = new BdfList();
@@ -260,8 +263,8 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
 			if (txn == null) {
 				clientHelper.mergeGroupMetadata(getLocalGroup().getId(), gm);
 			} else {
-				clientHelper
-						.mergeGroupMetadata(txn, getLocalGroup().getId(), gm);
+				clientHelper.mergeGroupMetadata(txn, getLocalGroup().getId(),
+						gm);
 			}
 		} catch (FormatException e) {
 			throw new DbException(e);
@@ -328,13 +331,13 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
 
 		SyndFeed f = getSyndFeed(getFeedInputStream(feed.getUrl()));
 		title = StringUtils.isNullOrEmpty(f.getTitle()) ? null : f.getTitle();
-		if (title != null) title = clean(title, stripAll);
+		if (title != null) title = clean(title, STRIP_ALL);
 		description = StringUtils.isNullOrEmpty(f.getDescription()) ? null :
 				f.getDescription();
-		if (description != null) description = clean(description, stripAll);
+		if (description != null) description = clean(description, STRIP_ALL);
 		author =
 				StringUtils.isNullOrEmpty(f.getAuthor()) ? null : f.getAuthor();
-		if (author != null) author = clean(author, stripAll);
+		if (author != null) author = clean(author, STRIP_ALL);
 
 		if (f.getEntries().size() == 0)
 			throw new FeedException("Feed has no entries");
@@ -469,7 +472,7 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
 	}
 
 	private String getPostBody(String text) {
-		text = clean(text, article);
+		text = clean(text, ARTICLE);
 		return StringUtils.truncateUtf8(text, MAX_BLOG_POST_BODY_LENGTH);
 	}
 
diff --git a/briar-core/src/org/briarproject/feed/FeedModule.java b/briar-core/src/main/java/org/briarproject/briar/feed/FeedModule.java
similarity index 70%
rename from briar-core/src/org/briarproject/feed/FeedModule.java
rename to briar-core/src/main/java/org/briarproject/briar/feed/FeedModule.java
index 2845370a4b17a8e08b3af691c0848fa9ae348c4f..d47a088b88000a74ee1974c7ab22c6d3e486c472 100644
--- a/briar-core/src/org/briarproject/feed/FeedModule.java
+++ b/briar-core/src/main/java/org/briarproject/briar/feed/FeedModule.java
@@ -1,8 +1,8 @@
-package org.briarproject.feed;
+package org.briarproject.briar.feed;
 
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.feed.FeedManager;
-import org.briarproject.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.briar.api.feed.FeedManager;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
diff --git a/briar-core/src/org/briarproject/forum/ForumFactoryImpl.java b/briar-core/src/main/java/org/briarproject/briar/forum/ForumFactoryImpl.java
similarity index 53%
rename from briar-core/src/org/briarproject/forum/ForumFactoryImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/forum/ForumFactoryImpl.java
index f2582223414fe96250f0122c7fe3c9620f87bfb9..5570d52542fcc8eed76d7bd51bbb8ae973dd32a7 100644
--- a/briar-core/src/org/briarproject/forum/ForumFactoryImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/forum/ForumFactoryImpl.java
@@ -1,21 +1,26 @@
-package org.briarproject.forum;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumFactory;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupFactory;
-import org.briarproject.util.StringUtils;
+package org.briarproject.briar.forum;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupFactory;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.api.forum.Forum;
+import org.briarproject.briar.api.forum.ForumFactory;
 
 import java.security.SecureRandom;
 
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH;
-import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
+import static org.briarproject.briar.api.forum.ForumConstants.FORUM_SALT_LENGTH;
+import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
+import static org.briarproject.briar.api.forum.ForumManager.CLIENT_ID;
 
+@Immutable
+@NotNullByDefault
 class ForumFactoryImpl implements ForumFactory {
 
 	private final GroupFactory groupFactory;
@@ -47,11 +52,10 @@ class ForumFactoryImpl implements ForumFactory {
 		try {
 			BdfList forum = BdfList.of(name, salt);
 			byte[] descriptor = clientHelper.toByteArray(forum);
-			Group g = groupFactory
-					.createGroup(ForumManagerImpl.CLIENT_ID, descriptor);
+			Group g = groupFactory.createGroup(CLIENT_ID, descriptor);
 			return new Forum(g, name, salt);
 		} catch (FormatException e) {
-			throw new RuntimeException(e);
+			throw new AssertionError(e);
 		}
 	}
 
diff --git a/briar-core/src/org/briarproject/forum/ForumManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/forum/ForumManagerImpl.java
similarity index 75%
rename from briar-core/src/org/briarproject/forum/ForumManagerImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/forum/ForumManagerImpl.java
index b4d7d84cba70f78f6c388ee4e6562b5d9062a8ed..348fe52100da5209d383b51c48e95f424c09d6a6 100644
--- a/briar-core/src/org/briarproject/forum/ForumManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/forum/ForumManagerImpl.java
@@ -1,34 +1,33 @@
-package org.briarproject.forum;
+package org.briarproject.briar.forum;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageTracker;
-import org.briarproject.api.clients.MessageTracker.GroupCount;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataParser;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.ForumPostReceivedEvent;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumFactory;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.forum.ForumPost;
-import org.briarproject.api.forum.ForumPostFactory;
-import org.briarproject.api.forum.ForumPostHeader;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.Author.Status;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.clients.BdfIncomingMessageHook;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataParser;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.MessageTracker;
+import org.briarproject.briar.api.client.MessageTracker.GroupCount;
+import org.briarproject.briar.api.forum.Forum;
+import org.briarproject.briar.api.forum.ForumFactory;
+import org.briarproject.briar.api.forum.ForumManager;
+import org.briarproject.briar.api.forum.ForumPost;
+import org.briarproject.briar.api.forum.ForumPostFactory;
+import org.briarproject.briar.api.forum.ForumPostHeader;
+import org.briarproject.briar.api.forum.event.ForumPostReceivedEvent;
+import org.briarproject.briar.client.BdfIncomingMessageHook;
 
 import java.security.GeneralSecurityException;
 import java.util.ArrayList;
@@ -42,19 +41,22 @@ import java.util.Map.Entry;
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
 
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
 import javax.inject.Inject;
 
-import static org.briarproject.api.forum.ForumConstants.KEY_AUTHOR;
-import static org.briarproject.api.forum.ForumConstants.KEY_ID;
-import static org.briarproject.api.forum.ForumConstants.KEY_LOCAL;
-import static org.briarproject.api.forum.ForumConstants.KEY_NAME;
-import static org.briarproject.api.forum.ForumConstants.KEY_PARENT;
-import static org.briarproject.api.forum.ForumConstants.KEY_PUBLIC_NAME;
-import static org.briarproject.api.forum.ForumConstants.KEY_TIMESTAMP;
-import static org.briarproject.api.identity.Author.Status.ANONYMOUS;
-import static org.briarproject.api.identity.Author.Status.OURSELVES;
-import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
+import static org.briarproject.bramble.api.identity.Author.Status.ANONYMOUS;
+import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
+import static org.briarproject.briar.api.forum.ForumConstants.KEY_AUTHOR;
+import static org.briarproject.briar.api.forum.ForumConstants.KEY_ID;
+import static org.briarproject.briar.api.forum.ForumConstants.KEY_LOCAL;
+import static org.briarproject.briar.api.forum.ForumConstants.KEY_NAME;
+import static org.briarproject.briar.api.forum.ForumConstants.KEY_PARENT;
+import static org.briarproject.briar.api.forum.ForumConstants.KEY_PUBLIC_NAME;
+import static org.briarproject.briar.api.forum.ForumConstants.KEY_TIMESTAMP;
+import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
 
+@ThreadSafe
 @NotNullByDefault
 class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
 
@@ -125,9 +127,8 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
 			final LocalAuthor author) {
 		ForumPost p;
 		try {
-			p = forumPostFactory
-					.createPost(groupId, timestamp, parentId,
-							author, body);
+			p = forumPostFactory.createPost(groupId, timestamp, parentId,
+					author, body);
 		} catch (GeneralSecurityException e) {
 			throw new RuntimeException(e);
 		} catch (FormatException e) {
@@ -240,8 +241,7 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
 				statuses.put(id, identityManager.getAuthorStatus(txn, id));
 			}
 			// Parse the metadata
-			for (Entry<MessageId, BdfDictionary> entry : metadata
-					.entrySet()) {
+			for (Entry<MessageId, BdfDictionary> entry : metadata.entrySet()) {
 				BdfDictionary meta = entry.getValue();
 				headers.add(getForumPostHeader(txn, entry.getKey(), meta,
 						statuses));
@@ -294,6 +294,7 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
 		MessageId parentId = null;
 		if (meta.containsKey(KEY_PARENT))
 			parentId = new MessageId(meta.getRaw(KEY_PARENT));
+		// TODO: Remove support for anonymous forum posts
 		BdfDictionary d1 = meta.getDictionary(KEY_AUTHOR, null);
 		if (d1 != null) {
 			AuthorId authorId = new AuthorId(d1.getRaw(KEY_ID));
diff --git a/briar-core/src/org/briarproject/forum/ForumModule.java b/briar-core/src/main/java/org/briarproject/briar/forum/ForumModule.java
similarity index 59%
rename from briar-core/src/org/briarproject/forum/ForumModule.java
rename to briar-core/src/main/java/org/briarproject/briar/forum/ForumModule.java
index 0cc501d0af7ac43f4609ff4829985773ec12ed7b..8e742a7550296561e9a94cbe281158ab8643f993 100644
--- a/briar-core/src/org/briarproject/forum/ForumModule.java
+++ b/briar-core/src/main/java/org/briarproject/briar/forum/ForumModule.java
@@ -1,15 +1,14 @@
-package org.briarproject.forum;
+package org.briarproject.briar.forum;
 
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.forum.ForumFactory;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.forum.ForumPostFactory;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.sync.GroupFactory;
-import org.briarproject.api.sync.ValidationManager;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.sync.GroupFactory;
+import org.briarproject.bramble.api.sync.ValidationManager;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.forum.ForumFactory;
+import org.briarproject.briar.api.forum.ForumManager;
+import org.briarproject.briar.api.forum.ForumPostFactory;
 
 import java.security.SecureRandom;
 
@@ -19,10 +18,14 @@ import javax.inject.Singleton;
 import dagger.Module;
 import dagger.Provides;
 
+import static org.briarproject.briar.api.forum.ForumManager.CLIENT_ID;
+
 @Module
 public class ForumModule {
 
 	public static class EagerSingletons {
+		@Inject
+		ForumManager forumManager;
 		@Inject
 		ForumPostValidator forumPostValidator;
 	}
@@ -32,7 +35,7 @@ public class ForumModule {
 	ForumManager provideForumManager(ForumManagerImpl forumManager,
 			ValidationManager validationManager) {
 
-		validationManager.registerIncomingMessageHook(ForumManager.CLIENT_ID,
+		validationManager.registerIncomingMessageHook(CLIENT_ID,
 				forumManager);
 
 		return forumManager;
@@ -58,8 +61,7 @@ public class ForumModule {
 			Clock clock) {
 		ForumPostValidator validator = new ForumPostValidator(authorFactory,
 				clientHelper, metadataEncoder, clock);
-		validationManager.registerMessageValidator(
-				ForumManagerImpl.CLIENT_ID, validator);
+		validationManager.registerMessageValidator(CLIENT_ID, validator);
 		return validator;
 	}
 
diff --git a/briar-core/src/main/java/org/briarproject/briar/forum/ForumPostFactoryImpl.java b/briar-core/src/main/java/org/briarproject/briar/forum/ForumPostFactoryImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..2c26fa3667fdb9a33a8a4540ad5e4b7d4a64cd1b
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/forum/ForumPostFactoryImpl.java
@@ -0,0 +1,55 @@
+package org.briarproject.briar.forum;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.api.forum.ForumPost;
+import org.briarproject.briar.api.forum.ForumPostFactory;
+
+import java.security.GeneralSecurityException;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+import javax.inject.Inject;
+
+import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
+
+@Immutable
+@NotNullByDefault
+class ForumPostFactoryImpl implements ForumPostFactory {
+
+	private final ClientHelper clientHelper;
+
+	@Inject
+	ForumPostFactoryImpl(ClientHelper clientHelper) {
+		this.clientHelper = clientHelper;
+	}
+
+	@Override
+	public ForumPost createPost(GroupId groupId, long timestamp,
+			@Nullable MessageId parent, LocalAuthor author, String body)
+			throws FormatException, GeneralSecurityException {
+		// Validate the arguments
+		if (StringUtils.utf8IsTooLong(body, MAX_FORUM_POST_BODY_LENGTH))
+			throw new IllegalArgumentException();
+		// Serialise the data to be signed
+		BdfList authorList =
+				BdfList.of(author.getName(), author.getPublicKey());
+		BdfList signed = BdfList.of(groupId, timestamp, parent, authorList,
+				body);
+		// Sign the data
+		byte[] sig = clientHelper.sign(SIGNING_LABEL_POST, signed,
+				author.getPrivateKey());
+		// Serialise the signed message
+		BdfList message = BdfList.of(parent, authorList, body, sig);
+		Message m = clientHelper.createMessage(groupId, timestamp, message);
+		return new ForumPost(m, parent, author);
+	}
+
+}
diff --git a/briar-core/src/org/briarproject/forum/ForumPostValidator.java b/briar-core/src/main/java/org/briarproject/briar/forum/ForumPostValidator.java
similarity index 59%
rename from briar-core/src/org/briarproject/forum/ForumPostValidator.java
rename to briar-core/src/main/java/org/briarproject/briar/forum/ForumPostValidator.java
index b7d2f70660889b0094038f99015ebc6468ec866c..527960530a9da2f6a8c513d84248eaa7f01b698e 100644
--- a/briar-core/src/org/briarproject/forum/ForumPostValidator.java
+++ b/briar-core/src/main/java/org/briarproject/briar/forum/ForumPostValidator.java
@@ -1,32 +1,37 @@
-package org.briarproject.forum;
+package org.briarproject.briar.forum;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.UniqueId;
-import org.briarproject.api.clients.BdfMessageContext;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.InvalidMessageException;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.system.Clock;
-import org.briarproject.clients.BdfMessageValidator;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.UniqueId;
+import org.briarproject.bramble.api.client.BdfMessageContext;
+import org.briarproject.bramble.api.client.BdfMessageValidator;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.InvalidMessageException;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.system.Clock;
 
 import java.security.GeneralSecurityException;
 import java.util.Collection;
 import java.util.Collections;
 
-import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
-import static org.briarproject.api.forum.ForumPostFactory.SIGNING_LABEL_POST;
-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.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
+import javax.annotation.concurrent.Immutable;
 
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
+import static org.briarproject.bramble.util.ValidationUtils.checkLength;
+import static org.briarproject.bramble.util.ValidationUtils.checkSize;
+import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
+import static org.briarproject.briar.api.forum.ForumPostFactory.SIGNING_LABEL_POST;
+
+@Immutable
 @NotNullByDefault
 class ForumPostValidator extends BdfMessageValidator {
 
diff --git a/briar-core/src/org/briarproject/introduction/IntroduceeEngine.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeEngine.java
similarity index 69%
rename from briar-core/src/org/briarproject/introduction/IntroduceeEngine.java
rename to briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeEngine.java
index 4115fe0c09e695096360b78c5f215f285cdf3384..e7c213d9998b97e2427231af7ea1ff759394873c 100644
--- a/briar-core/src/org/briarproject/introduction/IntroduceeEngine.java
+++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeEngine.java
@@ -1,19 +1,20 @@
-package org.briarproject.introduction;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ProtocolEngine;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.IntroductionAbortedEvent;
-import org.briarproject.api.event.IntroductionRequestReceivedEvent;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.introduction.IntroduceeAction;
-import org.briarproject.api.introduction.IntroduceeProtocolState;
-import org.briarproject.api.introduction.IntroductionRequest;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+package org.briarproject.briar.introduction;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.ProtocolEngine;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.introduction.IntroduceeAction;
+import org.briarproject.briar.api.introduction.IntroduceeProtocolState;
+import org.briarproject.briar.api.introduction.IntroductionRequest;
+import org.briarproject.briar.api.introduction.event.IntroductionAbortedEvent;
+import org.briarproject.briar.api.introduction.event.IntroductionRequestReceivedEvent;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -21,56 +22,60 @@ import java.util.Collections;
 import java.util.List;
 import java.util.logging.Logger;
 
+import javax.annotation.concurrent.Immutable;
+
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.introduction.IntroduceeAction.ACK;
-import static org.briarproject.api.introduction.IntroduceeAction.LOCAL_ABORT;
-import static org.briarproject.api.introduction.IntroduceeAction.LOCAL_ACCEPT;
-import static org.briarproject.api.introduction.IntroduceeAction.LOCAL_DECLINE;
-import static org.briarproject.api.introduction.IntroduceeAction.REMOTE_ABORT;
-import static org.briarproject.api.introduction.IntroduceeProtocolState.AWAIT_ACK;
-import static org.briarproject.api.introduction.IntroduceeProtocolState.AWAIT_REMOTE_RESPONSE;
-import static org.briarproject.api.introduction.IntroduceeProtocolState.AWAIT_REQUEST;
-import static org.briarproject.api.introduction.IntroduceeProtocolState.AWAIT_RESPONSES;
-import static org.briarproject.api.introduction.IntroduceeProtocolState.ERROR;
-import static org.briarproject.api.introduction.IntroduceeProtocolState.FINISHED;
-import static org.briarproject.api.introduction.IntroductionConstants.ACCEPT;
-import static org.briarproject.api.introduction.IntroductionConstants.ANSWERED;
-import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_ID_1;
-import static org.briarproject.api.introduction.IntroductionConstants.EXISTS;
-import static org.briarproject.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
-import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.INTRODUCER;
-import static org.briarproject.api.introduction.IntroductionConstants.MAC;
-import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TIME;
-import static org.briarproject.api.introduction.IntroductionConstants.MSG;
-import static org.briarproject.api.introduction.IntroductionConstants.NAME;
-import static org.briarproject.api.introduction.IntroductionConstants.NOT_OUR_RESPONSE;
-import static org.briarproject.api.introduction.IntroductionConstants.OUR_MAC;
-import static org.briarproject.api.introduction.IntroductionConstants.OUR_PUBLIC_KEY;
-import static org.briarproject.api.introduction.IntroductionConstants.OUR_SIGNATURE;
-import static org.briarproject.api.introduction.IntroductionConstants.OUR_TIME;
-import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY;
-import static org.briarproject.api.introduction.IntroductionConstants.REMOTE_AUTHOR_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.REMOTE_AUTHOR_IS_US;
-import static org.briarproject.api.introduction.IntroductionConstants.ROLE_INTRODUCEE;
-import static org.briarproject.api.introduction.IntroductionConstants.SESSION_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.SIGNATURE;
-import static org.briarproject.api.introduction.IntroductionConstants.STATE;
-import static org.briarproject.api.introduction.IntroductionConstants.TASK;
-import static org.briarproject.api.introduction.IntroductionConstants.TASK_ABORT;
-import static org.briarproject.api.introduction.IntroductionConstants.TASK_ACTIVATE_CONTACT;
-import static org.briarproject.api.introduction.IntroductionConstants.TASK_ADD_CONTACT;
-import static org.briarproject.api.introduction.IntroductionConstants.TIME;
-import static org.briarproject.api.introduction.IntroductionConstants.TRANSPORT;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ABORT;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
-
-public class IntroduceeEngine
+import static org.briarproject.briar.api.introduction.IntroduceeAction.ACK;
+import static org.briarproject.briar.api.introduction.IntroduceeAction.LOCAL_ABORT;
+import static org.briarproject.briar.api.introduction.IntroduceeAction.LOCAL_ACCEPT;
+import static org.briarproject.briar.api.introduction.IntroduceeAction.LOCAL_DECLINE;
+import static org.briarproject.briar.api.introduction.IntroduceeAction.REMOTE_ABORT;
+import static org.briarproject.briar.api.introduction.IntroduceeProtocolState.AWAIT_ACK;
+import static org.briarproject.briar.api.introduction.IntroduceeProtocolState.AWAIT_REMOTE_RESPONSE;
+import static org.briarproject.briar.api.introduction.IntroduceeProtocolState.AWAIT_REQUEST;
+import static org.briarproject.briar.api.introduction.IntroduceeProtocolState.AWAIT_RESPONSES;
+import static org.briarproject.briar.api.introduction.IntroduceeProtocolState.ERROR;
+import static org.briarproject.briar.api.introduction.IntroduceeProtocolState.FINISHED;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ACCEPT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ANSWERED;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.CONTACT_ID_1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.EXISTS;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.INTRODUCER;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MAC;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MESSAGE_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MESSAGE_TIME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MSG;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.NAME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.NOT_OUR_RESPONSE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.OUR_MAC;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.OUR_PUBLIC_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.OUR_SIGNATURE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.OUR_TIME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.PUBLIC_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.REMOTE_AUTHOR_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.REMOTE_AUTHOR_IS_US;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ROLE_INTRODUCEE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.SESSION_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.SIGNATURE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.STATE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TASK;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TASK_ABORT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TASK_ACTIVATE_CONTACT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TASK_ADD_CONTACT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TIME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TRANSPORT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_ABORT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_ACK;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_REQUEST;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_RESPONSE;
+
+@Immutable
+@NotNullByDefault
+class IntroduceeEngine
 		implements ProtocolEngine<BdfDictionary, BdfDictionary, BdfDictionary> {
 
 	private static final Logger LOG =
diff --git a/briar-core/src/org/briarproject/introduction/IntroduceeManager.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeManager.java
similarity index 71%
rename from briar-core/src/org/briarproject/introduction/IntroduceeManager.java
rename to briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeManager.java
index e0227b6bc4f436820bd75407aa8169b2fd0a9bd6..588f5396537cf6ab810c510c466680ab226f6fbb 100644
--- a/briar-core/src/org/briarproject/introduction/IntroduceeManager.java
+++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeManager.java
@@ -1,37 +1,37 @@
-package org.briarproject.introduction;
-
-import org.briarproject.api.Bytes;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.clients.ClientHelper;
-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.crypto.KeyPair;
-import org.briarproject.api.crypto.KeyParser;
-import org.briarproject.api.crypto.PrivateKey;
-import org.briarproject.api.crypto.PublicKey;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.IntroductionSucceededEvent;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.properties.TransportProperties;
-import org.briarproject.api.properties.TransportPropertyManager;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.system.Clock;
-import org.jetbrains.annotations.Nullable;
+package org.briarproject.briar.introduction;
+
+import org.briarproject.bramble.api.Bytes;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.KeyPair;
+import org.briarproject.bramble.api.crypto.KeyParser;
+import org.briarproject.bramble.api.crypto.PrivateKey;
+import org.briarproject.bramble.api.crypto.PublicKey;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.properties.TransportProperties;
+import org.briarproject.bramble.api.properties.TransportPropertyManager;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.introduction.event.IntroductionSucceededEvent;
 
 import java.io.IOException;
 import java.security.GeneralSecurityException;
@@ -40,59 +40,64 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.data.BdfDictionary.NULL_VALUE;
-import static org.briarproject.api.introduction.IntroduceeProtocolState.AWAIT_REQUEST;
-import static org.briarproject.api.introduction.IntroductionConstants.ACCEPT;
-import static org.briarproject.api.introduction.IntroductionConstants.ADDED_CONTACT_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.ANSWERED;
-import static org.briarproject.api.introduction.IntroductionConstants.CONTACT;
-import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_ID_1;
-import static org.briarproject.api.introduction.IntroductionConstants.EXISTS;
-import static org.briarproject.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
-import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.INTRODUCER;
-import static org.briarproject.api.introduction.IntroductionConstants.LOCAL_AUTHOR_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.MAC;
-import static org.briarproject.api.introduction.IntroductionConstants.MAC_KEY;
-import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TIME;
-import static org.briarproject.api.introduction.IntroductionConstants.NAME;
-import static org.briarproject.api.introduction.IntroductionConstants.NONCE;
-import static org.briarproject.api.introduction.IntroductionConstants.NOT_OUR_RESPONSE;
-import static org.briarproject.api.introduction.IntroductionConstants.OUR_MAC;
-import static org.briarproject.api.introduction.IntroductionConstants.OUR_PRIVATE_KEY;
-import static org.briarproject.api.introduction.IntroductionConstants.OUR_PUBLIC_KEY;
-import static org.briarproject.api.introduction.IntroductionConstants.OUR_SIGNATURE;
-import static org.briarproject.api.introduction.IntroductionConstants.OUR_TIME;
-import static org.briarproject.api.introduction.IntroductionConstants.OUR_TRANSPORT;
-import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY;
-import static org.briarproject.api.introduction.IntroductionConstants.REMOTE_AUTHOR_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.REMOTE_AUTHOR_IS_US;
-import static org.briarproject.api.introduction.IntroductionConstants.ROLE;
-import static org.briarproject.api.introduction.IntroductionConstants.ROLE_INTRODUCEE;
-import static org.briarproject.api.introduction.IntroductionConstants.SIGNATURE;
-import static org.briarproject.api.introduction.IntroductionConstants.STATE;
-import static org.briarproject.api.introduction.IntroductionConstants.STORAGE_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.TASK;
-import static org.briarproject.api.introduction.IntroductionConstants.TASK_ABORT;
-import static org.briarproject.api.introduction.IntroductionConstants.TASK_ACTIVATE_CONTACT;
-import static org.briarproject.api.introduction.IntroductionConstants.TASK_ADD_CONTACT;
-import static org.briarproject.api.introduction.IntroductionConstants.TIME;
-import static org.briarproject.api.introduction.IntroductionConstants.TRANSPORT;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ABORT;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
-import static org.briarproject.api.introduction.IntroductionManager.CLIENT_ID;
-
+import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
+import static org.briarproject.briar.api.introduction.IntroduceeProtocolState.AWAIT_REQUEST;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ACCEPT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ADDED_CONTACT_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ANSWERED;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.CONTACT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.CONTACT_ID_1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.EXISTS;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.INTRODUCER;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.LOCAL_AUTHOR_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MAC;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MAC_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MESSAGE_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MESSAGE_TIME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.NAME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.NONCE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.NOT_OUR_RESPONSE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.OUR_MAC;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.OUR_PRIVATE_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.OUR_PUBLIC_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.OUR_SIGNATURE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.OUR_TIME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.OUR_TRANSPORT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.PUBLIC_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.REMOTE_AUTHOR_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.REMOTE_AUTHOR_IS_US;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ROLE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ROLE_INTRODUCEE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.SIGNATURE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.STATE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.STORAGE_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TASK;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TASK_ABORT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TASK_ACTIVATE_CONTACT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TASK_ADD_CONTACT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TIME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TRANSPORT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_ABORT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_ACK;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_RESPONSE;
+import static org.briarproject.briar.api.introduction.IntroductionManager.CLIENT_ID;
+
+@Immutable
+@NotNullByDefault
 class IntroduceeManager {
 
 	private static final Logger LOG =
 			Logger.getLogger(IntroduceeManager.class.getName());
+
 	static final String SIGNING_LABEL_RESPONSE = CLIENT_ID + "/RESPONSE";
 
 	private final MessageSender messageSender;
@@ -168,7 +173,7 @@ class IntroduceeManager {
 		d.put(REMOTE_AUTHOR_ID, remoteAuthorId);
 
 		// check if someone is trying to introduce us to ourselves
-		if(remoteAuthorId.equals(introducer.getLocalAuthorId())) {
+		if (remoteAuthorId.equals(introducer.getLocalAuthorId())) {
 			LOG.warning("Received Introduction Request to Ourselves");
 			throw new FormatException();
 		}
@@ -188,12 +193,12 @@ class IntroduceeManager {
 			BdfDictionary message) throws DbException, FormatException {
 
 		IntroduceeEngine engine = new IntroduceeEngine();
-		processStateUpdate(txn, message, engine.onMessageReceived(state, message));
+		processStateUpdate(txn, message,
+				engine.onMessageReceived(state, message));
 	}
 
-	public void acceptIntroduction(Transaction txn, BdfDictionary state,
-			final long timestamp)
-			throws DbException, FormatException {
+	void acceptIntroduction(Transaction txn, BdfDictionary state,
+			long timestamp) throws DbException, FormatException {
 
 		// get data to connect and derive a shared secret later
 		long now = clock.currentTimeMillis();
@@ -222,9 +227,8 @@ class IntroduceeManager {
 		processStateUpdate(txn, null, engine.onLocalAction(state, localAction));
 	}
 
-	public void declineIntroduction(Transaction txn, BdfDictionary state,
-			final long timestamp)
-			throws DbException, FormatException {
+	void declineIntroduction(Transaction txn, BdfDictionary state,
+			long timestamp) throws DbException, FormatException {
 
 		// update session state
 		state.put(ACCEPT, false);
@@ -240,9 +244,10 @@ class IntroduceeManager {
 				engine.onLocalAction(state, localAction));
 	}
 
-	private void processStateUpdate(Transaction txn, BdfDictionary msg,
-			IntroduceeEngine.StateUpdate<BdfDictionary, BdfDictionary>
-					result) throws DbException, FormatException {
+	private void processStateUpdate(Transaction txn,
+			@Nullable BdfDictionary msg,
+			IntroduceeEngine.StateUpdate<BdfDictionary, BdfDictionary> result)
+			throws DbException, FormatException {
 
 		// perform actions based on new local state
 		BdfDictionary followUpAction = performTasks(txn, result.localState);
@@ -281,7 +286,8 @@ class IntroduceeManager {
 	}
 
 	@Nullable
-	private BdfDictionary performTasks(Transaction txn, BdfDictionary localState)
+	private BdfDictionary performTasks(Transaction txn,
+			BdfDictionary localState)
 			throws FormatException, DbException {
 
 		if (!localState.containsKey(TASK) || localState.get(TASK) == NULL_VALUE)
@@ -313,8 +319,8 @@ class IntroduceeManager {
 			try {
 				// derive secret master key
 				secretKey =
-					deriveSecretKey(publicKeyBytes, privateKeyBytes, alice,
-							theirEphemeralKey);
+						deriveSecretKey(publicKeyBytes, privateKeyBytes, alice,
+								theirEphemeralKey);
 				// derive MAC keys and nonces, sign our nonce and calculate MAC
 				deriveMacKeysAndNonces(localState, author, secretKey, alice);
 			} catch (GeneralSecurityException e) {
@@ -429,13 +435,13 @@ class IntroduceeManager {
 
 	/**
 	 * Derives nonces, signs our nonce and calculates MAC
-	 *
+	 * <p>
 	 * Derives two nonces and two mac keys from the secret master key.
 	 * The other introducee's nonce and MAC key are added to the localState.
-	 *
+	 * <p>
 	 * Our nonce is signed with the local author's long-term private key.
 	 * The signature is added to the localState.
-	 *
+	 * <p>
 	 * Calculates a MAC and stores it in the localState.
 	 */
 	private void deriveMacKeysAndNonces(BdfDictionary localState,
diff --git a/briar-core/src/org/briarproject/introduction/IntroducerEngine.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroducerEngine.java
similarity index 68%
rename from briar-core/src/org/briarproject/introduction/IntroducerEngine.java
rename to briar-core/src/main/java/org/briarproject/briar/introduction/IntroducerEngine.java
index 0f180a622f01eea69da8f3c7aa0cb0775a3e6bd6..ea08aebd77271de3748ac9410a1c7d87b15b659e 100644
--- a/briar-core/src/org/briarproject/introduction/IntroducerEngine.java
+++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroducerEngine.java
@@ -1,19 +1,20 @@
-package org.briarproject.introduction;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ProtocolEngine;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.IntroductionAbortedEvent;
-import org.briarproject.api.event.IntroductionResponseReceivedEvent;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.introduction.IntroducerAction;
-import org.briarproject.api.introduction.IntroducerProtocolState;
-import org.briarproject.api.introduction.IntroductionResponse;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+package org.briarproject.briar.introduction;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.ProtocolEngine;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.introduction.IntroducerAction;
+import org.briarproject.briar.api.introduction.IntroducerProtocolState;
+import org.briarproject.briar.api.introduction.IntroductionResponse;
+import org.briarproject.briar.api.introduction.event.IntroductionAbortedEvent;
+import org.briarproject.briar.api.introduction.event.IntroductionResponseReceivedEvent;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -21,51 +22,55 @@ import java.util.Collections;
 import java.util.List;
 import java.util.logging.Logger;
 
+import javax.annotation.concurrent.Immutable;
+
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.introduction.IntroducerAction.LOCAL_ABORT;
-import static org.briarproject.api.introduction.IntroducerAction.LOCAL_REQUEST;
-import static org.briarproject.api.introduction.IntroducerAction.REMOTE_ACCEPT_1;
-import static org.briarproject.api.introduction.IntroducerAction.REMOTE_ACCEPT_2;
-import static org.briarproject.api.introduction.IntroducerAction.REMOTE_DECLINE_1;
-import static org.briarproject.api.introduction.IntroducerAction.REMOTE_DECLINE_2;
-import static org.briarproject.api.introduction.IntroducerProtocolState.AWAIT_ACKS;
-import static org.briarproject.api.introduction.IntroducerProtocolState.AWAIT_ACK_1;
-import static org.briarproject.api.introduction.IntroducerProtocolState.AWAIT_ACK_2;
-import static org.briarproject.api.introduction.IntroducerProtocolState.AWAIT_RESPONSES;
-import static org.briarproject.api.introduction.IntroducerProtocolState.AWAIT_RESPONSE_1;
-import static org.briarproject.api.introduction.IntroducerProtocolState.AWAIT_RESPONSE_2;
-import static org.briarproject.api.introduction.IntroducerProtocolState.ERROR;
-import static org.briarproject.api.introduction.IntroducerProtocolState.FINISHED;
-import static org.briarproject.api.introduction.IntroductionConstants.ACCEPT;
-import static org.briarproject.api.introduction.IntroductionConstants.AUTHOR_ID_1;
-import static org.briarproject.api.introduction.IntroductionConstants.AUTHOR_ID_2;
-import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_1;
-import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_2;
-import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_ID_1;
-import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_ID_2;
-import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID_1;
-import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID_2;
-import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TIME;
-import static org.briarproject.api.introduction.IntroductionConstants.MSG;
-import static org.briarproject.api.introduction.IntroductionConstants.NAME;
-import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY;
-import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY1;
-import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY2;
-import static org.briarproject.api.introduction.IntroductionConstants.RESPONSE_1;
-import static org.briarproject.api.introduction.IntroductionConstants.RESPONSE_2;
-import static org.briarproject.api.introduction.IntroductionConstants.ROLE_INTRODUCER;
-import static org.briarproject.api.introduction.IntroductionConstants.SESSION_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.STATE;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ABORT;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
-
-public class IntroducerEngine
+import static org.briarproject.briar.api.introduction.IntroducerAction.LOCAL_ABORT;
+import static org.briarproject.briar.api.introduction.IntroducerAction.LOCAL_REQUEST;
+import static org.briarproject.briar.api.introduction.IntroducerAction.REMOTE_ACCEPT_1;
+import static org.briarproject.briar.api.introduction.IntroducerAction.REMOTE_ACCEPT_2;
+import static org.briarproject.briar.api.introduction.IntroducerAction.REMOTE_DECLINE_1;
+import static org.briarproject.briar.api.introduction.IntroducerAction.REMOTE_DECLINE_2;
+import static org.briarproject.briar.api.introduction.IntroducerProtocolState.AWAIT_ACKS;
+import static org.briarproject.briar.api.introduction.IntroducerProtocolState.AWAIT_ACK_1;
+import static org.briarproject.briar.api.introduction.IntroducerProtocolState.AWAIT_ACK_2;
+import static org.briarproject.briar.api.introduction.IntroducerProtocolState.AWAIT_RESPONSES;
+import static org.briarproject.briar.api.introduction.IntroducerProtocolState.AWAIT_RESPONSE_1;
+import static org.briarproject.briar.api.introduction.IntroducerProtocolState.AWAIT_RESPONSE_2;
+import static org.briarproject.briar.api.introduction.IntroducerProtocolState.ERROR;
+import static org.briarproject.briar.api.introduction.IntroducerProtocolState.FINISHED;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ACCEPT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.AUTHOR_ID_1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.AUTHOR_ID_2;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.CONTACT_1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.CONTACT_2;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.CONTACT_ID_1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.CONTACT_ID_2;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID_1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID_2;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MESSAGE_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MESSAGE_TIME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MSG;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.NAME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.PUBLIC_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.PUBLIC_KEY1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.PUBLIC_KEY2;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.RESPONSE_1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.RESPONSE_2;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ROLE_INTRODUCER;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.SESSION_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.STATE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_ABORT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_ACK;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_REQUEST;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_RESPONSE;
+
+@Immutable
+@NotNullByDefault
+class IntroducerEngine
 		implements ProtocolEngine<BdfDictionary, BdfDictionary, BdfDictionary> {
 
 	private static final Logger LOG =
@@ -124,7 +129,8 @@ public class IntroducerEngine
 				logLocalAction(currentState, localState, msg2);
 
 				List<Event> events = Collections.emptyList();
-				return new StateUpdate<BdfDictionary, BdfDictionary>(false, false,
+				return new StateUpdate<BdfDictionary, BdfDictionary>(false,
+						false,
 						localState, messages, events);
 			} else {
 				throw new IllegalArgumentException("Unknown Local Action");
@@ -188,12 +194,14 @@ public class IntroducerEngine
 				if (action == REMOTE_ACCEPT_1 || action == REMOTE_DECLINE_1) {
 					localState.put(RESPONSE_1, msg.getRaw(MESSAGE_ID));
 					messages = Collections.emptyList();
-					events = Collections.singletonList(getEvent(localState, msg));
+					events = Collections
+							.singletonList(getEvent(localState, msg));
 				} else if (action == REMOTE_ACCEPT_2 ||
 						action == REMOTE_DECLINE_2) {
 					localState.put(RESPONSE_2, msg.getRaw(MESSAGE_ID));
 					messages = Collections.emptyList();
-					events = Collections.singletonList(getEvent(localState, msg));
+					events = Collections
+							.singletonList(getEvent(localState, msg));
 				} else return noUpdate(localState);
 			} else {
 				throw new IllegalArgumentException("Bad state");
@@ -239,7 +247,8 @@ public class IntroducerEngine
 			String from = getMessagePartner(localState, msg);
 			String to = getOtherContact(localState, msg);
 
-			LOG.info("Received " + t + " in state " + currentState.name() + " from " +
+			LOG.info("Received " + t + " in state " + currentState.name() +
+					" from " +
 					from + " to " + to + " with session ID " +
 					Arrays.hashCode(msg.getRaw(SESSION_ID)) + " in group " +
 					Arrays.hashCode(msg.getRaw(GROUP_ID)) + ". " +
@@ -274,15 +283,14 @@ public class IntroducerEngine
 			BdfDictionary localState, BdfDictionary delivered) {
 		try {
 			return noUpdate(localState);
-		}
-		catch (FormatException e) {
+		} catch (FormatException e) {
 			if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
 			return null;
 		}
 	}
 
 	private IntroducerProtocolState getState(Long state) {
-		 return IntroducerProtocolState.fromValue(state.intValue());
+		return IntroducerProtocolState.fromValue(state.intValue());
 	}
 
 	private Event getEvent(BdfDictionary localState, BdfDictionary msg)
@@ -291,7 +299,8 @@ public class IntroducerEngine
 		ContactId contactId =
 				new ContactId(localState.getLong(CONTACT_ID_1).intValue());
 		AuthorId authorId = new AuthorId(localState.getRaw(AUTHOR_ID_1));
-		if (Arrays.equals(msg.getRaw(GROUP_ID), localState.getRaw(GROUP_ID_2))) {
+		if (Arrays
+				.equals(msg.getRaw(GROUP_ID), localState.getRaw(GROUP_ID_2))) {
 			contactId =
 					new ContactId(localState.getLong(CONTACT_ID_2).intValue());
 			authorId = new AuthorId(localState.getRaw(AUTHOR_ID_2));
@@ -331,7 +340,8 @@ public class IntroducerEngine
 			BdfDictionary msg) throws FormatException {
 
 		String from = localState.getString(CONTACT_1);
-		if (Arrays.equals(msg.getRaw(GROUP_ID), localState.getRaw(GROUP_ID_2))) {
+		if (Arrays
+				.equals(msg.getRaw(GROUP_ID), localState.getRaw(GROUP_ID_2))) {
 			from = localState.getString(CONTACT_2);
 		}
 		return from;
@@ -341,7 +351,8 @@ public class IntroducerEngine
 			throws FormatException {
 
 		String to = localState.getString(CONTACT_2);
-		if (Arrays.equals(msg.getRaw(GROUP_ID), localState.getRaw(GROUP_ID_2))) {
+		if (Arrays
+				.equals(msg.getRaw(GROUP_ID), localState.getRaw(GROUP_ID_2))) {
 			to = localState.getString(CONTACT_1);
 		}
 		return to;
diff --git a/briar-core/src/org/briarproject/introduction/IntroducerManager.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroducerManager.java
similarity index 57%
rename from briar-core/src/org/briarproject/introduction/IntroducerManager.java
rename to briar-core/src/main/java/org/briarproject/briar/introduction/IntroducerManager.java
index a7ecd00cbe07ca81b03a281a7622c86dacac9bcd..07e031c6325d173a17e7afd4c8fce242e15be060 100644
--- a/briar-core/src/org/briarproject/introduction/IntroducerManager.java
+++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroducerManager.java
@@ -1,54 +1,59 @@
-package org.briarproject.introduction;
-
-import org.briarproject.api.Bytes;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.system.Clock;
-import org.briarproject.util.StringUtils;
+package org.briarproject.briar.introduction;
+
+import org.briarproject.bramble.api.Bytes;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.bramble.util.StringUtils;
 
 import java.io.IOException;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.introduction.IntroducerProtocolState.PREPARE_REQUESTS;
-import static org.briarproject.api.introduction.IntroductionConstants.AUTHOR_ID_1;
-import static org.briarproject.api.introduction.IntroductionConstants.AUTHOR_ID_2;
-import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_1;
-import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_2;
-import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_ID_1;
-import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_ID_2;
-import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID_1;
-import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID_2;
-import static org.briarproject.api.introduction.IntroductionConstants.MAX_INTRODUCTION_MESSAGE_LENGTH;
-import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TIME;
-import static org.briarproject.api.introduction.IntroductionConstants.MSG;
-import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY1;
-import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY2;
-import static org.briarproject.api.introduction.IntroductionConstants.ROLE;
-import static org.briarproject.api.introduction.IntroductionConstants.ROLE_INTRODUCER;
-import static org.briarproject.api.introduction.IntroductionConstants.SESSION_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.STATE;
-import static org.briarproject.api.introduction.IntroductionConstants.STORAGE_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ABORT;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
-
+import static org.briarproject.briar.api.introduction.IntroducerProtocolState.PREPARE_REQUESTS;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.AUTHOR_ID_1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.AUTHOR_ID_2;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.CONTACT_1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.CONTACT_2;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.CONTACT_ID_1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.CONTACT_ID_2;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID_1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID_2;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MAX_INTRODUCTION_MESSAGE_LENGTH;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MESSAGE_TIME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MSG;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.PUBLIC_KEY1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.PUBLIC_KEY2;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ROLE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ROLE_INTRODUCER;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.SESSION_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.STATE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.STORAGE_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_ABORT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_REQUEST;
+
+@Immutable
+@NotNullByDefault
 class IntroducerManager {
 
 	private static final Logger LOG =
-		Logger.getLogger(IntroducerManager.class.getName());
+			Logger.getLogger(IntroducerManager.class.getName());
 
 	private final MessageSender messageSender;
 	private final ClientHelper clientHelper;
@@ -105,7 +110,8 @@ class IntroducerManager {
 	}
 
 	void makeIntroduction(Transaction txn, Contact c1, Contact c2,
-			String msg, long timestamp) throws DbException, FormatException {
+			@Nullable String msg, long timestamp)
+			throws DbException, FormatException {
 
 		// TODO check for existing session with those contacts?
 		//      deny new introduction under which conditions?
@@ -145,7 +151,8 @@ class IntroducerManager {
 					result) throws DbException, FormatException {
 
 		// save new local state
-		MessageId storageId = new MessageId(result.localState.getRaw(STORAGE_ID));
+		MessageId storageId =
+				new MessageId(result.localState.getRaw(STORAGE_ID));
 		clientHelper.mergeMessageMetadata(txn, storageId, result.localState);
 
 		// send messages
diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionGroupFactory.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionGroupFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..8aadc03d72eb4016826986fe36b0248ab36e7914
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionGroupFactory.java
@@ -0,0 +1,30 @@
+package org.briarproject.briar.introduction;
+
+import org.briarproject.bramble.api.client.ContactGroupFactory;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.sync.Group;
+
+import javax.inject.Inject;
+
+import static org.briarproject.briar.api.introduction.IntroductionManager.CLIENT_ID;
+
+class IntroductionGroupFactory {
+
+	private final ContactGroupFactory contactGroupFactory;
+	private final Group localGroup;
+
+	@Inject
+	IntroductionGroupFactory(ContactGroupFactory contactGroupFactory) {
+		this.contactGroupFactory = contactGroupFactory;
+		localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID);
+	}
+
+	Group createIntroductionGroup(Contact c) {
+		return contactGroupFactory.createContactGroup(CLIENT_ID, c);
+	}
+
+	public Group createLocalGroup() {
+		return localGroup;
+	}
+
+}
diff --git a/briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java
similarity index 75%
rename from briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java
index 8bdae86880a0ce323f33512499448d4130fd475f..6b3884138f459db5791314084d865e3ffe1bb694 100644
--- a/briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java
@@ -1,36 +1,36 @@
-package org.briarproject.introduction;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.Client;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageTracker;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.contact.ContactManager.AddContactHook;
-import org.briarproject.api.contact.ContactManager.RemoveContactHook;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataParser;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.NoSuchContactException;
-import org.briarproject.api.db.NoSuchMessageException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.introduction.IntroducerProtocolState;
-import org.briarproject.api.introduction.IntroductionManager;
-import org.briarproject.api.introduction.IntroductionMessage;
-import org.briarproject.api.introduction.IntroductionRequest;
-import org.briarproject.api.introduction.IntroductionResponse;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.sync.MessageStatus;
-import org.briarproject.clients.ConversationClientImpl;
+package org.briarproject.briar.introduction;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager.AddContactHook;
+import org.briarproject.bramble.api.contact.ContactManager.RemoveContactHook;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataParser;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.NoSuchContactException;
+import org.briarproject.bramble.api.db.NoSuchMessageException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Client;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.MessageStatus;
+import org.briarproject.briar.api.client.MessageTracker;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.introduction.IntroducerProtocolState;
+import org.briarproject.briar.api.introduction.IntroductionManager;
+import org.briarproject.briar.api.introduction.IntroductionMessage;
+import org.briarproject.briar.api.introduction.IntroductionRequest;
+import org.briarproject.briar.api.introduction.IntroductionResponse;
+import org.briarproject.briar.client.ConversationClientImpl;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -38,44 +38,47 @@ import java.util.Collection;
 import java.util.Map;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.introduction.IntroduceeProtocolState.FINISHED;
-import static org.briarproject.api.introduction.IntroductionConstants.ACCEPT;
-import static org.briarproject.api.introduction.IntroductionConstants.ANSWERED;
-import static org.briarproject.api.introduction.IntroductionConstants.AUTHOR_ID_1;
-import static org.briarproject.api.introduction.IntroductionConstants.AUTHOR_ID_2;
-import static org.briarproject.api.introduction.IntroductionConstants.CONTACT;
-import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_1;
-import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_2;
-import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_ID_1;
-import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_ID_2;
-import static org.briarproject.api.introduction.IntroductionConstants.EXISTS;
-import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID_1;
-import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID_2;
-import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TIME;
-import static org.briarproject.api.introduction.IntroductionConstants.MSG;
-import static org.briarproject.api.introduction.IntroductionConstants.NAME;
-import static org.briarproject.api.introduction.IntroductionConstants.NOT_OUR_RESPONSE;
-import static org.briarproject.api.introduction.IntroductionConstants.REMOTE_AUTHOR_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.REMOTE_AUTHOR_IS_US;
-import static org.briarproject.api.introduction.IntroductionConstants.RESPONSE_1;
-import static org.briarproject.api.introduction.IntroductionConstants.RESPONSE_2;
-import static org.briarproject.api.introduction.IntroductionConstants.ROLE;
-import static org.briarproject.api.introduction.IntroductionConstants.ROLE_INTRODUCEE;
-import static org.briarproject.api.introduction.IntroductionConstants.ROLE_INTRODUCER;
-import static org.briarproject.api.introduction.IntroductionConstants.SESSION_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.STATE;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ABORT;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
-import static org.briarproject.api.sync.Group.Visibility.SHARED;
-import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
-
+import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
+import static org.briarproject.briar.api.introduction.IntroduceeProtocolState.FINISHED;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ACCEPT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ANSWERED;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.AUTHOR_ID_1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.AUTHOR_ID_2;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.CONTACT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.CONTACT_1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.CONTACT_2;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.CONTACT_ID_1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.CONTACT_ID_2;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.EXISTS;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID_1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID_2;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MESSAGE_TIME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MSG;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.NAME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.NOT_OUR_RESPONSE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.REMOTE_AUTHOR_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.REMOTE_AUTHOR_IS_US;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.RESPONSE_1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.RESPONSE_2;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ROLE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ROLE_INTRODUCEE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ROLE_INTRODUCER;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.SESSION_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.STATE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_ABORT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_ACK;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_REQUEST;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_RESPONSE;
+import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
+
+@Immutable
 @NotNullByDefault
 class IntroductionManagerImpl extends ConversationClientImpl
 		implements IntroductionManager, Client, AddContactHook,
@@ -273,9 +276,8 @@ class IntroductionManagerImpl extends ConversationClientImpl
 	}
 
 	@Override
-	public void makeIntroduction(Contact c1, Contact c2, String msg,
-			final long timestamp)
-			throws DbException, FormatException {
+	public void makeIntroduction(Contact c1, Contact c2, @Nullable String msg,
+			final long timestamp) throws DbException, FormatException {
 
 		Transaction txn = db.startTransaction(false);
 		try {
diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionModule.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionModule.java
new file mode 100644
index 0000000000000000000000000000000000000000..a4c3b8e2937ad889379e17313e5e9bb47441b79c
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionModule.java
@@ -0,0 +1,62 @@
+package org.briarproject.briar.introduction;
+
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.client.MessageQueueManager;
+import org.briarproject.briar.api.introduction.IntroductionManager;
+import org.briarproject.briar.api.messaging.ConversationManager;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import dagger.Module;
+import dagger.Provides;
+
+import static org.briarproject.briar.api.introduction.IntroductionManager.CLIENT_ID;
+
+@Module
+public class IntroductionModule {
+
+	public static class EagerSingletons {
+		@Inject
+		IntroductionManager introductionManager;
+		@Inject
+		IntroductionValidator introductionValidator;
+	}
+
+	@Provides
+	@Singleton
+	IntroductionValidator provideValidator(
+			MessageQueueManager messageQueueManager,
+			MetadataEncoder metadataEncoder, ClientHelper clientHelper,
+			Clock clock) {
+
+		IntroductionValidator introductionValidator = new IntroductionValidator(
+				clientHelper, metadataEncoder, clock);
+		messageQueueManager.registerMessageValidator(CLIENT_ID,
+				introductionValidator);
+
+		return introductionValidator;
+	}
+
+	@Provides
+	@Singleton
+	IntroductionManager provideIntroductionManager(
+			LifecycleManager lifecycleManager, ContactManager contactManager,
+			MessageQueueManager messageQueueManager,
+			ConversationManager conversationManager,
+			IntroductionManagerImpl introductionManager) {
+
+		lifecycleManager.registerClient(introductionManager);
+		contactManager.registerAddContactHook(introductionManager);
+		contactManager.registerRemoveContactHook(introductionManager);
+		messageQueueManager.registerIncomingMessageHook(CLIENT_ID,
+				introductionManager);
+		conversationManager.registerConversationClient(introductionManager);
+
+		return introductionManager;
+	}
+}
diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionValidator.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionValidator.java
new file mode 100644
index 0000000000000000000000000000000000000000..3b71d42d587198504a60467949dcb8c62740fa81
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionValidator.java
@@ -0,0 +1,188 @@
+package org.briarproject.briar.introduction;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.BdfMessageContext;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.client.BdfQueueMessageValidator;
+
+import javax.annotation.concurrent.Immutable;
+
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
+import static org.briarproject.bramble.api.plugin.TransportId.MAX_TRANSPORT_ID_LENGTH;
+import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MAX_PROPERTIES_PER_TRANSPORT;
+import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
+import static org.briarproject.bramble.util.ValidationUtils.checkLength;
+import static org.briarproject.bramble.util.ValidationUtils.checkSize;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ACCEPT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MAC;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MAC_LENGTH;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MAX_INTRODUCTION_MESSAGE_LENGTH;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MESSAGE_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MESSAGE_TIME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MSG;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.NAME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.PUBLIC_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.SESSION_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.SIGNATURE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TIME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TRANSPORT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_ABORT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_ACK;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_REQUEST;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_RESPONSE;
+
+@Immutable
+@NotNullByDefault
+class IntroductionValidator extends BdfQueueMessageValidator {
+
+	IntroductionValidator(ClientHelper clientHelper,
+			MetadataEncoder metadataEncoder, Clock clock) {
+		super(clientHelper, metadataEncoder, clock);
+	}
+
+	@Override
+	protected BdfMessageContext validateMessage(Message m, Group g,
+			BdfList body) throws FormatException {
+
+		BdfDictionary d;
+		long type = body.getLong(0);
+		byte[] id = body.getRaw(1);
+		checkLength(id, SessionId.LENGTH);
+
+		if (type == TYPE_REQUEST) {
+			d = validateRequest(body);
+		} else if (type == TYPE_RESPONSE) {
+			d = validateResponse(body);
+		} else if (type == TYPE_ACK) {
+			d = validateAck(body);
+		} else if (type == TYPE_ABORT) {
+			d = validateAbort(body);
+		} else {
+			throw new FormatException();
+		}
+
+		d.put(TYPE, type);
+		d.put(SESSION_ID, id);
+		d.put(GROUP_ID, m.getGroupId());
+		d.put(MESSAGE_ID, m.getId());
+		d.put(MESSAGE_TIME, m.getTimestamp());
+		return new BdfMessageContext(d);
+	}
+
+	private BdfDictionary validateRequest(BdfList message)
+			throws FormatException {
+
+		checkSize(message, 4, 5);
+
+		// parse contact name
+		String name = message.getString(2);
+		checkLength(name, 1, MAX_AUTHOR_NAME_LENGTH);
+
+		// parse contact's public key
+		byte[] key = message.getRaw(3);
+		checkLength(key, 0, MAX_PUBLIC_KEY_LENGTH);
+
+		// parse (optional) message
+		String msg = null;
+		if (message.size() == 5) {
+			msg = message.getString(4);
+			checkLength(msg, 0, MAX_INTRODUCTION_MESSAGE_LENGTH);
+		}
+
+		// Return the metadata
+		BdfDictionary d = new BdfDictionary();
+		d.put(NAME, name);
+		d.put(PUBLIC_KEY, key);
+		if (msg != null) {
+			d.put(MSG, msg);
+		}
+		return d;
+	}
+
+	private BdfDictionary validateResponse(BdfList message)
+			throws FormatException {
+
+		checkSize(message, 3, 6);
+
+		// parse accept/decline
+		boolean accept = message.getBoolean(2);
+
+		long time = 0;
+		byte[] pubkey = null;
+		BdfDictionary tp = new BdfDictionary();
+		if (accept) {
+			checkSize(message, 6);
+
+			// parse timestamp
+			time = message.getLong(3);
+
+			// parse ephemeral public key
+			pubkey = message.getRaw(4);
+			checkLength(pubkey, 0, MAX_PUBLIC_KEY_LENGTH);
+
+			// parse transport properties
+			tp = message.getDictionary(5);
+			if (tp.size() < 1) throw new FormatException();
+			for (String tId : tp.keySet()) {
+				checkLength(tId, 1, MAX_TRANSPORT_ID_LENGTH);
+				BdfDictionary tProps = tp.getDictionary(tId);
+				checkSize(tProps, 0, MAX_PROPERTIES_PER_TRANSPORT);
+				for (String propId : tProps.keySet()) {
+					checkLength(propId, 0, MAX_PROPERTY_LENGTH);
+					String prop = tProps.getString(propId);
+					checkLength(prop, 0, MAX_PROPERTY_LENGTH);
+				}
+			}
+		} else {
+			checkSize(message, 3);
+		}
+
+		// Return the metadata
+		BdfDictionary d = new BdfDictionary();
+		d.put(ACCEPT, accept);
+		if (accept) {
+			d.put(TIME, time);
+			d.put(E_PUBLIC_KEY, pubkey);
+			d.put(TRANSPORT, tp);
+		}
+		return d;
+	}
+
+	private BdfDictionary validateAck(BdfList message) throws FormatException {
+		checkSize(message, 4);
+
+		byte[] mac = message.getRaw(2);
+		checkLength(mac, 1, MAC_LENGTH);
+
+		byte[] sig = message.getRaw(3);
+		checkLength(sig, 1, MAX_SIGNATURE_LENGTH);
+
+		// Return the metadata
+		BdfDictionary d = new BdfDictionary();
+		d.put(MAC, mac);
+		d.put(SIGNATURE, sig);
+		return d;
+	}
+
+	private BdfDictionary validateAbort(BdfList message)
+			throws FormatException {
+
+		checkSize(message, 2);
+
+		// Return the metadata
+		return new BdfDictionary();
+	}
+}
diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/MessageSender.java b/briar-core/src/main/java/org/briarproject/briar/introduction/MessageSender.java
new file mode 100644
index 0000000000000000000000000000000000000000..7848aaf3dcd4fadba978f7cf576e763873c174d5
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/introduction/MessageSender.java
@@ -0,0 +1,125 @@
+package org.briarproject.briar.introduction;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.client.MessageQueueManager;
+
+import javax.annotation.concurrent.Immutable;
+import javax.inject.Inject;
+
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ACCEPT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MAC;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MESSAGE_TIME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MSG;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.NAME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.PUBLIC_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.SESSION_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.SIGNATURE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TIME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TRANSPORT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_ABORT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_ACK;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_REQUEST;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_RESPONSE;
+
+@Immutable
+@NotNullByDefault
+class MessageSender {
+
+	private final DatabaseComponent db;
+	private final ClientHelper clientHelper;
+	private final Clock clock;
+	private final MetadataEncoder metadataEncoder;
+	private final MessageQueueManager messageQueueManager;
+
+	@Inject
+	MessageSender(DatabaseComponent db, ClientHelper clientHelper, Clock clock,
+			MetadataEncoder metadataEncoder,
+			MessageQueueManager messageQueueManager) {
+
+		this.db = db;
+		this.clientHelper = clientHelper;
+		this.clock = clock;
+		this.metadataEncoder = metadataEncoder;
+		this.messageQueueManager = messageQueueManager;
+	}
+
+	void sendMessage(Transaction txn, BdfDictionary message)
+			throws DbException, FormatException {
+
+		BdfList bdfList = encodeMessage(message);
+		byte[] body = clientHelper.toByteArray(bdfList);
+		GroupId groupId = new GroupId(message.getRaw(GROUP_ID));
+		Group group = db.getGroup(txn, groupId);
+		long timestamp = clock.currentTimeMillis();
+
+		message.put(MESSAGE_TIME, timestamp);
+		Metadata metadata = metadataEncoder.encode(message);
+
+		messageQueueManager.sendMessage(txn, group, timestamp, body, metadata);
+	}
+
+	private BdfList encodeMessage(BdfDictionary d) throws FormatException {
+
+		BdfList body;
+		long type = d.getLong(TYPE);
+		if (type == TYPE_REQUEST) {
+			body = encodeRequest(d);
+		} else if (type == TYPE_RESPONSE) {
+			body = encodeResponse(d);
+		} else if (type == TYPE_ACK) {
+			body = encodeAck(d);
+		} else if (type == TYPE_ABORT) {
+			body = encodeAbort(d);
+		} else {
+			throw new FormatException();
+		}
+		return body;
+	}
+
+	private BdfList encodeRequest(BdfDictionary d) throws FormatException {
+		BdfList list = BdfList.of(TYPE_REQUEST, d.getRaw(SESSION_ID),
+				d.getString(NAME), d.getRaw(PUBLIC_KEY));
+
+		if (d.containsKey(MSG)) {
+			list.add(d.getString(MSG));
+		}
+		return list;
+	}
+
+	private BdfList encodeResponse(BdfDictionary d) throws FormatException {
+		BdfList list = BdfList.of(TYPE_RESPONSE, d.getRaw(SESSION_ID),
+				d.getBoolean(ACCEPT));
+
+		if (d.getBoolean(ACCEPT)) {
+			list.add(d.getLong(TIME));
+			list.add(d.getRaw(E_PUBLIC_KEY));
+			list.add(d.getDictionary(TRANSPORT));
+		}
+		return list;
+	}
+
+	private BdfList encodeAck(BdfDictionary d) throws FormatException {
+		return BdfList.of(TYPE_ACK, d.getRaw(SESSION_ID), d.getRaw(MAC),
+				d.getRaw(SIGNATURE));
+	}
+
+	private BdfList encodeAbort(BdfDictionary d) throws FormatException {
+		return BdfList.of(TYPE_ABORT, d.getRaw(SESSION_ID));
+	}
+
+}
diff --git a/briar-core/src/org/briarproject/messaging/ConversationManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/messaging/ConversationManagerImpl.java
similarity index 64%
rename from briar-core/src/org/briarproject/messaging/ConversationManagerImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/messaging/ConversationManagerImpl.java
index 2a480850a605fb0fcf705ac98ea8d740e18f21c2..6d310756ca98a286095c41b4642de1aa1541de91 100644
--- a/briar-core/src/org/briarproject/messaging/ConversationManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/messaging/ConversationManagerImpl.java
@@ -1,18 +1,20 @@
-package org.briarproject.messaging;
+package org.briarproject.briar.messaging;
 
-import org.briarproject.api.clients.MessageTracker.GroupCount;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.messaging.ConversationManager;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.api.client.MessageTracker.GroupCount;
+import org.briarproject.briar.api.messaging.ConversationManager;
 
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArraySet;
 
+import javax.annotation.concurrent.ThreadSafe;
 import javax.inject.Inject;
 
+@ThreadSafe
 @NotNullByDefault
 class ConversationManagerImpl implements ConversationManager {
 
@@ -27,10 +29,8 @@ class ConversationManagerImpl implements ConversationManager {
 
 	@Override
 	public void registerConversationClient(ConversationClient client) {
-		if (!clients.add(client)) {
-			throw new IllegalStateException(
-					"This client is already registered");
-		}
+		if (!clients.add(client))
+			throw new IllegalStateException("Client is already registered");
 	}
 
 	@Override
diff --git a/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java
similarity index 75%
rename from briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java
index 90fbe5c79f5e6887aae9a33d2cf8325bb7d04f72..28a4726b064db48e73c506c83e09a5c7f6d7ff91 100644
--- a/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java
@@ -1,41 +1,43 @@
-package org.briarproject.messaging;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.Client;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.ContactGroupFactory;
-import org.briarproject.api.clients.MessageTracker;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.contact.ContactManager.AddContactHook;
-import org.briarproject.api.contact.ContactManager.RemoveContactHook;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataParser;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.PrivateMessageReceivedEvent;
-import org.briarproject.api.messaging.MessagingManager;
-import org.briarproject.api.messaging.PrivateMessage;
-import org.briarproject.api.messaging.PrivateMessageHeader;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.sync.MessageStatus;
-import org.briarproject.clients.ConversationClientImpl;
+package org.briarproject.briar.messaging;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.client.ContactGroupFactory;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager.AddContactHook;
+import org.briarproject.bramble.api.contact.ContactManager.RemoveContactHook;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataParser;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Client;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.MessageStatus;
+import org.briarproject.briar.api.client.MessageTracker;
+import org.briarproject.briar.api.messaging.MessagingManager;
+import org.briarproject.briar.api.messaging.PrivateMessage;
+import org.briarproject.briar.api.messaging.PrivateMessageHeader;
+import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent;
+import org.briarproject.briar.client.ConversationClientImpl;
 
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Map;
 
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-import static org.briarproject.api.sync.Group.Visibility.SHARED;
-import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
+import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
+import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
 
+@Immutable
 @NotNullByDefault
 class MessagingManagerImpl extends ConversationClientImpl
 		implements MessagingManager, Client, AddContactHook, RemoveContactHook {
diff --git a/briar-core/src/org/briarproject/messaging/MessagingModule.java b/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingModule.java
similarity index 64%
rename from briar-core/src/org/briarproject/messaging/MessagingModule.java
rename to briar-core/src/main/java/org/briarproject/briar/messaging/MessagingModule.java
index 243042dbc49c857e88a3cc158110d9d8d19601cb..87aed0765b51880fd816de075907e04429b0086e 100644
--- a/briar-core/src/org/briarproject/messaging/MessagingModule.java
+++ b/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingModule.java
@@ -1,14 +1,14 @@
-package org.briarproject.messaging;
+package org.briarproject.briar.messaging;
 
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.messaging.ConversationManager;
-import org.briarproject.api.messaging.MessagingManager;
-import org.briarproject.api.messaging.PrivateMessageFactory;
-import org.briarproject.api.sync.ValidationManager;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.sync.ValidationManager;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.messaging.ConversationManager;
+import org.briarproject.briar.api.messaging.MessagingManager;
+import org.briarproject.briar.api.messaging.PrivateMessageFactory;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -16,15 +16,18 @@ import javax.inject.Singleton;
 import dagger.Module;
 import dagger.Provides;
 
-import static org.briarproject.messaging.MessagingManagerImpl.CLIENT_ID;
+import static org.briarproject.briar.messaging.MessagingManagerImpl.CLIENT_ID;
 
 @Module
 public class MessagingModule {
 
 	public static class EagerSingletons {
-		@Inject MessagingManager messagingManager;
-		@Inject ConversationManager conversationManager;
-		@Inject PrivateMessageValidator privateMessageValidator;
+		@Inject
+		MessagingManager messagingManager;
+		@Inject
+		ConversationManager conversationManager;
+		@Inject
+		PrivateMessageValidator privateMessageValidator;
 	}
 
 	@Provides
diff --git a/briar-core/src/main/java/org/briarproject/briar/messaging/PrivateMessageFactoryImpl.java b/briar-core/src/main/java/org/briarproject/briar/messaging/PrivateMessageFactoryImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..d3b73f8b5b51d0ca704bec365c219f14f2d5e776
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/messaging/PrivateMessageFactoryImpl.java
@@ -0,0 +1,40 @@
+package org.briarproject.briar.messaging;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.briar.api.messaging.PrivateMessage;
+import org.briarproject.briar.api.messaging.PrivateMessageFactory;
+
+import javax.annotation.concurrent.Immutable;
+import javax.inject.Inject;
+
+import static org.briarproject.bramble.util.StringUtils.utf8IsTooLong;
+import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
+
+@Immutable
+@NotNullByDefault
+class PrivateMessageFactoryImpl implements PrivateMessageFactory {
+
+	private final ClientHelper clientHelper;
+
+	@Inject
+	PrivateMessageFactoryImpl(ClientHelper clientHelper) {
+		this.clientHelper = clientHelper;
+	}
+
+	@Override
+	public PrivateMessage createPrivateMessage(GroupId groupId, long timestamp,
+			String body) throws FormatException {
+		// Validate the arguments
+		if (utf8IsTooLong(body, MAX_PRIVATE_MESSAGE_BODY_LENGTH))
+			throw new IllegalArgumentException();
+		// Serialise the message
+		BdfList message = BdfList.of(body);
+		Message m = clientHelper.createMessage(groupId, timestamp, message);
+		return new PrivateMessage(m);
+	}
+}
diff --git a/briar-core/src/main/java/org/briarproject/briar/messaging/PrivateMessageValidator.java b/briar-core/src/main/java/org/briarproject/briar/messaging/PrivateMessageValidator.java
new file mode 100644
index 0000000000000000000000000000000000000000..a93218210d51b553395d93f58edbde6e6237f244
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/messaging/PrivateMessageValidator.java
@@ -0,0 +1,46 @@
+package org.briarproject.briar.messaging;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.BdfMessageContext;
+import org.briarproject.bramble.api.client.BdfMessageValidator;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.system.Clock;
+
+import javax.annotation.concurrent.Immutable;
+
+import static org.briarproject.bramble.util.ValidationUtils.checkLength;
+import static org.briarproject.bramble.util.ValidationUtils.checkSize;
+import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
+import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
+
+@Immutable
+@NotNullByDefault
+class PrivateMessageValidator extends BdfMessageValidator {
+
+	PrivateMessageValidator(ClientHelper clientHelper,
+			MetadataEncoder metadataEncoder, Clock clock) {
+		super(clientHelper, metadataEncoder, clock);
+	}
+
+	@Override
+	protected BdfMessageContext validateMessage(Message m, Group g,
+			BdfList body) throws FormatException {
+		// private message body
+		checkSize(body, 1);
+		// Private message body
+		String privateMessageBody = body.getString(0);
+		checkLength(privateMessageBody, 0, MAX_PRIVATE_MESSAGE_BODY_LENGTH);
+		// Return the metadata
+		BdfDictionary meta = new BdfDictionary();
+		meta.put("timestamp", m.getTimestamp());
+		meta.put("local", false);
+		meta.put(MSG_KEY_READ, false);
+		return new BdfMessageContext(meta);
+	}
+}
diff --git a/briar-core/src/org/briarproject/privategroup/GroupConstants.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/GroupConstants.java
similarity index 83%
rename from briar-core/src/org/briarproject/privategroup/GroupConstants.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/GroupConstants.java
index b1e203aa7a1da3c23f3732948aa6f74f1e7a1aca..684ecb401eedfe1c2134f5005f7e76c4c7631d62 100644
--- a/briar-core/src/org/briarproject/privategroup/GroupConstants.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/GroupConstants.java
@@ -1,6 +1,6 @@
-package org.briarproject.privategroup;
+package org.briarproject.briar.privategroup;
 
-import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
+import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
 
 interface GroupConstants {
 
diff --git a/briar-core/src/org/briarproject/privategroup/GroupMessageFactoryImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/GroupMessageFactoryImpl.java
similarity index 74%
rename from briar-core/src/org/briarproject/privategroup/GroupMessageFactoryImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/GroupMessageFactoryImpl.java
index 71d6ebbeefad49bef35ae9b46d8305983a027f3d..5c2b9fc8de590c42e3b495400fa93619921afca6 100644
--- a/briar-core/src/org/briarproject/privategroup/GroupMessageFactoryImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/GroupMessageFactoryImpl.java
@@ -1,24 +1,26 @@
-package org.briarproject.privategroup;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.privategroup.GroupMessage;
-import org.briarproject.api.privategroup.GroupMessageFactory;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.Nullable;
+package org.briarproject.briar.privategroup;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.privategroup.GroupMessage;
+import org.briarproject.briar.api.privategroup.GroupMessageFactory;
 
 import java.security.GeneralSecurityException;
 
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-import static org.briarproject.api.privategroup.MessageType.JOIN;
-import static org.briarproject.api.privategroup.MessageType.POST;
+import static org.briarproject.briar.api.privategroup.MessageType.JOIN;
+import static org.briarproject.briar.api.privategroup.MessageType.POST;
 
+@Immutable
 @NotNullByDefault
 class GroupMessageFactoryImpl implements GroupMessageFactory {
 
diff --git a/briar-core/src/org/briarproject/privategroup/GroupMessageValidator.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/GroupMessageValidator.java
similarity index 69%
rename from briar-core/src/org/briarproject/privategroup/GroupMessageValidator.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/GroupMessageValidator.java
index 76f5b6b3747b6aebb961d1907e2561166d2835ce..94089cdb5e601ad6e3d0799ad661f42bdbc0776d 100644
--- a/briar-core/src/org/briarproject/privategroup/GroupMessageValidator.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/GroupMessageValidator.java
@@ -1,47 +1,52 @@
-package org.briarproject.privategroup;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.BdfMessageContext;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.privategroup.PrivateGroupFactory;
-import org.briarproject.api.privategroup.invitation.GroupInvitationFactory;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.InvalidMessageException;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.system.Clock;
-import org.briarproject.clients.BdfMessageValidator;
+package org.briarproject.briar.privategroup;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.BdfMessageContext;
+import org.briarproject.bramble.api.client.BdfMessageValidator;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.InvalidMessageException;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory;
 
 import java.security.GeneralSecurityException;
 import java.util.ArrayList;
 import java.util.Collection;
 
-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.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
-import static org.briarproject.api.privategroup.GroupMessageFactory.SIGNING_LABEL_JOIN;
-import static org.briarproject.api.privategroup.GroupMessageFactory.SIGNING_LABEL_POST;
-import static org.briarproject.api.privategroup.MessageType.JOIN;
-import static org.briarproject.api.privategroup.MessageType.POST;
-import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH;
-import static org.briarproject.api.privategroup.invitation.GroupInvitationFactory.SIGNING_LABEL_INVITE;
-import static org.briarproject.privategroup.GroupConstants.KEY_INITIAL_JOIN_MSG;
-import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_ID;
-import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_NAME;
-import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_PUBLIC_KEY;
-import static org.briarproject.privategroup.GroupConstants.KEY_PARENT_MSG_ID;
-import static org.briarproject.privategroup.GroupConstants.KEY_PREVIOUS_MSG_ID;
-import static org.briarproject.privategroup.GroupConstants.KEY_READ;
-import static org.briarproject.privategroup.GroupConstants.KEY_TIMESTAMP;
-import static org.briarproject.privategroup.GroupConstants.KEY_TYPE;
-
+import javax.annotation.concurrent.Immutable;
+
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
+import static org.briarproject.bramble.util.ValidationUtils.checkLength;
+import static org.briarproject.bramble.util.ValidationUtils.checkSize;
+import static org.briarproject.briar.api.privategroup.GroupMessageFactory.SIGNING_LABEL_JOIN;
+import static org.briarproject.briar.api.privategroup.GroupMessageFactory.SIGNING_LABEL_POST;
+import static org.briarproject.briar.api.privategroup.MessageType.JOIN;
+import static org.briarproject.briar.api.privategroup.MessageType.POST;
+import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH;
+import static org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory.SIGNING_LABEL_INVITE;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_INITIAL_JOIN_MSG;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_MEMBER_ID;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_MEMBER_NAME;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_MEMBER_PUBLIC_KEY;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_PARENT_MSG_ID;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_PREVIOUS_MSG_ID;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_READ;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_TIMESTAMP;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_TYPE;
+
+@Immutable
 @NotNullByDefault
 class GroupMessageValidator extends BdfMessageValidator {
 
diff --git a/briar-core/src/org/briarproject/privategroup/PrivateGroupFactoryImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupFactoryImpl.java
similarity index 64%
rename from briar-core/src/org/briarproject/privategroup/PrivateGroupFactoryImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupFactoryImpl.java
index 183bcbd7b704d93449c4d845f10ebb89a3242edf..4a19e68ebbe127840874063cc135a902953e5f80 100644
--- a/briar-core/src/org/briarproject/privategroup/PrivateGroupFactoryImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupFactoryImpl.java
@@ -1,24 +1,25 @@
-package org.briarproject.privategroup;
+package org.briarproject.briar.privategroup;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.privategroup.PrivateGroupFactory;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupFactory;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupFactory;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
 
 import java.security.SecureRandom;
 
 import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-import static org.briarproject.api.privategroup.PrivateGroupConstants.GROUP_SALT_LENGTH;
-import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH;
+import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.GROUP_SALT_LENGTH;
+import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH;
+import static org.briarproject.briar.api.privategroup.PrivateGroupManager.CLIENT_ID;
 
 @Immutable
 @NotNullByDefault
@@ -63,8 +64,7 @@ class PrivateGroupFactoryImpl implements PrivateGroupFactory {
 					salt
 			);
 			byte[] descriptor = clientHelper.toByteArray(group);
-			Group g = groupFactory
-					.createGroup(PrivateGroupManagerImpl.CLIENT_ID, descriptor);
+			Group g = groupFactory.createGroup(CLIENT_ID, descriptor);
 			return new PrivateGroup(g, name, author, salt);
 		} catch (FormatException e) {
 			throw new RuntimeException(e);
diff --git a/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java
similarity index 81%
rename from briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java
index 94febea167477b1599dca8e8e3caa10663f61e04..91d66bd5a572c8f747dbe2a2701bdff651e11c04 100644
--- a/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java
@@ -1,40 +1,40 @@
-package org.briarproject.privategroup;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageTracker;
-import org.briarproject.api.clients.MessageTracker.GroupCount;
-import org.briarproject.api.clients.ProtocolStateException;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataParser;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.GroupDissolvedEvent;
-import org.briarproject.api.event.GroupMessageAddedEvent;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.Author.Status;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.privategroup.ContactRelationshipRevealedEvent;
-import org.briarproject.api.privategroup.GroupMember;
-import org.briarproject.api.privategroup.GroupMessage;
-import org.briarproject.api.privategroup.GroupMessageHeader;
-import org.briarproject.api.privategroup.JoinMessageHeader;
-import org.briarproject.api.privategroup.MessageType;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.privategroup.PrivateGroupFactory;
-import org.briarproject.api.privategroup.PrivateGroupManager;
-import org.briarproject.api.privategroup.Visibility;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.clients.BdfIncomingMessageHook;
+package org.briarproject.briar.privategroup;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataParser;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.MessageTracker;
+import org.briarproject.briar.api.client.MessageTracker.GroupCount;
+import org.briarproject.briar.api.client.ProtocolStateException;
+import org.briarproject.briar.api.privategroup.GroupMember;
+import org.briarproject.briar.api.privategroup.GroupMessage;
+import org.briarproject.briar.api.privategroup.GroupMessageHeader;
+import org.briarproject.briar.api.privategroup.JoinMessageHeader;
+import org.briarproject.briar.api.privategroup.MessageType;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
+import org.briarproject.briar.api.privategroup.PrivateGroupManager;
+import org.briarproject.briar.api.privategroup.Visibility;
+import org.briarproject.briar.api.privategroup.event.ContactRelationshipRevealedEvent;
+import org.briarproject.briar.api.privategroup.event.GroupDissolvedEvent;
+import org.briarproject.briar.api.privategroup.event.GroupMessageAddedEvent;
+import org.briarproject.briar.client.BdfIncomingMessageHook;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -48,33 +48,35 @@ import java.util.Map.Entry;
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
 
+import javax.annotation.concurrent.ThreadSafe;
 import javax.inject.Inject;
 
-import static org.briarproject.api.identity.Author.Status.OURSELVES;
-import static org.briarproject.api.privategroup.MessageType.JOIN;
-import static org.briarproject.api.privategroup.MessageType.POST;
-import static org.briarproject.api.privategroup.Visibility.INVISIBLE;
-import static org.briarproject.api.privategroup.Visibility.REVEALED_BY_CONTACT;
-import static org.briarproject.api.privategroup.Visibility.REVEALED_BY_US;
-import static org.briarproject.api.privategroup.Visibility.VISIBLE;
-import static org.briarproject.privategroup.GroupConstants.GROUP_KEY_CREATOR_ID;
-import static org.briarproject.privategroup.GroupConstants.GROUP_KEY_DISSOLVED;
-import static org.briarproject.privategroup.GroupConstants.GROUP_KEY_MEMBERS;
-import static org.briarproject.privategroup.GroupConstants.GROUP_KEY_OUR_GROUP;
-import static org.briarproject.privategroup.GroupConstants.GROUP_KEY_VISIBILITY;
-import static org.briarproject.privategroup.GroupConstants.KEY_INITIAL_JOIN_MSG;
-import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_ID;
-import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_NAME;
-import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_PUBLIC_KEY;
-import static org.briarproject.privategroup.GroupConstants.KEY_PARENT_MSG_ID;
-import static org.briarproject.privategroup.GroupConstants.KEY_PREVIOUS_MSG_ID;
-import static org.briarproject.privategroup.GroupConstants.KEY_READ;
-import static org.briarproject.privategroup.GroupConstants.KEY_TIMESTAMP;
-import static org.briarproject.privategroup.GroupConstants.KEY_TYPE;
-
+import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
+import static org.briarproject.briar.api.privategroup.MessageType.JOIN;
+import static org.briarproject.briar.api.privategroup.MessageType.POST;
+import static org.briarproject.briar.api.privategroup.Visibility.INVISIBLE;
+import static org.briarproject.briar.api.privategroup.Visibility.REVEALED_BY_CONTACT;
+import static org.briarproject.briar.api.privategroup.Visibility.REVEALED_BY_US;
+import static org.briarproject.briar.api.privategroup.Visibility.VISIBLE;
+import static org.briarproject.briar.privategroup.GroupConstants.GROUP_KEY_CREATOR_ID;
+import static org.briarproject.briar.privategroup.GroupConstants.GROUP_KEY_DISSOLVED;
+import static org.briarproject.briar.privategroup.GroupConstants.GROUP_KEY_MEMBERS;
+import static org.briarproject.briar.privategroup.GroupConstants.GROUP_KEY_OUR_GROUP;
+import static org.briarproject.briar.privategroup.GroupConstants.GROUP_KEY_VISIBILITY;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_INITIAL_JOIN_MSG;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_MEMBER_ID;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_MEMBER_NAME;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_MEMBER_PUBLIC_KEY;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_PARENT_MSG_ID;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_PREVIOUS_MSG_ID;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_READ;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_TIMESTAMP;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_TYPE;
+
+@ThreadSafe
 @NotNullByDefault
-public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
-		PrivateGroupManager {
+class PrivateGroupManagerImpl extends BdfIncomingMessageHook
+		implements PrivateGroupManager {
 
 	private final PrivateGroupFactory privateGroupFactory;
 	private final IdentityManager identityManager;
@@ -412,7 +414,7 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
 			BdfList list = meta.getList(GROUP_KEY_MEMBERS);
 			Map<Author, Visibility> members =
 					new HashMap<Author, Visibility>(list.size());
-			for (int i = 0 ; i < list.size(); i++) {
+			for (int i = 0; i < list.size(); i++) {
 				BdfDictionary d = list.getDictionary(i);
 				Author member = getAuthor(d);
 				Visibility v = getVisibility(d);
@@ -451,7 +453,7 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
 		BdfList members = meta.getList(GROUP_KEY_MEMBERS);
 		Visibility v = INVISIBLE;
 		boolean foundMember = false, changed = false;
-		for (int i = 0 ; i < members.size(); i++) {
+		for (int i = 0; i < members.size(); i++) {
 			BdfDictionary d = members.getDictionary(i);
 			AuthorId memberId = new AuthorId(d.getRaw(KEY_MEMBER_ID));
 			if (a.equals(memberId)) {
diff --git a/briar-core/src/org/briarproject/privategroup/PrivateGroupModule.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupModule.java
similarity index 66%
rename from briar-core/src/org/briarproject/privategroup/PrivateGroupModule.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupModule.java
index 0ec50e101c8fab0ccd3cb4be5542e6f8ee3905aa..883664e0369603d3c8fb32ae03d88fdf1b774dea 100644
--- a/briar-core/src/org/briarproject/privategroup/PrivateGroupModule.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupModule.java
@@ -1,14 +1,14 @@
-package org.briarproject.privategroup;
+package org.briarproject.briar.privategroup;
 
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.privategroup.GroupMessageFactory;
-import org.briarproject.api.privategroup.PrivateGroupFactory;
-import org.briarproject.api.privategroup.PrivateGroupManager;
-import org.briarproject.api.privategroup.invitation.GroupInvitationFactory;
-import org.briarproject.api.sync.ValidationManager;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.sync.ValidationManager;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.privategroup.GroupMessageFactory;
+import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
+import org.briarproject.briar.api.privategroup.PrivateGroupManager;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -16,7 +16,7 @@ import javax.inject.Singleton;
 import dagger.Module;
 import dagger.Provides;
 
-import static org.briarproject.api.privategroup.PrivateGroupManager.CLIENT_ID;
+import static org.briarproject.briar.api.privategroup.PrivateGroupManager.CLIENT_ID;
 
 @Module
 public class PrivateGroupModule {
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/AbortMessage.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/AbortMessage.java
similarity index 56%
rename from briar-core/src/org/briarproject/privategroup/invitation/AbortMessage.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/AbortMessage.java
index 7dd247ee1c18eafcf8f664476b4c2ec10044dc21..23d69d074624aaa8d32b3292784428e2eef3ecca 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/AbortMessage.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/AbortMessage.java
@@ -1,8 +1,8 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
 
 import javax.annotation.concurrent.Immutable;
 
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/AbstractProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngine.java
similarity index 79%
rename from briar-core/src/org/briarproject/privategroup/invitation/AbstractProtocolEngine.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngine.java
index 6eb230247f248f7475d2ca113757051357fa2911..36c00ffb1000a65e54810ac48187b43380d798af 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/AbstractProtocolEngine.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngine.java
@@ -1,39 +1,39 @@
-package org.briarproject.privategroup.invitation;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageTracker;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.privategroup.GroupMessage;
-import org.briarproject.api.privategroup.GroupMessageFactory;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.privategroup.PrivateGroupFactory;
-import org.briarproject.api.privategroup.PrivateGroupManager;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.Group.Visibility;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.system.Clock;
+package org.briarproject.briar.privategroup.invitation;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.Group.Visibility;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.client.MessageTracker;
+import org.briarproject.briar.api.privategroup.GroupMessage;
+import org.briarproject.briar.api.privategroup.GroupMessageFactory;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
+import org.briarproject.briar.api.privategroup.PrivateGroupManager;
 
 import java.util.Map;
 
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
 
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.GROUP_KEY_CONTACT_ID;
-import static org.briarproject.privategroup.invitation.MessageType.ABORT;
-import static org.briarproject.privategroup.invitation.MessageType.INVITE;
-import static org.briarproject.privategroup.invitation.MessageType.JOIN;
-import static org.briarproject.privategroup.invitation.MessageType.LEAVE;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.GROUP_KEY_CONTACT_ID;
+import static org.briarproject.briar.privategroup.invitation.MessageType.ABORT;
+import static org.briarproject.briar.privategroup.invitation.MessageType.INVITE;
+import static org.briarproject.briar.privategroup.invitation.MessageType.JOIN;
+import static org.briarproject.briar.privategroup.invitation.MessageType.LEAVE;
 
 @Immutable
 @NotNullByDefault
@@ -88,7 +88,7 @@ abstract class AbstractProtocolEngine<S extends Session>
 	boolean isValidDependency(S session, @Nullable MessageId dependency) {
 		MessageId expected = session.getLastRemoteMessageId();
 		if (dependency == null) return expected == null;
-		return dependency.equals(expected);
+		return expected != null && dependency.equals(expected);
 	}
 
 	void setPrivateGroupVisibility(Transaction txn, S session, Visibility v)
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/CreatorProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngine.java
similarity index 82%
rename from briar-core/src/org/briarproject/privategroup/invitation/CreatorProtocolEngine.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngine.java
index d31e88aa28e52dbca48d6e156ceccfe5ccc87831..ef5f7e85f55499bac1f2467cb26e27ca021e5716 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/CreatorProtocolEngine.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngine.java
@@ -1,35 +1,35 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageTracker;
-import org.briarproject.api.clients.ProtocolStateException;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.GroupInvitationResponseReceivedEvent;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.privategroup.GroupMessageFactory;
-import org.briarproject.api.privategroup.PrivateGroupFactory;
-import org.briarproject.api.privategroup.PrivateGroupManager;
-import org.briarproject.api.privategroup.invitation.GroupInvitationResponse;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.client.MessageTracker;
+import org.briarproject.briar.api.client.ProtocolStateException;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.privategroup.GroupMessageFactory;
+import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
+import org.briarproject.briar.api.privategroup.PrivateGroupManager;
+import org.briarproject.briar.api.privategroup.event.GroupInvitationResponseReceivedEvent;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse;
 
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
 
-import static org.briarproject.api.sync.Group.Visibility.INVISIBLE;
-import static org.briarproject.api.sync.Group.Visibility.SHARED;
-import static org.briarproject.privategroup.invitation.CreatorState.DISSOLVED;
-import static org.briarproject.privategroup.invitation.CreatorState.ERROR;
-import static org.briarproject.privategroup.invitation.CreatorState.INVITED;
-import static org.briarproject.privategroup.invitation.CreatorState.JOINED;
-import static org.briarproject.privategroup.invitation.CreatorState.LEFT;
-import static org.briarproject.privategroup.invitation.CreatorState.START;
+import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
+import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
+import static org.briarproject.briar.privategroup.invitation.CreatorState.DISSOLVED;
+import static org.briarproject.briar.privategroup.invitation.CreatorState.ERROR;
+import static org.briarproject.briar.privategroup.invitation.CreatorState.INVITED;
+import static org.briarproject.briar.privategroup.invitation.CreatorState.JOINED;
+import static org.briarproject.briar.privategroup.invitation.CreatorState.LEFT;
+import static org.briarproject.briar.privategroup.invitation.CreatorState.START;
 
 @Immutable
 @NotNullByDefault
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/CreatorSession.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/CreatorSession.java
similarity index 68%
rename from briar-core/src/org/briarproject/privategroup/invitation/CreatorSession.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/CreatorSession.java
index 62b6a05f730826a3b1cfb1fa24b9664b6b3d3509..f152158248c92e48866a29299ce008b7669dde18 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/CreatorSession.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/CreatorSession.java
@@ -1,14 +1,14 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
 
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
 
-import static org.briarproject.privategroup.invitation.CreatorState.START;
-import static org.briarproject.privategroup.invitation.Role.CREATOR;
+import static org.briarproject.briar.privategroup.invitation.CreatorState.START;
+import static org.briarproject.briar.privategroup.invitation.Role.CREATOR;
 
 @Immutable
 @NotNullByDefault
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/CreatorState.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/CreatorState.java
similarity index 62%
rename from briar-core/src/org/briarproject/privategroup/invitation/CreatorState.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/CreatorState.java
index a759ee7f34899d1e1d90c56e13f793de41c45424..4afe89c4d8319b410f1ab4be1b945446e2db30a0 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/CreatorState.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/CreatorState.java
@@ -1,7 +1,12 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.FormatException;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 enum CreatorState implements State {
 
 	START(0), INVITED(1), JOINED(2), LEFT(3), DISSOLVED(4), ERROR(5);
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationConstants.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationConstants.java
similarity index 93%
rename from briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationConstants.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationConstants.java
index 7cfe17f2dd09dcf92e00e78d75cc7fd48f281872..c55bc19f4f6b6dc2a66f61d7c059b21a12ee9d3f 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationConstants.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationConstants.java
@@ -1,4 +1,4 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
 interface GroupInvitationConstants {
 
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationFactoryImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationFactoryImpl.java
similarity index 61%
rename from briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationFactoryImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationFactoryImpl.java
index 502d4f0761aa8ecff8f9b83d7d64ec2a652b0ec0..d527674737daa3f52466a8cb5c51b58e9d7fcee5 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationFactoryImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationFactoryImpl.java
@@ -1,21 +1,25 @@
-package org.briarproject.privategroup.invitation;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.ContactGroupFactory;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.privategroup.invitation.GroupInvitationFactory;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
+package org.briarproject.briar.privategroup.invitation;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.client.ContactGroupFactory;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory;
 
 import java.security.GeneralSecurityException;
 
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-import static org.briarproject.api.privategroup.invitation.GroupInvitationManager.CLIENT_ID;
+import static org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager.CLIENT_ID;
 
+@Immutable
+@NotNullByDefault
 class GroupInvitationFactoryImpl implements GroupInvitationFactory {
 
 	private final ContactGroupFactory contactGroupFactory;
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java
similarity index 86%
rename from briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationManagerImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java
index 6873a910dbe705aba397ab1fab3444bbd0f954b4..4c57e9aff3cee702725a981dcb60ffedd886ced4 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java
@@ -1,40 +1,39 @@
-package org.briarproject.privategroup.invitation;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.Client;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.ContactGroupFactory;
-import org.briarproject.api.clients.MessageTracker;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.contact.ContactManager.AddContactHook;
-import org.briarproject.api.contact.ContactManager.RemoveContactHook;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataParser;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.privategroup.PrivateGroupFactory;
-import org.briarproject.api.privategroup.PrivateGroupManager;
-import org.briarproject.api.privategroup.PrivateGroupManager.PrivateGroupHook;
-import org.briarproject.api.privategroup.invitation.GroupInvitationItem;
-import org.briarproject.api.privategroup.invitation.GroupInvitationManager;
-import org.briarproject.api.privategroup.invitation.GroupInvitationRequest;
-import org.briarproject.api.privategroup.invitation.GroupInvitationResponse;
-import org.briarproject.api.sharing.InvitationMessage;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.sync.MessageStatus;
-import org.briarproject.clients.ConversationClientImpl;
-import org.jetbrains.annotations.Nullable;
+package org.briarproject.briar.privategroup.invitation;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.client.ContactGroupFactory;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager.AddContactHook;
+import org.briarproject.bramble.api.contact.ContactManager.RemoveContactHook;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataParser;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Client;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.MessageStatus;
+import org.briarproject.briar.api.client.MessageTracker;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
+import org.briarproject.briar.api.privategroup.PrivateGroupManager;
+import org.briarproject.briar.api.privategroup.PrivateGroupManager.PrivateGroupHook;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationItem;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse;
+import org.briarproject.briar.api.sharing.InvitationMessage;
+import org.briarproject.briar.client.ConversationClientImpl;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -42,19 +41,20 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
+import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-import static org.briarproject.api.sync.Group.Visibility.SHARED;
-import static org.briarproject.privategroup.invitation.CreatorState.START;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.GROUP_KEY_CONTACT_ID;
-import static org.briarproject.privategroup.invitation.MessageType.ABORT;
-import static org.briarproject.privategroup.invitation.MessageType.INVITE;
-import static org.briarproject.privategroup.invitation.MessageType.JOIN;
-import static org.briarproject.privategroup.invitation.MessageType.LEAVE;
-import static org.briarproject.privategroup.invitation.Role.CREATOR;
-import static org.briarproject.privategroup.invitation.Role.INVITEE;
-import static org.briarproject.privategroup.invitation.Role.PEER;
+import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
+import static org.briarproject.briar.privategroup.invitation.CreatorState.START;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.GROUP_KEY_CONTACT_ID;
+import static org.briarproject.briar.privategroup.invitation.MessageType.ABORT;
+import static org.briarproject.briar.privategroup.invitation.MessageType.INVITE;
+import static org.briarproject.briar.privategroup.invitation.MessageType.JOIN;
+import static org.briarproject.briar.privategroup.invitation.MessageType.LEAVE;
+import static org.briarproject.briar.privategroup.invitation.Role.CREATOR;
+import static org.briarproject.briar.privategroup.invitation.Role.INVITEE;
+import static org.briarproject.briar.privategroup.invitation.Role.PEER;
 
 @Immutable
 @NotNullByDefault
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationMessage.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationMessage.java
similarity index 75%
rename from briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationMessage.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationMessage.java
index 9ab719cb04d10317143ea76b8a8276f803a014d4..9344d52135b0a8c8e84335975b019f5039db685c 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationMessage.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationMessage.java
@@ -1,8 +1,8 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
 
 import javax.annotation.concurrent.Immutable;
 
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationModule.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationModule.java
similarity index 72%
rename from briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationModule.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationModule.java
index 5e2733806dcbf45fe00858719cae408933446b17..1c2ecc00ef96320704f9a4cdd17cf456800d7c0a 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationModule.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationModule.java
@@ -1,17 +1,17 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.messaging.ConversationManager;
-import org.briarproject.api.privategroup.PrivateGroupFactory;
-import org.briarproject.api.privategroup.PrivateGroupManager;
-import org.briarproject.api.privategroup.invitation.GroupInvitationFactory;
-import org.briarproject.api.privategroup.invitation.GroupInvitationManager;
-import org.briarproject.api.sync.ValidationManager;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.sync.ValidationManager;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.messaging.ConversationManager;
+import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
+import org.briarproject.briar.api.privategroup.PrivateGroupManager;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -19,7 +19,7 @@ import javax.inject.Singleton;
 import dagger.Module;
 import dagger.Provides;
 
-import static org.briarproject.api.privategroup.invitation.GroupInvitationManager.CLIENT_ID;
+import static org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager.CLIENT_ID;
 
 @Module
 public class GroupInvitationModule {
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationValidator.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationValidator.java
similarity index 67%
rename from briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationValidator.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationValidator.java
index 175a593c49903013cadde62cedfbb37433e37489..125588cabc85b3a61acae90182e8b2a4bf4e5637 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/GroupInvitationValidator.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationValidator.java
@@ -1,23 +1,23 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.UniqueId;
-import org.briarproject.api.clients.BdfMessageContext;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.privategroup.PrivateGroupFactory;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.system.Clock;
-import org.briarproject.clients.BdfMessageValidator;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.UniqueId;
+import org.briarproject.bramble.api.client.BdfMessageContext;
+import org.briarproject.bramble.api.client.BdfMessageValidator;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
 
 import java.security.GeneralSecurityException;
 import java.util.Collections;
@@ -25,17 +25,19 @@ import java.util.Collections;
 import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-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.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
-import static org.briarproject.api.privategroup.PrivateGroupConstants.GROUP_SALT_LENGTH;
-import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_INVITATION_MSG_LENGTH;
-import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH;
-import static org.briarproject.api.privategroup.invitation.GroupInvitationFactory.SIGNING_LABEL_INVITE;
-import static org.briarproject.privategroup.invitation.MessageType.ABORT;
-import static org.briarproject.privategroup.invitation.MessageType.INVITE;
-import static org.briarproject.privategroup.invitation.MessageType.JOIN;
-import static org.briarproject.privategroup.invitation.MessageType.LEAVE;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
+import static org.briarproject.bramble.util.ValidationUtils.checkLength;
+import static org.briarproject.bramble.util.ValidationUtils.checkSize;
+import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.GROUP_SALT_LENGTH;
+import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_INVITATION_MSG_LENGTH;
+import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH;
+import static org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory.SIGNING_LABEL_INVITE;
+import static org.briarproject.briar.privategroup.invitation.MessageType.ABORT;
+import static org.briarproject.briar.privategroup.invitation.MessageType.INVITE;
+import static org.briarproject.briar.privategroup.invitation.MessageType.JOIN;
+import static org.briarproject.briar.privategroup.invitation.MessageType.LEAVE;
 
 @Immutable
 @NotNullByDefault
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/InviteMessage.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteMessage.java
similarity index 77%
rename from briar-core/src/org/briarproject/privategroup/invitation/InviteMessage.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteMessage.java
index b286e8c09cb1f894678228a0c75986b809b3ae5b..b1847aafa141ac73607246b9f588c7e4fe8adfc8 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/InviteMessage.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteMessage.java
@@ -1,9 +1,9 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
 
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/InviteeProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngine.java
similarity index 83%
rename from briar-core/src/org/briarproject/privategroup/invitation/InviteeProtocolEngine.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngine.java
index 231af013511dc8b8dd2df537266948ae4e8094ea..d1bf5bd6088076c8b87f4907fa4ce44907c369df 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/InviteeProtocolEngine.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngine.java
@@ -1,40 +1,40 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageTracker;
-import org.briarproject.api.clients.ProtocolStateException;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.GroupInvitationRequestReceivedEvent;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.privategroup.GroupMessageFactory;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.privategroup.PrivateGroupFactory;
-import org.briarproject.api.privategroup.PrivateGroupManager;
-import org.briarproject.api.privategroup.invitation.GroupInvitationRequest;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.client.MessageTracker;
+import org.briarproject.briar.api.client.ProtocolStateException;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.privategroup.GroupMessageFactory;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
+import org.briarproject.briar.api.privategroup.PrivateGroupManager;
+import org.briarproject.briar.api.privategroup.event.GroupInvitationRequestReceivedEvent;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest;
 
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
 
-import static org.briarproject.api.sync.Group.Visibility.INVISIBLE;
-import static org.briarproject.api.sync.Group.Visibility.SHARED;
-import static org.briarproject.api.sync.Group.Visibility.VISIBLE;
-import static org.briarproject.privategroup.invitation.InviteeState.ACCEPTED;
-import static org.briarproject.privategroup.invitation.InviteeState.DISSOLVED;
-import static org.briarproject.privategroup.invitation.InviteeState.ERROR;
-import static org.briarproject.privategroup.invitation.InviteeState.INVITED;
-import static org.briarproject.privategroup.invitation.InviteeState.JOINED;
-import static org.briarproject.privategroup.invitation.InviteeState.LEFT;
-import static org.briarproject.privategroup.invitation.InviteeState.START;
+import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
+import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
+import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE;
+import static org.briarproject.briar.privategroup.invitation.InviteeState.ACCEPTED;
+import static org.briarproject.briar.privategroup.invitation.InviteeState.DISSOLVED;
+import static org.briarproject.briar.privategroup.invitation.InviteeState.ERROR;
+import static org.briarproject.briar.privategroup.invitation.InviteeState.INVITED;
+import static org.briarproject.briar.privategroup.invitation.InviteeState.JOINED;
+import static org.briarproject.briar.privategroup.invitation.InviteeState.LEFT;
+import static org.briarproject.briar.privategroup.invitation.InviteeState.START;
 
 @Immutable
 @NotNullByDefault
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/InviteeSession.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteeSession.java
similarity index 68%
rename from briar-core/src/org/briarproject/privategroup/invitation/InviteeSession.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteeSession.java
index 12730ccbdccd982bdd8bb7d02a472df48ab0aa84..cade5865cbbd0ad08dc2cf5f6a58d06d6999d1b0 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/InviteeSession.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteeSession.java
@@ -1,14 +1,14 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
 
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
 
-import static org.briarproject.privategroup.invitation.InviteeState.START;
-import static org.briarproject.privategroup.invitation.Role.INVITEE;
+import static org.briarproject.briar.privategroup.invitation.InviteeState.START;
+import static org.briarproject.briar.privategroup.invitation.Role.INVITEE;
 
 @Immutable
 @NotNullByDefault
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/InviteeState.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteeState.java
similarity index 63%
rename from briar-core/src/org/briarproject/privategroup/invitation/InviteeState.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteeState.java
index 3299d747ea9c759f04e8fd8d740805e01fc885ca..7fa69e6af9c1c6113a70a92edf86b48d31b80dd6 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/InviteeState.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteeState.java
@@ -1,7 +1,12 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.FormatException;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 enum InviteeState implements State {
 
 	START(0), INVITED(1), ACCEPTED(2), JOINED(3), LEFT(4), DISSOLVED(5),
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/JoinMessage.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/JoinMessage.java
similarity index 66%
rename from briar-core/src/org/briarproject/privategroup/invitation/JoinMessage.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/JoinMessage.java
index 7b9c7df179d3163dfcb14bb9e08470d02d5c046f..77d6e3eef37e4b971aa6e30064ea92d3d43bc26f 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/JoinMessage.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/JoinMessage.java
@@ -1,10 +1,10 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
 
+import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
 
 @Immutable
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/LeaveMessage.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/LeaveMessage.java
similarity index 66%
rename from briar-core/src/org/briarproject/privategroup/invitation/LeaveMessage.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/LeaveMessage.java
index 86abb687e49609ae73512b566f2e4bb1dd59531a..cf323fe8101ca98955532415a5b3e1a6cb8acf44 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/LeaveMessage.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/LeaveMessage.java
@@ -1,10 +1,10 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
 
+import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
 
 @Immutable
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/LocalAction.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/LocalAction.java
similarity index 50%
rename from briar-core/src/org/briarproject/privategroup/invitation/LocalAction.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/LocalAction.java
index 3d2532ab1878c97b628fffed51ecf866bfbc4bf2..dbd13810ffaa1ea02ce71cb0f125ba7f4aaa087a 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/LocalAction.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/LocalAction.java
@@ -1,4 +1,4 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
 enum LocalAction {
 
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/MessageEncoder.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageEncoder.java
similarity index 70%
rename from briar-core/src/org/briarproject/privategroup/invitation/MessageEncoder.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageEncoder.java
index 7ced5fbaa12a1cf2c2245aa408deb7c9f4fad8d6..4312e519d5d0beb88e66a7180beee84fea630b04 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/MessageEncoder.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageEncoder.java
@@ -1,11 +1,11 @@
-package org.briarproject.privategroup.invitation;
-
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
+package org.briarproject.briar.privategroup.invitation;
+
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
 
 import javax.annotation.Nullable;
 
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/MessageEncoderImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageEncoderImpl.java
similarity index 65%
rename from briar-core/src/org/briarproject/privategroup/invitation/MessageEncoderImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageEncoderImpl.java
index 18180fe81a998e4fcaa02a7d63ba61195585fa24..17e0843d71d3a077b2229df0523f659ced14d11e 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/MessageEncoderImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageEncoderImpl.java
@@ -1,31 +1,31 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageFactory;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageFactory;
+import org.briarproject.bramble.api.sync.MessageId;
 
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.MSG_KEY_AVAILABLE_TO_ANSWER;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.MSG_KEY_LOCAL;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.MSG_KEY_MESSAGE_TYPE;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.MSG_KEY_PRIVATE_GROUP_ID;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.MSG_KEY_TIMESTAMP;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.MSG_KEY_VISIBLE_IN_UI;
-import static org.briarproject.privategroup.invitation.MessageType.ABORT;
-import static org.briarproject.privategroup.invitation.MessageType.INVITE;
-import static org.briarproject.privategroup.invitation.MessageType.JOIN;
-import static org.briarproject.privategroup.invitation.MessageType.LEAVE;
+import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_AVAILABLE_TO_ANSWER;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_LOCAL;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_MESSAGE_TYPE;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_PRIVATE_GROUP_ID;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_TIMESTAMP;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_VISIBLE_IN_UI;
+import static org.briarproject.briar.privategroup.invitation.MessageType.ABORT;
+import static org.briarproject.briar.privategroup.invitation.MessageType.INVITE;
+import static org.briarproject.briar.privategroup.invitation.MessageType.JOIN;
+import static org.briarproject.briar.privategroup.invitation.MessageType.LEAVE;
 
 @Immutable
 @NotNullByDefault
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/MessageMetadata.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageMetadata.java
similarity index 78%
rename from briar-core/src/org/briarproject/privategroup/invitation/MessageMetadata.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageMetadata.java
index 503a5e79db8e1a3e5e0cefd7f3ba4650c45ee9ac..92c62748dfadaa0ca66872acc3c1aea91d1b4659 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/MessageMetadata.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageMetadata.java
@@ -1,7 +1,12 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
 
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 class MessageMetadata {
 
 	private final MessageType type;
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/MessageParser.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageParser.java
similarity index 62%
rename from briar-core/src/org/briarproject/privategroup/invitation/MessageParser.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageParser.java
index c2e39d460609d3ea320b121b6671eb205f9ddd84..9e6a7ad9dbeb423a32e526983162a46f7a829c8e 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/MessageParser.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageParser.java
@@ -1,11 +1,11 @@
-package org.briarproject.privategroup.invitation;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
+package org.briarproject.briar.privategroup.invitation;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
 
 @NotNullByDefault
 interface MessageParser {
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/MessageParserImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageParserImpl.java
similarity index 69%
rename from briar-core/src/org/briarproject/privategroup/invitation/MessageParserImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageParserImpl.java
index 13837cb36c98aac84ed1c612f08464e7bd577d12..b31ff7d3174240e7a1c85d1edab0f06d288fb702 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/MessageParserImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageParserImpl.java
@@ -1,29 +1,29 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.privategroup.PrivateGroupFactory;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
 
 import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.MSG_KEY_AVAILABLE_TO_ANSWER;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.MSG_KEY_LOCAL;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.MSG_KEY_MESSAGE_TYPE;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.MSG_KEY_PRIVATE_GROUP_ID;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.MSG_KEY_TIMESTAMP;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.MSG_KEY_VISIBLE_IN_UI;
-import static org.briarproject.privategroup.invitation.MessageType.INVITE;
+import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_AVAILABLE_TO_ANSWER;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_LOCAL;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_MESSAGE_TYPE;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_PRIVATE_GROUP_ID;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_TIMESTAMP;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_VISIBLE_IN_UI;
+import static org.briarproject.briar.privategroup.invitation.MessageType.INVITE;
 
 @Immutable
 @NotNullByDefault
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/MessageType.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageType.java
similarity index 58%
rename from briar-core/src/org/briarproject/privategroup/invitation/MessageType.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageType.java
index a8f04a28746b2f993170e341460761c86b244a0e..090d2e193c5f3a4ef42b130416073f9dea6c741a 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/MessageType.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageType.java
@@ -1,7 +1,12 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.FormatException;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 enum MessageType {
 
 	INVITE(0), JOIN(1), LEAVE(2), ABORT(3);
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/PeerProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/PeerProtocolEngine.java
similarity index 86%
rename from briar-core/src/org/briarproject/privategroup/invitation/PeerProtocolEngine.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/PeerProtocolEngine.java
index 7eaebba496d456f507577d9354a6db3e36fe7242..c1908735fde51d986fd5646dcc79296bae0c13d5 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/PeerProtocolEngine.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/PeerProtocolEngine.java
@@ -1,35 +1,35 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageTracker;
-import org.briarproject.api.clients.ProtocolStateException;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.privategroup.GroupMessageFactory;
-import org.briarproject.api.privategroup.PrivateGroupFactory;
-import org.briarproject.api.privategroup.PrivateGroupManager;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.client.MessageTracker;
+import org.briarproject.briar.api.client.ProtocolStateException;
+import org.briarproject.briar.api.privategroup.GroupMessageFactory;
+import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
+import org.briarproject.briar.api.privategroup.PrivateGroupManager;
 
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
 
-import static org.briarproject.api.sync.Group.Visibility.INVISIBLE;
-import static org.briarproject.api.sync.Group.Visibility.SHARED;
-import static org.briarproject.api.sync.Group.Visibility.VISIBLE;
-import static org.briarproject.privategroup.invitation.PeerState.AWAIT_MEMBER;
-import static org.briarproject.privategroup.invitation.PeerState.BOTH_JOINED;
-import static org.briarproject.privategroup.invitation.PeerState.ERROR;
-import static org.briarproject.privategroup.invitation.PeerState.LOCAL_JOINED;
-import static org.briarproject.privategroup.invitation.PeerState.LOCAL_LEFT;
-import static org.briarproject.privategroup.invitation.PeerState.NEITHER_JOINED;
-import static org.briarproject.privategroup.invitation.PeerState.START;
+import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
+import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
+import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE;
+import static org.briarproject.briar.privategroup.invitation.PeerState.AWAIT_MEMBER;
+import static org.briarproject.briar.privategroup.invitation.PeerState.BOTH_JOINED;
+import static org.briarproject.briar.privategroup.invitation.PeerState.ERROR;
+import static org.briarproject.briar.privategroup.invitation.PeerState.LOCAL_JOINED;
+import static org.briarproject.briar.privategroup.invitation.PeerState.LOCAL_LEFT;
+import static org.briarproject.briar.privategroup.invitation.PeerState.NEITHER_JOINED;
+import static org.briarproject.briar.privategroup.invitation.PeerState.START;
 
 @Immutable
 @NotNullByDefault
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/PeerSession.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/PeerSession.java
similarity index 66%
rename from briar-core/src/org/briarproject/privategroup/invitation/PeerSession.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/PeerSession.java
index 2a6517dde443b9964791c51d24e6dd1b1205923e..e0e1b56c071496a5432aca32df650de0eda73b2d 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/PeerSession.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/PeerSession.java
@@ -1,14 +1,14 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
 
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
 
-import static org.briarproject.privategroup.invitation.PeerState.START;
-import static org.briarproject.privategroup.invitation.Role.PEER;
+import static org.briarproject.briar.privategroup.invitation.PeerState.START;
+import static org.briarproject.briar.privategroup.invitation.Role.PEER;
 
 @Immutable
 @NotNullByDefault
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/PeerState.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/PeerState.java
similarity index 63%
rename from briar-core/src/org/briarproject/privategroup/invitation/PeerState.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/PeerState.java
index eda52e5de71c34a11e572f0ec36bc9eaa0b3afc8..94f9d19afe624a57645bde631c98219c062761e8 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/PeerState.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/PeerState.java
@@ -1,7 +1,12 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.FormatException;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 enum PeerState implements State {
 
 	START(0), AWAIT_MEMBER(1), NEITHER_JOINED(2), LOCAL_JOINED(3),
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/ProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/ProtocolEngine.java
similarity index 75%
rename from briar-core/src/org/briarproject/privategroup/invitation/ProtocolEngine.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/ProtocolEngine.java
index 1908548f54b333219b5b39b35f51204414c99e16..b0833260d2ae066514a304a2094d4f9d97304cd0 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/ProtocolEngine.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/ProtocolEngine.java
@@ -1,9 +1,9 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import javax.annotation.Nullable;
 
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/ProtocolEngineFactory.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/ProtocolEngineFactory.java
similarity index 64%
rename from briar-core/src/org/briarproject/privategroup/invitation/ProtocolEngineFactory.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/ProtocolEngineFactory.java
index 95e5882de72547ea387502be6c8664e2b3105189..00ddc95b7f2021b3edfd098408bf2f18fbe12308 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/ProtocolEngineFactory.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/ProtocolEngineFactory.java
@@ -1,6 +1,6 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 @NotNullByDefault
 interface ProtocolEngineFactory {
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/ProtocolEngineFactoryImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/ProtocolEngineFactoryImpl.java
similarity index 78%
rename from briar-core/src/org/briarproject/privategroup/invitation/ProtocolEngineFactoryImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/ProtocolEngineFactoryImpl.java
index ed48f1224135ec32b5c0e6c23e5205f9b8935374..af3bbe81673944079a40db128630757507390689 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/ProtocolEngineFactoryImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/ProtocolEngineFactoryImpl.java
@@ -1,14 +1,14 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageTracker;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.privategroup.GroupMessageFactory;
-import org.briarproject.api.privategroup.PrivateGroupFactory;
-import org.briarproject.api.privategroup.PrivateGroupManager;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.client.MessageTracker;
+import org.briarproject.briar.api.privategroup.GroupMessageFactory;
+import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
+import org.briarproject.briar.api.privategroup.PrivateGroupManager;
 
 import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/Role.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/Role.java
similarity index 55%
rename from briar-core/src/org/briarproject/privategroup/invitation/Role.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/Role.java
index 2e84f63b57250cbf424da0946ba91f7bb445de12..b79794276c00d5b4d0a9d9fe54987a36ca64438b 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/Role.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/Role.java
@@ -1,7 +1,12 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.FormatException;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
 enum Role {
 
 	CREATOR(0), INVITEE(1), PEER(2);
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/Session.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/Session.java
similarity index 84%
rename from briar-core/src/org/briarproject/privategroup/invitation/Session.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/Session.java
index 1cd5c76889b96324a26ecac69e51da3c5816e944..040ab401a83c1f0e9e459b668b8a3f7fdc2b6fb3 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/Session.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/Session.java
@@ -1,8 +1,8 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
 
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/SessionEncoder.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/SessionEncoder.java
new file mode 100644
index 0000000000000000000000000000000000000000..876a53feae94b7b59576b9dfc30fb645a52a4335
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/SessionEncoder.java
@@ -0,0 +1,10 @@
+package org.briarproject.briar.privategroup.invitation;
+
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+interface SessionEncoder {
+
+	BdfDictionary encodeSession(Session s);
+}
diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/SessionEncoderImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/SessionEncoderImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..78e36bf3a5b15732e6298678cc71d10b026d003e
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/SessionEncoderImpl.java
@@ -0,0 +1,47 @@
+package org.briarproject.briar.privategroup.invitation;
+
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.MessageId;
+
+import javax.annotation.concurrent.Immutable;
+import javax.inject.Inject;
+
+import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_INVITE_TIMESTAMP;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LAST_LOCAL_MESSAGE_ID;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LAST_REMOTE_MESSAGE_ID;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LOCAL_TIMESTAMP;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_PRIVATE_GROUP_ID;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_ROLE;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_SESSION_ID;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_STATE;
+
+@Immutable
+@NotNullByDefault
+class SessionEncoderImpl implements SessionEncoder {
+
+	@Inject
+	SessionEncoderImpl() {
+	}
+
+	@Override
+	public BdfDictionary encodeSession(Session s) {
+		BdfDictionary d = new BdfDictionary();
+		d.put(SESSION_KEY_SESSION_ID, s.getPrivateGroupId());
+		d.put(SESSION_KEY_PRIVATE_GROUP_ID, s.getPrivateGroupId());
+		MessageId lastLocalMessageId = s.getLastLocalMessageId();
+		if (lastLocalMessageId == null)
+			d.put(SESSION_KEY_LAST_LOCAL_MESSAGE_ID, NULL_VALUE);
+		else d.put(SESSION_KEY_LAST_LOCAL_MESSAGE_ID, lastLocalMessageId);
+		MessageId lastRemoteMessageId = s.getLastRemoteMessageId();
+		if (lastRemoteMessageId == null)
+			d.put(SESSION_KEY_LAST_REMOTE_MESSAGE_ID, NULL_VALUE);
+		else d.put(SESSION_KEY_LAST_REMOTE_MESSAGE_ID, lastRemoteMessageId);
+		d.put(SESSION_KEY_LOCAL_TIMESTAMP, s.getLocalTimestamp());
+		d.put(SESSION_KEY_INVITE_TIMESTAMP, s.getInviteTimestamp());
+		d.put(SESSION_KEY_ROLE, s.getRole().getValue());
+		d.put(SESSION_KEY_STATE, s.getState().getValue());
+		return d;
+	}
+}
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/SessionParser.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/SessionParser.java
similarity index 58%
rename from briar-core/src/org/briarproject/privategroup/invitation/SessionParser.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/SessionParser.java
index 8f488298b0b327db3fb94e2a8ca87178ded9fb97..baf0de80e2f392f270c1e57ce52e94d6de5dd061 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/SessionParser.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/SessionParser.java
@@ -1,10 +1,10 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.api.client.SessionId;
 
 @NotNullByDefault
 interface SessionParser {
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/SessionParserImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/SessionParserImpl.java
similarity index 62%
rename from briar-core/src/org/briarproject/privategroup/invitation/SessionParserImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/SessionParserImpl.java
index c8e468db39654bca7c41d0dc4b1112a59c6e75e7..e8813b6dcd50082ea577c4229c5f6a9a1d2795fd 100644
--- a/briar-core/src/org/briarproject/privategroup/invitation/SessionParserImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/SessionParserImpl.java
@@ -1,28 +1,28 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.SessionId;
 
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_INVITE_TIMESTAMP;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LAST_LOCAL_MESSAGE_ID;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LAST_REMOTE_MESSAGE_ID;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LOCAL_TIMESTAMP;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_PRIVATE_GROUP_ID;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_ROLE;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_SESSION_ID;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_STATE;
-import static org.briarproject.privategroup.invitation.Role.CREATOR;
-import static org.briarproject.privategroup.invitation.Role.INVITEE;
-import static org.briarproject.privategroup.invitation.Role.PEER;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_INVITE_TIMESTAMP;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LAST_LOCAL_MESSAGE_ID;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LAST_REMOTE_MESSAGE_ID;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LOCAL_TIMESTAMP;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_PRIVATE_GROUP_ID;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_ROLE;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_SESSION_ID;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_STATE;
+import static org.briarproject.briar.privategroup.invitation.Role.CREATOR;
+import static org.briarproject.briar.privategroup.invitation.Role.INVITEE;
+import static org.briarproject.briar.privategroup.invitation.Role.PEER;
 
 @Immutable
 @NotNullByDefault
diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/State.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/State.java
new file mode 100644
index 0000000000000000000000000000000000000000..46df85efdc5dff661db8862eb557b514fe16a6e9
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/State.java
@@ -0,0 +1,6 @@
+package org.briarproject.briar.privategroup.invitation;
+
+interface State {
+
+	int getValue();
+}
diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogInviteeSessionState.java b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogInviteeSessionState.java
new file mode 100644
index 0000000000000000000000000000000000000000..564eec6cc7be4dc7122ca6b1b2864a6bd7ca9b56
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogInviteeSessionState.java
@@ -0,0 +1,47 @@
+package org.briarproject.briar.sharing;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.SessionId;
+
+import javax.annotation.concurrent.NotThreadSafe;
+
+import static org.briarproject.briar.api.blog.BlogConstants.BLOG_AUTHOR_NAME;
+import static org.briarproject.briar.api.blog.BlogConstants.BLOG_PUBLIC_KEY;
+
+@NotThreadSafe
+@NotNullByDefault
+class BlogInviteeSessionState extends InviteeSessionState {
+
+	private final String blogAuthorName;
+	private final byte[] blogPublicKey;
+
+	BlogInviteeSessionState(SessionId sessionId, MessageId storageId,
+			GroupId groupId, State state, ContactId contactId, GroupId blogId,
+			String blogAuthorName, byte[] blogPublicKey,
+			MessageId invitationId) {
+		super(sessionId, storageId, groupId, state, contactId, blogId,
+				invitationId);
+		this.blogAuthorName = blogAuthorName;
+		this.blogPublicKey = blogPublicKey;
+	}
+
+	@Override
+	public BdfDictionary toBdfDictionary() {
+		BdfDictionary d = super.toBdfDictionary();
+		d.put(BLOG_AUTHOR_NAME, getBlogAuthorName());
+		d.put(BLOG_PUBLIC_KEY, getBlogPublicKey());
+		return d;
+	}
+
+	String getBlogAuthorName() {
+		return blogAuthorName;
+	}
+
+	byte[] getBlogPublicKey() {
+		return blogPublicKey;
+	}
+}
diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharerSessionState.java b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharerSessionState.java
new file mode 100644
index 0000000000000000000000000000000000000000..bc4b34b5e5d3a22d726fea772aa7a5dc789b06bc
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharerSessionState.java
@@ -0,0 +1,49 @@
+package org.briarproject.briar.sharing;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.SessionId;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.NotThreadSafe;
+
+import static org.briarproject.briar.api.blog.BlogConstants.BLOG_AUTHOR_NAME;
+import static org.briarproject.briar.api.blog.BlogConstants.BLOG_PUBLIC_KEY;
+
+@NotThreadSafe
+@NotNullByDefault
+class BlogSharerSessionState extends SharerSessionState {
+
+	private final String blogAuthorName;
+	private final byte[] blogPublicKey;
+
+	BlogSharerSessionState(SessionId sessionId, MessageId storageId,
+			GroupId groupId, State state, ContactId contactId, GroupId blogId,
+			String blogAuthorName, byte[] blogPublicKey,
+			@Nullable MessageId responseId) {
+		super(sessionId, storageId, groupId, state, contactId, blogId,
+				responseId);
+
+		this.blogAuthorName = blogAuthorName;
+		this.blogPublicKey = blogPublicKey;
+	}
+
+	@Override
+	public BdfDictionary toBdfDictionary() {
+		BdfDictionary d = super.toBdfDictionary();
+		d.put(BLOG_AUTHOR_NAME, getBlogAuthorName());
+		d.put(BLOG_PUBLIC_KEY, getBlogPublicKey());
+		return d;
+	}
+
+	String getBlogAuthorName() {
+		return blogAuthorName;
+	}
+
+	byte[] getBlogPublicKey() {
+		return blogPublicKey;
+	}
+}
diff --git a/briar-core/src/org/briarproject/sharing/BlogSharingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharingManagerImpl.java
similarity index 77%
rename from briar-core/src/org/briarproject/sharing/BlogSharingManagerImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharingManagerImpl.java
index c28ad5792dceaaebddd09c9f457e428598810d12..b68187b07831d7ed96bf33fc16506ee675560280 100644
--- a/briar-core/src/org/briarproject/sharing/BlogSharingManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharingManagerImpl.java
@@ -1,53 +1,55 @@
-package org.briarproject.sharing;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.blogs.Blog;
-import org.briarproject.api.blogs.BlogFactory;
-import org.briarproject.api.blogs.BlogInvitationRequest;
-import org.briarproject.api.blogs.BlogInvitationResponse;
-import org.briarproject.api.blogs.BlogManager;
-import org.briarproject.api.blogs.BlogManager.RemoveBlogHook;
-import org.briarproject.api.blogs.BlogSharingManager;
-import org.briarproject.api.blogs.BlogSharingMessage.BlogInvitation;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.ContactGroupFactory;
-import org.briarproject.api.clients.MessageQueueManager;
-import org.briarproject.api.clients.MessageTracker;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.data.MetadataParser;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.BlogInvitationReceivedEvent;
-import org.briarproject.api.event.BlogInvitationResponseReceivedEvent;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sharing.InvitationMessage;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.system.Clock;
+package org.briarproject.briar.sharing;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.client.ContactGroupFactory;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.data.MetadataParser;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.blog.Blog;
+import org.briarproject.briar.api.blog.BlogFactory;
+import org.briarproject.briar.api.blog.BlogInvitationRequest;
+import org.briarproject.briar.api.blog.BlogInvitationResponse;
+import org.briarproject.briar.api.blog.BlogManager;
+import org.briarproject.briar.api.blog.BlogManager.RemoveBlogHook;
+import org.briarproject.briar.api.blog.BlogSharingManager;
+import org.briarproject.briar.api.blog.BlogSharingMessage.BlogInvitation;
+import org.briarproject.briar.api.blog.event.BlogInvitationRequestReceivedEvent;
+import org.briarproject.briar.api.blog.event.BlogInvitationResponseReceivedEvent;
+import org.briarproject.briar.api.client.MessageQueueManager;
+import org.briarproject.briar.api.client.MessageTracker;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.sharing.InvitationMessage;
 
 import java.security.SecureRandom;
 
+import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
-import static org.briarproject.api.blogs.BlogConstants.BLOG_AUTHOR_NAME;
-import static org.briarproject.api.blogs.BlogConstants.BLOG_PUBLIC_KEY;
-import static org.briarproject.api.sharing.SharingConstants.INVITATION_ID;
-import static org.briarproject.api.sharing.SharingConstants.RESPONSE_ID;
+import static org.briarproject.briar.api.blog.BlogConstants.BLOG_AUTHOR_NAME;
+import static org.briarproject.briar.api.blog.BlogConstants.BLOG_PUBLIC_KEY;
+import static org.briarproject.briar.api.sharing.SharingConstants.INVITATION_ID;
+import static org.briarproject.briar.api.sharing.SharingConstants.RESPONSE_ID;
 
+@Immutable
 @NotNullByDefault
 class BlogSharingManagerImpl extends
-		SharingManagerImpl<Blog, BlogInvitation, BlogInviteeSessionState, BlogSharerSessionState, BlogInvitationReceivedEvent, BlogInvitationResponseReceivedEvent>
+		SharingManagerImpl<Blog, BlogInvitation, BlogInviteeSessionState, BlogSharerSessionState, BlogInvitationRequestReceivedEvent, BlogInvitationResponseReceivedEvent>
 		implements BlogSharingManager, RemoveBlogHook {
 
 	private final IdentityManager identityManager;
@@ -143,7 +145,7 @@ class BlogSharingManagerImpl extends
 	}
 
 	@Override
-	protected InvitationReceivedEventFactory<BlogInviteeSessionState, BlogInvitationReceivedEvent> getIRFactory() {
+	protected InvitationReceivedEventFactory<BlogInviteeSessionState, BlogInvitationRequestReceivedEvent> getIRFactory() {
 		return irFactory;
 	}
 
@@ -295,7 +297,7 @@ class BlogSharingManagerImpl extends
 	}
 
 	private static class IRFactory implements
-			InvitationReceivedEventFactory<BlogInviteeSessionState, BlogInvitationReceivedEvent> {
+			InvitationReceivedEventFactory<BlogInviteeSessionState, BlogInvitationRequestReceivedEvent> {
 
 		private final SFactory sFactory;
 
@@ -304,7 +306,7 @@ class BlogSharingManagerImpl extends
 		}
 
 		@Override
-		public BlogInvitationReceivedEvent build(
+		public BlogInvitationRequestReceivedEvent build(
 				BlogInviteeSessionState localState, long time, String msg) {
 			Blog blog = sFactory.parse(localState);
 			ContactId contactId = localState.getContactId();
@@ -313,7 +315,8 @@ class BlogSharingManagerImpl extends
 							localState.getSessionId(), localState.getGroupId(),
 							contactId, blog.getAuthor().getName(), msg, true,
 							time, false, false, false, false);
-			return new BlogInvitationReceivedEvent(blog, contactId, request);
+			return new BlogInvitationRequestReceivedEvent(blog, contactId,
+					request);
 		}
 	}
 
diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharingValidator.java b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharingValidator.java
new file mode 100644
index 0000000000000000000000000000000000000000..9dbcecd0821d85e8e7e834bbb8c4eed138e0faef
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharingValidator.java
@@ -0,0 +1,92 @@
+package org.briarproject.briar.sharing;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.BdfMessageContext;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.client.BdfQueueMessageValidator;
+
+import javax.annotation.concurrent.Immutable;
+import javax.inject.Inject;
+
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.bramble.util.ValidationUtils.checkLength;
+import static org.briarproject.bramble.util.ValidationUtils.checkSize;
+import static org.briarproject.briar.api.blog.BlogConstants.BLOG_AUTHOR_NAME;
+import static org.briarproject.briar.api.blog.BlogConstants.BLOG_PUBLIC_KEY;
+import static org.briarproject.briar.api.sharing.SharingConstants.INVITATION_MSG;
+import static org.briarproject.briar.api.sharing.SharingConstants.LOCAL;
+import static org.briarproject.briar.api.sharing.SharingConstants.MAX_INVITATION_MESSAGE_LENGTH;
+import static org.briarproject.briar.api.sharing.SharingConstants.SESSION_ID;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_ACCEPT;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_DECLINE;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE;
+import static org.briarproject.briar.api.sharing.SharingConstants.TIME;
+import static org.briarproject.briar.api.sharing.SharingConstants.TYPE;
+
+@Immutable
+@NotNullByDefault
+class BlogSharingValidator extends BdfQueueMessageValidator {
+
+	@Inject
+	BlogSharingValidator(ClientHelper clientHelper,
+			MetadataEncoder metadataEncoder, Clock clock) {
+		super(clientHelper, metadataEncoder, clock);
+	}
+
+	@Override
+	protected BdfMessageContext validateMessage(Message m, Group g,
+			BdfList body) throws FormatException {
+
+		BdfDictionary d = new BdfDictionary();
+		long type = body.getLong(0);
+		byte[] id = body.getRaw(1);
+		checkLength(id, SessionId.LENGTH);
+
+		if (type == SHARE_MSG_TYPE_INVITATION) {
+			checkSize(body, 3, 4);
+
+			BdfList author = body.getList(2);
+			checkSize(author, 2);
+
+			String authorName = author.getString(0);
+			checkLength(authorName, 1, MAX_AUTHOR_NAME_LENGTH);
+
+			byte[] publicKey = author.getRaw(1);
+			checkLength(publicKey, 1, MAX_PUBLIC_KEY_LENGTH);
+
+			d.put(BLOG_AUTHOR_NAME, authorName);
+			d.put(BLOG_PUBLIC_KEY, publicKey);
+
+			if (body.size() > 3) {
+				String msg = body.getString(3);
+				checkLength(msg, 0, MAX_INVITATION_MESSAGE_LENGTH);
+				d.put(INVITATION_MSG, msg);
+			}
+		} else {
+			checkSize(body, 2);
+			if (type != SHARE_MSG_TYPE_ACCEPT &&
+					type != SHARE_MSG_TYPE_DECLINE &&
+					type != SHARE_MSG_TYPE_LEAVE &&
+					type != SHARE_MSG_TYPE_ABORT) {
+				throw new FormatException();
+			}
+		}
+		// Return the metadata
+		d.put(TYPE, type);
+		d.put(SESSION_ID, id);
+		d.put(LOCAL, false);
+		d.put(TIME, m.getTimestamp());
+		return new BdfMessageContext(d);
+	}
+}
diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/ForumInviteeSessionState.java b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumInviteeSessionState.java
new file mode 100644
index 0000000000000000000000000000000000000000..d6a462982fd615cafecea793c08bbe02104952c9
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumInviteeSessionState.java
@@ -0,0 +1,47 @@
+package org.briarproject.briar.sharing;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.SessionId;
+
+import javax.annotation.concurrent.NotThreadSafe;
+
+import static org.briarproject.briar.api.forum.ForumConstants.FORUM_NAME;
+import static org.briarproject.briar.api.forum.ForumConstants.FORUM_SALT;
+
+@NotThreadSafe
+@NotNullByDefault
+class ForumInviteeSessionState extends InviteeSessionState {
+
+	private final String forumName;
+	private final byte[] forumSalt;
+
+	ForumInviteeSessionState(SessionId sessionId, MessageId storageId,
+			GroupId groupId, State state, ContactId contactId, GroupId forumId,
+			String forumName, byte[] forumSalt, MessageId invitationId) {
+		super(sessionId, storageId, groupId, state, contactId, forumId,
+				invitationId);
+
+		this.forumName = forumName;
+		this.forumSalt = forumSalt;
+	}
+
+	@Override
+	public BdfDictionary toBdfDictionary() {
+		BdfDictionary d = super.toBdfDictionary();
+		d.put(FORUM_NAME, getForumName());
+		d.put(FORUM_SALT, getForumSalt());
+		return d;
+	}
+
+	String getForumName() {
+		return forumName;
+	}
+
+	byte[] getForumSalt() {
+		return forumSalt;
+	}
+}
diff --git a/briar-core/src/org/briarproject/sharing/ForumSharerSessionState.java b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumSharerSessionState.java
similarity index 54%
rename from briar-core/src/org/briarproject/sharing/ForumSharerSessionState.java
rename to briar-core/src/main/java/org/briarproject/briar/sharing/ForumSharerSessionState.java
index 1403b75a67aae8137c4fe2568cfa79a6a880d494..12280066ebc7727c918be700488f6c16c386f01a 100644
--- a/briar-core/src/org/briarproject/sharing/ForumSharerSessionState.java
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumSharerSessionState.java
@@ -1,15 +1,20 @@
-package org.briarproject.sharing;
+package org.briarproject.briar.sharing;
 
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.SessionId;
 
-import static org.briarproject.api.forum.ForumConstants.FORUM_NAME;
-import static org.briarproject.api.forum.ForumConstants.FORUM_SALT;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.NotThreadSafe;
 
+import static org.briarproject.briar.api.forum.ForumConstants.FORUM_NAME;
+import static org.briarproject.briar.api.forum.ForumConstants.FORUM_SALT;
+
+@NotThreadSafe
+@NotNullByDefault
 class ForumSharerSessionState extends SharerSessionState {
 
 	private final String forumName;
@@ -26,6 +31,7 @@ class ForumSharerSessionState extends SharerSessionState {
 		this.forumSalt = forumSalt;
 	}
 
+	@Override
 	public BdfDictionary toBdfDictionary() {
 		BdfDictionary d = super.toBdfDictionary();
 		d.put(FORUM_NAME, getForumName());
diff --git a/briar-core/src/org/briarproject/sharing/ForumSharingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumSharingManagerImpl.java
similarity index 77%
rename from briar-core/src/org/briarproject/sharing/ForumSharingManagerImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/sharing/ForumSharingManagerImpl.java
index 29462307477a4bb5196e35832259212af1e01c5c..e564f7bcc6f6b110b206bb00fe04d82b11815c08 100644
--- a/briar-core/src/org/briarproject/sharing/ForumSharingManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumSharingManagerImpl.java
@@ -1,48 +1,48 @@
-package org.briarproject.sharing;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.ContactGroupFactory;
-import org.briarproject.api.clients.MessageQueueManager;
-import org.briarproject.api.clients.MessageTracker;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.data.MetadataParser;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.ForumInvitationReceivedEvent;
-import org.briarproject.api.event.ForumInvitationResponseReceivedEvent;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumFactory;
-import org.briarproject.api.forum.ForumInvitationRequest;
-import org.briarproject.api.forum.ForumInvitationResponse;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.forum.ForumManager.RemoveForumHook;
-import org.briarproject.api.forum.ForumSharingManager;
-import org.briarproject.api.forum.ForumSharingMessage.ForumInvitation;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sharing.InvitationMessage;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.system.Clock;
+package org.briarproject.briar.sharing;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.client.ContactGroupFactory;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.data.MetadataParser;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.client.MessageQueueManager;
+import org.briarproject.briar.api.client.MessageTracker;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.forum.Forum;
+import org.briarproject.briar.api.forum.ForumFactory;
+import org.briarproject.briar.api.forum.ForumInvitationRequest;
+import org.briarproject.briar.api.forum.ForumInvitationResponse;
+import org.briarproject.briar.api.forum.ForumManager;
+import org.briarproject.briar.api.forum.ForumManager.RemoveForumHook;
+import org.briarproject.briar.api.forum.ForumSharingManager;
+import org.briarproject.briar.api.forum.ForumSharingMessage.ForumInvitation;
+import org.briarproject.briar.api.forum.event.ForumInvitationRequestReceivedEvent;
+import org.briarproject.briar.api.forum.event.ForumInvitationResponseReceivedEvent;
+import org.briarproject.briar.api.sharing.InvitationMessage;
 
 import java.security.SecureRandom;
 
 import javax.inject.Inject;
 
-import static org.briarproject.api.forum.ForumConstants.FORUM_NAME;
-import static org.briarproject.api.forum.ForumConstants.FORUM_SALT;
-import static org.briarproject.api.sharing.SharingConstants.INVITATION_ID;
-import static org.briarproject.api.sharing.SharingConstants.RESPONSE_ID;
+import static org.briarproject.briar.api.forum.ForumConstants.FORUM_NAME;
+import static org.briarproject.briar.api.forum.ForumConstants.FORUM_SALT;
+import static org.briarproject.briar.api.sharing.SharingConstants.INVITATION_ID;
+import static org.briarproject.briar.api.sharing.SharingConstants.RESPONSE_ID;
 
 @NotNullByDefault
 class ForumSharingManagerImpl extends
-		SharingManagerImpl<Forum, ForumInvitation, ForumInviteeSessionState, ForumSharerSessionState, ForumInvitationReceivedEvent, ForumInvitationResponseReceivedEvent>
+		SharingManagerImpl<Forum, ForumInvitation, ForumInviteeSessionState, ForumSharerSessionState, ForumInvitationRequestReceivedEvent, ForumInvitationResponseReceivedEvent>
 		implements ForumSharingManager, RemoveForumHook {
 
 	private final SFactory sFactory;
@@ -119,7 +119,7 @@ class ForumSharingManagerImpl extends
 	}
 
 	@Override
-	protected InvitationReceivedEventFactory<ForumInviteeSessionState, ForumInvitationReceivedEvent> getIRFactory() {
+	protected InvitationReceivedEventFactory<ForumInviteeSessionState, ForumInvitationRequestReceivedEvent> getIRFactory() {
 		return irFactory;
 	}
 
@@ -253,7 +253,7 @@ class ForumSharingManagerImpl extends
 	}
 
 	private static class IRFactory implements
-			InvitationReceivedEventFactory<ForumInviteeSessionState, ForumInvitationReceivedEvent> {
+			InvitationReceivedEventFactory<ForumInviteeSessionState, ForumInvitationRequestReceivedEvent> {
 
 		private final SFactory sFactory;
 
@@ -262,7 +262,7 @@ class ForumSharingManagerImpl extends
 		}
 
 		@Override
-		public ForumInvitationReceivedEvent build(
+		public ForumInvitationRequestReceivedEvent build(
 				ForumInviteeSessionState localState, long time, String msg) {
 			Forum forum = sFactory.parse(localState);
 			ContactId contactId = localState.getContactId();
@@ -270,7 +270,8 @@ class ForumSharingManagerImpl extends
 					localState.getInvitationId(), localState.getSessionId(),
 					localState.getGroupId(), contactId, forum.getName(), msg,
 					true, time, false, false, false, false);
-			return new ForumInvitationReceivedEvent(forum, contactId, request);
+			return new ForumInvitationRequestReceivedEvent(forum, contactId,
+					request);
 		}
 	}
 
diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/ForumSharingValidator.java b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumSharingValidator.java
new file mode 100644
index 0000000000000000000000000000000000000000..7be98da26b1c6e09245272af845eeaee37bf00a3
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumSharingValidator.java
@@ -0,0 +1,89 @@
+package org.briarproject.briar.sharing;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.BdfMessageContext;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.client.BdfQueueMessageValidator;
+
+import javax.annotation.concurrent.Immutable;
+import javax.inject.Inject;
+
+import static org.briarproject.bramble.util.ValidationUtils.checkLength;
+import static org.briarproject.bramble.util.ValidationUtils.checkSize;
+import static org.briarproject.briar.api.forum.ForumConstants.FORUM_NAME;
+import static org.briarproject.briar.api.forum.ForumConstants.FORUM_SALT;
+import static org.briarproject.briar.api.forum.ForumConstants.FORUM_SALT_LENGTH;
+import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
+import static org.briarproject.briar.api.sharing.SharingConstants.INVITATION_MSG;
+import static org.briarproject.briar.api.sharing.SharingConstants.LOCAL;
+import static org.briarproject.briar.api.sharing.SharingConstants.MAX_INVITATION_MESSAGE_LENGTH;
+import static org.briarproject.briar.api.sharing.SharingConstants.SESSION_ID;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_ACCEPT;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_DECLINE;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE;
+import static org.briarproject.briar.api.sharing.SharingConstants.TIME;
+import static org.briarproject.briar.api.sharing.SharingConstants.TYPE;
+
+@Immutable
+@NotNullByDefault
+class ForumSharingValidator extends BdfQueueMessageValidator {
+
+	@Inject
+	ForumSharingValidator(ClientHelper clientHelper,
+			MetadataEncoder metadataEncoder, Clock clock) {
+		super(clientHelper, metadataEncoder, clock);
+	}
+
+	@Override
+	protected BdfMessageContext validateMessage(Message m, Group g,
+			BdfList body) throws FormatException {
+
+		BdfDictionary d = new BdfDictionary();
+		long type = body.getLong(0);
+		byte[] id = body.getRaw(1);
+		checkLength(id, SessionId.LENGTH);
+
+		if (type == SHARE_MSG_TYPE_INVITATION) {
+			checkSize(body, 4, 5);
+
+			String name = body.getString(2);
+			checkLength(name, 1, MAX_FORUM_NAME_LENGTH);
+
+			byte[] salt = body.getRaw(3);
+			checkLength(salt, FORUM_SALT_LENGTH);
+
+			d.put(FORUM_NAME, name);
+			d.put(FORUM_SALT, salt);
+
+			if (body.size() > 4) {
+				String msg = body.getString(4);
+				checkLength(msg, 0, MAX_INVITATION_MESSAGE_LENGTH);
+				d.put(INVITATION_MSG, msg);
+			}
+		} else {
+			checkSize(body, 2);
+			if (type != SHARE_MSG_TYPE_ACCEPT &&
+					type != SHARE_MSG_TYPE_DECLINE &&
+					type != SHARE_MSG_TYPE_LEAVE &&
+					type != SHARE_MSG_TYPE_ABORT) {
+				throw new FormatException();
+			}
+		}
+		// Return the metadata
+		d.put(TYPE, type);
+		d.put(SESSION_ID, id);
+		d.put(LOCAL, false);
+		d.put(TIME, m.getTimestamp());
+		return new BdfMessageContext(d);
+	}
+}
diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/InvitationFactory.java b/briar-core/src/main/java/org/briarproject/briar/sharing/InvitationFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..4b55d3c6b94b42647b006b1d62e17011d61de4b5
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/InvitationFactory.java
@@ -0,0 +1,11 @@
+package org.briarproject.briar.sharing;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.api.sharing.SharingMessage;
+
+@NotNullByDefault
+interface InvitationFactory<I extends SharingMessage.Invitation, SS extends SharerSessionState>
+		extends org.briarproject.briar.api.sharing.InvitationFactory<I> {
+
+	I build(SS localState, long time);
+}
diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/InvitationReceivedEventFactory.java b/briar-core/src/main/java/org/briarproject/briar/sharing/InvitationReceivedEventFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..b440daf8cfa171814281ae9d1cda56d3b67ce886
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/InvitationReceivedEventFactory.java
@@ -0,0 +1,10 @@
+package org.briarproject.briar.sharing;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.api.sharing.event.InvitationRequestReceivedEvent;
+
+@NotNullByDefault
+interface InvitationReceivedEventFactory<IS extends InviteeSessionState, IR extends InvitationRequestReceivedEvent> {
+
+	IR build(IS localState, long time, String msg);
+}
diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/InvitationResponseReceivedEventFactory.java b/briar-core/src/main/java/org/briarproject/briar/sharing/InvitationResponseReceivedEventFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..31ca766b2620173a4d75f593a5ec7b973971e436
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/InvitationResponseReceivedEventFactory.java
@@ -0,0 +1,10 @@
+package org.briarproject.briar.sharing;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent;
+
+@NotNullByDefault
+interface InvitationResponseReceivedEventFactory<SS extends SharerSessionState, IRR extends InvitationResponseReceivedEvent> {
+
+	IRR build(SS localState, boolean accept, long time);
+}
diff --git a/briar-core/src/org/briarproject/sharing/InviteeEngine.java b/briar-core/src/main/java/org/briarproject/briar/sharing/InviteeEngine.java
similarity index 74%
rename from briar-core/src/org/briarproject/sharing/InviteeEngine.java
rename to briar-core/src/main/java/org/briarproject/briar/sharing/InviteeEngine.java
index 96af6e3207da4eb44e35a4c2d61a3cc5e76ae00b..a8a5a16fd62037089d01d65a9e5eb5c8ab8cc706 100644
--- a/briar-core/src/org/briarproject/sharing/InviteeEngine.java
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/InviteeEngine.java
@@ -1,37 +1,43 @@
-package org.briarproject.sharing;
+package org.briarproject.briar.sharing;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ProtocolEngine;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.InvitationRequestReceivedEvent;
-import org.briarproject.api.sharing.SharingMessage.Invitation;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.client.ProtocolEngine;
+import org.briarproject.briar.api.sharing.SharingMessage.Invitation;
+import org.briarproject.briar.api.sharing.event.InvitationRequestReceivedEvent;
 
 import java.util.Collections;
 import java.util.List;
 import java.util.logging.Logger;
 
+import javax.annotation.concurrent.Immutable;
+
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ACCEPT;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_DECLINE;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE;
-import static org.briarproject.api.sharing.SharingConstants.TASK_ADD_SHAREABLE_TO_LIST_SHARED_WITH_US;
-import static org.briarproject.api.sharing.SharingConstants.TASK_ADD_SHARED_SHAREABLE;
-import static org.briarproject.api.sharing.SharingConstants.TASK_REMOVE_SHAREABLE_FROM_LIST_SHARED_WITH_US;
-import static org.briarproject.api.sharing.SharingConstants.TASK_UNSHARE_SHAREABLE_SHARED_WITH_US;
-import static org.briarproject.api.sharing.SharingMessage.BaseMessage;
-import static org.briarproject.api.sharing.SharingMessage.SimpleMessage;
-
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_ACCEPT;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_DECLINE;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE;
+import static org.briarproject.briar.api.sharing.SharingConstants.TASK_ADD_SHAREABLE_TO_LIST_SHARED_WITH_US;
+import static org.briarproject.briar.api.sharing.SharingConstants.TASK_ADD_SHARED_SHAREABLE;
+import static org.briarproject.briar.api.sharing.SharingConstants.TASK_REMOVE_SHAREABLE_FROM_LIST_SHARED_WITH_US;
+import static org.briarproject.briar.api.sharing.SharingConstants.TASK_UNSHARE_SHAREABLE_SHARED_WITH_US;
+import static org.briarproject.briar.api.sharing.SharingMessage.BaseMessage;
+import static org.briarproject.briar.api.sharing.SharingMessage.SimpleMessage;
+
+@Immutable
+@NotNullByDefault
 class InviteeEngine<IS extends InviteeSessionState, IR extends InvitationRequestReceivedEvent>
 		implements ProtocolEngine<InviteeSessionState.Action, IS, BaseMessage> {
 
 	private static final Logger LOG =
 			Logger.getLogger(InviteeEngine.class.getName());
 
-	private final InvitationReceivedEventFactory<IS, IR> invitationReceivedEventFactory;
+	private final InvitationReceivedEventFactory<IS, IR>
+			invitationReceivedEventFactory;
 	private final Clock clock;
 
 	InviteeEngine(
@@ -50,7 +56,8 @@ class InviteeEngine<IS extends InviteeSessionState, IR extends InvitationRequest
 			InviteeSessionState.State nextState = currentState.next(action);
 			localState.setState(nextState);
 
-			if (action == InviteeSessionState.Action.LOCAL_ABORT && currentState != InviteeSessionState.State.ERROR) {
+			if (action == InviteeSessionState.Action.LOCAL_ABORT &&
+					currentState != InviteeSessionState.State.ERROR) {
 				return abortSession(currentState, localState);
 			}
 
@@ -64,7 +71,8 @@ class InviteeEngine<IS extends InviteeSessionState, IR extends InvitationRequest
 			List<BaseMessage> messages;
 			List<Event> events = Collections.emptyList();
 
-			if (action == InviteeSessionState.Action.LOCAL_ACCEPT || action == InviteeSessionState.Action.LOCAL_DECLINE) {
+			if (action == InviteeSessionState.Action.LOCAL_ACCEPT ||
+					action == InviteeSessionState.Action.LOCAL_DECLINE) {
 				BaseMessage msg;
 				if (action == InviteeSessionState.Action.LOCAL_ACCEPT) {
 					localState.setTask(TASK_ADD_SHARED_SHAREABLE);
@@ -80,15 +88,13 @@ class InviteeEngine<IS extends InviteeSessionState, IR extends InvitationRequest
 				}
 				messages = Collections.singletonList(msg);
 				logLocalAction(currentState, localState, msg);
-			}
-			else if (action == InviteeSessionState.Action.LOCAL_LEAVE) {
+			} else if (action == InviteeSessionState.Action.LOCAL_LEAVE) {
 				BaseMessage msg = new SimpleMessage(SHARE_MSG_TYPE_LEAVE,
 						localState.getGroupId(), localState.getSessionId(),
 						clock.currentTimeMillis());
 				messages = Collections.singletonList(msg);
 				logLocalAction(currentState, localState, msg);
-			}
-			else {
+			} else {
 				throw new IllegalArgumentException("Unknown Local Action");
 			}
 			return new StateUpdate<IS, BaseMessage>(false,
@@ -104,7 +110,8 @@ class InviteeEngine<IS extends InviteeSessionState, IR extends InvitationRequest
 
 		try {
 			InviteeSessionState.State currentState = localState.getState();
-			InviteeSessionState.Action action = InviteeSessionState.Action.getRemote(msg.getType());
+			InviteeSessionState.Action action =
+					InviteeSessionState.Action.getRemote(msg.getType());
 			InviteeSessionState.State nextState = currentState.next(action);
 			localState.setState(nextState);
 
@@ -127,17 +134,18 @@ class InviteeEngine<IS extends InviteeSessionState, IR extends InvitationRequest
 				deleteMsg = true;
 			}
 			// the sharer left the forum she had shared with us
-			else if (action == InviteeSessionState.Action.REMOTE_LEAVE && currentState == InviteeSessionState.State.FINISHED) {
+			else if (action == InviteeSessionState.Action.REMOTE_LEAVE &&
+					currentState == InviteeSessionState.State.FINISHED) {
 				localState.setTask(TASK_UNSHARE_SHAREABLE_SHARED_WITH_US);
-			}
-			else if (currentState == InviteeSessionState.State.FINISHED) {
+			} else if (currentState == InviteeSessionState.State.FINISHED) {
 				// ignore and delete messages coming in while in that state
 				// note that LEAVE is possible, but was handled above
 				deleteMsg = true;
 			}
 			// the sharer left the forum before we couldn't even respond
 			else if (action == InviteeSessionState.Action.REMOTE_LEAVE) {
-				localState.setTask(TASK_REMOVE_SHAREABLE_FROM_LIST_SHARED_WITH_US);
+				localState.setTask(
+						TASK_REMOVE_SHAREABLE_FROM_LIST_SHARED_WITH_US);
 			}
 			// we have just received our invitation
 			else if (action == InviteeSessionState.Action.REMOTE_INVITATION) {
@@ -146,8 +154,7 @@ class InviteeEngine<IS extends InviteeSessionState, IR extends InvitationRequest
 				Event event = invitationReceivedEventFactory.build(localState,
 						msg.getTime(), invitation.getMessage());
 				events = Collections.singletonList(event);
-			}
-			else {
+			} else {
 				throw new IllegalArgumentException("Bad state");
 			}
 			return new StateUpdate<IS, BaseMessage>(deleteMsg,
@@ -173,7 +180,8 @@ class InviteeEngine<IS extends InviteeSessionState, IR extends InvitationRequest
 		);
 	}
 
-	private void logMessageReceived(InviteeSessionState.State currentState, InviteeSessionState.State nextState,
+	private void logMessageReceived(InviteeSessionState.State currentState,
+			InviteeSessionState.State nextState,
 			long type, BaseMessage msg) {
 
 		if (!LOG.isLoggable(INFO)) return;
diff --git a/briar-core/src/org/briarproject/sharing/InviteeSessionState.java b/briar-core/src/main/java/org/briarproject/briar/sharing/InviteeSessionState.java
similarity index 60%
rename from briar-core/src/org/briarproject/sharing/InviteeSessionState.java
rename to briar-core/src/main/java/org/briarproject/briar/sharing/InviteeSessionState.java
index ec77dfe82da44c9c6c5e22d7a88eed862e6004b5..cb90748f701c6122243037e9f6fbcec1f4f05d88 100644
--- a/briar-core/src/org/briarproject/sharing/InviteeSessionState.java
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/InviteeSessionState.java
@@ -1,44 +1,45 @@
-package org.briarproject.sharing;
+package org.briarproject.briar.sharing;
 
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.NotNull;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.SessionId;
 
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
 import javax.annotation.concurrent.NotThreadSafe;
 
-import static org.briarproject.api.sharing.SharingConstants.INVITATION_ID;
-import static org.briarproject.api.sharing.SharingConstants.IS_SHARER;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE;
-import static org.briarproject.api.sharing.SharingConstants.STATE;
-import static org.briarproject.sharing.InviteeSessionState.Action.LOCAL_ACCEPT;
-import static org.briarproject.sharing.InviteeSessionState.Action.LOCAL_DECLINE;
-import static org.briarproject.sharing.InviteeSessionState.Action.LOCAL_LEAVE;
-import static org.briarproject.sharing.InviteeSessionState.Action.REMOTE_INVITATION;
-import static org.briarproject.sharing.InviteeSessionState.Action.REMOTE_LEAVE;
+import static org.briarproject.briar.api.sharing.SharingConstants.INVITATION_ID;
+import static org.briarproject.briar.api.sharing.SharingConstants.IS_SHARER;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE;
+import static org.briarproject.briar.api.sharing.SharingConstants.STATE;
+import static org.briarproject.briar.sharing.InviteeSessionState.Action.LOCAL_ACCEPT;
+import static org.briarproject.briar.sharing.InviteeSessionState.Action.LOCAL_DECLINE;
+import static org.briarproject.briar.sharing.InviteeSessionState.Action.LOCAL_LEAVE;
+import static org.briarproject.briar.sharing.InviteeSessionState.Action.REMOTE_INVITATION;
+import static org.briarproject.briar.sharing.InviteeSessionState.Action.REMOTE_LEAVE;
 
 @NotThreadSafe
 @NotNullByDefault
 public abstract class InviteeSessionState extends SharingSessionState {
 
 	private State state;
-	@NotNull
 	private final MessageId invitationId;
 
 	public InviteeSessionState(SessionId sessionId, MessageId storageId,
 			GroupId groupId, State state, ContactId contactId,
-			GroupId shareableId, @NotNull MessageId invitationId) {
+			GroupId shareableId, MessageId invitationId) {
 
 		super(sessionId, storageId, groupId, contactId, shareableId);
 		this.state = state;
 		this.invitationId = invitationId;
 	}
 
+	@Override
 	public BdfDictionary toBdfDictionary() {
 		BdfDictionary d = super.toBdfDictionary();
 		d.put(STATE, getState().getValue());
@@ -55,12 +56,14 @@ public abstract class InviteeSessionState extends SharingSessionState {
 		return state;
 	}
 
-	@NotNull
 	public MessageId getInvitationId() {
 		return invitationId;
 	}
 
+	@Immutable
+	@NotNullByDefault
 	public enum State {
+
 		ERROR(0),
 		AWAIT_INVITATION(1) {
 			@Override
@@ -114,7 +117,9 @@ public abstract class InviteeSessionState extends SharingSessionState {
 		}
 	}
 
+	@NotNullByDefault
 	public enum Action {
+
 		LOCAL_ACCEPT,
 		LOCAL_DECLINE,
 		LOCAL_LEAVE,
@@ -123,6 +128,7 @@ public abstract class InviteeSessionState extends SharingSessionState {
 		REMOTE_LEAVE,
 		REMOTE_ABORT;
 
+		@Nullable
 		public static Action getRemote(long type) {
 			if (type == SHARE_MSG_TYPE_INVITATION) return REMOTE_INVITATION;
 			if (type == SHARE_MSG_TYPE_LEAVE) return REMOTE_LEAVE;
diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/InviteeSessionStateFactory.java b/briar-core/src/main/java/org/briarproject/briar/sharing/InviteeSessionStateFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..3a0e3813e9810c1663e21c7a0dddbba0dd7ebe5f
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/InviteeSessionStateFactory.java
@@ -0,0 +1,20 @@
+package org.briarproject.briar.sharing;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.sharing.Shareable;
+
+interface InviteeSessionStateFactory<S extends Shareable, IS extends InviteeSessionState> {
+
+	IS build(SessionId sessionId, MessageId storageId, GroupId groupId,
+			InviteeSessionState.State state, ContactId contactId,
+			GroupId shareableId, BdfDictionary d) throws FormatException;
+
+	IS build(SessionId sessionId, MessageId storageId, GroupId groupId,
+			InviteeSessionState.State state, ContactId contactId, S shareable,
+			MessageId invitationId);
+}
diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/ShareableFactory.java b/briar-core/src/main/java/org/briarproject/briar/sharing/ShareableFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..2d18d56ceda10d736f8bfab22d6c3af2799521cb
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/ShareableFactory.java
@@ -0,0 +1,26 @@
+package org.briarproject.briar.sharing;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.briar.api.sharing.Shareable;
+import org.briarproject.briar.api.sharing.SharingMessage;
+
+@NotNullByDefault
+interface ShareableFactory<S extends Shareable, I extends SharingMessage.Invitation, IS extends InviteeSessionState, SS extends SharerSessionState> {
+
+	BdfList encode(S sh);
+
+	S get(Transaction txn, GroupId groupId) throws DbException;
+
+	S parse(BdfList shareable) throws FormatException;
+
+	S parse(I msg);
+
+	S parse(IS state);
+
+	S parse(SS state);
+}
diff --git a/briar-core/src/org/briarproject/sharing/SharerEngine.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharerEngine.java
similarity index 81%
rename from briar-core/src/org/briarproject/sharing/SharerEngine.java
rename to briar-core/src/main/java/org/briarproject/briar/sharing/SharerEngine.java
index 3ddb17760671c8618b3a8d761d0c454aed5f01e3..476580f915d64eef3784f178aa605c92067d1ca5 100644
--- a/briar-core/src/org/briarproject/sharing/SharerEngine.java
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharerEngine.java
@@ -1,31 +1,36 @@
-package org.briarproject.sharing;
+package org.briarproject.briar.sharing;
 
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ProtocolEngine;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.InvitationResponseReceivedEvent;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.client.ProtocolEngine;
+import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent;
 
 import java.util.Collections;
 import java.util.List;
 import java.util.logging.Logger;
 
+import javax.annotation.concurrent.Immutable;
+
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ACCEPT;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_DECLINE;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE;
-import static org.briarproject.api.sharing.SharingConstants.TASK_ADD_SHAREABLE_TO_LIST_TO_BE_SHARED_BY_US;
-import static org.briarproject.api.sharing.SharingConstants.TASK_REMOVE_SHAREABLE_FROM_LIST_TO_BE_SHARED_BY_US;
-import static org.briarproject.api.sharing.SharingConstants.TASK_SHARE_SHAREABLE;
-import static org.briarproject.api.sharing.SharingConstants.TASK_UNSHARE_SHAREABLE_SHARED_BY_US;
-import static org.briarproject.api.sharing.SharingMessage.BaseMessage;
-import static org.briarproject.api.sharing.SharingMessage.Invitation;
-import static org.briarproject.api.sharing.SharingMessage.SimpleMessage;
-import static org.briarproject.sharing.SharerSessionState.Action.REMOTE_ACCEPT;
-import static org.briarproject.sharing.SharerSessionState.Action.REMOTE_DECLINE;
-
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_ACCEPT;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_DECLINE;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE;
+import static org.briarproject.briar.api.sharing.SharingConstants.TASK_ADD_SHAREABLE_TO_LIST_TO_BE_SHARED_BY_US;
+import static org.briarproject.briar.api.sharing.SharingConstants.TASK_REMOVE_SHAREABLE_FROM_LIST_TO_BE_SHARED_BY_US;
+import static org.briarproject.briar.api.sharing.SharingConstants.TASK_SHARE_SHAREABLE;
+import static org.briarproject.briar.api.sharing.SharingConstants.TASK_UNSHARE_SHAREABLE_SHARED_BY_US;
+import static org.briarproject.briar.api.sharing.SharingMessage.BaseMessage;
+import static org.briarproject.briar.api.sharing.SharingMessage.Invitation;
+import static org.briarproject.briar.api.sharing.SharingMessage.SimpleMessage;
+import static org.briarproject.briar.sharing.SharerSessionState.Action.REMOTE_ACCEPT;
+import static org.briarproject.briar.sharing.SharerSessionState.Action.REMOTE_DECLINE;
+
+@Immutable
+@NotNullByDefault
 class SharerEngine<I extends Invitation, SS extends SharerSessionState, IRR extends InvitationResponseReceivedEvent>
 		implements ProtocolEngine<SharerSessionState.Action, SS, BaseMessage> {
 
diff --git a/briar-core/src/org/briarproject/sharing/SharerSessionState.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharerSessionState.java
similarity index 64%
rename from briar-core/src/org/briarproject/sharing/SharerSessionState.java
rename to briar-core/src/main/java/org/briarproject/briar/sharing/SharerSessionState.java
index a7406f0b1b408435c6f9ada2ddee2bf74d2729c2..597c88c688d9f23e65ac3662317c14083bd150e5 100644
--- a/briar-core/src/org/briarproject/sharing/SharerSessionState.java
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharerSessionState.java
@@ -1,27 +1,27 @@
-package org.briarproject.sharing;
+package org.briarproject.briar.sharing;
 
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.SessionId;
 
+import javax.annotation.Nullable;
 import javax.annotation.concurrent.NotThreadSafe;
 
-import static org.briarproject.api.sharing.SharingConstants.IS_SHARER;
-import static org.briarproject.api.sharing.SharingConstants.RESPONSE_ID;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ACCEPT;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_DECLINE;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE;
-import static org.briarproject.api.sharing.SharingConstants.STATE;
-import static org.briarproject.sharing.SharerSessionState.Action.LOCAL_INVITATION;
-import static org.briarproject.sharing.SharerSessionState.Action.LOCAL_LEAVE;
-import static org.briarproject.sharing.SharerSessionState.Action.REMOTE_ACCEPT;
-import static org.briarproject.sharing.SharerSessionState.Action.REMOTE_DECLINE;
-import static org.briarproject.sharing.SharerSessionState.Action.REMOTE_LEAVE;
+import static org.briarproject.briar.api.sharing.SharingConstants.IS_SHARER;
+import static org.briarproject.briar.api.sharing.SharingConstants.RESPONSE_ID;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_ACCEPT;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_DECLINE;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE;
+import static org.briarproject.briar.api.sharing.SharingConstants.STATE;
+import static org.briarproject.briar.sharing.SharerSessionState.Action.LOCAL_INVITATION;
+import static org.briarproject.briar.sharing.SharerSessionState.Action.LOCAL_LEAVE;
+import static org.briarproject.briar.sharing.SharerSessionState.Action.REMOTE_ACCEPT;
+import static org.briarproject.briar.sharing.SharerSessionState.Action.REMOTE_DECLINE;
+import static org.briarproject.briar.sharing.SharerSessionState.Action.REMOTE_LEAVE;
 
 @NotThreadSafe
 @NotNullByDefault
@@ -42,6 +42,7 @@ public abstract class SharerSessionState extends SharingSessionState {
 		this.responseId = responseId;
 	}
 
+	@Override
 	public BdfDictionary toBdfDictionary() {
 		BdfDictionary d = super.toBdfDictionary();
 		d.put(STATE, getState().getValue());
@@ -64,7 +65,7 @@ public abstract class SharerSessionState extends SharingSessionState {
 
 	@Nullable
 	public String getMessage() {
-		return this.msg;
+		return msg;
 	}
 
 	public void setResponseId(@Nullable MessageId responseId) {
diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SharerSessionStateFactory.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharerSessionStateFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..a0a36f8f8995d90bcb16d18225e439082dd269ce
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharerSessionStateFactory.java
@@ -0,0 +1,21 @@
+package org.briarproject.briar.sharing;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.sharing.Shareable;
+
+@NotNullByDefault
+interface SharerSessionStateFactory<S extends Shareable, SS extends SharerSessionState> {
+
+	SS build(SessionId sessionId, MessageId storageId, GroupId groupId,
+			SharerSessionState.State state, ContactId contactId,
+			GroupId shareableId, BdfDictionary d) throws FormatException;
+
+	SS build(SessionId sessionId, MessageId storageId, GroupId groupId,
+			SharerSessionState.State state, ContactId contactId, S shareable);
+}
diff --git a/briar-core/src/org/briarproject/sharing/SharingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java
similarity index 84%
rename from briar-core/src/org/briarproject/sharing/SharingManagerImpl.java
rename to briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java
index fbb0276f2a939bdce466ea17e7ea9ec2e2d57562..4c99ceb54a5c9742f5e63be0a39619dc0156b37f 100644
--- a/briar-core/src/org/briarproject/sharing/SharingManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java
@@ -1,45 +1,45 @@
-package org.briarproject.sharing;
-
-import org.briarproject.api.Bytes;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.Client;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.ContactGroupFactory;
-import org.briarproject.api.clients.MessageQueueManager;
-import org.briarproject.api.clients.MessageTracker;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.contact.ContactManager.AddContactHook;
-import org.briarproject.api.contact.ContactManager.RemoveContactHook;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.data.MetadataParser;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.db.NoSuchMessageException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.InvitationRequestReceivedEvent;
-import org.briarproject.api.event.InvitationResponseReceivedEvent;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sharing.InvitationMessage;
-import org.briarproject.api.sharing.Shareable;
-import org.briarproject.api.sharing.SharingInvitationItem;
-import org.briarproject.api.sharing.SharingManager;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.sync.MessageStatus;
-import org.briarproject.api.system.Clock;
-import org.briarproject.clients.ConversationClientImpl;
-import org.briarproject.util.StringUtils;
+package org.briarproject.briar.sharing;
+
+import org.briarproject.bramble.api.Bytes;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.client.ContactGroupFactory;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager.AddContactHook;
+import org.briarproject.bramble.api.contact.ContactManager.RemoveContactHook;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.data.MetadataParser;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.db.NoSuchMessageException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.event.Event;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Client;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.MessageStatus;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.api.client.MessageQueueManager;
+import org.briarproject.briar.api.client.MessageTracker;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.sharing.InvitationMessage;
+import org.briarproject.briar.api.sharing.Shareable;
+import org.briarproject.briar.api.sharing.SharingInvitationItem;
+import org.briarproject.briar.api.sharing.SharingManager;
+import org.briarproject.briar.api.sharing.event.InvitationRequestReceivedEvent;
+import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent;
+import org.briarproject.briar.client.ConversationClientImpl;
 
 import java.io.IOException;
 import java.security.SecureRandom;
@@ -57,39 +57,39 @@ import javax.annotation.Nullable;
 
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.clients.ProtocolEngine.StateUpdate;
-import static org.briarproject.api.sharing.SharingConstants.CONTACT_ID;
-import static org.briarproject.api.sharing.SharingConstants.IS_SHARER;
-import static org.briarproject.api.sharing.SharingConstants.LOCAL;
-import static org.briarproject.api.sharing.SharingConstants.MAX_INVITATION_MESSAGE_LENGTH;
-import static org.briarproject.api.sharing.SharingConstants.SESSION_ID;
-import static org.briarproject.api.sharing.SharingConstants.SHAREABLE_ID;
-import static org.briarproject.api.sharing.SharingConstants.SHARED_BY_US;
-import static org.briarproject.api.sharing.SharingConstants.SHARED_WITH_US;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ACCEPT;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_DECLINE;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE;
-import static org.briarproject.api.sharing.SharingConstants.SHARING_SALT_LENGTH;
-import static org.briarproject.api.sharing.SharingConstants.STATE;
-import static org.briarproject.api.sharing.SharingConstants.TASK_ADD_SHAREABLE_TO_LIST_SHARED_WITH_US;
-import static org.briarproject.api.sharing.SharingConstants.TASK_ADD_SHAREABLE_TO_LIST_TO_BE_SHARED_BY_US;
-import static org.briarproject.api.sharing.SharingConstants.TASK_ADD_SHARED_SHAREABLE;
-import static org.briarproject.api.sharing.SharingConstants.TASK_REMOVE_SHAREABLE_FROM_LIST_SHARED_WITH_US;
-import static org.briarproject.api.sharing.SharingConstants.TASK_REMOVE_SHAREABLE_FROM_LIST_TO_BE_SHARED_BY_US;
-import static org.briarproject.api.sharing.SharingConstants.TASK_SHARE_SHAREABLE;
-import static org.briarproject.api.sharing.SharingConstants.TASK_UNSHARE_SHAREABLE_SHARED_BY_US;
-import static org.briarproject.api.sharing.SharingConstants.TASK_UNSHARE_SHAREABLE_SHARED_WITH_US;
-import static org.briarproject.api.sharing.SharingConstants.TIME;
-import static org.briarproject.api.sharing.SharingConstants.TO_BE_SHARED_BY_US;
-import static org.briarproject.api.sharing.SharingConstants.TYPE;
-import static org.briarproject.api.sharing.SharingMessage.BaseMessage;
-import static org.briarproject.api.sharing.SharingMessage.Invitation;
-import static org.briarproject.api.sync.Group.Visibility.INVISIBLE;
-import static org.briarproject.api.sync.Group.Visibility.SHARED;
-import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
-import static org.briarproject.sharing.InviteeSessionState.State.AWAIT_LOCAL_RESPONSE;
+import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
+import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
+import static org.briarproject.briar.api.client.ProtocolEngine.StateUpdate;
+import static org.briarproject.briar.api.sharing.SharingConstants.CONTACT_ID;
+import static org.briarproject.briar.api.sharing.SharingConstants.IS_SHARER;
+import static org.briarproject.briar.api.sharing.SharingConstants.LOCAL;
+import static org.briarproject.briar.api.sharing.SharingConstants.MAX_INVITATION_MESSAGE_LENGTH;
+import static org.briarproject.briar.api.sharing.SharingConstants.SESSION_ID;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHAREABLE_ID;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARED_BY_US;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARED_WITH_US;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_ACCEPT;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_DECLINE;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARING_SALT_LENGTH;
+import static org.briarproject.briar.api.sharing.SharingConstants.STATE;
+import static org.briarproject.briar.api.sharing.SharingConstants.TASK_ADD_SHAREABLE_TO_LIST_SHARED_WITH_US;
+import static org.briarproject.briar.api.sharing.SharingConstants.TASK_ADD_SHAREABLE_TO_LIST_TO_BE_SHARED_BY_US;
+import static org.briarproject.briar.api.sharing.SharingConstants.TASK_ADD_SHARED_SHAREABLE;
+import static org.briarproject.briar.api.sharing.SharingConstants.TASK_REMOVE_SHAREABLE_FROM_LIST_SHARED_WITH_US;
+import static org.briarproject.briar.api.sharing.SharingConstants.TASK_REMOVE_SHAREABLE_FROM_LIST_TO_BE_SHARED_BY_US;
+import static org.briarproject.briar.api.sharing.SharingConstants.TASK_SHARE_SHAREABLE;
+import static org.briarproject.briar.api.sharing.SharingConstants.TASK_UNSHARE_SHAREABLE_SHARED_BY_US;
+import static org.briarproject.briar.api.sharing.SharingConstants.TASK_UNSHARE_SHAREABLE_SHARED_WITH_US;
+import static org.briarproject.briar.api.sharing.SharingConstants.TIME;
+import static org.briarproject.briar.api.sharing.SharingConstants.TO_BE_SHARED_BY_US;
+import static org.briarproject.briar.api.sharing.SharingConstants.TYPE;
+import static org.briarproject.briar.api.sharing.SharingMessage.BaseMessage;
+import static org.briarproject.briar.api.sharing.SharingMessage.Invitation;
+import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
+import static org.briarproject.briar.sharing.InviteeSessionState.State.AWAIT_LOCAL_RESPONSE;
 
 @NotNullByDefault
 abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS extends InviteeSessionState, SS extends SharerSessionState, IR extends InvitationRequestReceivedEvent, IRR extends InvitationResponseReceivedEvent>
@@ -273,7 +273,7 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
 
 	@Override
 	public void sendInvitation(GroupId groupId, ContactId contactId,
-			String msg) throws DbException {
+			@Nullable String msg) throws DbException {
 
 		Transaction txn = db.startTransaction(false);
 		try {
@@ -369,7 +369,8 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
 	}
 
 	@Override
-	public Collection<InvitationMessage> getInvitationMessages(ContactId contactId)
+	public Collection<InvitationMessage> getInvitationMessages(
+			ContactId contactId)
 			throws DbException {
 
 		Transaction txn = db.startTransaction(true);
@@ -406,12 +407,12 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
 							available = ((InviteeSessionState) s).getState() ==
 									AWAIT_LOCAL_RESPONSE;
 						}
-						InvitationMessage im = createInvitationRequest(m.getKey(), msg,
-								contactId, available, time, local,
-								status.isSent(), status.isSeen(), read);
+						InvitationMessage im =
+								createInvitationRequest(m.getKey(), msg,
+										contactId, available, time, local,
+										status.isSent(), status.isSeen(), read);
 						list.add(im);
-					}
-					else if (type == SHARE_MSG_TYPE_ACCEPT ||
+					} else if (type == SHARE_MSG_TYPE_ACCEPT ||
 							type == SHARE_MSG_TYPE_DECLINE) {
 						boolean accept = type == SHARE_MSG_TYPE_ACCEPT;
 						BaseMessage msg = BaseMessage
@@ -422,8 +423,7 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
 								accept, time, local, status.isSent(),
 								status.isSeen(), read);
 						list.add(im);
-					}
-					else {
+					} else {
 						throw new RuntimeException("Unexpected Message Type");
 					}
 				} catch (FormatException e) {
@@ -441,7 +441,8 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
 	}
 
 	@Override
-	public Collection<SharingInvitationItem> getInvitations() throws DbException {
+	public Collection<SharingInvitationItem> getInvitations()
+			throws DbException {
 		List<SharingInvitationItem> invitations =
 				new ArrayList<SharingInvitationItem>();
 		Transaction txn = db.startTransaction(true);
@@ -663,9 +664,8 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
 				BdfList.of(salt));
 		SessionId sessionId = new SessionId(m.getId().getBytes());
 
-		SS s = getSSFactory().build(sessionId, sessionId,
-				group.getId(), SharerSessionState.State.PREPARE_INVITATION,
-				contactId, f);
+		SS s = getSSFactory().build(sessionId, m.getId(), group.getId(),
+				SharerSessionState.State.PREPARE_INVITATION, contactId, f);
 
 		// save local state to database
 		BdfDictionary d = s.toBdfDictionary();
@@ -741,8 +741,9 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
 			throws DbException, FormatException {
 
 		// we should be able to get the sharer state directly from sessionId
+		MessageId storageId = new MessageId(sessionId.getBytes());
 		BdfDictionary d =
-				clientHelper.getMessageMetadataAsDictionary(txn, sessionId);
+				clientHelper.getMessageMetadataAsDictionary(txn, storageId);
 
 		if (!d.getBoolean(IS_SHARER)) throw new FormatException();
 
diff --git a/briar-core/src/org/briarproject/sharing/SharingModule.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingModule.java
similarity index 60%
rename from briar-core/src/org/briarproject/sharing/SharingModule.java
rename to briar-core/src/main/java/org/briarproject/briar/sharing/SharingModule.java
index da616a43d7b20c7f3e520a3e3c5c2e91ca218020..f56e6b8ca88b99279002853e3508a9390ac8673e 100644
--- a/briar-core/src/org/briarproject/sharing/SharingModule.java
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingModule.java
@@ -1,16 +1,16 @@
-package org.briarproject.sharing;
-
-import org.briarproject.api.blogs.BlogManager;
-import org.briarproject.api.blogs.BlogSharingManager;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageQueueManager;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.forum.ForumSharingManager;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.messaging.ConversationManager;
-import org.briarproject.api.system.Clock;
+package org.briarproject.briar.sharing;
+
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.blog.BlogManager;
+import org.briarproject.briar.api.blog.BlogSharingManager;
+import org.briarproject.briar.api.client.MessageQueueManager;
+import org.briarproject.briar.api.forum.ForumManager;
+import org.briarproject.briar.api.forum.ForumSharingManager;
+import org.briarproject.briar.api.messaging.ConversationManager;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -38,11 +38,10 @@ public class SharingModule {
 			MessageQueueManager messageQueueManager, ClientHelper clientHelper,
 			MetadataEncoder metadataEncoder, Clock clock) {
 
-		BlogSharingValidator
-				validator = new BlogSharingValidator(clientHelper,
-				metadataEncoder, clock);
+		BlogSharingValidator validator =
+				new BlogSharingValidator(clientHelper, metadataEncoder, clock);
 		messageQueueManager.registerMessageValidator(
-				BlogSharingManagerImpl.CLIENT_ID, validator);
+				BlogSharingManager.CLIENT_ID, validator);
 
 		return validator;
 	}
@@ -50,18 +49,16 @@ public class SharingModule {
 	@Provides
 	@Singleton
 	BlogSharingManager provideBlogSharingManager(
-			LifecycleManager lifecycleManager,
-			ContactManager contactManager,
+			LifecycleManager lifecycleManager, ContactManager contactManager,
 			MessageQueueManager messageQueueManager,
-			ConversationManager conversationManager,
-			BlogManager blogManager,
+			ConversationManager conversationManager, BlogManager blogManager,
 			BlogSharingManagerImpl blogSharingManager) {
 
 		lifecycleManager.registerClient(blogSharingManager);
 		contactManager.registerAddContactHook(blogSharingManager);
 		contactManager.registerRemoveContactHook(blogSharingManager);
 		messageQueueManager.registerIncomingMessageHook(
-				BlogSharingManagerImpl.CLIENT_ID, blogSharingManager);
+				BlogSharingManager.CLIENT_ID, blogSharingManager);
 		conversationManager.registerConversationClient(blogSharingManager);
 		blogManager.registerRemoveBlogHook(blogSharingManager);
 
@@ -74,11 +71,10 @@ public class SharingModule {
 			MessageQueueManager messageQueueManager, ClientHelper clientHelper,
 			MetadataEncoder metadataEncoder, Clock clock) {
 
-		ForumSharingValidator
-				validator = new ForumSharingValidator(clientHelper,
-				metadataEncoder, clock);
+		ForumSharingValidator validator =
+				new ForumSharingValidator(clientHelper, metadataEncoder, clock);
 		messageQueueManager.registerMessageValidator(
-				ForumSharingManagerImpl.CLIENT_ID, validator);
+				ForumSharingManager.CLIENT_ID, validator);
 
 		return validator;
 	}
@@ -86,18 +82,16 @@ public class SharingModule {
 	@Provides
 	@Singleton
 	ForumSharingManager provideForumSharingManager(
-			LifecycleManager lifecycleManager,
-			ContactManager contactManager,
+			LifecycleManager lifecycleManager, ContactManager contactManager,
 			MessageQueueManager messageQueueManager,
-			ConversationManager conversationManager,
-			ForumManager forumManager,
+			ConversationManager conversationManager, ForumManager forumManager,
 			ForumSharingManagerImpl forumSharingManager) {
 
 		lifecycleManager.registerClient(forumSharingManager);
 		contactManager.registerAddContactHook(forumSharingManager);
 		contactManager.registerRemoveContactHook(forumSharingManager);
 		messageQueueManager.registerIncomingMessageHook(
-				ForumSharingManagerImpl.CLIENT_ID, forumSharingManager);
+				ForumSharingManager.CLIENT_ID, forumSharingManager);
 		conversationManager.registerConversationClient(forumSharingManager);
 		forumManager.registerRemoveForumHook(forumSharingManager);
 
diff --git a/briar-core/src/org/briarproject/sharing/SharingSessionState.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingSessionState.java
similarity index 63%
rename from briar-core/src/org/briarproject/sharing/SharingSessionState.java
rename to briar-core/src/main/java/org/briarproject/briar/sharing/SharingSessionState.java
index 6864df09ed5d7f70dc93f064aaf2a72316aaa497..048d56a5841b86184aa3bfdb024430a0b4a359ee 100644
--- a/briar-core/src/org/briarproject/sharing/SharingSessionState.java
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingSessionState.java
@@ -1,22 +1,26 @@
-package org.briarproject.sharing;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-
-import static org.briarproject.api.sharing.SharingConstants.CONTACT_ID;
-import static org.briarproject.api.sharing.SharingConstants.GROUP_ID;
-import static org.briarproject.api.sharing.SharingConstants.IS_SHARER;
-import static org.briarproject.api.sharing.SharingConstants.SESSION_ID;
-import static org.briarproject.api.sharing.SharingConstants.SHAREABLE_ID;
-import static org.briarproject.api.sharing.SharingConstants.STATE;
-import static org.briarproject.api.sharing.SharingConstants.STORAGE_ID;
-
-// This class is not thread-safe
-public abstract class SharingSessionState {
+package org.briarproject.briar.sharing;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.SessionId;
+
+import javax.annotation.concurrent.NotThreadSafe;
+
+import static org.briarproject.briar.api.sharing.SharingConstants.CONTACT_ID;
+import static org.briarproject.briar.api.sharing.SharingConstants.GROUP_ID;
+import static org.briarproject.briar.api.sharing.SharingConstants.IS_SHARER;
+import static org.briarproject.briar.api.sharing.SharingConstants.SESSION_ID;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHAREABLE_ID;
+import static org.briarproject.briar.api.sharing.SharingConstants.STATE;
+import static org.briarproject.briar.api.sharing.SharingConstants.STORAGE_ID;
+
+@NotThreadSafe
+@NotNullByDefault
+abstract class SharingSessionState {
 
 	private final SessionId sessionId;
 	private final MessageId storageId;
@@ -25,7 +29,7 @@ public abstract class SharingSessionState {
 	private final GroupId shareableId;
 	private int task = -1; // TODO get rid of task, see #376
 
-	public SharingSessionState(SessionId sessionId, MessageId storageId,
+	SharingSessionState(SessionId sessionId, MessageId storageId,
 			GroupId groupId, ContactId contactId, GroupId shareableId) {
 
 		this.sessionId = sessionId;
@@ -35,7 +39,7 @@ public abstract class SharingSessionState {
 		this.shareableId = shareableId;
 	}
 
-	public static SharingSessionState fromBdfDictionary(
+	static SharingSessionState fromBdfDictionary(
 			InviteeSessionStateFactory isFactory,
 			SharerSessionStateFactory ssFactory, BdfDictionary d)
 			throws FormatException {
diff --git a/briar-core/src/org/briarproject/util/HtmlUtils.java b/briar-core/src/main/java/org/briarproject/briar/util/HtmlUtils.java
similarity index 54%
rename from briar-core/src/org/briarproject/util/HtmlUtils.java
rename to briar-core/src/main/java/org/briarproject/briar/util/HtmlUtils.java
index e9c338401bac5e176ae1432a803da934b6b61630..bc20e8599566747a2672d446f1bdc0c4513b6f09 100644
--- a/briar-core/src/org/briarproject/util/HtmlUtils.java
+++ b/briar-core/src/main/java/org/briarproject/briar/util/HtmlUtils.java
@@ -1,12 +1,14 @@
-package org.briarproject.util;
+package org.briarproject.briar.util;
 
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.jsoup.Jsoup;
 import org.jsoup.safety.Whitelist;
 
+@NotNullByDefault
 public class HtmlUtils {
 
-	public static Whitelist stripAll = Whitelist.none();
-	public static Whitelist article =
+	public static Whitelist STRIP_ALL = Whitelist.none();
+	public static Whitelist ARTICLE =
 			Whitelist.basic().addTags("h1", "h2", "h3", "h4", "h5", "h6");
 
 	public static String clean(String s, Whitelist list) {
diff --git a/briar-core/src/org/briarproject/CoreEagerSingletons.java b/briar-core/src/org/briarproject/CoreEagerSingletons.java
deleted file mode 100644
index 314543a31374e4701c6cd3cfd40e0666330294c9..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/CoreEagerSingletons.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package org.briarproject;
-
-import org.briarproject.blogs.BlogsModule;
-import org.briarproject.contact.ContactModule;
-import org.briarproject.crypto.CryptoModule;
-import org.briarproject.db.DatabaseExecutorModule;
-import org.briarproject.feed.FeedModule;
-import org.briarproject.forum.ForumModule;
-import org.briarproject.identity.IdentityModule;
-import org.briarproject.introduction.IntroductionModule;
-import org.briarproject.lifecycle.LifecycleModule;
-import org.briarproject.messaging.MessagingModule;
-import org.briarproject.plugins.PluginsModule;
-import org.briarproject.privategroup.PrivateGroupModule;
-import org.briarproject.privategroup.invitation.GroupInvitationModule;
-import org.briarproject.properties.PropertiesModule;
-import org.briarproject.sharing.SharingModule;
-import org.briarproject.sync.SyncModule;
-import org.briarproject.system.SystemModule;
-import org.briarproject.transport.TransportModule;
-
-public interface CoreEagerSingletons {
-
-	void inject(BlogsModule.EagerSingletons init);
-
-	void inject(ContactModule.EagerSingletons init);
-
-	void inject(CryptoModule.EagerSingletons init);
-
-	void inject(DatabaseExecutorModule.EagerSingletons init);
-
-	void inject(ForumModule.EagerSingletons init);
-
-	void inject(GroupInvitationModule.EagerSingletons init);
-
-	void inject(IdentityModule.EagerSingletons init);
-
-	void inject(IntroductionModule.EagerSingletons init);
-
-	void inject(LifecycleModule.EagerSingletons init);
-
-	void inject(MessagingModule.EagerSingletons init);
-
-	void inject(PluginsModule.EagerSingletons init);
-
-	void inject(PrivateGroupModule.EagerSingletons init);
-
-	void inject(PropertiesModule.EagerSingletons init);
-
-	void inject(SharingModule.EagerSingletons init);
-
-	void inject(SyncModule.EagerSingletons init);
-
-	void inject(SystemModule.EagerSingletons init);
-
-	void inject(TransportModule.EagerSingletons init);
-
-	void inject(FeedModule.EagerSingletons init);
-}
diff --git a/briar-core/src/org/briarproject/CoreModule.java b/briar-core/src/org/briarproject/CoreModule.java
deleted file mode 100644
index aee24de22f3d4264c2c88f63bd528a6aa01ce97d..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/CoreModule.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.briarproject;
-
-import org.briarproject.blogs.BlogsModule;
-import org.briarproject.clients.ClientsModule;
-import org.briarproject.contact.ContactModule;
-import org.briarproject.crypto.CryptoModule;
-import org.briarproject.data.DataModule;
-import org.briarproject.db.DatabaseExecutorModule;
-import org.briarproject.db.DatabaseModule;
-import org.briarproject.event.EventModule;
-import org.briarproject.feed.FeedModule;
-import org.briarproject.forum.ForumModule;
-import org.briarproject.identity.IdentityModule;
-import org.briarproject.introduction.IntroductionModule;
-import org.briarproject.invitation.InvitationModule;
-import org.briarproject.keyagreement.KeyAgreementModule;
-import org.briarproject.lifecycle.LifecycleModule;
-import org.briarproject.messaging.MessagingModule;
-import org.briarproject.plugins.PluginsModule;
-import org.briarproject.privategroup.PrivateGroupModule;
-import org.briarproject.privategroup.invitation.GroupInvitationModule;
-import org.briarproject.properties.PropertiesModule;
-import org.briarproject.reliability.ReliabilityModule;
-import org.briarproject.reporting.ReportingModule;
-import org.briarproject.settings.SettingsModule;
-import org.briarproject.sharing.SharingModule;
-import org.briarproject.socks.SocksModule;
-import org.briarproject.sync.SyncModule;
-import org.briarproject.system.SystemModule;
-import org.briarproject.transport.TransportModule;
-
-import dagger.Module;
-
-@Module(includes = {
-		BlogsModule.class,
-		ClientsModule.class,
-		ContactModule.class,
-		CryptoModule.class,
-		DataModule.class,
-		DatabaseModule.class,
-		DatabaseExecutorModule.class,
-		EventModule.class,
-		ForumModule.class,
-		GroupInvitationModule.class,
-		IdentityModule.class,
-		IntroductionModule.class,
-		InvitationModule.class,
-		KeyAgreementModule.class,
-		LifecycleModule.class,
-		MessagingModule.class,
-		PluginsModule.class,
-		PrivateGroupModule.class,
-		PropertiesModule.class,
-		ReliabilityModule.class,
-		ReportingModule.class,
-		SettingsModule.class,
-		SharingModule.class,
-		SocksModule.class,
-		SyncModule.class,
-		SystemModule.class,
-		TransportModule.class,
-		FeedModule.class
-})
-public class CoreModule {
-
-	public static void initEagerSingletons(CoreEagerSingletons c) {
-		c.inject(new BlogsModule.EagerSingletons());
-		c.inject(new ContactModule.EagerSingletons());
-		c.inject(new CryptoModule.EagerSingletons());
-		c.inject(new DatabaseExecutorModule.EagerSingletons());
-		c.inject(new ForumModule.EagerSingletons());
-		c.inject(new GroupInvitationModule.EagerSingletons());
-		c.inject(new IdentityModule.EagerSingletons());
-		c.inject(new LifecycleModule.EagerSingletons());
-		c.inject(new MessagingModule.EagerSingletons());
-		c.inject(new PluginsModule.EagerSingletons());
-		c.inject(new PrivateGroupModule.EagerSingletons());
-		c.inject(new PropertiesModule.EagerSingletons());
-		c.inject(new SharingModule.EagerSingletons());
-		c.inject(new SyncModule.EagerSingletons());
-		c.inject(new SystemModule.EagerSingletons());
-		c.inject(new TransportModule.EagerSingletons());
-		c.inject(new IntroductionModule.EagerSingletons());
-		c.inject(new FeedModule.EagerSingletons());
-	}
-}
diff --git a/briar-core/src/org/briarproject/clients/BdfMessageValidator.java b/briar-core/src/org/briarproject/clients/BdfMessageValidator.java
deleted file mode 100644
index 700724766586b54d99767b4bdca4eb74663e0023..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/clients/BdfMessageValidator.java
+++ /dev/null
@@ -1,139 +0,0 @@
-package org.briarproject.clients;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.BdfMessageContext;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageQueueManager.QueueMessageValidator;
-import org.briarproject.api.clients.QueueMessage;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.InvalidMessageException;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageContext;
-import org.briarproject.api.sync.ValidationManager.MessageValidator;
-import org.briarproject.api.system.Clock;
-import org.briarproject.util.StringUtils;
-
-import java.util.logging.Logger;
-
-import javax.annotation.Nullable;
-
-import static org.briarproject.api.clients.QueueMessage.QUEUE_MESSAGE_HEADER_LENGTH;
-import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
-
-@NotNullByDefault
-public abstract class BdfMessageValidator implements MessageValidator,
-		QueueMessageValidator {
-
-	protected static final Logger LOG =
-			Logger.getLogger(BdfMessageValidator.class.getName());
-
-	protected final ClientHelper clientHelper;
-	protected final MetadataEncoder metadataEncoder;
-	protected final Clock clock;
-
-	protected BdfMessageValidator(ClientHelper clientHelper,
-			MetadataEncoder metadataEncoder, Clock clock) {
-		this.clientHelper = clientHelper;
-		this.metadataEncoder = metadataEncoder;
-		this.clock = clock;
-	}
-
-	protected abstract BdfMessageContext validateMessage(Message m, Group g,
-			BdfList body) throws InvalidMessageException, FormatException;
-
-	@Override
-	public MessageContext validateMessage(Message m, Group g)
-			throws InvalidMessageException {
-		return validateMessage(m, g, MESSAGE_HEADER_LENGTH);
-	}
-
-	@Override
-	public MessageContext validateMessage(QueueMessage q, Group g)
-			throws InvalidMessageException {
-		return validateMessage(q, g, QUEUE_MESSAGE_HEADER_LENGTH);
-	}
-
-	private MessageContext validateMessage(Message m, Group g, int headerLength)
-			throws InvalidMessageException {
-		// Reject the message if it's too far in the future
-		long now = clock.currentTimeMillis();
-		if (m.getTimestamp() - now > MAX_CLOCK_DIFFERENCE) {
-			throw new InvalidMessageException(
-					"Timestamp is too far in the future");
-		}
-		byte[] raw = m.getRaw();
-		if (raw.length <= headerLength) {
-			throw new InvalidMessageException("Message is too short");
-		}
-		try {
-			BdfList body = clientHelper.toList(raw, headerLength,
-					raw.length - headerLength);
-			BdfMessageContext result = validateMessage(m, g, body);
-			Metadata meta = metadataEncoder.encode(result.getDictionary());
-			return new MessageContext(meta, result.getDependencies());
-		} catch (FormatException e) {
-			throw new InvalidMessageException(e);
-		}
-	}
-
-	protected void checkLength(@Nullable String s, int minLength, int maxLength)
-			throws FormatException {
-		if (s != null) {
-			int length = StringUtils.toUtf8(s).length;
-			if (length < minLength) throw new FormatException();
-			if (length > maxLength) throw new FormatException();
-		}
-	}
-
-	protected void checkLength(@Nullable String s, int length)
-			throws FormatException {
-		if (s != null && StringUtils.toUtf8(s).length != length)
-			throw new FormatException();
-	}
-
-	protected void checkLength(@Nullable byte[] b, int minLength, int maxLength)
-			throws FormatException {
-		if (b != null) {
-			if (b.length < minLength) throw new FormatException();
-			if (b.length > maxLength) throw new FormatException();
-		}
-	}
-
-	protected void checkLength(@Nullable byte[] b, int length)
-			throws FormatException {
-		if (b != null && b.length != length) throw new FormatException();
-	}
-
-	protected void checkSize(@Nullable BdfList list, int minSize, int maxSize)
-			throws FormatException {
-		if (list != null) {
-			if (list.size() < minSize) throw new FormatException();
-			if (list.size() > maxSize) throw new FormatException();
-		}
-	}
-
-	protected void checkSize(@Nullable BdfList list, int size)
-			throws FormatException {
-		if (list != null && list.size() != size) throw new FormatException();
-	}
-
-	protected void checkSize(@Nullable BdfDictionary dictionary, int minSize,
-			int maxSize) throws FormatException {
-		if (dictionary != null) {
-			if (dictionary.size() < minSize) throw new FormatException();
-			if (dictionary.size() > maxSize) throw new FormatException();
-		}
-	}
-
-	protected void checkSize(@Nullable BdfDictionary dictionary, int size)
-			throws FormatException {
-		if (dictionary != null && dictionary.size() != size)
-			throw new FormatException();
-	}
-}
diff --git a/briar-core/src/org/briarproject/clients/ClientsModule.java b/briar-core/src/org/briarproject/clients/ClientsModule.java
deleted file mode 100644
index cd8e17538aece2ec4ae6185b7de24b3a5eadc596..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/clients/ClientsModule.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package org.briarproject.clients;
-
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.ContactGroupFactory;
-import org.briarproject.api.clients.MessageQueueManager;
-import org.briarproject.api.clients.MessageTracker;
-import org.briarproject.api.clients.QueueMessageFactory;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.data.BdfReaderFactory;
-import org.briarproject.api.data.BdfWriterFactory;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.data.MetadataParser;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.sync.GroupFactory;
-import org.briarproject.api.sync.MessageFactory;
-import org.briarproject.api.sync.ValidationManager;
-
-import javax.inject.Singleton;
-
-import dagger.Module;
-import dagger.Provides;
-
-@Module
-public class ClientsModule {
-
-	@Provides
-	ClientHelper provideClientHelper(DatabaseComponent db,
-			MessageFactory messageFactory, BdfReaderFactory bdfReaderFactory,
-			BdfWriterFactory bdfWriterFactory, MetadataParser metadataParser,
-			MetadataEncoder metadataEncoder, CryptoComponent cryptoComponent) {
-		return new ClientHelperImpl(db, messageFactory, bdfReaderFactory,
-				bdfWriterFactory, metadataParser, metadataEncoder,
-				cryptoComponent);
-	}
-
-	@Provides
-	ContactGroupFactory provideContactGroupFactory(GroupFactory groupFactory,
-			ClientHelper clientHelper) {
-		return new ContactGroupFactoryImpl(groupFactory, clientHelper);
-	}
-
-	@Provides
-	@Singleton
-	MessageQueueManager provideMessageQueueManager(DatabaseComponent db,
-			ClientHelper clientHelper, QueueMessageFactory queueMessageFactory,
-			ValidationManager validationManager) {
-		return new MessageQueueManagerImpl(db, clientHelper,
-				queueMessageFactory, validationManager);
-	}
-
-	@Provides
-	QueueMessageFactory provideQueueMessageFactory(CryptoComponent crypto) {
-		return new QueueMessageFactoryImpl(crypto);
-	}
-
-	@Provides
-	MessageTracker provideMessageTracker(MessageTrackerImpl messageTracker) {
-		return messageTracker;
-	}
-}
diff --git a/briar-core/src/org/briarproject/clients/ConversationClientImpl.java b/briar-core/src/org/briarproject/clients/ConversationClientImpl.java
deleted file mode 100644
index a19e939fc5fa29ab2e31ea2b6c0d3c9552076ce0..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/clients/ConversationClientImpl.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.briarproject.clients;
-
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageTracker;
-import org.briarproject.api.clients.MessageTracker.GroupCount;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.data.MetadataParser;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.messaging.ConversationManager.ConversationClient;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-
-@NotNullByDefault
-public abstract class ConversationClientImpl extends BdfIncomingMessageHook
-		implements ConversationClient {
-
-	protected final MessageTracker messageTracker;
-
-	protected ConversationClientImpl(DatabaseComponent db,
-			ClientHelper clientHelper, MetadataParser metadataParser,
-			MessageTracker messageTracker) {
-		super(db, clientHelper, metadataParser);
-		this.messageTracker = messageTracker;
-	}
-
-	@Override
-	public GroupCount getGroupCount(Transaction txn, ContactId contactId)
-			throws DbException {
-		Contact contact = db.getContact(txn, contactId);
-		GroupId groupId = getContactGroup(contact).getId();
-		return messageTracker.getGroupCount(txn, groupId);
-	}
-
-	@Override
-	public void setReadFlag(GroupId g, MessageId m, boolean read)
-			throws DbException {
-		messageTracker.setReadFlag(g, m, read);
-	}
-}
diff --git a/briar-core/src/org/briarproject/crypto/Signature.java b/briar-core/src/org/briarproject/crypto/Signature.java
deleted file mode 100644
index 78379f693be58edd6adbb28a03c179aa55a7735a..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/crypto/Signature.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.briarproject.crypto;
-
-import org.briarproject.api.crypto.PrivateKey;
-import org.briarproject.api.crypto.PublicKey;
-
-import java.security.GeneralSecurityException;
-
-interface Signature {
-
-	/**
-	 * @see {@link java.security.Signature#initSign(java.security.PrivateKey)}
-	 */
-	void initSign(PrivateKey k) throws GeneralSecurityException;
-
-	/**
-	 * @see {@link java.security.Signature#initVerify(java.security.PublicKey)}
-	 */
-	void initVerify(PublicKey k) throws GeneralSecurityException;
-
-	/** @see {@link java.security.Signature#update(byte)} */
-	void update(byte b);
-
-	/** @see {@link java.security.Signature#update(byte[])} */
-	void update(byte[] b);
-
-	/** @see {@link java.security.Signature#update(byte[], int, int)} */
-	void update(byte[] b, int off, int len);
-
-	/** @see {@link java.security.Signature#sign()} */
-	byte[] sign();
-
-	/** @see {@link java.security.Signature#verify(byte[])} */
-	boolean verify(byte[] signature);
-}
diff --git a/briar-core/src/org/briarproject/data/BdfReaderFactoryImpl.java b/briar-core/src/org/briarproject/data/BdfReaderFactoryImpl.java
deleted file mode 100644
index 0f1196c66120b77f7142bb8bf8aeb39266ed8d66..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/data/BdfReaderFactoryImpl.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.briarproject.data;
-
-import org.briarproject.api.data.BdfReader;
-import org.briarproject.api.data.BdfReaderFactory;
-
-import java.io.InputStream;
-
-import static org.briarproject.api.data.BdfReader.DEFAULT_NESTED_LIMIT;
-
-class BdfReaderFactoryImpl implements BdfReaderFactory {
-
-	@Override
-	public BdfReader createReader(InputStream in) {
-		return new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT);
-	}
-
-	@Override
-	public BdfReader createReader(InputStream in, int nestedLimit) {
-		return new BdfReaderImpl(in, nestedLimit);
-	}
-}
diff --git a/briar-core/src/org/briarproject/data/BdfWriterFactoryImpl.java b/briar-core/src/org/briarproject/data/BdfWriterFactoryImpl.java
deleted file mode 100644
index f98f9c871d6dbf197c47d32da45122ea4978e3f8..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/data/BdfWriterFactoryImpl.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.briarproject.data;
-
-import org.briarproject.api.data.BdfWriter;
-import org.briarproject.api.data.BdfWriterFactory;
-
-import java.io.OutputStream;
-
-class BdfWriterFactoryImpl implements BdfWriterFactory {
-
-	public BdfWriter createWriter(OutputStream out) {
-		return new BdfWriterImpl(out);
-	}
-}
diff --git a/briar-core/src/org/briarproject/db/DbStateException.java b/briar-core/src/org/briarproject/db/DbStateException.java
deleted file mode 100644
index f324faf2589ed937903118a7ce59144983adb157..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/db/DbStateException.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.briarproject.db;
-
-import java.sql.SQLException;
-
-/** Thrown when the database is in an illegal state. */
-class DbStateException extends SQLException {
-
-	private static final long serialVersionUID = 10793396057218891L;
-}
diff --git a/briar-core/src/org/briarproject/forum/ForumPostFactoryImpl.java b/briar-core/src/org/briarproject/forum/ForumPostFactoryImpl.java
deleted file mode 100644
index 70a545e1f9f6d80c3729ad026aa100ed56d55516..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/forum/ForumPostFactoryImpl.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package org.briarproject.forum;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.forum.ForumPost;
-import org.briarproject.api.forum.ForumPostFactory;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.util.StringUtils;
-
-import java.security.GeneralSecurityException;
-
-import javax.inject.Inject;
-
-import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
-
-class ForumPostFactoryImpl implements ForumPostFactory {
-
-	private final ClientHelper clientHelper;
-
-	@Inject
-	ForumPostFactoryImpl(ClientHelper clientHelper) {
-		this.clientHelper = clientHelper;
-	}
-
-	@Override
-	public ForumPost createPost(GroupId groupId, long timestamp,
-			MessageId parent, LocalAuthor author, String body)
-			throws FormatException, GeneralSecurityException {
-		// Validate the arguments
-		if (StringUtils.utf8IsTooLong(body, MAX_FORUM_POST_BODY_LENGTH))
-			throw new IllegalArgumentException();
-		// Serialise the data to be signed
-		BdfList authorList =
-				BdfList.of(author.getName(), author.getPublicKey());
-		BdfList signed = BdfList.of(groupId, timestamp, parent, authorList,
-				body);
-		// Sign the data
-		byte[] sig = clientHelper
-				.sign(SIGNING_LABEL_POST, signed, author.getPrivateKey());
-		// Serialise the signed message
-		BdfList message = BdfList.of(parent, authorList, body, sig);
-		Message m = clientHelper.createMessage(groupId, timestamp, message);
-		return new ForumPost(m, parent, author);
-	}
-
-}
diff --git a/briar-core/src/org/briarproject/identity/AuthorReader.java b/briar-core/src/org/briarproject/identity/AuthorReader.java
deleted file mode 100644
index 16be01ae63951150979a90bc28354a1f2d6c33cc..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/identity/AuthorReader.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.briarproject.identity;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.data.BdfReader;
-import org.briarproject.api.data.ObjectReader;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorFactory;
-
-import java.io.IOException;
-
-import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
-import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
-
-class AuthorReader implements ObjectReader<Author> {
-
-	private final AuthorFactory authorFactory;
-
-	AuthorReader(AuthorFactory authorFactory) {
-		this.authorFactory = authorFactory;
-	}
-
-	public Author readObject(BdfReader r) throws IOException {
-		r.readListStart();
-		String name = r.readString(MAX_AUTHOR_NAME_LENGTH);
-		if (name.length() == 0) throw new FormatException();
-		byte[] publicKey = r.readRaw(MAX_PUBLIC_KEY_LENGTH);
-		r.readListEnd();
-		return authorFactory.createAuthor(name, publicKey);
-	}
-}
diff --git a/briar-core/src/org/briarproject/introduction/IntroductionGroupFactory.java b/briar-core/src/org/briarproject/introduction/IntroductionGroupFactory.java
deleted file mode 100644
index 8cdd9d0f58c40dbce1244cf4231aef2a074e26fa..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/introduction/IntroductionGroupFactory.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.briarproject.introduction;
-
-import org.briarproject.api.clients.ContactGroupFactory;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.sync.Group;
-
-import javax.inject.Inject;
-
-public class IntroductionGroupFactory {
-
-	final private ContactGroupFactory contactGroupFactory;
-	final private Group localGroup;
-
-	@Inject
-	IntroductionGroupFactory(ContactGroupFactory contactGroupFactory) {
-		this.contactGroupFactory = contactGroupFactory;
-		localGroup = contactGroupFactory
-				.createLocalGroup(IntroductionManagerImpl.CLIENT_ID);
-	}
-
-	public Group createIntroductionGroup(Contact c) {
-		return contactGroupFactory
-				.createContactGroup(IntroductionManagerImpl.CLIENT_ID, c);
-	}
-
-	public Group createLocalGroup() {
-		return localGroup;
-	}
-
-}
diff --git a/briar-core/src/org/briarproject/introduction/IntroductionModule.java b/briar-core/src/org/briarproject/introduction/IntroductionModule.java
deleted file mode 100644
index 14a92654ef7e64c2e32b23f02cb30b2901473ec3..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/introduction/IntroductionModule.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package org.briarproject.introduction;
-
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageQueueManager;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.introduction.IntroductionManager;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.messaging.ConversationManager;
-import org.briarproject.api.system.Clock;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-import dagger.Module;
-import dagger.Provides;
-
-import static org.briarproject.api.introduction.IntroductionManager.CLIENT_ID;
-import static org.briarproject.api.sync.ValidationManager.MessageValidator;
-
-@Module
-public class IntroductionModule {
-
-	public static class EagerSingletons {
-		@Inject IntroductionManager introductionManager;
-		@Inject MessageValidator introductionValidator;
-	}
-
-	@Provides
-	@Singleton
-	MessageValidator provideValidator(MessageQueueManager messageQueueManager,
-			MetadataEncoder metadataEncoder, ClientHelper clientHelper,
-			Clock clock) {
-
-		IntroductionValidator introductionValidator = new IntroductionValidator(
-				clientHelper, metadataEncoder, clock);
-
-		messageQueueManager
-				.registerMessageValidator(CLIENT_ID, introductionValidator);
-
-		return introductionValidator;
-	}
-
-	@Provides
-	@Singleton
-	IntroductionManager provideIntroductionManager(
-			LifecycleManager lifecycleManager,
-			ContactManager contactManager,
-			MessageQueueManager messageQueueManager,
-			ConversationManager conversationManager,
-			IntroductionManagerImpl introductionManager) {
-
-		lifecycleManager.registerClient(introductionManager);
-		contactManager.registerAddContactHook(introductionManager);
-		contactManager.registerRemoveContactHook(introductionManager);
-		messageQueueManager
-				.registerIncomingMessageHook(CLIENT_ID, introductionManager);
-		conversationManager.registerConversationClient(introductionManager);
-
-		return introductionManager;
-	}
-}
diff --git a/briar-core/src/org/briarproject/introduction/IntroductionValidator.java b/briar-core/src/org/briarproject/introduction/IntroductionValidator.java
deleted file mode 100644
index d22163227f4e8a74cce990c92fdef86a29714cf1..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/introduction/IntroductionValidator.java
+++ /dev/null
@@ -1,183 +0,0 @@
-package org.briarproject.introduction;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.BdfMessageContext;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.system.Clock;
-import org.briarproject.clients.BdfMessageValidator;
-
-import static org.briarproject.api.TransportId.MAX_TRANSPORT_ID_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.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
-import static org.briarproject.api.introduction.IntroductionConstants.ACCEPT;
-import static org.briarproject.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
-import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.MAC;
-import static org.briarproject.api.introduction.IntroductionConstants.MAC_LENGTH;
-import static org.briarproject.api.introduction.IntroductionConstants.MAX_INTRODUCTION_MESSAGE_LENGTH;
-import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TIME;
-import static org.briarproject.api.introduction.IntroductionConstants.MSG;
-import static org.briarproject.api.introduction.IntroductionConstants.NAME;
-import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY;
-import static org.briarproject.api.introduction.IntroductionConstants.SESSION_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.SIGNATURE;
-import static org.briarproject.api.introduction.IntroductionConstants.TIME;
-import static org.briarproject.api.introduction.IntroductionConstants.TRANSPORT;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ABORT;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
-import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTIES_PER_TRANSPORT;
-import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
-
-@NotNullByDefault
-class IntroductionValidator extends BdfMessageValidator {
-
-	IntroductionValidator(ClientHelper clientHelper,
-			MetadataEncoder metadataEncoder, Clock clock) {
-		super(clientHelper, metadataEncoder, clock);
-	}
-
-	@Override
-	protected BdfMessageContext validateMessage(Message m, Group g, BdfList body)
-			throws FormatException {
-
-		BdfDictionary d;
-		long type = body.getLong(0);
-		byte[] id = body.getRaw(1);
-		checkLength(id, SessionId.LENGTH);
-
-		if (type == TYPE_REQUEST) {
-			d = validateRequest(body);
-		} else if (type == TYPE_RESPONSE) {
-			d = validateResponse(body);
-		} else if (type == TYPE_ACK) {
-			d = validateAck(body);
-		} else if (type == TYPE_ABORT) {
-			d = validateAbort(body);
-		} else {
-			throw new FormatException();
-		}
-
-		d.put(TYPE, type);
-		d.put(SESSION_ID, id);
-		d.put(GROUP_ID, m.getGroupId());
-		d.put(MESSAGE_ID, m.getId());
-		d.put(MESSAGE_TIME, m.getTimestamp());
-		return new BdfMessageContext(d);
-	}
-
-	private BdfDictionary validateRequest(BdfList message)
-			throws FormatException {
-
-		checkSize(message, 4, 5);
-
-		// parse contact name
-		String name = message.getString(2);
-		checkLength(name, 1, MAX_AUTHOR_NAME_LENGTH);
-
-		// parse contact's public key
-		byte[] key = message.getRaw(3);
-		checkLength(key, 0, MAX_PUBLIC_KEY_LENGTH);
-
-		// parse (optional) message
-		String msg = null;
-		if (message.size() == 5) {
-			msg = message.getString(4);
-			checkLength(msg, 0, MAX_INTRODUCTION_MESSAGE_LENGTH);
-		}
-
-		// Return the metadata
-		BdfDictionary d = new BdfDictionary();
-		d.put(NAME, name);
-		d.put(PUBLIC_KEY, key);
-		if (msg != null) {
-			d.put(MSG, msg);
-		}
-		return d;
-	}
-
-	private BdfDictionary validateResponse(BdfList message)
-			throws FormatException {
-
-		checkSize(message, 3, 6);
-
-		// parse accept/decline
-		boolean accept = message.getBoolean(2);
-
-		long time = 0;
-		byte[] pubkey = null;
-		BdfDictionary tp = new BdfDictionary();
-		if (accept) {
-			checkSize(message, 6);
-
-			// parse timestamp
-			time = message.getLong(3);
-
-			// parse ephemeral public key
-			pubkey = message.getRaw(4);
-			checkLength(pubkey, 0, MAX_PUBLIC_KEY_LENGTH);
-
-			// parse transport properties
-			tp = message.getDictionary(5);
-			if (tp.size() < 1) throw new FormatException();
-			for (String tId : tp.keySet()) {
-				checkLength(tId, 1, MAX_TRANSPORT_ID_LENGTH);
-				BdfDictionary tProps = tp.getDictionary(tId);
-				checkSize(tProps, 0, MAX_PROPERTIES_PER_TRANSPORT);
-				for (String propId : tProps.keySet()) {
-					checkLength(propId, 0, MAX_PROPERTY_LENGTH);
-					String prop = tProps.getString(propId);
-					checkLength(prop, 0, MAX_PROPERTY_LENGTH);
-				}
-			}
-		} else {
-			checkSize(message, 3);
-		}
-
-		// Return the metadata
-		BdfDictionary d = new BdfDictionary();
-		d.put(ACCEPT, accept);
-		if (accept) {
-			d.put(TIME, time);
-			d.put(E_PUBLIC_KEY, pubkey);
-			d.put(TRANSPORT, tp);
-		}
-		return d;
-	}
-
-	private BdfDictionary validateAck(BdfList message) throws FormatException {
-		checkSize(message, 4);
-
-		byte[] mac = message.getRaw(2);
-		checkLength(mac, 1, MAC_LENGTH);
-
-		byte[] sig = message.getRaw(3);
-		checkLength(sig, 1, MAX_SIGNATURE_LENGTH);
-
-		// Return the metadata
-		BdfDictionary d = new BdfDictionary();
-		d.put(MAC, mac);
-		d.put(SIGNATURE, sig);
-		return d;
-	}
-
-	private BdfDictionary validateAbort(BdfList message)
-			throws FormatException {
-
-		checkSize(message, 2);
-
-		// Return the metadata
-		return new BdfDictionary();
-	}
-}
diff --git a/briar-core/src/org/briarproject/introduction/MessageSender.java b/briar-core/src/org/briarproject/introduction/MessageSender.java
deleted file mode 100644
index bfa8138d8f4a6775599615e204223169930fc351..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/introduction/MessageSender.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package org.briarproject.introduction;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageQueueManager;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.system.Clock;
-
-import javax.inject.Inject;
-
-import static org.briarproject.api.introduction.IntroductionConstants.ACCEPT;
-import static org.briarproject.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
-import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.MAC;
-import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TIME;
-import static org.briarproject.api.introduction.IntroductionConstants.MSG;
-import static org.briarproject.api.introduction.IntroductionConstants.NAME;
-import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY;
-import static org.briarproject.api.introduction.IntroductionConstants.SESSION_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.SIGNATURE;
-import static org.briarproject.api.introduction.IntroductionConstants.TIME;
-import static org.briarproject.api.introduction.IntroductionConstants.TRANSPORT;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ABORT;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
-
-public class MessageSender {
-
-	final private DatabaseComponent db;
-	final private ClientHelper clientHelper;
-	final private Clock clock;
-	final private MetadataEncoder metadataEncoder;
-	final private MessageQueueManager messageQueueManager;
-
-	@Inject
-	MessageSender(DatabaseComponent db, ClientHelper clientHelper, Clock clock,
-			MetadataEncoder metadataEncoder,
-			MessageQueueManager messageQueueManager) {
-
-		this.db = db;
-		this.clientHelper = clientHelper;
-		this.clock = clock;
-		this.metadataEncoder = metadataEncoder;
-		this.messageQueueManager = messageQueueManager;
-	}
-
-	public void sendMessage(Transaction txn, BdfDictionary message)
-			throws DbException, FormatException {
-
-		BdfList bdfList = encodeMessage(message);
-		byte[] body = clientHelper.toByteArray(bdfList);
-		GroupId groupId = new GroupId(message.getRaw(GROUP_ID));
-		Group group = db.getGroup(txn, groupId);
-		long timestamp = clock.currentTimeMillis();
-
-		message.put(MESSAGE_TIME, timestamp);
-		Metadata metadata = metadataEncoder.encode(message);
-
-		messageQueueManager
-				.sendMessage(txn, group, timestamp, body, metadata);
-	}
-
-	private BdfList encodeMessage(BdfDictionary d)
-			throws FormatException {
-
-		BdfList body;
-		long type = d.getLong(TYPE);
-		if (type == TYPE_REQUEST) {
-			body = encodeRequest(d);
-		} else if (type == TYPE_RESPONSE) {
-			body = encodeResponse(d);
-		} else if (type == TYPE_ACK) {
-			body = encodeAck(d);
-		} else if (type == TYPE_ABORT) {
-			body = encodeAbort(d);
-		} else {
-			throw new FormatException();
-		}
-		return body;
-	}
-
-	private BdfList encodeRequest(BdfDictionary d)
-			throws FormatException {
-		BdfList list = BdfList.of(TYPE_REQUEST, d.getRaw(SESSION_ID),
-				d.getString(NAME), d.getRaw(PUBLIC_KEY));
-
-		if (d.containsKey(MSG)) {
-			list.add(d.getString(MSG));
-		}
-		return list;
-	}
-
-	private BdfList encodeResponse(BdfDictionary d)
-			throws FormatException {
-		BdfList list = BdfList.of(TYPE_RESPONSE, d.getRaw(SESSION_ID),
-				d.getBoolean(ACCEPT));
-
-		if (d.getBoolean(ACCEPT)) {
-			list.add(d.getLong(TIME));
-			list.add(d.getRaw(E_PUBLIC_KEY));
-			list.add(d.getDictionary(TRANSPORT));
-		}
-		return list;
-	}
-
-	private BdfList encodeAck(BdfDictionary d) throws FormatException {
-		return BdfList.of(TYPE_ACK, d.getRaw(SESSION_ID),
-				d.getRaw(MAC), d.getRaw(SIGNATURE));
-	}
-
-	private BdfList encodeAbort(BdfDictionary d) throws FormatException {
-		return BdfList.of(TYPE_ABORT, d.getRaw(SESSION_ID));
-	}
-
-}
diff --git a/briar-core/src/org/briarproject/invitation/InvitationModule.java b/briar-core/src/org/briarproject/invitation/InvitationModule.java
deleted file mode 100644
index b4262bca0d863ac5d2d8b93fcadd64cc50fb81d2..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/invitation/InvitationModule.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.briarproject.invitation;
-
-import javax.inject.Singleton;
-
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.data.BdfReaderFactory;
-import org.briarproject.api.data.BdfWriterFactory;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.invitation.InvitationTaskFactory;
-import org.briarproject.api.plugins.ConnectionManager;
-import org.briarproject.api.plugins.PluginManager;
-import org.briarproject.api.sync.GroupFactory;
-import org.briarproject.api.system.Clock;
-import org.briarproject.api.transport.KeyManager;
-import org.briarproject.api.transport.StreamReaderFactory;
-import org.briarproject.api.transport.StreamWriterFactory;
-
-import dagger.Module;
-import dagger.Provides;
-
-@Module
-public class InvitationModule {
-
-	@Provides
-	@Singleton
-	InvitationTaskFactory provideInvitationTaskFactory(
-			InvitationTaskFactoryImpl invitationTaskFactory) {
-		return invitationTaskFactory;
-	}
-}
diff --git a/briar-core/src/org/briarproject/keyagreement/AbortException.java b/briar-core/src/org/briarproject/keyagreement/AbortException.java
deleted file mode 100644
index 670bbc3ee14f63d6bd1d543d58d06652576c4437..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/keyagreement/AbortException.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.briarproject.keyagreement;
-
-class AbortException extends Exception {
-	public boolean receivedAbort;
-
-	public AbortException() {
-		this(false);
-	}
-
-	public AbortException(boolean receivedAbort) {
-		super();
-		this.receivedAbort = receivedAbort;
-	}
-
-	public AbortException(Exception e) {
-		this(e, false);
-	}
-
-	public AbortException(Exception e, boolean receivedAbort) {
-		super(e);
-		this.receivedAbort = receivedAbort;
-	}
-}
diff --git a/briar-core/src/org/briarproject/messaging/PrivateMessageFactoryImpl.java b/briar-core/src/org/briarproject/messaging/PrivateMessageFactoryImpl.java
deleted file mode 100644
index cb68389c7b82f46d7cce4b9f79753a1e87f2daea..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/messaging/PrivateMessageFactoryImpl.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.briarproject.messaging;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.messaging.PrivateMessage;
-import org.briarproject.api.messaging.PrivateMessageFactory;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-
-import javax.inject.Inject;
-
-import static org.briarproject.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
-import static org.briarproject.util.StringUtils.utf8IsTooLong;
-
-@NotNullByDefault
-class PrivateMessageFactoryImpl implements PrivateMessageFactory {
-
-	private final ClientHelper clientHelper;
-
-	@Inject
-	PrivateMessageFactoryImpl(ClientHelper clientHelper) {
-		this.clientHelper = clientHelper;
-	}
-
-	@Override
-	public PrivateMessage createPrivateMessage(GroupId groupId, long timestamp,
-			String body) throws FormatException {
-		// Validate the arguments
-		if (utf8IsTooLong(body, MAX_PRIVATE_MESSAGE_BODY_LENGTH))
-			throw new IllegalArgumentException();
-		// Serialise the message
-		BdfList message = BdfList.of(body);
-		Message m = clientHelper.createMessage(groupId, timestamp, message);
-		return new PrivateMessage(m);
-	}
-}
diff --git a/briar-core/src/org/briarproject/messaging/PrivateMessageValidator.java b/briar-core/src/org/briarproject/messaging/PrivateMessageValidator.java
deleted file mode 100644
index 9eeae2409606d424638a75f8ed55e27e5e01f7b8..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/messaging/PrivateMessageValidator.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.briarproject.messaging;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.BdfMessageContext;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.system.Clock;
-import org.briarproject.clients.BdfMessageValidator;
-
-import static org.briarproject.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
-import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
-
-@NotNullByDefault
-class PrivateMessageValidator extends BdfMessageValidator {
-
-	PrivateMessageValidator(ClientHelper clientHelper,
-			MetadataEncoder metadataEncoder, Clock clock) {
-		super(clientHelper, metadataEncoder, clock);
-	}
-
-	@Override
-	protected BdfMessageContext validateMessage(Message m, Group g,
-			BdfList body) throws FormatException {
-		// private message body
-		checkSize(body, 1);
-		// Private message body
-		String privateMessageBody = body.getString(0);
-		checkLength(privateMessageBody, 0, MAX_PRIVATE_MESSAGE_BODY_LENGTH);
-		// Return the metadata
-		BdfDictionary meta = new BdfDictionary();
-		meta.put("timestamp", m.getTimestamp());
-		meta.put("local", false);
-		meta.put(MSG_KEY_READ, false);
-		return new BdfMessageContext(meta);
-	}
-}
diff --git a/briar-core/src/org/briarproject/plugins/BackoffFactoryImpl.java b/briar-core/src/org/briarproject/plugins/BackoffFactoryImpl.java
deleted file mode 100644
index 1c3e5eceef3231451ebfa8f6d89ab0d10eb426ba..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/plugins/BackoffFactoryImpl.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.briarproject.plugins;
-
-import org.briarproject.api.plugins.Backoff;
-import org.briarproject.api.plugins.BackoffFactory;
-
-class BackoffFactoryImpl implements BackoffFactory {
-
-	@Override
-	public Backoff createBackoff(int minInterval, int maxInterval,
-			double base) {
-		return new BackoffImpl(minInterval, maxInterval, base);
-	}
-}
diff --git a/briar-core/src/org/briarproject/plugins/tcp/PortMapper.java b/briar-core/src/org/briarproject/plugins/tcp/PortMapper.java
deleted file mode 100644
index 292d37a9d876310255f55a8b79c3ce0847f73147..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/plugins/tcp/PortMapper.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.briarproject.plugins.tcp;
-
-interface PortMapper {
-
-	MappingResult map(int port);
-}
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/InviteAction.java b/briar-core/src/org/briarproject/privategroup/invitation/InviteAction.java
deleted file mode 100644
index f43af230a80b3b2be49176e91fbe2770d8d5e761..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/privategroup/invitation/InviteAction.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.briarproject.privategroup.invitation;
-
-import org.briarproject.api.nullsafety.NotNullByDefault;
-
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.Immutable;
-
-@Immutable
-@NotNullByDefault
-class InviteAction {
-
-	@Nullable
-	private final String message;
-	private final long timestamp;
-	private final byte[] signature;
-
-	InviteAction(@Nullable String message, long timestamp, byte[] signature) {
-		this.message = message;
-		this.timestamp = timestamp;
-		this.signature = signature;
-	}
-
-	@Nullable
-	String getMessage() {
-		return message;
-	}
-
-	long getTimestamp() {
-		return timestamp;
-	}
-
-	byte[] getSignature() {
-		return signature;
-	}
-}
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/SessionEncoder.java b/briar-core/src/org/briarproject/privategroup/invitation/SessionEncoder.java
deleted file mode 100644
index 5ba2cb48c5fc27ee54b56d5ac8aaac02db810cff..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/privategroup/invitation/SessionEncoder.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.briarproject.privategroup.invitation;
-
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-
-@NotNullByDefault
-interface SessionEncoder {
-
-	BdfDictionary encodeSession(Session s);
-}
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/SessionEncoderImpl.java b/briar-core/src/org/briarproject/privategroup/invitation/SessionEncoderImpl.java
deleted file mode 100644
index 32f85534a58452e07b0cebdcf604ec5e47b77200..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/privategroup/invitation/SessionEncoderImpl.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.briarproject.privategroup.invitation;
-
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.MessageId;
-
-import javax.annotation.concurrent.Immutable;
-import javax.inject.Inject;
-
-import static org.briarproject.api.data.BdfDictionary.NULL_VALUE;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_INVITE_TIMESTAMP;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LAST_LOCAL_MESSAGE_ID;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LAST_REMOTE_MESSAGE_ID;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LOCAL_TIMESTAMP;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_PRIVATE_GROUP_ID;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_ROLE;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_SESSION_ID;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_STATE;
-
-@Immutable
-@NotNullByDefault
-class SessionEncoderImpl implements SessionEncoder {
-
-	@Inject
-	SessionEncoderImpl() {
-	}
-
-	@Override
-	public BdfDictionary encodeSession(Session s) {
-		BdfDictionary d = new BdfDictionary();
-		d.put(SESSION_KEY_SESSION_ID, s.getPrivateGroupId());
-		d.put(SESSION_KEY_PRIVATE_GROUP_ID, s.getPrivateGroupId());
-		MessageId lastLocalMessageId = s.getLastLocalMessageId();
-		if (lastLocalMessageId == null)
-			d.put(SESSION_KEY_LAST_LOCAL_MESSAGE_ID, NULL_VALUE);
-		else d.put(SESSION_KEY_LAST_LOCAL_MESSAGE_ID, lastLocalMessageId);
-		MessageId lastRemoteMessageId = s.getLastRemoteMessageId();
-		if (lastRemoteMessageId == null)
-			d.put(SESSION_KEY_LAST_REMOTE_MESSAGE_ID, NULL_VALUE);
-		else d.put(SESSION_KEY_LAST_REMOTE_MESSAGE_ID, lastRemoteMessageId);
-		d.put(SESSION_KEY_LOCAL_TIMESTAMP, s.getLocalTimestamp());
-		d.put(SESSION_KEY_INVITE_TIMESTAMP, s.getInviteTimestamp());
-		d.put(SESSION_KEY_ROLE, s.getRole().getValue());
-		d.put(SESSION_KEY_STATE, s.getState().getValue());
-		return d;
-	}
-}
diff --git a/briar-core/src/org/briarproject/privategroup/invitation/State.java b/briar-core/src/org/briarproject/privategroup/invitation/State.java
deleted file mode 100644
index 6c112668ac1ab2484cd10ea2106c8c64724ac2c7..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/privategroup/invitation/State.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.briarproject.privategroup.invitation;
-
-interface State {
-
-	int getValue();
-}
diff --git a/briar-core/src/org/briarproject/properties/TransportPropertyValidator.java b/briar-core/src/org/briarproject/properties/TransportPropertyValidator.java
deleted file mode 100644
index 14aef6715d4ee1575a03163ff4e4b0666e5500e4..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/properties/TransportPropertyValidator.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.briarproject.properties;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.BdfMessageContext;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.system.Clock;
-import org.briarproject.clients.BdfMessageValidator;
-
-import static org.briarproject.api.TransportId.MAX_TRANSPORT_ID_LENGTH;
-import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTIES_PER_TRANSPORT;
-import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
-
-@NotNullByDefault
-public class TransportPropertyValidator extends BdfMessageValidator {
-
-	TransportPropertyValidator(ClientHelper clientHelper,
-			MetadataEncoder metadataEncoder, Clock clock) {
-		super(clientHelper, metadataEncoder, clock);
-	}
-
-	@Override
-	protected BdfMessageContext validateMessage(Message m, Group g,
-			BdfList body) throws FormatException {
-		// Transport ID, version, properties
-		checkSize(body, 3);
-		// Transport ID
-		String transportId = body.getString(0);
-		checkLength(transportId, 1, MAX_TRANSPORT_ID_LENGTH);
-		// Version
-		long version = body.getLong(1);
-		if (version < 0) throw new FormatException();
-		// Properties
-		BdfDictionary dictionary = body.getDictionary(2);
-		checkSize(dictionary, 0, MAX_PROPERTIES_PER_TRANSPORT);
-		for (String key : dictionary.keySet()) {
-			checkLength(key, 0, MAX_PROPERTY_LENGTH);
-			String value = dictionary.getString(key);
-			checkLength(value, 0, MAX_PROPERTY_LENGTH);
-		}
-		// Return the metadata
-		BdfDictionary meta = new BdfDictionary();
-		meta.put("transportId", transportId);
-		meta.put("version", version);
-		meta.put("local", false);
-		return new BdfMessageContext(meta);
-	}
-}
diff --git a/briar-core/src/org/briarproject/reliability/ReliabilityLayerFactoryImpl.java b/briar-core/src/org/briarproject/reliability/ReliabilityLayerFactoryImpl.java
deleted file mode 100644
index 7aee1db755b395e602cf7e2a296ae1d4a198cc9f..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/reliability/ReliabilityLayerFactoryImpl.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.briarproject.reliability;
-
-import java.util.concurrent.Executor;
-
-import javax.inject.Inject;
-
-import org.briarproject.api.lifecycle.IoExecutor;
-import org.briarproject.api.reliability.ReliabilityLayer;
-import org.briarproject.api.reliability.ReliabilityLayerFactory;
-import org.briarproject.api.reliability.WriteHandler;
-import org.briarproject.api.system.Clock;
-import org.briarproject.system.SystemClock;
-
-class ReliabilityLayerFactoryImpl implements ReliabilityLayerFactory {
-
-	private final Executor ioExecutor;
-	private final Clock clock;
-
-	@Inject
-	ReliabilityLayerFactoryImpl(@IoExecutor Executor ioExecutor) {
-		this.ioExecutor = ioExecutor;
-		clock = new SystemClock();
-	}
-
-	public ReliabilityLayer createReliabilityLayer(WriteHandler writeHandler) {
-		return new ReliabilityLayerImpl(ioExecutor, clock, writeHandler);
-	}
-}
diff --git a/briar-core/src/org/briarproject/reporting/ReportingModule.java b/briar-core/src/org/briarproject/reporting/ReportingModule.java
deleted file mode 100644
index 333b3afca06339862198382907349b3488f21472..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/reporting/ReportingModule.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.briarproject.reporting;
-
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.reporting.DevConfig;
-import org.briarproject.api.reporting.DevReporter;
-
-import javax.net.SocketFactory;
-
-import dagger.Module;
-import dagger.Provides;
-
-@Module
-public class ReportingModule {
-
-	@Provides
-	DevReporter provideDevReportTask(CryptoComponent crypto,
-			DevConfig devConfig, SocketFactory torSocketFactory) {
-		return new DevReporterImpl(crypto, devConfig, torSocketFactory);
-	}
-}
diff --git a/briar-core/src/org/briarproject/sharing/BlogInviteeSessionState.java b/briar-core/src/org/briarproject/sharing/BlogInviteeSessionState.java
deleted file mode 100644
index 8298333ff1ad0d0da780130171053f3d08d6c7cb..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/sharing/BlogInviteeSessionState.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.briarproject.sharing;
-
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.NotNull;
-
-import javax.annotation.concurrent.NotThreadSafe;
-
-import static org.briarproject.api.blogs.BlogConstants.BLOG_AUTHOR_NAME;
-import static org.briarproject.api.blogs.BlogConstants.BLOG_PUBLIC_KEY;
-
-@NotThreadSafe
-@NotNullByDefault
-public class BlogInviteeSessionState extends InviteeSessionState {
-
-	private final String blogAuthorName;
-	private final byte[] blogPublicKey;
-
-	public BlogInviteeSessionState(SessionId sessionId, MessageId storageId,
-			GroupId groupId, State state, ContactId contactId, GroupId blogId,
-			String blogAuthorName, byte[] blogPublicKey,
-			@NotNull MessageId invitationId) {
-		super(sessionId, storageId, groupId, state, contactId, blogId,
-				invitationId);
-		this.blogAuthorName = blogAuthorName;
-		this.blogPublicKey = blogPublicKey;
-	}
-
-	public BdfDictionary toBdfDictionary() {
-		BdfDictionary d = super.toBdfDictionary();
-		d.put(BLOG_AUTHOR_NAME, getBlogAuthorName());
-		d.put(BLOG_PUBLIC_KEY, getBlogPublicKey());
-		return d;
-	}
-
-	public String getBlogAuthorName() {
-		return blogAuthorName;
-	}
-
-	public byte[] getBlogPublicKey() {
-		return blogPublicKey;
-	}
-}
diff --git a/briar-core/src/org/briarproject/sharing/BlogSharerSessionState.java b/briar-core/src/org/briarproject/sharing/BlogSharerSessionState.java
deleted file mode 100644
index aa48bf498cf82915a15167c1e1d0572c7465f96b..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/sharing/BlogSharerSessionState.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.briarproject.sharing;
-
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.Nullable;
-
-import javax.annotation.concurrent.NotThreadSafe;
-
-import static org.briarproject.api.blogs.BlogConstants.BLOG_AUTHOR_NAME;
-import static org.briarproject.api.blogs.BlogConstants.BLOG_PUBLIC_KEY;
-
-@NotThreadSafe
-@NotNullByDefault
-public class BlogSharerSessionState extends SharerSessionState {
-
-	private final String blogAuthorName;
-	private final byte[] blogPublicKey;
-
-	public BlogSharerSessionState(SessionId sessionId, MessageId storageId,
-			GroupId groupId, State state, ContactId contactId, GroupId blogId,
-			String blogAuthorName,byte[] blogPublicKey,
-			@Nullable MessageId responseId) {
-		super(sessionId, storageId, groupId, state, contactId, blogId,
-				responseId);
-
-		this.blogAuthorName = blogAuthorName;
-		this.blogPublicKey = blogPublicKey;
-	}
-
-	public BdfDictionary toBdfDictionary() {
-		BdfDictionary d = super.toBdfDictionary();
-		d.put(BLOG_AUTHOR_NAME, getBlogAuthorName());
-		d.put(BLOG_PUBLIC_KEY, getBlogPublicKey());
-		return d;
-	}
-
-	public String getBlogAuthorName() {
-		return blogAuthorName;
-	}
-
-	public byte[] getBlogPublicKey() {
-		return blogPublicKey;
-	}
-}
diff --git a/briar-core/src/org/briarproject/sharing/BlogSharingValidator.java b/briar-core/src/org/briarproject/sharing/BlogSharingValidator.java
deleted file mode 100644
index 3244abca1a4ca71bca0dd354b9894df2a1308483..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/sharing/BlogSharingValidator.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package org.briarproject.sharing;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.BdfMessageContext;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.system.Clock;
-import org.briarproject.clients.BdfMessageValidator;
-
-import javax.inject.Inject;
-
-import static org.briarproject.api.blogs.BlogConstants.BLOG_AUTHOR_NAME;
-import static org.briarproject.api.blogs.BlogConstants.BLOG_PUBLIC_KEY;
-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.sharing.SharingConstants.INVITATION_MSG;
-import static org.briarproject.api.sharing.SharingConstants.LOCAL;
-import static org.briarproject.api.sharing.SharingConstants.MAX_INVITATION_MESSAGE_LENGTH;
-import static org.briarproject.api.sharing.SharingConstants.SESSION_ID;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ACCEPT;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_DECLINE;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE;
-import static org.briarproject.api.sharing.SharingConstants.TIME;
-import static org.briarproject.api.sharing.SharingConstants.TYPE;
-
-@NotNullByDefault
-class BlogSharingValidator extends BdfMessageValidator {
-
-	@Inject
-	BlogSharingValidator(ClientHelper clientHelper,
-			MetadataEncoder metadataEncoder, Clock clock) {
-		super(clientHelper, metadataEncoder, clock);
-	}
-
-	@Override
-	protected BdfMessageContext validateMessage(Message m, Group g,
-			BdfList body) throws FormatException {
-
-		BdfDictionary d = new BdfDictionary();
-		long type = body.getLong(0);
-		byte[] id = body.getRaw(1);
-		checkLength(id, SessionId.LENGTH);
-
-		if (type == SHARE_MSG_TYPE_INVITATION) {
-			checkSize(body, 3, 4);
-
-			BdfList author = body.getList(2);
-			checkSize(author, 2);
-
-			String authorName = author.getString(0);
-			checkLength(authorName, 1, MAX_AUTHOR_NAME_LENGTH);
-
-			byte[] publicKey = author.getRaw(1);
-			checkLength(publicKey, 1, MAX_PUBLIC_KEY_LENGTH);
-
-			d.put(BLOG_AUTHOR_NAME, authorName);
-			d.put(BLOG_PUBLIC_KEY, publicKey);
-
-			if (body.size() > 3) {
-				String msg = body.getString(3);
-				checkLength(msg, 0, MAX_INVITATION_MESSAGE_LENGTH);
-				d.put(INVITATION_MSG, msg);
-			}
-		} else {
-			checkSize(body, 2);
-			if (type != SHARE_MSG_TYPE_ACCEPT &&
-					type != SHARE_MSG_TYPE_DECLINE &&
-					type != SHARE_MSG_TYPE_LEAVE &&
-					type != SHARE_MSG_TYPE_ABORT) {
-				throw new FormatException();
-			}
-		}
-		// Return the metadata
-		d.put(TYPE, type);
-		d.put(SESSION_ID, id);
-		d.put(LOCAL, false);
-		d.put(TIME, m.getTimestamp());
-		return new BdfMessageContext(d);
-	}
-}
diff --git a/briar-core/src/org/briarproject/sharing/ForumInviteeSessionState.java b/briar-core/src/org/briarproject/sharing/ForumInviteeSessionState.java
deleted file mode 100644
index 79c732e932702417cea9bfdf837b1b20739111c2..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/sharing/ForumInviteeSessionState.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.briarproject.sharing;
-
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.NotNull;
-
-import static org.briarproject.api.forum.ForumConstants.FORUM_NAME;
-import static org.briarproject.api.forum.ForumConstants.FORUM_SALT;
-
-public class ForumInviteeSessionState extends InviteeSessionState {
-
-	private final String forumName;
-	private final byte[] forumSalt;
-
-	public ForumInviteeSessionState(SessionId sessionId, MessageId storageId,
-			GroupId groupId, State state, ContactId contactId, GroupId forumId,
-			String forumName, byte[] forumSalt,
-			@NotNull MessageId invitationId) {
-		super(sessionId, storageId, groupId, state, contactId, forumId,
-				invitationId);
-
-		this.forumName = forumName;
-		this.forumSalt = forumSalt;
-	}
-
-	public BdfDictionary toBdfDictionary() {
-		BdfDictionary d = super.toBdfDictionary();
-		d.put(FORUM_NAME, getForumName());
-		d.put(FORUM_SALT, getForumSalt());
-		return d;
-	}
-
-	public String getForumName() {
-		return forumName;
-	}
-
-	public byte[] getForumSalt() {
-		return forumSalt;
-	}
-}
diff --git a/briar-core/src/org/briarproject/sharing/ForumSharingValidator.java b/briar-core/src/org/briarproject/sharing/ForumSharingValidator.java
deleted file mode 100644
index 471446b6f4dd9ae1617ad58ab9f6bf9d6f9932ec..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/sharing/ForumSharingValidator.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package org.briarproject.sharing;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.BdfMessageContext;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.nullsafety.NotNullByDefault;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.system.Clock;
-import org.briarproject.clients.BdfMessageValidator;
-
-import javax.inject.Inject;
-
-import static org.briarproject.api.forum.ForumConstants.FORUM_NAME;
-import static org.briarproject.api.forum.ForumConstants.FORUM_SALT;
-import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH;
-import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
-import static org.briarproject.api.sharing.SharingConstants.INVITATION_MSG;
-import static org.briarproject.api.sharing.SharingConstants.LOCAL;
-import static org.briarproject.api.sharing.SharingConstants.MAX_INVITATION_MESSAGE_LENGTH;
-import static org.briarproject.api.sharing.SharingConstants.SESSION_ID;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ACCEPT;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_DECLINE;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE;
-import static org.briarproject.api.sharing.SharingConstants.TIME;
-import static org.briarproject.api.sharing.SharingConstants.TYPE;
-
-@NotNullByDefault
-class ForumSharingValidator extends BdfMessageValidator {
-
-	@Inject
-	ForumSharingValidator(ClientHelper clientHelper,
-			MetadataEncoder metadataEncoder, Clock clock) {
-		super(clientHelper, metadataEncoder, clock);
-	}
-
-	@Override
-	protected BdfMessageContext validateMessage(Message m, Group g,
-			BdfList body) throws FormatException {
-
-		BdfDictionary d = new BdfDictionary();
-		long type = body.getLong(0);
-		byte[] id = body.getRaw(1);
-		checkLength(id, SessionId.LENGTH);
-
-		if (type == SHARE_MSG_TYPE_INVITATION) {
-			checkSize(body, 4, 5);
-
-			String name = body.getString(2);
-			checkLength(name, 1, MAX_FORUM_NAME_LENGTH);
-
-			byte[] salt = body.getRaw(3);
-			checkLength(salt, FORUM_SALT_LENGTH);
-
-			d.put(FORUM_NAME, name);
-			d.put(FORUM_SALT, salt);
-
-			if (body.size() > 4) {
-				String msg = body.getString(4);
-				checkLength(msg, 0, MAX_INVITATION_MESSAGE_LENGTH);
-				d.put(INVITATION_MSG, msg);
-			}
-		} else {
-			checkSize(body, 2);
-			if (type != SHARE_MSG_TYPE_ACCEPT &&
-					type != SHARE_MSG_TYPE_DECLINE &&
-					type != SHARE_MSG_TYPE_LEAVE &&
-					type != SHARE_MSG_TYPE_ABORT) {
-				throw new FormatException();
-			}
-		}
-		// Return the metadata
-		d.put(TYPE, type);
-		d.put(SESSION_ID, id);
-		d.put(LOCAL, false);
-		d.put(TIME, m.getTimestamp());
-		return new BdfMessageContext(d);
-	}
-}
diff --git a/briar-core/src/org/briarproject/sharing/InvitationFactory.java b/briar-core/src/org/briarproject/sharing/InvitationFactory.java
deleted file mode 100644
index 2c2d32c2938504279ec9431d67fcefcd64bfbac8..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/sharing/InvitationFactory.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.briarproject.sharing;
-
-import org.briarproject.api.sharing.SharingMessage;
-
-public interface InvitationFactory<I extends SharingMessage.Invitation, SS extends SharerSessionState> extends
-		org.briarproject.api.sharing.InvitationFactory<I> {
-
-	I build(SS localState, long time);
-}
diff --git a/briar-core/src/org/briarproject/sharing/InvitationReceivedEventFactory.java b/briar-core/src/org/briarproject/sharing/InvitationReceivedEventFactory.java
deleted file mode 100644
index 9172656e9f74e1f2bc37747d1a07ff4798f6d9e8..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/sharing/InvitationReceivedEventFactory.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.briarproject.sharing;
-
-import org.briarproject.api.event.InvitationRequestReceivedEvent;
-
-public interface InvitationReceivedEventFactory<IS extends InviteeSessionState, IR extends InvitationRequestReceivedEvent> {
-
-	IR build(IS localState, long time, String msg);
-}
diff --git a/briar-core/src/org/briarproject/sharing/InvitationResponseReceivedEventFactory.java b/briar-core/src/org/briarproject/sharing/InvitationResponseReceivedEventFactory.java
deleted file mode 100644
index ea5cdd91abea250acf4c633de7c08e21a432f86a..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/sharing/InvitationResponseReceivedEventFactory.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.briarproject.sharing;
-
-import org.briarproject.api.event.InvitationResponseReceivedEvent;
-
-public interface InvitationResponseReceivedEventFactory<SS extends SharerSessionState, IRR extends InvitationResponseReceivedEvent> {
-
-	IRR build(SS localState, boolean accept, long time);
-}
diff --git a/briar-core/src/org/briarproject/sharing/InviteeSessionStateFactory.java b/briar-core/src/org/briarproject/sharing/InviteeSessionStateFactory.java
deleted file mode 100644
index 0a514f519213cff5309b76797409261fc1c26e20..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/sharing/InviteeSessionStateFactory.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.briarproject.sharing;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.sharing.Shareable;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-
-public interface InviteeSessionStateFactory<S extends Shareable, IS extends InviteeSessionState> {
-
-	IS build(SessionId sessionId, MessageId storageId, GroupId groupId,
-			InviteeSessionState.State state, ContactId contactId,
-			GroupId shareableId, BdfDictionary d) throws FormatException;
-
-	IS build(SessionId sessionId, MessageId storageId, GroupId groupId,
-			InviteeSessionState.State state, ContactId contactId, S shareable,
-			MessageId invitationId);
-}
diff --git a/briar-core/src/org/briarproject/sharing/ShareableFactory.java b/briar-core/src/org/briarproject/sharing/ShareableFactory.java
deleted file mode 100644
index 6f961270da321073d3b9746b6ee217b7672aa4da..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/sharing/ShareableFactory.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.briarproject.sharing;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.sharing.Shareable;
-import org.briarproject.api.sharing.SharingMessage;
-import org.briarproject.api.sync.GroupId;
-
-interface ShareableFactory<S extends Shareable, I extends SharingMessage.Invitation, IS extends InviteeSessionState, SS extends SharerSessionState> {
-
-	BdfList encode(S sh);
-
-	S get(Transaction txn, GroupId groupId) throws DbException;
-
-	S parse(BdfList shareable) throws FormatException;
-
-	S parse(I msg);
-
-	S parse(IS state);
-
-	S parse(SS state);
-}
diff --git a/briar-core/src/org/briarproject/sharing/SharerSessionStateFactory.java b/briar-core/src/org/briarproject/sharing/SharerSessionStateFactory.java
deleted file mode 100644
index d045114fc4710062ee142f660efbb4f86d07e8da..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/sharing/SharerSessionStateFactory.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.briarproject.sharing;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.sharing.Shareable;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-
-public interface SharerSessionStateFactory<S extends Shareable, SS extends SharerSessionState> {
-
-	SS build(SessionId sessionId, MessageId storageId, GroupId groupId,
-			SharerSessionState.State state, ContactId contactId,
-			GroupId shareableId, BdfDictionary d) throws FormatException;
-
-	SS build(SessionId sessionId, MessageId storageId, GroupId groupId,
-			SharerSessionState.State state, ContactId contactId, S shareable);
-}
diff --git a/briar-core/src/org/briarproject/sync/GroupFactoryImpl.java b/briar-core/src/org/briarproject/sync/GroupFactoryImpl.java
deleted file mode 100644
index e5ee94a2d34a885e55a45c57e984e256a26c9bd0..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/sync/GroupFactoryImpl.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.briarproject.sync;
-
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupFactory;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.util.StringUtils;
-
-import javax.inject.Inject;
-
-class GroupFactoryImpl implements GroupFactory {
-
-	private final CryptoComponent crypto;
-
-	@Inject
-	GroupFactoryImpl(CryptoComponent crypto) {
-		this.crypto = crypto;
-	}
-
-	public Group createGroup(ClientId c, byte[] descriptor) {
-		byte[] hash =
-				crypto.hash(GroupId.LABEL, StringUtils.toUtf8(c.getString()),
-						descriptor);
-		return new Group(new GroupId(hash), c, descriptor);
-	}
-}
diff --git a/briar-core/src/org/briarproject/sync/PacketReaderFactoryImpl.java b/briar-core/src/org/briarproject/sync/PacketReaderFactoryImpl.java
deleted file mode 100644
index aad376cc406eda6817cac9c35854d8b2a9574687..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/sync/PacketReaderFactoryImpl.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.briarproject.sync;
-
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.sync.PacketReader;
-import org.briarproject.api.sync.PacketReaderFactory;
-
-import java.io.InputStream;
-
-import javax.inject.Inject;
-
-class PacketReaderFactoryImpl implements PacketReaderFactory {
-
-	private final CryptoComponent crypto;
-
-	@Inject
-	PacketReaderFactoryImpl(CryptoComponent crypto) {
-		this.crypto = crypto;
-	}
-
-	public PacketReader createPacketReader(InputStream in) {
-		return new PacketReaderImpl(crypto, in);
-	}
-}
diff --git a/briar-core/src/org/briarproject/sync/PacketWriterFactoryImpl.java b/briar-core/src/org/briarproject/sync/PacketWriterFactoryImpl.java
deleted file mode 100644
index b5da5e653a1f279a115fff335bb61ae55a133b5a..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/sync/PacketWriterFactoryImpl.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.briarproject.sync;
-
-import org.briarproject.api.sync.PacketWriter;
-import org.briarproject.api.sync.PacketWriterFactory;
-
-import java.io.OutputStream;
-
-class PacketWriterFactoryImpl implements PacketWriterFactory {
-
-	public PacketWriter createPacketWriter(OutputStream out) {
-		return new PacketWriterImpl(out);
-	}
-}
diff --git a/briar-core/src/org/briarproject/transport/TransportKeyManager.java b/briar-core/src/org/briarproject/transport/TransportKeyManager.java
deleted file mode 100644
index 56ed6b9ca5909a98c9224a0d52e1b81e731bbea0..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/transport/TransportKeyManager.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.briarproject.transport;
-
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.transport.StreamContext;
-
-interface TransportKeyManager {
-
-	void start(Transaction txn) throws DbException;
-
-	void addContact(Transaction txn, ContactId c, SecretKey master,
-			long timestamp, boolean alice) throws DbException;
-
-	void removeContact(ContactId c);
-
-	StreamContext getStreamContext(Transaction txn, ContactId c)
-			throws DbException;
-
-	StreamContext getStreamContext(Transaction txn, byte[] tag)
-			throws DbException;
-
-}
diff --git a/briar-core/src/org/briarproject/transport/TransportKeyManagerFactory.java b/briar-core/src/org/briarproject/transport/TransportKeyManagerFactory.java
deleted file mode 100644
index ca1021a0c1e5628dd70e6d481434bacd2c33f4d8..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/transport/TransportKeyManagerFactory.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.briarproject.transport;
-
-import org.briarproject.api.TransportId;
-
-interface TransportKeyManagerFactory {
-
-	TransportKeyManager createTransportKeyManager(TransportId transportId,
-			long maxLatency);
-
-}
diff --git a/briar-desktop/build.gradle b/briar-desktop/build.gradle
deleted file mode 100644
index 56f489dc1ccf77acfa890d85647ef7061533b9b0..0000000000000000000000000000000000000000
--- a/briar-desktop/build.gradle
+++ /dev/null
@@ -1,17 +0,0 @@
-apply plugin: 'java'
-sourceCompatibility = 1.7
-targetCompatibility = 1.7
-
-apply plugin: 'witness'
-
-dependencies {
-	compile project(':briar-api')
-	compile fileTree(dir: '../briar-core/libs', include: '*.jar')
-	compile project(':briar-core')
-	compile fileTree(dir: 'libs', include: '*.jar')
-}
-
-sourceSets {
-	main.java.srcDirs = ['src']
-	main.resources.srcDirs = ['src']
-}
diff --git a/briar-desktop/src/org/briarproject/plugins/file/LinuxRemovableDriveMonitor.java b/briar-desktop/src/org/briarproject/plugins/file/LinuxRemovableDriveMonitor.java
deleted file mode 100644
index bc3967416a77f6b9f3aab10ee8e859d7102e5850..0000000000000000000000000000000000000000
--- a/briar-desktop/src/org/briarproject/plugins/file/LinuxRemovableDriveMonitor.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.briarproject.plugins.file;
-
-class LinuxRemovableDriveMonitor extends UnixRemovableDriveMonitor {
-
-	@Override
-	protected String[] getPathsToWatch() {
-		return new String[] { "/mnt", "/media" };
-	}
-}
diff --git a/briar-desktop/src/org/briarproject/plugins/file/MacRemovableDriveMonitor.java b/briar-desktop/src/org/briarproject/plugins/file/MacRemovableDriveMonitor.java
deleted file mode 100644
index 11ff779133e063da203283fc676d57c802d03557..0000000000000000000000000000000000000000
--- a/briar-desktop/src/org/briarproject/plugins/file/MacRemovableDriveMonitor.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.briarproject.plugins.file;
-
-class MacRemovableDriveMonitor extends UnixRemovableDriveMonitor {
-
-	@Override
-	protected String[] getPathsToWatch() {
-		return new String[] { "/Volumes" };
-	}
-}
diff --git a/briar-desktop/src/org/briarproject/plugins/modem/ModemFactory.java b/briar-desktop/src/org/briarproject/plugins/modem/ModemFactory.java
deleted file mode 100644
index f70c7cdab48bfabf9720d88d8447089efc5342a9..0000000000000000000000000000000000000000
--- a/briar-desktop/src/org/briarproject/plugins/modem/ModemFactory.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.briarproject.plugins.modem;
-
-interface ModemFactory {
-
-	Modem createModem(Modem.Callback callback, String portName);
-}
diff --git a/briar-desktop/src/org/briarproject/plugins/modem/SerialPortList.java b/briar-desktop/src/org/briarproject/plugins/modem/SerialPortList.java
deleted file mode 100644
index 469263085c08d47a1262d47e340c20f1fea99ff5..0000000000000000000000000000000000000000
--- a/briar-desktop/src/org/briarproject/plugins/modem/SerialPortList.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.briarproject.plugins.modem;
-
-interface SerialPortList {
-
-	String[] getPortNames();
-}
diff --git a/briar-desktop/src/org/briarproject/plugins/modem/SerialPortListImpl.java b/briar-desktop/src/org/briarproject/plugins/modem/SerialPortListImpl.java
deleted file mode 100644
index 9d6ad8d7824b2304ce5284daefe484cb781bd70e..0000000000000000000000000000000000000000
--- a/briar-desktop/src/org/briarproject/plugins/modem/SerialPortListImpl.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.briarproject.plugins.modem;
-
-class SerialPortListImpl implements SerialPortList {
-
-	public String[] getPortNames() {
-		return jssc.SerialPortList.getPortNames();
-	}
-}
diff --git a/briar-tests/build.gradle b/briar-tests/build.gradle
index fa7ddcd9490507f299953c5c5fe28c39dce66c26..31009696687ed30f5e8e69fdb81a5537b2bd7241 100644
--- a/briar-tests/build.gradle
+++ b/briar-tests/build.gradle
@@ -5,10 +5,8 @@ targetCompatibility = 1.7
 apply plugin: 'witness'
 
 dependencies {
-	compile project(':briar-api')
 	compile project(':briar-core')
-	compile fileTree(dir: '../briar-desktop/libs', include: '*.jar')
-	compile project(':briar-desktop')
+	compile project(':bramble-j2se')
 	compile "junit:junit:4.12"
 	compile "org.jmock:jmock:2.8.1"
 	compile "org.jmock:jmock-junit4:2.8.1"
@@ -41,5 +39,5 @@ sourceSets {
 }
 
 tasks.withType(Test) {
-	systemProperty 'java.library.path', '../briar-desktop/libs'
+	systemProperty 'java.library.path', '../bramble-j2se/libs'
 }
diff --git a/briar-tests/src/org/briarproject/ImmediateExecutor.java b/briar-tests/src/org/briarproject/ImmediateExecutor.java
index ce0267885452e75a4e7fcac39e729248529c269d..424e6674b2fca15051e9ee3a8693f67f5b54669c 100644
--- a/briar-tests/src/org/briarproject/ImmediateExecutor.java
+++ b/briar-tests/src/org/briarproject/ImmediateExecutor.java
@@ -1,9 +1,13 @@
 package org.briarproject;
 
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
 import java.util.concurrent.Executor;
 
+@NotNullByDefault
 public class ImmediateExecutor implements Executor {
 
+	@Override
 	public void execute(Runnable r) {
 		r.run();
 	}
diff --git a/briar-tests/src/org/briarproject/TestDatabaseConfig.java b/briar-tests/src/org/briarproject/TestDatabaseConfig.java
index af847ec2cf5f301b5c4a0239c115ecd62005d568..0d366e867792c03e9a38c8375f66429095b98599 100644
--- a/briar-tests/src/org/briarproject/TestDatabaseConfig.java
+++ b/briar-tests/src/org/briarproject/TestDatabaseConfig.java
@@ -1,10 +1,12 @@
 package org.briarproject;
 
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.db.DatabaseConfig;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.db.DatabaseConfig;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.File;
 
+@NotNullByDefault
 public class TestDatabaseConfig implements DatabaseConfig {
 
 	private final File dir;
diff --git a/briar-tests/src/org/briarproject/TestSeedProvider.java b/briar-tests/src/org/briarproject/TestSeedProvider.java
index 39014d239b2c37cfdb840356d65f20d518386a9d..a6d761a4c913a98801a9b61fcc78bd96210ccbc2 100644
--- a/briar-tests/src/org/briarproject/TestSeedProvider.java
+++ b/briar-tests/src/org/briarproject/TestSeedProvider.java
@@ -1,9 +1,12 @@
 package org.briarproject;
 
-import org.briarproject.api.system.SeedProvider;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.system.SeedProvider;
 
+@NotNullByDefault
 public class TestSeedProvider implements SeedProvider {
 
+	@Override
 	public byte[] getSeed() {
 		return TestUtils.getRandomBytes(32);
 	}
diff --git a/briar-tests/src/org/briarproject/TestUtils.java b/briar-tests/src/org/briarproject/TestUtils.java
index 562d27685dfa1049380846f136ec98c58fecefa0..6e28dce8cfea41777300c61dfd4ef51c1adac86a 100644
--- a/briar-tests/src/org/briarproject/TestUtils.java
+++ b/briar-tests/src/org/briarproject/TestUtils.java
@@ -1,12 +1,12 @@
 package org.briarproject;
 
-import org.briarproject.api.UniqueId;
-import org.briarproject.api.clients.MessageTracker;
-import org.briarproject.api.clients.MessageTracker.GroupCount;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.util.IoUtils;
+import org.briarproject.bramble.api.UniqueId;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.util.IoUtils;
+import org.briarproject.briar.api.client.MessageTracker;
+import org.briarproject.briar.api.client.MessageTracker.GroupCount;
 
 import java.io.File;
 import java.util.Random;
diff --git a/briar-tests/src/org/briarproject/ValidatorTestCase.java b/briar-tests/src/org/briarproject/ValidatorTestCase.java
index f7a7693fdae94e2d1e3adb038f4b6517de899f05..0ece8f562d773a41f2d6b3c88520dcf26568c5ba 100644
--- a/briar-tests/src/org/briarproject/ValidatorTestCase.java
+++ b/briar-tests/src/org/briarproject/ValidatorTestCase.java
@@ -1,14 +1,14 @@
 package org.briarproject;
 
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.system.Clock;
 
 public abstract class ValidatorTestCase extends BriarMockTestCase {
 
diff --git a/briar-tests/src/org/briarproject/clients/BdfMessageValidatorTest.java b/briar-tests/src/org/briarproject/bramble/client/BdfMessageValidatorTest.java
similarity index 80%
rename from briar-tests/src/org/briarproject/clients/BdfMessageValidatorTest.java
rename to briar-tests/src/org/briarproject/bramble/client/BdfMessageValidatorTest.java
index 1714b261b3ac6713776d851cd1974fe50d9891b2..c14032271dbc39bdc6402e32cf2f75c24e39d6ef 100644
--- a/briar-tests/src/org/briarproject/clients/BdfMessageValidatorTest.java
+++ b/briar-tests/src/org/briarproject/bramble/client/BdfMessageValidatorTest.java
@@ -1,35 +1,36 @@
-package org.briarproject.clients;
+package org.briarproject.bramble.client;
 
 import org.briarproject.ValidatorTestCase;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.BdfMessageContext;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.InvalidMessageException;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageContext;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.BdfMessageContext;
+import org.briarproject.bramble.api.client.BdfMessageValidator;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.InvalidMessageException;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageContext;
 import org.jmock.Expectations;
 import org.jmock.lib.legacy.ClassImposteriser;
 import org.junit.Test;
 
-import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
+import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertSame;
-import static org.junit.Assert.fail;
 
 public class BdfMessageValidatorTest extends ValidatorTestCase {
 
-	private final BdfMessageValidator subclassNotCalled =
+	@NotNullByDefault
+	private final BdfMessageValidator failIfSubclassIsCalled =
 			new BdfMessageValidator(clientHelper, metadataEncoder, clock) {
 				@Override
 				protected BdfMessageContext validateMessage(Message m, Group g,
 						BdfList body)
 						throws InvalidMessageException, FormatException {
-					fail();
-					return null;
+					throw new AssertionError();
 				}
 			};
 
@@ -48,7 +49,7 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
 			will(returnValue(timestamp - MAX_CLOCK_DIFFERENCE - 1));
 		}});
 
-		subclassNotCalled.validateMessage(message, group);
+		failIfSubclassIsCalled.validateMessage(message, group);
 	}
 
 	@Test
@@ -63,6 +64,7 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
 			will(returnValue(meta));
 		}});
 
+		@NotNullByDefault
 		BdfMessageValidator v = new BdfMessageValidator(clientHelper,
 				metadataEncoder, clock) {
 			@Override
@@ -94,7 +96,7 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
 			will(returnValue(invalidRaw));
 		}});
 
-		subclassNotCalled.validateMessage(invalidMessage, group);
+		failIfSubclassIsCalled.validateMessage(invalidMessage, group);
 	}
 
 	@Test
@@ -113,6 +115,7 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
 			will(returnValue(meta));
 		}});
 
+		@NotNullByDefault
 		BdfMessageValidator v = new BdfMessageValidator(clientHelper,
 				metadataEncoder, clock) {
 			@Override
@@ -139,7 +142,7 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
 			will(throwException(new FormatException()));
 		}});
 
-		subclassNotCalled.validateMessage(message, group);
+		failIfSubclassIsCalled.validateMessage(message, group);
 	}
 
 	@Test(expected = InvalidMessageException.class)
@@ -152,6 +155,7 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
 			will(returnValue(body));
 		}});
 
+		@NotNullByDefault
 		BdfMessageValidator v = new BdfMessageValidator(clientHelper,
 				metadataEncoder, clock) {
 			@Override
diff --git a/briar-tests/src/org/briarproject/clients/ClientHelperImplTest.java b/briar-tests/src/org/briarproject/bramble/client/ClientHelperImplTest.java
similarity index 90%
rename from briar-tests/src/org/briarproject/clients/ClientHelperImplTest.java
rename to briar-tests/src/org/briarproject/bramble/client/ClientHelperImplTest.java
index ccea806ff2037885b5580e02eb341da66816fb71..818db58b612aa9ed8e386bb15873471599f47156 100644
--- a/briar-tests/src/org/briarproject/clients/ClientHelperImplTest.java
+++ b/briar-tests/src/org/briarproject/bramble/client/ClientHelperImplTest.java
@@ -1,26 +1,26 @@
-package org.briarproject.clients;
+package org.briarproject.bramble.client;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestUtils;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.BdfReader;
-import org.briarproject.api.data.BdfReaderFactory;
-import org.briarproject.api.data.BdfWriter;
-import org.briarproject.api.data.BdfWriterFactory;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.data.MetadataParser;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageFactory;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.BdfReader;
+import org.briarproject.bramble.api.data.BdfReaderFactory;
+import org.briarproject.bramble.api.data.BdfWriter;
+import org.briarproject.bramble.api.data.BdfWriterFactory;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.data.MetadataParser;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageFactory;
+import org.briarproject.bramble.api.sync.MessageId;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.junit.Test;
diff --git a/briar-tests/src/org/briarproject/contact/ContactManagerImplTest.java b/briar-tests/src/org/briarproject/bramble/contact/ContactManagerImplTest.java
similarity index 89%
rename from briar-tests/src/org/briarproject/contact/ContactManagerImplTest.java
rename to briar-tests/src/org/briarproject/bramble/contact/ContactManagerImplTest.java
index d7ebb8302c88e3e404608dafaf9d5efe975340b6..99243107e4f47d912114780564ebe050dc273222 100644
--- a/briar-tests/src/org/briarproject/contact/ContactManagerImplTest.java
+++ b/briar-tests/src/org/briarproject/bramble/contact/ContactManagerImplTest.java
@@ -1,15 +1,15 @@
-package org.briarproject.contact;
+package org.briarproject.bramble.contact;
 
 import org.briarproject.BriarTestCase;
-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.DatabaseComponent;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.transport.KeyManager;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.transport.KeyManager;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.junit.Test;
diff --git a/briar-tests/src/org/briarproject/crypto/AsciiArmourTest.java b/briar-tests/src/org/briarproject/bramble/crypto/AsciiArmourTest.java
similarity index 97%
rename from briar-tests/src/org/briarproject/crypto/AsciiArmourTest.java
rename to briar-tests/src/org/briarproject/bramble/crypto/AsciiArmourTest.java
index e07f3e6c39a50ceeede823db656299dda522d7d1..21fb4e3102c50c29304d10f592e0ca9ab195366b 100644
--- a/briar-tests/src/org/briarproject/crypto/AsciiArmourTest.java
+++ b/briar-tests/src/org/briarproject/bramble/crypto/AsciiArmourTest.java
@@ -1,4 +1,4 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
 import org.briarproject.BriarTestCase;
 import org.junit.Test;
diff --git a/briar-tests/src/org/briarproject/crypto/Blake2sDigestTest.java b/briar-tests/src/org/briarproject/bramble/crypto/Blake2sDigestTest.java
similarity index 98%
rename from briar-tests/src/org/briarproject/crypto/Blake2sDigestTest.java
rename to briar-tests/src/org/briarproject/bramble/crypto/Blake2sDigestTest.java
index 843e6857a903200267aa4b7bcc3f536d777612d8..cd6494a400f0905bbba60533d31b144765f90e92 100644
--- a/briar-tests/src/org/briarproject/crypto/Blake2sDigestTest.java
+++ b/briar-tests/src/org/briarproject/bramble/crypto/Blake2sDigestTest.java
@@ -1,7 +1,7 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
 import org.briarproject.BriarTestCase;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.util.StringUtils;
 import org.junit.Test;
 
 import java.util.Random;
diff --git a/briar-tests/src/org/briarproject/crypto/EllipticCurveMultiplicationTest.java b/briar-tests/src/org/briarproject/bramble/crypto/EllipticCurveMultiplicationTest.java
similarity index 97%
rename from briar-tests/src/org/briarproject/crypto/EllipticCurveMultiplicationTest.java
rename to briar-tests/src/org/briarproject/bramble/crypto/EllipticCurveMultiplicationTest.java
index 6ee969089583f9992b85fc9243c73eaf4c07603a..241e57c6ae8c449ea7a88b65beb67128218e1211 100644
--- a/briar-tests/src/org/briarproject/crypto/EllipticCurveMultiplicationTest.java
+++ b/briar-tests/src/org/briarproject/bramble/crypto/EllipticCurveMultiplicationTest.java
@@ -1,4 +1,4 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
 import org.briarproject.BriarTestCase;
 import org.junit.Test;
@@ -17,7 +17,7 @@ import org.spongycastle.math.ec.ECPoint;
 import java.math.BigInteger;
 import java.security.SecureRandom;
 
-import static org.briarproject.crypto.EllipticCurveConstants.PARAMETERS;
+import static org.briarproject.bramble.crypto.EllipticCurveConstants.PARAMETERS;
 import static org.junit.Assert.assertEquals;
 
 public class EllipticCurveMultiplicationTest extends BriarTestCase {
diff --git a/briar-tests/src/org/briarproject/crypto/EllipticCurvePerformanceTest.java b/briar-tests/src/org/briarproject/bramble/crypto/EllipticCurvePerformanceTest.java
similarity index 97%
rename from briar-tests/src/org/briarproject/crypto/EllipticCurvePerformanceTest.java
rename to briar-tests/src/org/briarproject/bramble/crypto/EllipticCurvePerformanceTest.java
index 7f18689e847194d76113804665c506828356e94b..b9e695eda67af04b34f8272232497e4bf05ec3f9 100644
--- a/briar-tests/src/org/briarproject/crypto/EllipticCurvePerformanceTest.java
+++ b/briar-tests/src/org/briarproject/bramble/crypto/EllipticCurvePerformanceTest.java
@@ -1,4 +1,4 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
 import org.spongycastle.asn1.sec.SECNamedCurves;
 import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves;
@@ -69,7 +69,7 @@ public class EllipticCurvePerformanceTest {
 		ECPublicKeyParameters public2 =
 				(ECPublicKeyParameters) keyPair2.getPublic();
 		// Time some ECDH key agreements
-		List<Long> samples = new ArrayList<Long>();
+		List<Long> samples = new ArrayList<>();
 		for (int i = 0; i < SAMPLES; i++) {
 			ECDHCBasicAgreement agreement = new ECDHCBasicAgreement();
 			long start = System.nanoTime();
@@ -79,7 +79,7 @@ public class EllipticCurvePerformanceTest {
 		}
 		long agreementMedian = median(samples);
 		// Time some signatures
-		List<byte[]> signatures = new ArrayList<byte[]>();
+		List<byte[]> signatures = new ArrayList<>();
 		samples.clear();
 		for (int i = 0; i < SAMPLES; i++) {
 			Digest digest = new Blake2sDigest();
diff --git a/briar-tests/src/org/briarproject/crypto/FortunaGeneratorTest.java b/briar-tests/src/org/briarproject/bramble/crypto/FortunaGeneratorTest.java
similarity index 98%
rename from briar-tests/src/org/briarproject/crypto/FortunaGeneratorTest.java
rename to briar-tests/src/org/briarproject/bramble/crypto/FortunaGeneratorTest.java
index 9946ea464099de84fa21d7e9a88a1986f92d4b20..44f986b7e61eedbac144c4ca9f30264db087084b 100644
--- a/briar-tests/src/org/briarproject/crypto/FortunaGeneratorTest.java
+++ b/briar-tests/src/org/briarproject/bramble/crypto/FortunaGeneratorTest.java
@@ -1,4 +1,4 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
 import org.briarproject.BriarTestCase;
 import org.junit.Test;
diff --git a/briar-tests/src/org/briarproject/crypto/FortunaSecureRandomTest.java b/briar-tests/src/org/briarproject/bramble/crypto/FortunaSecureRandomTest.java
similarity index 85%
rename from briar-tests/src/org/briarproject/crypto/FortunaSecureRandomTest.java
rename to briar-tests/src/org/briarproject/bramble/crypto/FortunaSecureRandomTest.java
index 260c38cd8553cbce71ee9c19a47b21154ab56997..86e302ec0c9958d5e94d3f6a7f69f74fd65e7508 100644
--- a/briar-tests/src/org/briarproject/crypto/FortunaSecureRandomTest.java
+++ b/briar-tests/src/org/briarproject/bramble/crypto/FortunaSecureRandomTest.java
@@ -1,16 +1,16 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
 import org.briarproject.BriarTestCase;
-import org.briarproject.api.crypto.MessageDigest;
+import org.briarproject.bramble.api.crypto.MessageDigest;
 import org.junit.Test;
 import org.spongycastle.crypto.BlockCipher;
 import org.spongycastle.crypto.digests.SHA256Digest;
 import org.spongycastle.crypto.engines.AESLightEngine;
 import org.spongycastle.crypto.params.KeyParameter;
 
-import static org.briarproject.crypto.FortunaSecureRandom.SELF_TEST_VECTOR_1;
-import static org.briarproject.crypto.FortunaSecureRandom.SELF_TEST_VECTOR_2;
-import static org.briarproject.crypto.FortunaSecureRandom.SELF_TEST_VECTOR_3;
+import static org.briarproject.bramble.crypto.FortunaSecureRandom.SELF_TEST_VECTOR_1;
+import static org.briarproject.bramble.crypto.FortunaSecureRandom.SELF_TEST_VECTOR_2;
+import static org.briarproject.bramble.crypto.FortunaSecureRandom.SELF_TEST_VECTOR_3;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertTrue;
 
diff --git a/briar-tests/src/org/briarproject/crypto/KeyAgreementTest.java b/briar-tests/src/org/briarproject/bramble/crypto/KeyAgreementTest.java
similarity index 84%
rename from briar-tests/src/org/briarproject/crypto/KeyAgreementTest.java
rename to briar-tests/src/org/briarproject/bramble/crypto/KeyAgreementTest.java
index 2990e8f460ad5b2296c21bdeb342beb1bd6561aa..00cb0e79822f251a3f01783dae723c8943bafc1b 100644
--- a/briar-tests/src/org/briarproject/crypto/KeyAgreementTest.java
+++ b/briar-tests/src/org/briarproject/bramble/crypto/KeyAgreementTest.java
@@ -1,11 +1,11 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestSeedProvider;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.KeyPair;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.system.SeedProvider;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.KeyPair;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.system.SeedProvider;
 import org.junit.Test;
 
 import static org.junit.Assert.assertArrayEquals;
diff --git a/briar-tests/src/org/briarproject/crypto/KeyDerivationTest.java b/briar-tests/src/org/briarproject/bramble/crypto/KeyDerivationTest.java
similarity index 95%
rename from briar-tests/src/org/briarproject/crypto/KeyDerivationTest.java
rename to briar-tests/src/org/briarproject/bramble/crypto/KeyDerivationTest.java
index 28276a4311bbbec20166a373a4e0d98b7803a66f..3d80762e06c8c13d8f2009544dc2aee73b892da9 100644
--- a/briar-tests/src/org/briarproject/crypto/KeyDerivationTest.java
+++ b/briar-tests/src/org/briarproject/bramble/crypto/KeyDerivationTest.java
@@ -1,12 +1,12 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestSeedProvider;
 import org.briarproject.TestUtils;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.transport.TransportKeys;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.transport.TransportKeys;
 import org.junit.Test;
 
 import java.util.ArrayList;
@@ -141,7 +141,7 @@ public class KeyDerivationTest extends BriarTestCase {
 	}
 
 	private void assertAllDifferent(TransportKeys... transportKeys) {
-		List<SecretKey> secretKeys = new ArrayList<SecretKey>();
+		List<SecretKey> secretKeys = new ArrayList<>();
 		for (TransportKeys k : transportKeys) {
 			secretKeys.add(k.getPreviousIncomingKeys().getTagKey());
 			secretKeys.add(k.getPreviousIncomingKeys().getHeaderKey());
diff --git a/briar-tests/src/org/briarproject/crypto/KeyEncodingAndParsingTest.java b/briar-tests/src/org/briarproject/bramble/crypto/KeyEncodingAndParsingTest.java
similarity index 93%
rename from briar-tests/src/org/briarproject/crypto/KeyEncodingAndParsingTest.java
rename to briar-tests/src/org/briarproject/bramble/crypto/KeyEncodingAndParsingTest.java
index b7abf54fb45abfe18a4d6648a2dd0e4301a3c551..350354bf0e582a16e3cbc74b5604a47fdf45cdcf 100644
--- a/briar-tests/src/org/briarproject/crypto/KeyEncodingAndParsingTest.java
+++ b/briar-tests/src/org/briarproject/bramble/crypto/KeyEncodingAndParsingTest.java
@@ -1,18 +1,18 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestSeedProvider;
 import org.briarproject.TestUtils;
-import org.briarproject.api.crypto.KeyPair;
-import org.briarproject.api.crypto.KeyParser;
-import org.briarproject.api.crypto.PrivateKey;
-import org.briarproject.api.crypto.PublicKey;
+import org.briarproject.bramble.api.crypto.KeyPair;
+import org.briarproject.bramble.api.crypto.KeyParser;
+import org.briarproject.bramble.api.crypto.PrivateKey;
+import org.briarproject.bramble.api.crypto.PublicKey;
 import org.junit.Test;
 
 import java.security.GeneralSecurityException;
 
-import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
-import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertTrue;
 
diff --git a/briar-tests/src/org/briarproject/crypto/MacTest.java b/briar-tests/src/org/briarproject/bramble/crypto/MacTest.java
similarity index 91%
rename from briar-tests/src/org/briarproject/crypto/MacTest.java
rename to briar-tests/src/org/briarproject/bramble/crypto/MacTest.java
index c63fa66c299d864df7d875d051dfbfbe6dc9956a..8b9e59bab4515636b55de7526f03b9d3d5668ea2 100644
--- a/briar-tests/src/org/briarproject/crypto/MacTest.java
+++ b/briar-tests/src/org/briarproject/bramble/crypto/MacTest.java
@@ -1,10 +1,10 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestSeedProvider;
 import org.briarproject.TestUtils;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.SecretKey;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.SecretKey;
 import org.junit.Test;
 
 import java.util.Arrays;
diff --git a/briar-tests/src/org/briarproject/crypto/MessageEncrypterTest.java b/briar-tests/src/org/briarproject/bramble/crypto/MessageEncrypterTest.java
similarity index 77%
rename from briar-tests/src/org/briarproject/crypto/MessageEncrypterTest.java
rename to briar-tests/src/org/briarproject/bramble/crypto/MessageEncrypterTest.java
index 351fa48af43aff0e0d6841419d469d8d7fc5e218..ea36d9ca366d51d8cc9984f30870b1fc1e591eb6 100644
--- a/briar-tests/src/org/briarproject/crypto/MessageEncrypterTest.java
+++ b/briar-tests/src/org/briarproject/bramble/crypto/MessageEncrypterTest.java
@@ -1,14 +1,11 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
 import org.briarproject.BriarTestCase;
-import org.briarproject.api.crypto.KeyPair;
-import org.briarproject.api.crypto.PrivateKey;
-import org.briarproject.api.crypto.PublicKey;
+import org.briarproject.bramble.api.crypto.KeyPair;
+import org.briarproject.bramble.api.crypto.PrivateKey;
+import org.briarproject.bramble.api.crypto.PublicKey;
 import org.junit.Test;
-import org.spongycastle.crypto.AsymmetricCipherKeyPair;
 import org.spongycastle.crypto.CryptoException;
-import org.spongycastle.crypto.params.ECPrivateKeyParameters;
-import org.spongycastle.crypto.params.ECPublicKeyParameters;
 
 import java.security.SecureRandom;
 
diff --git a/briar-tests/src/org/briarproject/crypto/PasswordBasedKdfTest.java b/briar-tests/src/org/briarproject/bramble/crypto/PasswordBasedKdfTest.java
similarity index 97%
rename from briar-tests/src/org/briarproject/crypto/PasswordBasedKdfTest.java
rename to briar-tests/src/org/briarproject/bramble/crypto/PasswordBasedKdfTest.java
index 98ae7854d005a4ccd85f94b5938e05cf76d97714..5d070af0d088b4f30e95867e136edb16eb3f7bbb 100644
--- a/briar-tests/src/org/briarproject/crypto/PasswordBasedKdfTest.java
+++ b/briar-tests/src/org/briarproject/bramble/crypto/PasswordBasedKdfTest.java
@@ -1,4 +1,4 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestSeedProvider;
diff --git a/briar-tests/src/org/briarproject/crypto/PasswordStrengthEstimatorImplTest.java b/briar-tests/src/org/briarproject/bramble/crypto/PasswordStrengthEstimatorImplTest.java
similarity index 80%
rename from briar-tests/src/org/briarproject/crypto/PasswordStrengthEstimatorImplTest.java
rename to briar-tests/src/org/briarproject/bramble/crypto/PasswordStrengthEstimatorImplTest.java
index 249ed4a1654170dfba226ade45ed8d22671955b6..3eea773aa4dc1e85f3d5e358d4049c016bdc8dd2 100644
--- a/briar-tests/src/org/briarproject/crypto/PasswordStrengthEstimatorImplTest.java
+++ b/briar-tests/src/org/briarproject/bramble/crypto/PasswordStrengthEstimatorImplTest.java
@@ -1,10 +1,10 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
 import org.briarproject.BriarTestCase;
-import org.briarproject.api.crypto.PasswordStrengthEstimator;
+import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
 import org.junit.Test;
 
-import static org.briarproject.api.crypto.PasswordStrengthEstimator.QUITE_STRONG;
+import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_STRONG;
 import static org.junit.Assert.assertTrue;
 
 public class PasswordStrengthEstimatorImplTest extends BriarTestCase {
diff --git a/briar-tests/src/org/briarproject/crypto/SignatureTest.java b/briar-tests/src/org/briarproject/bramble/crypto/SignatureTest.java
similarity index 96%
rename from briar-tests/src/org/briarproject/crypto/SignatureTest.java
rename to briar-tests/src/org/briarproject/bramble/crypto/SignatureTest.java
index 36d718540867bfe7eeec612db75605eef8c81861..7971809ddc30855ca2768ef486ee230a7e42dfda 100644
--- a/briar-tests/src/org/briarproject/crypto/SignatureTest.java
+++ b/briar-tests/src/org/briarproject/bramble/crypto/SignatureTest.java
@@ -1,10 +1,10 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestSeedProvider;
 import org.briarproject.TestUtils;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.KeyPair;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.KeyPair;
 import org.junit.Test;
 
 import java.util.Arrays;
diff --git a/briar-tests/src/org/briarproject/crypto/StreamDecrypterImplTest.java b/briar-tests/src/org/briarproject/bramble/crypto/StreamDecrypterImplTest.java
similarity index 91%
rename from briar-tests/src/org/briarproject/crypto/StreamDecrypterImplTest.java
rename to briar-tests/src/org/briarproject/bramble/crypto/StreamDecrypterImplTest.java
index fb60f2cb2969cdeef185f9a43cbc8d07976c76e6..50d6c10c2bbf3ba79ab4899d7c9f55e553c745e9 100644
--- a/briar-tests/src/org/briarproject/crypto/StreamDecrypterImplTest.java
+++ b/briar-tests/src/org/briarproject/bramble/crypto/StreamDecrypterImplTest.java
@@ -1,9 +1,9 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestUtils;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.util.ByteUtils;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.util.ByteUtils;
 import org.junit.Test;
 
 import java.io.ByteArrayInputStream;
@@ -11,11 +11,11 @@ import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 
 import static junit.framework.Assert.assertEquals;
-import static org.briarproject.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.MAC_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.STREAM_HEADER_IV_LENGTH;
-import static org.briarproject.util.ByteUtils.INT_16_BYTES;
+import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAC_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_IV_LENGTH;
+import static org.briarproject.bramble.util.ByteUtils.INT_16_BYTES;
 import static org.junit.Assert.assertArrayEquals;
 
 public class StreamDecrypterImplTest extends BriarTestCase {
diff --git a/briar-tests/src/org/briarproject/crypto/StreamEncrypterImplTest.java b/briar-tests/src/org/briarproject/bramble/crypto/StreamEncrypterImplTest.java
similarity index 96%
rename from briar-tests/src/org/briarproject/crypto/StreamEncrypterImplTest.java
rename to briar-tests/src/org/briarproject/bramble/crypto/StreamEncrypterImplTest.java
index 4dccd6739fd061756ba10e6cc0a285a6afab7131..bb542662c583c8f6d8c341ac6afd2ca88b272ff7 100644
--- a/briar-tests/src/org/briarproject/crypto/StreamEncrypterImplTest.java
+++ b/briar-tests/src/org/briarproject/bramble/crypto/StreamEncrypterImplTest.java
@@ -1,16 +1,16 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestUtils;
-import org.briarproject.api.crypto.SecretKey;
+import org.briarproject.bramble.api.crypto.SecretKey;
 import org.junit.Test;
 
 import java.io.ByteArrayOutputStream;
 
-import static org.briarproject.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.MAC_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.STREAM_HEADER_IV_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAC_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_IV_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
 import static org.junit.Assert.assertArrayEquals;
 
 public class StreamEncrypterImplTest extends BriarTestCase {
diff --git a/briar-tests/src/org/briarproject/crypto/TestAuthenticatedCipher.java b/briar-tests/src/org/briarproject/bramble/crypto/TestAuthenticatedCipher.java
similarity index 75%
rename from briar-tests/src/org/briarproject/crypto/TestAuthenticatedCipher.java
rename to briar-tests/src/org/briarproject/bramble/crypto/TestAuthenticatedCipher.java
index 7d7acd74d98dff4f19623f10e6c71b7f3490079c..dd7982795a9ca52f912caac4b3f366ce2bf9af84 100644
--- a/briar-tests/src/org/briarproject/crypto/TestAuthenticatedCipher.java
+++ b/briar-tests/src/org/briarproject/bramble/crypto/TestAuthenticatedCipher.java
@@ -1,20 +1,24 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
-import org.briarproject.api.crypto.SecretKey;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.security.GeneralSecurityException;
 
-import static org.briarproject.api.transport.TransportConstants.MAC_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAC_LENGTH;
 
+@NotNullByDefault
 class TestAuthenticatedCipher implements AuthenticatedCipher {
 
 	private boolean encrypt = false;
 
+	@Override
 	public void init(boolean encrypt, SecretKey key, byte[] iv)
 			throws GeneralSecurityException {
 		this.encrypt = encrypt;
 	}
 
+	@Override
 	public int process(byte[] input, int inputOff, int len, byte[] output,
 			int outputOff) throws GeneralSecurityException {
 		if (encrypt) {
@@ -32,6 +36,7 @@ class TestAuthenticatedCipher implements AuthenticatedCipher {
 		}
 	}
 
+	@Override
 	public int getMacBytes() {
 		return MAC_LENGTH;
 	}
diff --git a/briar-tests/src/org/briarproject/crypto/XSalsa20Poly1305AuthenticatedCipherTest.java b/briar-tests/src/org/briarproject/bramble/crypto/XSalsa20Poly1305AuthenticatedCipherTest.java
similarity index 96%
rename from briar-tests/src/org/briarproject/crypto/XSalsa20Poly1305AuthenticatedCipherTest.java
rename to briar-tests/src/org/briarproject/bramble/crypto/XSalsa20Poly1305AuthenticatedCipherTest.java
index 6d45fc975769459c7cd45207260ac5538fa81f21..8c19201f9f1d69138a88cd8e57f28f0e2f4f6c76 100644
--- a/briar-tests/src/org/briarproject/crypto/XSalsa20Poly1305AuthenticatedCipherTest.java
+++ b/briar-tests/src/org/briarproject/bramble/crypto/XSalsa20Poly1305AuthenticatedCipherTest.java
@@ -1,8 +1,8 @@
-package org.briarproject.crypto;
+package org.briarproject.bramble.crypto;
 
 import org.briarproject.BriarTestCase;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.util.StringUtils;
 import org.junit.Test;
 
 import java.security.GeneralSecurityException;
diff --git a/briar-tests/src/org/briarproject/data/BdfDictionaryTest.java b/briar-tests/src/org/briarproject/bramble/data/BdfDictionaryTest.java
similarity index 89%
rename from briar-tests/src/org/briarproject/data/BdfDictionaryTest.java
rename to briar-tests/src/org/briarproject/bramble/data/BdfDictionaryTest.java
index 06ead4cdfc00659a76f71463fd41c2c0c939591e..5aabfdd609f4052c89a0c177ca8c2546a034e82f 100644
--- a/briar-tests/src/org/briarproject/data/BdfDictionaryTest.java
+++ b/briar-tests/src/org/briarproject/bramble/data/BdfDictionaryTest.java
@@ -1,16 +1,16 @@
-package org.briarproject.data;
+package org.briarproject.bramble.data;
 
 import org.briarproject.BriarTestCase;
-import org.briarproject.api.Bytes;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
+import org.briarproject.bramble.api.Bytes;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
 import org.junit.Test;
 
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.Map.Entry;
 
-import static org.briarproject.api.data.BdfDictionary.NULL_VALUE;
+import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -19,14 +19,16 @@ public class BdfDictionaryTest extends BriarTestCase {
 
 	@Test
 	public void testConstructors() {
-		assertEquals(Collections.emptyMap(), new BdfDictionary());
+		assertEquals(Collections.<String, Object>emptyMap(),
+				new BdfDictionary());
 		assertEquals(Collections.singletonMap("foo", NULL_VALUE),
 				new BdfDictionary(Collections.singletonMap("foo", NULL_VALUE)));
 	}
 
 	@Test
 	public void testFactoryMethod() {
-		assertEquals(Collections.emptyMap(), BdfDictionary.of());
+		assertEquals(Collections.<String, Object>emptyMap(),
+				BdfDictionary.of());
 		assertEquals(Collections.singletonMap("foo", NULL_VALUE),
 				BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)));
 	}
diff --git a/briar-tests/src/org/briarproject/data/BdfListTest.java b/briar-tests/src/org/briarproject/bramble/data/BdfListTest.java
similarity index 96%
rename from briar-tests/src/org/briarproject/data/BdfListTest.java
rename to briar-tests/src/org/briarproject/bramble/data/BdfListTest.java
index 1cced78ffd7ddae11fabd9a0cad68fc41783ced7..7fd85878f64a115298524691277486f2714be357 100644
--- a/briar-tests/src/org/briarproject/data/BdfListTest.java
+++ b/briar-tests/src/org/briarproject/bramble/data/BdfListTest.java
@@ -1,17 +1,17 @@
-package org.briarproject.data;
+package org.briarproject.bramble.data;
 
 import org.briarproject.BriarTestCase;
-import org.briarproject.api.Bytes;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.data.BdfList;
+import org.briarproject.bramble.api.Bytes;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.data.BdfList;
 import org.junit.Test;
 
 import java.util.Arrays;
 import java.util.Collections;
 
-import static org.briarproject.api.data.BdfDictionary.NULL_VALUE;
+import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 
diff --git a/briar-tests/src/org/briarproject/data/BdfReaderImplTest.java b/briar-tests/src/org/briarproject/bramble/data/BdfReaderImplTest.java
similarity index 97%
rename from briar-tests/src/org/briarproject/data/BdfReaderImplTest.java
rename to briar-tests/src/org/briarproject/bramble/data/BdfReaderImplTest.java
index 5d74a63d560599b9c9153bfaa3efa481134a9592..7520fdebd3ca72253865be8df67cc6c1ed76c3ab 100644
--- a/briar-tests/src/org/briarproject/data/BdfReaderImplTest.java
+++ b/briar-tests/src/org/briarproject/bramble/data/BdfReaderImplTest.java
@@ -1,17 +1,17 @@
-package org.briarproject.data;
+package org.briarproject.bramble.data;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestUtils;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.util.StringUtils;
 import org.junit.Test;
 
 import java.io.ByteArrayInputStream;
 
-import static org.briarproject.api.data.BdfDictionary.NULL_VALUE;
-import static org.briarproject.data.BdfReaderImpl.DEFAULT_NESTED_LIMIT;
+import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
+import static org.briarproject.bramble.data.BdfReaderImpl.DEFAULT_NESTED_LIMIT;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
diff --git a/briar-tests/src/org/briarproject/data/BdfWriterImplTest.java b/briar-tests/src/org/briarproject/bramble/data/BdfWriterImplTest.java
similarity index 94%
rename from briar-tests/src/org/briarproject/data/BdfWriterImplTest.java
rename to briar-tests/src/org/briarproject/bramble/data/BdfWriterImplTest.java
index aa04a43aa737776c6be9835efba1bfee0ac6a661..c2856e5b0df73f577e9c868ef0ae1cfbae3fb85a 100644
--- a/briar-tests/src/org/briarproject/data/BdfWriterImplTest.java
+++ b/briar-tests/src/org/briarproject/bramble/data/BdfWriterImplTest.java
@@ -1,8 +1,8 @@
-package org.briarproject.data;
+package org.briarproject.bramble.data;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestUtils;
-import org.briarproject.util.StringUtils;
+import org.briarproject.bramble.util.StringUtils;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -13,7 +13,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
-import static org.briarproject.api.data.BdfDictionary.NULL_VALUE;
+import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
 import static org.junit.Assert.assertArrayEquals;
 
 public class BdfWriterImplTest extends BriarTestCase {
@@ -155,7 +155,7 @@ public class BdfWriterImplTest extends BriarTestCase {
 
 	@Test
 	public void testWriteList() throws IOException {
-		List<Object> l = new ArrayList<Object>();
+		List<Object> l = new ArrayList<>();
 		for (int i = 0; i < 3; i++) l.add(i);
 		w.writeList(l);
 		// LIST tag, elements as integers, END tag
@@ -164,7 +164,7 @@ public class BdfWriterImplTest extends BriarTestCase {
 
 	@Test
 	public void testListCanContainNull() throws IOException {
-		List<Object> l = new ArrayList<Object>();
+		List<Object> l = new ArrayList<>();
 		l.add(1);
 		l.add(null);
 		l.add(NULL_VALUE);
@@ -177,7 +177,7 @@ public class BdfWriterImplTest extends BriarTestCase {
 	@Test
 	public void testWriteDictionary() throws IOException {
 		// Use LinkedHashMap to get predictable iteration order
-		Map<String, Object> m = new LinkedHashMap<String, Object>();
+		Map<String, Object> m = new LinkedHashMap<>();
 		for (int i = 0; i < 4; i++) m.put(String.valueOf(i), i);
 		w.writeDictionary(m);
 		// DICTIONARY tag, keys as strings and values as integers, END tag
@@ -216,12 +216,12 @@ public class BdfWriterImplTest extends BriarTestCase {
 
 	@Test
 	public void testWriteNestedDictionariesAndLists() throws IOException {
-		Map<String, Object> inner = new LinkedHashMap<String, Object>();
+		Map<String, Object> inner = new LinkedHashMap<>();
 		inner.put("bar", new byte[0]);
-		List<Object> list = new ArrayList<Object>();
+		List<Object> list = new ArrayList<>();
 		list.add(1);
 		list.add(inner);
-		Map<String, Object> outer = new LinkedHashMap<String, Object>();
+		Map<String, Object> outer = new LinkedHashMap<>();
 		outer.put("foo", list);
 		w.writeDictionary(outer);
 		// DICTIONARY tag, "foo" as string, LIST tag, 1 as integer,
diff --git a/briar-tests/src/org/briarproject/data/MetadataEncoderParserIntegrationTest.java b/briar-tests/src/org/briarproject/bramble/data/MetadataEncoderParserIntegrationTest.java
similarity index 85%
rename from briar-tests/src/org/briarproject/data/MetadataEncoderParserIntegrationTest.java
rename to briar-tests/src/org/briarproject/bramble/data/MetadataEncoderParserIntegrationTest.java
index 3139ad598373f836e2fc50324c62df898d390ce1..953c99a1fdeceed3034237e2fbb99e952575d90f 100644
--- a/briar-tests/src/org/briarproject/data/MetadataEncoderParserIntegrationTest.java
+++ b/briar-tests/src/org/briarproject/bramble/data/MetadataEncoderParserIntegrationTest.java
@@ -1,9 +1,9 @@
-package org.briarproject.data;
+package org.briarproject.bramble.data;
 
 import org.briarproject.BriarTestCase;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.db.Metadata;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.db.Metadata;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -17,9 +17,9 @@ import static org.junit.Assert.assertEquals;
 
 public class MetadataEncoderParserIntegrationTest extends BriarTestCase {
 
-	MetadataEncoderImpl e;
-	MetadataParserImpl p;
-	BdfDictionary d;
+	private MetadataEncoderImpl e;
+	private MetadataParserImpl p;
+	private BdfDictionary d;
 
 	@Before
 	public void before() {
@@ -99,7 +99,7 @@ public class MetadataEncoderParserIntegrationTest extends BriarTestCase {
 
 	@Test
 	public void testList() throws FormatException {
-		List<Long> l = new ArrayList<Long>(4);
+		List<Long> l = new ArrayList<>(4);
 		l.add(42L);
 		l.add(1337L);
 		l.add(Long.MIN_VALUE);
@@ -114,7 +114,7 @@ public class MetadataEncoderParserIntegrationTest extends BriarTestCase {
 
 	@Test
 	public void testDictionary() throws FormatException {
-		Map<String, Boolean> m = new HashMap<String, Boolean>();
+		Map<String, Boolean> m = new HashMap<>();
 		m.put("1", true);
 		m.put("2", false);
 
@@ -130,19 +130,19 @@ public class MetadataEncoderParserIntegrationTest extends BriarTestCase {
 
 	@Test
 	public void testComplexDictionary() throws FormatException {
-		Map<String, List> m = new HashMap<String, List>();
-		List<String> one = new ArrayList<String>(3);
+		Map<String, List> m = new HashMap<>();
+		List<String> one = new ArrayList<>(3);
 		one.add("\uFDD0");
 		one.add("\uFDD1");
 		one.add("\uFDD2");
 		m.put("One", one);
-		List<String> two = new ArrayList<String>(2);
+		List<String> two = new ArrayList<>(2);
 		two.add("\u0080");
 		two.add("\uD800\uDC00");
 		m.put("Two", two);
 		d.put("test", m);
 
-		Map<String, Boolean> m2 = new HashMap<String, Boolean>();
+		Map<String, Boolean> m2 = new HashMap<>();
 		m2.put("should be true", true);
 		d.put("another test", m2);
 
@@ -156,8 +156,9 @@ public class MetadataEncoderParserIntegrationTest extends BriarTestCase {
 				.getList("One", null).get(2));
 		assertEquals("\u0080", p.parse(metadata).getDictionary("test", null)
 				.getList("Two", null).get(0));
-		assertEquals("\uD800\uDC00", p.parse(metadata).getDictionary("test", null)
-				.getList("Two", null).get(1));
+		assertEquals("\uD800\uDC00",
+				p.parse(metadata).getDictionary("test", null)
+						.getList("Two", null).get(1));
 
 		assertEquals(true, p.parse(metadata).getDictionary("another test", null)
 				.getBoolean("should be true", false));
diff --git a/briar-tests/src/org/briarproject/db/BasicH2Test.java b/briar-tests/src/org/briarproject/bramble/db/BasicH2Test.java
similarity index 96%
rename from briar-tests/src/org/briarproject/db/BasicH2Test.java
rename to briar-tests/src/org/briarproject/bramble/db/BasicH2Test.java
index 1802fe2ca20cdc72b8ee32ad42b7d239c7fc886a..a5658ed95656277689c01a787a8877f08c8a87c6 100644
--- a/briar-tests/src/org/briarproject/db/BasicH2Test.java
+++ b/briar-tests/src/org/briarproject/bramble/db/BasicH2Test.java
@@ -1,4 +1,4 @@
-package org.briarproject.db;
+package org.briarproject.bramble.db;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestUtils;
@@ -250,9 +250,7 @@ public class BasicH2Test extends BriarTestCase {
 			}
 			int[] batchAffected = ps.executeBatch();
 			assertEquals(ids.length, batchAffected.length);
-			for (int i = 0; i < batchAffected.length; i++) {
-				assertEquals(1, batchAffected[i]);
-			}
+			for (int affected : batchAffected) assertEquals(1, affected);
 			ps.close();
 		} catch (SQLException e) {
 			connection.close();
@@ -273,8 +271,7 @@ public class BasicH2Test extends BriarTestCase {
 			}
 			int[] batchAffected = ps.executeBatch();
 			assertEquals(ids.length, batchAffected.length);
-			for (int i = 0; i < batchAffected.length; i++)
-				assertEquals(1, batchAffected[i]);
+			for (int affected : batchAffected) assertEquals(1, affected);
 			ps.close();
 		} catch (SQLException e) {
 			connection.close();
@@ -286,9 +283,9 @@ public class BasicH2Test extends BriarTestCase {
 		String sql = "DELETE FROM foo WHERE uniqueId = ?";
 		try {
 			PreparedStatement ps = connection.prepareStatement(sql);
-			for (int i = 0; i < ids.length; i++) {
-				if (ids[i] == null) ps.setNull(1, BINARY);
-				else ps.setBytes(1, ids[i]);
+			for (byte[] id : ids) {
+				if (id == null) ps.setNull(1, BINARY);
+				else ps.setBytes(1, id);
 				ps.addBatch();
 			}
 			int[] batchAffected = ps.executeBatch();
@@ -325,7 +322,7 @@ public class BasicH2Test extends BriarTestCase {
 
 	private List<String> getNames() throws SQLException {
 		String sql = "SELECT name FROM foo ORDER BY uniqueId";
-		List<String> names = new ArrayList<String>();
+		List<String> names = new ArrayList<>();
 		try {
 			PreparedStatement ps = connection.prepareStatement(sql);
 			ResultSet rs = ps.executeQuery();
diff --git a/briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java b/briar-tests/src/org/briarproject/bramble/db/DatabaseComponentImplTest.java
similarity index 93%
rename from briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java
rename to briar-tests/src/org/briarproject/bramble/db/DatabaseComponentImplTest.java
index d61f0cce936f28491e9221121962454eb3b5a83a..62b7cc0834153915e53ac6bb53e5ac71be9fcfe6 100644
--- a/briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java
+++ b/briar-tests/src/org/briarproject/bramble/db/DatabaseComponentImplTest.java
@@ -1,54 +1,54 @@
-package org.briarproject.db;
+package org.briarproject.bramble.db;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestUtils;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.db.ContactExistsException;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.db.NoSuchContactException;
-import org.briarproject.api.db.NoSuchGroupException;
-import org.briarproject.api.db.NoSuchLocalAuthorException;
-import org.briarproject.api.db.NoSuchMessageException;
-import org.briarproject.api.db.NoSuchTransportException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.ContactAddedEvent;
-import org.briarproject.api.event.ContactRemovedEvent;
-import org.briarproject.api.event.ContactStatusChangedEvent;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.GroupAddedEvent;
-import org.briarproject.api.event.GroupRemovedEvent;
-import org.briarproject.api.event.GroupVisibilityUpdatedEvent;
-import org.briarproject.api.event.LocalAuthorAddedEvent;
-import org.briarproject.api.event.LocalAuthorRemovedEvent;
-import org.briarproject.api.event.MessageAddedEvent;
-import org.briarproject.api.event.MessageRequestedEvent;
-import org.briarproject.api.event.MessageSharedEvent;
-import org.briarproject.api.event.MessageStateChangedEvent;
-import org.briarproject.api.event.MessageToAckEvent;
-import org.briarproject.api.event.MessageToRequestEvent;
-import org.briarproject.api.event.MessagesAckedEvent;
-import org.briarproject.api.event.MessagesSentEvent;
-import org.briarproject.api.event.SettingsUpdatedEvent;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.lifecycle.ShutdownManager;
-import org.briarproject.api.settings.Settings;
-import org.briarproject.api.sync.Ack;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.sync.Offer;
-import org.briarproject.api.sync.Request;
-import org.briarproject.api.transport.IncomingKeys;
-import org.briarproject.api.transport.OutgoingKeys;
-import org.briarproject.api.transport.TransportKeys;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.event.ContactAddedEvent;
+import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
+import org.briarproject.bramble.api.contact.event.ContactStatusChangedEvent;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.db.ContactExistsException;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.db.NoSuchContactException;
+import org.briarproject.bramble.api.db.NoSuchGroupException;
+import org.briarproject.bramble.api.db.NoSuchLocalAuthorException;
+import org.briarproject.bramble.api.db.NoSuchMessageException;
+import org.briarproject.bramble.api.db.NoSuchTransportException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.identity.event.LocalAuthorAddedEvent;
+import org.briarproject.bramble.api.identity.event.LocalAuthorRemovedEvent;
+import org.briarproject.bramble.api.lifecycle.ShutdownManager;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.settings.Settings;
+import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
+import org.briarproject.bramble.api.sync.Ack;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.Offer;
+import org.briarproject.bramble.api.sync.Request;
+import org.briarproject.bramble.api.sync.event.GroupAddedEvent;
+import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
+import org.briarproject.bramble.api.sync.event.GroupVisibilityUpdatedEvent;
+import org.briarproject.bramble.api.sync.event.MessageAddedEvent;
+import org.briarproject.bramble.api.sync.event.MessageRequestedEvent;
+import org.briarproject.bramble.api.sync.event.MessageSharedEvent;
+import org.briarproject.bramble.api.sync.event.MessageStateChangedEvent;
+import org.briarproject.bramble.api.sync.event.MessageToAckEvent;
+import org.briarproject.bramble.api.sync.event.MessageToRequestEvent;
+import org.briarproject.bramble.api.sync.event.MessagesAckedEvent;
+import org.briarproject.bramble.api.sync.event.MessagesSentEvent;
+import org.briarproject.bramble.api.transport.IncomingKeys;
+import org.briarproject.bramble.api.transport.OutgoingKeys;
+import org.briarproject.bramble.api.transport.TransportKeys;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.junit.Test;
@@ -59,14 +59,14 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Map;
 
-import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
-import static org.briarproject.api.sync.Group.Visibility.INVISIBLE;
-import static org.briarproject.api.sync.Group.Visibility.SHARED;
-import static org.briarproject.api.sync.Group.Visibility.VISIBLE;
-import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
-import static org.briarproject.api.sync.ValidationManager.State.UNKNOWN;
-import static org.briarproject.api.transport.TransportConstants.REORDERING_WINDOW_SIZE;
-import static org.briarproject.db.DatabaseConstants.MAX_OFFERED_MESSAGES;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
+import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
+import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE;
+import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
+import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
+import static org.briarproject.bramble.api.transport.TransportConstants.REORDERING_WINDOW_SIZE;
+import static org.briarproject.bramble.db.DatabaseConstants.MAX_OFFERED_MESSAGES;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -278,7 +278,8 @@ public class DatabaseComponentImplTest extends BriarTestCase {
 			oneOf(database).commitTransaction(txn);
 			// The message was added, so the listeners should be called
 			oneOf(eventBus).broadcast(with(any(MessageAddedEvent.class)));
-			oneOf(eventBus).broadcast(with(any(MessageStateChangedEvent.class)));
+			oneOf(eventBus)
+					.broadcast(with(any(MessageStateChangedEvent.class)));
 			oneOf(eventBus).broadcast(with(any(MessageSharedEvent.class)));
 		}});
 		DatabaseComponent db = createDatabaseComponent(database, eventBus,
diff --git a/briar-tests/src/org/briarproject/db/ExponentialBackoffTest.java b/briar-tests/src/org/briarproject/bramble/db/ExponentialBackoffTest.java
similarity index 98%
rename from briar-tests/src/org/briarproject/db/ExponentialBackoffTest.java
rename to briar-tests/src/org/briarproject/bramble/db/ExponentialBackoffTest.java
index 2fb80dd065e20fce87e0e60827b7c93b9a164892..376d7e54a74fc261a84043e65cabdb041997a867 100644
--- a/briar-tests/src/org/briarproject/db/ExponentialBackoffTest.java
+++ b/briar-tests/src/org/briarproject/bramble/db/ExponentialBackoffTest.java
@@ -1,4 +1,4 @@
-package org.briarproject.db;
+package org.briarproject.bramble.db;
 
 import org.briarproject.BriarTestCase;
 import org.junit.Test;
diff --git a/briar-tests/src/org/briarproject/db/H2DatabaseTest.java b/briar-tests/src/org/briarproject/bramble/db/H2DatabaseTest.java
similarity index 96%
rename from briar-tests/src/org/briarproject/db/H2DatabaseTest.java
rename to briar-tests/src/org/briarproject/bramble/db/H2DatabaseTest.java
index 5f1270265b169ea0cd9bd36299cf6ae905537839..faf91edcd4d1595a9fcdaa9a6ccd1999ee6252da 100644
--- a/briar-tests/src/org/briarproject/db/H2DatabaseTest.java
+++ b/briar-tests/src/org/briarproject/bramble/db/H2DatabaseTest.java
@@ -1,35 +1,34 @@
-package org.briarproject.db;
+package org.briarproject.bramble.db;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestDatabaseConfig;
 import org.briarproject.TestUtils;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.settings.Settings;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.sync.MessageStatus;
-import org.briarproject.api.sync.ValidationManager.State;
-import org.briarproject.api.transport.IncomingKeys;
-import org.briarproject.api.transport.OutgoingKeys;
-import org.briarproject.api.transport.TransportKeys;
-import org.briarproject.system.SystemClock;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.settings.Settings;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.MessageStatus;
+import org.briarproject.bramble.api.sync.ValidationManager.State;
+import org.briarproject.bramble.api.transport.IncomingKeys;
+import org.briarproject.bramble.api.transport.OutgoingKeys;
+import org.briarproject.bramble.api.transport.TransportKeys;
+import org.briarproject.bramble.system.SystemClock;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
 import java.io.File;
-import java.security.SecureRandom;
 import java.sql.Connection;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -43,16 +42,16 @@ import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.briarproject.api.db.Metadata.REMOVE;
-import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
-import static org.briarproject.api.sync.Group.Visibility.INVISIBLE;
-import static org.briarproject.api.sync.Group.Visibility.SHARED;
-import static org.briarproject.api.sync.Group.Visibility.VISIBLE;
-import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_LENGTH;
-import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
-import static org.briarproject.api.sync.ValidationManager.State.INVALID;
-import static org.briarproject.api.sync.ValidationManager.State.PENDING;
-import static org.briarproject.api.sync.ValidationManager.State.UNKNOWN;
+import static org.briarproject.bramble.api.db.Metadata.REMOVE;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
+import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
+import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE;
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_LENGTH;
+import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
+import static org.briarproject.bramble.api.sync.ValidationManager.State.INVALID;
+import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
+import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
diff --git a/briar-tests/src/org/briarproject/LockFairnessTest.java b/briar-tests/src/org/briarproject/bramble/db/LockFairnessTest.java
similarity index 98%
rename from briar-tests/src/org/briarproject/LockFairnessTest.java
rename to briar-tests/src/org/briarproject/bramble/db/LockFairnessTest.java
index 7daaf557e08b15ed9cb8b822528d113a93596d31..947e802bd4ba1e7da74dd3595997fecb7e24e969 100644
--- a/briar-tests/src/org/briarproject/LockFairnessTest.java
+++ b/briar-tests/src/org/briarproject/bramble/db/LockFairnessTest.java
@@ -1,5 +1,6 @@
-package org.briarproject;
+package org.briarproject.bramble.db;
 
+import org.briarproject.BriarTestCase;
 import org.junit.Test;
 
 import java.util.concurrent.CountDownLatch;
diff --git a/briar-tests/src/org/briarproject/db/TransactionIsolationTest.java b/briar-tests/src/org/briarproject/bramble/db/TransactionIsolationTest.java
similarity index 99%
rename from briar-tests/src/org/briarproject/db/TransactionIsolationTest.java
rename to briar-tests/src/org/briarproject/bramble/db/TransactionIsolationTest.java
index b01f5770a9413b9a2f0508a1b6e57aa05a37ff03..77b849b60e9b4e17a48bb4f0f20df76b682c6c40 100644
--- a/briar-tests/src/org/briarproject/db/TransactionIsolationTest.java
+++ b/briar-tests/src/org/briarproject/bramble/db/TransactionIsolationTest.java
@@ -1,4 +1,4 @@
-package org.briarproject.db;
+package org.briarproject.bramble.db;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestUtils;
diff --git a/briar-tests/src/org/briarproject/identity/IdentityManagerImplTest.java b/briar-tests/src/org/briarproject/bramble/identity/IdentityManagerImplTest.java
similarity index 79%
rename from briar-tests/src/org/briarproject/identity/IdentityManagerImplTest.java
rename to briar-tests/src/org/briarproject/bramble/identity/IdentityManagerImplTest.java
index ec73a0c1a5ec7258f1aa32572db3e73fdfc38759..afcc1db3ab9cfd4648d2034e71fbde76c2df5011 100644
--- a/briar-tests/src/org/briarproject/identity/IdentityManagerImplTest.java
+++ b/briar-tests/src/org/briarproject/bramble/identity/IdentityManagerImplTest.java
@@ -1,16 +1,16 @@
-package org.briarproject.identity;
+package org.briarproject.bramble.identity;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestUtils;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-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.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.junit.Test;
@@ -18,10 +18,10 @@ import org.junit.Test;
 import java.util.ArrayList;
 import java.util.Collection;
 
-import static org.briarproject.api.identity.Author.Status.OURSELVES;
-import static org.briarproject.api.identity.Author.Status.UNKNOWN;
-import static org.briarproject.api.identity.Author.Status.UNVERIFIED;
-import static org.briarproject.api.identity.Author.Status.VERIFIED;
+import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
+import static org.briarproject.bramble.api.identity.Author.Status.UNKNOWN;
+import static org.briarproject.bramble.api.identity.Author.Status.UNVERIFIED;
+import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
diff --git a/briar-tests/src/org/briarproject/keyagreement/KeyAgreementProtocolTest.java b/briar-tests/src/org/briarproject/bramble/keyagreement/KeyAgreementProtocolTest.java
similarity index 96%
rename from briar-tests/src/org/briarproject/keyagreement/KeyAgreementProtocolTest.java
rename to briar-tests/src/org/briarproject/bramble/keyagreement/KeyAgreementProtocolTest.java
index 63f52e82f304d40e5a0f32913322738ee2a79922..8efc0f535c087a5adc904b5191b13d4f2a9bedfe 100644
--- a/briar-tests/src/org/briarproject/keyagreement/KeyAgreementProtocolTest.java
+++ b/briar-tests/src/org/briarproject/bramble/keyagreement/KeyAgreementProtocolTest.java
@@ -1,13 +1,13 @@
-package org.briarproject.keyagreement;
+package org.briarproject.bramble.keyagreement;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestUtils;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.KeyPair;
-import org.briarproject.api.crypto.PublicKey;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.keyagreement.Payload;
-import org.briarproject.api.keyagreement.PayloadEncoder;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.KeyPair;
+import org.briarproject.bramble.api.crypto.PublicKey;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.keyagreement.Payload;
+import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
 import org.jmock.Expectations;
 import org.jmock.auto.Mock;
 import org.jmock.integration.junit4.JUnitRuleMockery;
@@ -15,7 +15,7 @@ import org.jmock.lib.legacy.ClassImposteriser;
 import org.junit.Rule;
 import org.junit.Test;
 
-import static org.briarproject.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
+import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.is;
 import static org.junit.Assert.assertThat;
diff --git a/briar-tests/src/org/briarproject/lifecycle/ShutdownManagerImplTest.java b/briar-tests/src/org/briarproject/bramble/lifecycle/ShutdownManagerImplTest.java
similarity index 81%
rename from briar-tests/src/org/briarproject/lifecycle/ShutdownManagerImplTest.java
rename to briar-tests/src/org/briarproject/bramble/lifecycle/ShutdownManagerImplTest.java
index 3af216ebf47bc7fe50fceeb188b2392efa368571..7fb15985421feb88af66cdbcefaac03dfff60449 100644
--- a/briar-tests/src/org/briarproject/lifecycle/ShutdownManagerImplTest.java
+++ b/briar-tests/src/org/briarproject/bramble/lifecycle/ShutdownManagerImplTest.java
@@ -1,7 +1,7 @@
-package org.briarproject.lifecycle;
+package org.briarproject.bramble.lifecycle;
 
 import org.briarproject.BriarTestCase;
-import org.briarproject.api.lifecycle.ShutdownManager;
+import org.briarproject.bramble.api.lifecycle.ShutdownManager;
 import org.junit.Test;
 
 import java.util.HashSet;
@@ -15,10 +15,12 @@ public class ShutdownManagerImplTest extends BriarTestCase {
 	@Test
 	public void testAddAndRemove() {
 		ShutdownManager s = createShutdownManager();
-		Set<Integer> handles = new HashSet<Integer>();
+		Set<Integer> handles = new HashSet<>();
 		for (int i = 0; i < 100; i++) {
 			int handle = s.addShutdownHook(new Runnable() {
-				public void run() {}
+				@Override
+				public void run() {
+				}
 			});
 			// The handles should all be distinct
 			assertTrue(handles.add(handle));
diff --git a/briar-tests/src/org/briarproject/lifecycle/WindowsShutdownManagerImplTest.java b/briar-tests/src/org/briarproject/bramble/lifecycle/WindowsShutdownManagerImplTest.java
similarity index 80%
rename from briar-tests/src/org/briarproject/lifecycle/WindowsShutdownManagerImplTest.java
rename to briar-tests/src/org/briarproject/bramble/lifecycle/WindowsShutdownManagerImplTest.java
index a4156c6d1b4de27bf72db0237a5f62cacfcf4247..28b72a852b77092158c950eaa64cff8d1742fcd4 100644
--- a/briar-tests/src/org/briarproject/lifecycle/WindowsShutdownManagerImplTest.java
+++ b/briar-tests/src/org/briarproject/bramble/lifecycle/WindowsShutdownManagerImplTest.java
@@ -1,41 +1,42 @@
-package org.briarproject.lifecycle;
-
-import org.briarproject.api.lifecycle.ShutdownManager;
-import org.junit.Test;
-
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-public class WindowsShutdownManagerImplTest extends ShutdownManagerImplTest {
-
-	@Override
-	protected ShutdownManager createShutdownManager() {
-		return new WindowsShutdownManagerImpl();
-	}
-
-	@Test
-	public void testManagerWaitsForHooksToRun() {
-		WindowsShutdownManagerImpl s = new WindowsShutdownManagerImpl();
-		SlowHook[] hooks = new SlowHook[10];
-		for (int i = 0; i < hooks.length; i++) {
-			hooks[i] = new SlowHook();
-			s.addShutdownHook(hooks[i]);
-		}
-		s.runShutdownHooks();
-		for (int i = 0; i < hooks.length; i++) assertTrue(hooks[i].finished);
-	}
-
-	private static class SlowHook implements Runnable {
-
-		private volatile boolean finished = false;
-
-		public void run() {
-			try {
-				Thread.sleep(100);
-				finished = true;
-			} catch (InterruptedException e) {
-				fail();
-			}
-		}
-	}
-}
+package org.briarproject.bramble.lifecycle;
+
+import org.briarproject.bramble.api.lifecycle.ShutdownManager;
+import org.junit.Test;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class WindowsShutdownManagerImplTest extends ShutdownManagerImplTest {
+
+	@Override
+	protected ShutdownManager createShutdownManager() {
+		return new WindowsShutdownManagerImpl();
+	}
+
+	@Test
+	public void testManagerWaitsForHooksToRun() {
+		WindowsShutdownManagerImpl s = new WindowsShutdownManagerImpl();
+		SlowHook[] hooks = new SlowHook[10];
+		for (int i = 0; i < hooks.length; i++) {
+			hooks[i] = new SlowHook();
+			s.addShutdownHook(hooks[i]);
+		}
+		s.runShutdownHooks();
+		for (SlowHook hook : hooks) assertTrue(hook.finished);
+	}
+
+	private static class SlowHook implements Runnable {
+
+		private volatile boolean finished = false;
+
+		@Override
+		public void run() {
+			try {
+				Thread.sleep(100);
+				finished = true;
+			} catch (InterruptedException e) {
+				fail();
+			}
+		}
+	}
+}
diff --git a/briar-tests/src/org/briarproject/plugins/BackoffImplTest.java b/briar-tests/src/org/briarproject/bramble/plugin/BackoffImplTest.java
similarity index 97%
rename from briar-tests/src/org/briarproject/plugins/BackoffImplTest.java
rename to briar-tests/src/org/briarproject/bramble/plugin/BackoffImplTest.java
index 81e48b5614df1243db9bd6a7ca0d9d8d73deec71..894dc4e480ecf369f362c3bdfd5241ad45ce86fd 100644
--- a/briar-tests/src/org/briarproject/plugins/BackoffImplTest.java
+++ b/briar-tests/src/org/briarproject/bramble/plugin/BackoffImplTest.java
@@ -1,4 +1,4 @@
-package org.briarproject.plugins;
+package org.briarproject.bramble.plugin;
 
 import org.briarproject.BriarTestCase;
 import org.junit.Test;
diff --git a/briar-tests/src/org/briarproject/plugins/ConnectionRegistryImplTest.java b/briar-tests/src/org/briarproject/bramble/plugin/ConnectionRegistryImplTest.java
similarity index 87%
rename from briar-tests/src/org/briarproject/plugins/ConnectionRegistryImplTest.java
rename to briar-tests/src/org/briarproject/bramble/plugin/ConnectionRegistryImplTest.java
index b18634e0aa7db117d6ce634cf4d0f411bb5370bd..c455cd82f6a2aede555905cf2fcc19d590b437cf 100644
--- a/briar-tests/src/org/briarproject/plugins/ConnectionRegistryImplTest.java
+++ b/briar-tests/src/org/briarproject/bramble/plugin/ConnectionRegistryImplTest.java
@@ -1,14 +1,14 @@
-package org.briarproject.plugins;
+package org.briarproject.bramble.plugin;
 
 import org.briarproject.BriarTestCase;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.event.ConnectionClosedEvent;
-import org.briarproject.api.event.ConnectionOpenedEvent;
-import org.briarproject.api.event.ContactConnectedEvent;
-import org.briarproject.api.event.ContactDisconnectedEvent;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.plugins.ConnectionRegistry;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.plugin.ConnectionRegistry;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.event.ConnectionClosedEvent;
+import org.briarproject.bramble.api.plugin.event.ConnectionOpenedEvent;
+import org.briarproject.bramble.api.plugin.event.ContactConnectedEvent;
+import org.briarproject.bramble.api.plugin.event.ContactDisconnectedEvent;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.junit.Test;
diff --git a/briar-tests/src/org/briarproject/plugins/PluginManagerImplTest.java b/briar-tests/src/org/briarproject/bramble/plugin/PluginManagerImplTest.java
similarity index 82%
rename from briar-tests/src/org/briarproject/plugins/PluginManagerImplTest.java
rename to briar-tests/src/org/briarproject/bramble/plugin/PluginManagerImplTest.java
index b8c9e4f6a2e5c470047b3c9686a678943ed66634..ad4e4b665fd2da8bf385821e6ea8914306e98ba2 100644
--- a/briar-tests/src/org/briarproject/plugins/PluginManagerImplTest.java
+++ b/briar-tests/src/org/briarproject/bramble/plugin/PluginManagerImplTest.java
@@ -1,19 +1,19 @@
-package org.briarproject.plugins;
+package org.briarproject.bramble.plugin;
 
 import org.briarproject.BriarTestCase;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.plugins.ConnectionManager;
-import org.briarproject.api.plugins.PluginConfig;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
-import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
-import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
-import org.briarproject.api.plugins.simplex.SimplexPlugin;
-import org.briarproject.api.plugins.simplex.SimplexPluginCallback;
-import org.briarproject.api.plugins.simplex.SimplexPluginFactory;
-import org.briarproject.api.properties.TransportPropertyManager;
-import org.briarproject.api.settings.SettingsManager;
-import org.briarproject.api.ui.UiCallback;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.plugin.ConnectionManager;
+import org.briarproject.bramble.api.plugin.PluginConfig;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPluginCallback;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
+import org.briarproject.bramble.api.properties.TransportPropertyManager;
+import org.briarproject.bramble.api.settings.SettingsManager;
+import org.briarproject.bramble.api.ui.UiCallback;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.jmock.lib.concurrent.Synchroniser;
diff --git a/briar-tests/src/org/briarproject/plugins/PollerTest.java b/briar-tests/src/org/briarproject/bramble/plugin/PollerTest.java
similarity index 92%
rename from briar-tests/src/org/briarproject/plugins/PollerTest.java
rename to briar-tests/src/org/briarproject/bramble/plugin/PollerTest.java
index 5531177d1b95c7e0f5ef7db678b3c0d295e611b9..3cdbcf8a67ca34248ef53a1b75c586e21a4c9215 100644
--- a/briar-tests/src/org/briarproject/plugins/PollerTest.java
+++ b/briar-tests/src/org/briarproject/bramble/plugin/PollerTest.java
@@ -1,23 +1,23 @@
-package org.briarproject.plugins;
+package org.briarproject.bramble.plugin;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.ImmediateExecutor;
 import org.briarproject.RunAction;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.event.ConnectionClosedEvent;
-import org.briarproject.api.event.ConnectionOpenedEvent;
-import org.briarproject.api.event.ContactStatusChangedEvent;
-import org.briarproject.api.event.TransportEnabledEvent;
-import org.briarproject.api.plugins.ConnectionManager;
-import org.briarproject.api.plugins.ConnectionRegistry;
-import org.briarproject.api.plugins.Plugin;
-import org.briarproject.api.plugins.PluginManager;
-import org.briarproject.api.plugins.TransportConnectionWriter;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
-import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
-import org.briarproject.api.plugins.simplex.SimplexPlugin;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.event.ContactStatusChangedEvent;
+import org.briarproject.bramble.api.plugin.ConnectionManager;
+import org.briarproject.bramble.api.plugin.ConnectionRegistry;
+import org.briarproject.bramble.api.plugin.Plugin;
+import org.briarproject.bramble.api.plugin.PluginManager;
+import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
+import org.briarproject.bramble.api.plugin.event.ConnectionClosedEvent;
+import org.briarproject.bramble.api.plugin.event.ConnectionOpenedEvent;
+import org.briarproject.bramble.api.plugin.event.TransportEnabledEvent;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
+import org.briarproject.bramble.api.system.Clock;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.jmock.lib.legacy.ClassImposteriser;
diff --git a/briar-tests/src/org/briarproject/plugins/file/LinuxRemovableDriveFinderTest.java b/briar-tests/src/org/briarproject/bramble/plugin/file/LinuxRemovableDriveFinderTest.java
similarity index 95%
rename from briar-tests/src/org/briarproject/plugins/file/LinuxRemovableDriveFinderTest.java
rename to briar-tests/src/org/briarproject/bramble/plugin/file/LinuxRemovableDriveFinderTest.java
index 6505284e7a61bedf343320321c5750ec8957d9c8..9de331d42ffefc13b96a8ba0ed5a86a70219ffc3 100644
--- a/briar-tests/src/org/briarproject/plugins/file/LinuxRemovableDriveFinderTest.java
+++ b/briar-tests/src/org/briarproject/bramble/plugin/file/LinuxRemovableDriveFinderTest.java
@@ -1,4 +1,4 @@
-package org.briarproject.plugins.file;
+package org.briarproject.bramble.plugin.file;
 
 import org.briarproject.BriarTestCase;
 import org.junit.Test;
diff --git a/briar-tests/src/org/briarproject/plugins/file/MacRemovableDriveFinderTest.java b/briar-tests/src/org/briarproject/bramble/plugin/file/MacRemovableDriveFinderTest.java
similarity index 94%
rename from briar-tests/src/org/briarproject/plugins/file/MacRemovableDriveFinderTest.java
rename to briar-tests/src/org/briarproject/bramble/plugin/file/MacRemovableDriveFinderTest.java
index 43e9910418688f944e00790420056642caedc20a..3050581d5d102a57822d5b60ed078d158d8b6c50 100644
--- a/briar-tests/src/org/briarproject/plugins/file/MacRemovableDriveFinderTest.java
+++ b/briar-tests/src/org/briarproject/bramble/plugin/file/MacRemovableDriveFinderTest.java
@@ -1,4 +1,4 @@
-package org.briarproject.plugins.file;
+package org.briarproject.bramble.plugin.file;
 
 import org.briarproject.BriarTestCase;
 import org.junit.Test;
diff --git a/briar-tests/src/org/briarproject/plugins/file/PollingRemovableDriveMonitorTest.java b/briar-tests/src/org/briarproject/bramble/plugin/file/PollingRemovableDriveMonitorTest.java
similarity index 88%
rename from briar-tests/src/org/briarproject/plugins/file/PollingRemovableDriveMonitorTest.java
rename to briar-tests/src/org/briarproject/bramble/plugin/file/PollingRemovableDriveMonitorTest.java
index 69e559525183a8aa014f566fe5632ca06ffa3fce..d2bd29cd4e52aa80677c9d1461b1bac41637153a 100644
--- a/briar-tests/src/org/briarproject/plugins/file/PollingRemovableDriveMonitorTest.java
+++ b/briar-tests/src/org/briarproject/bramble/plugin/file/PollingRemovableDriveMonitorTest.java
@@ -1,7 +1,8 @@
-package org.briarproject.plugins.file;
+package org.briarproject.bramble.plugin.file;
 
 import org.briarproject.BriarTestCase;
-import org.briarproject.plugins.file.RemovableDriveMonitor.Callback;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.plugin.file.RemovableDriveMonitor.Callback;
 import org.junit.Test;
 
 import java.io.File;
@@ -27,10 +28,12 @@ public class PollingRemovableDriveMonitorTest extends BriarTestCase {
 		// Create a finder that returns no files the first time, then two files
 		final File file1 = new File("foo");
 		final File file2 = new File("bar");
+		@NotNullByDefault
 		final RemovableDriveFinder finder = new RemovableDriveFinder() {
 
 			private AtomicBoolean firstCall = new AtomicBoolean(true);
 
+			@Override
 			public Collection<File> findRemovableDrives() throws IOException {
 				if (firstCall.getAndSet(false)) return Collections.emptyList();
 				else return Arrays.asList(file1, file2);
@@ -38,14 +41,17 @@ public class PollingRemovableDriveMonitorTest extends BriarTestCase {
 		};
 		// Create a callback that waits for two files
 		final CountDownLatch latch = new CountDownLatch(2);
-		final List<File> detected = new ArrayList<File>();
+		final List<File> detected = new ArrayList<>();
+		@NotNullByDefault
 		Callback callback = new Callback() {
 
+			@Override
 			public void driveInserted(File f) {
 				detected.add(f);
 				latch.countDown();
 			}
 
+			@Override
 			public void exceptionThrown(IOException e) {
 				fail();
 			}
@@ -70,6 +76,7 @@ public class PollingRemovableDriveMonitorTest extends BriarTestCase {
 
 			private AtomicBoolean firstCall = new AtomicBoolean(true);
 
+			@Override
 			public Collection<File> findRemovableDrives() throws IOException {
 				if (firstCall.getAndSet(false)) return Collections.emptyList();
 				else throw new IOException();
@@ -77,12 +84,15 @@ public class PollingRemovableDriveMonitorTest extends BriarTestCase {
 		};
 		// Create a callback that waits for an exception
 		final CountDownLatch latch = new CountDownLatch(1);
+		@NotNullByDefault
 		Callback callback = new Callback() {
 
+			@Override
 			public void driveInserted(File root) {
 				fail();
 			}
 
+			@Override
 			public void exceptionThrown(IOException e) {
 				latch.countDown();
 			}
diff --git a/briar-tests/src/org/briarproject/plugins/file/RemovableDrivePluginTest.java b/briar-tests/src/org/briarproject/bramble/plugin/file/RemovableDrivePluginTest.java
similarity index 94%
rename from briar-tests/src/org/briarproject/plugins/file/RemovableDrivePluginTest.java
rename to briar-tests/src/org/briarproject/bramble/plugin/file/RemovableDrivePluginTest.java
index cd6d4c2f892fb2587d700e8f70b4f51a79094972..25a2a1b16ba099d96dfcfb6fb1083a426d9abc3b 100644
--- a/briar-tests/src/org/briarproject/plugins/file/RemovableDrivePluginTest.java
+++ b/briar-tests/src/org/briarproject/bramble/plugin/file/RemovableDrivePluginTest.java
@@ -1,12 +1,12 @@
-package org.briarproject.plugins.file;
+package org.briarproject.bramble.plugin.file;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.ImmediateExecutor;
 import org.briarproject.TestUtils;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.plugins.TransportConnectionWriter;
-import org.briarproject.api.plugins.simplex.SimplexPluginCallback;
-import org.briarproject.plugins.file.RemovableDriveMonitor.Callback;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPluginCallback;
+import org.briarproject.bramble.plugin.file.RemovableDriveMonitor.Callback;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.jmock.lib.concurrent.Synchroniser;
@@ -22,7 +22,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.Executor;
 
-import static org.briarproject.api.transport.TransportConstants.MIN_STREAM_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MIN_STREAM_LENGTH;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -73,7 +73,7 @@ public class RemovableDrivePluginTest extends BriarTestCase {
 	public void testWriterIsNullIfNoDriveIsChosen() throws Exception {
 		final File drive1 = new File(testDir, "1");
 		final File drive2 = new File(testDir, "2");
-		final List<File> drives = new ArrayList<File>();
+		final List<File> drives = new ArrayList<>();
 		drives.add(drive1);
 		drives.add(drive2);
 
@@ -112,7 +112,7 @@ public class RemovableDrivePluginTest extends BriarTestCase {
 	public void testWriterIsNullIfOutputDirDoesNotExist() throws Exception {
 		final File drive1 = new File(testDir, "1");
 		final File drive2 = new File(testDir, "2");
-		final List<File> drives = new ArrayList<File>();
+		final List<File> drives = new ArrayList<>();
 		drives.add(drive1);
 		drives.add(drive2);
 
@@ -151,7 +151,7 @@ public class RemovableDrivePluginTest extends BriarTestCase {
 	public void testWriterIsNullIfOutputDirIsAFile() throws Exception {
 		final File drive1 = new File(testDir, "1");
 		final File drive2 = new File(testDir, "2");
-		final List<File> drives = new ArrayList<File>();
+		final List<File> drives = new ArrayList<>();
 		drives.add(drive1);
 		drives.add(drive2);
 		// Create drive1 as a file rather than a directory
@@ -192,7 +192,7 @@ public class RemovableDrivePluginTest extends BriarTestCase {
 	public void testWriterIsNotNullIfOutputDirIsADir() throws Exception {
 		final File drive1 = new File(testDir, "1");
 		final File drive2 = new File(testDir, "2");
-		final List<File> drives = new ArrayList<File>();
+		final List<File> drives = new ArrayList<>();
 		drives.add(drive1);
 		drives.add(drive2);
 		// Create drive1 as a directory
@@ -236,7 +236,7 @@ public class RemovableDrivePluginTest extends BriarTestCase {
 	public void testWritingToWriter() throws Exception {
 		final File drive1 = new File(testDir, "1");
 		final File drive2 = new File(testDir, "2");
-		final List<File> drives = new ArrayList<File>();
+		final List<File> drives = new ArrayList<>();
 		drives.add(drive1);
 		drives.add(drive2);
 		// Create drive1 as a directory
diff --git a/briar-tests/src/org/briarproject/plugins/file/UnixRemovableDriveMonitorTest.java b/briar-tests/src/org/briarproject/bramble/plugin/file/UnixRemovableDriveMonitorTest.java
similarity index 80%
rename from briar-tests/src/org/briarproject/plugins/file/UnixRemovableDriveMonitorTest.java
rename to briar-tests/src/org/briarproject/bramble/plugin/file/UnixRemovableDriveMonitorTest.java
index 06ac33bfc898c182805ce025de7ea1fc717e508a..6b49f7d70331a026f3533d67993edfa5dc0fb175 100644
--- a/briar-tests/src/org/briarproject/plugins/file/UnixRemovableDriveMonitorTest.java
+++ b/briar-tests/src/org/briarproject/bramble/plugin/file/UnixRemovableDriveMonitorTest.java
@@ -1,101 +1,112 @@
-package org.briarproject.plugins.file;
-
-import org.briarproject.BriarTestCase;
-import org.briarproject.TestUtils;
-import org.briarproject.plugins.file.RemovableDriveMonitor.Callback;
-import org.briarproject.util.OsUtils;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-public class UnixRemovableDriveMonitorTest extends BriarTestCase {
-
-	private final File testDir = TestUtils.getTestDirectory();
-
-	@Before
-	public void setUp() {
-		testDir.mkdirs();
-	}
-
-	@Test
-	public void testNonexistentDir() throws Exception {
-		if (!(OsUtils.isLinux() || OsUtils.isMacLeopardOrNewer())) {
-			System.err.println("WARNING: Skipping test, can't run on this OS");
-			return;
-		}
-		File doesNotExist = new File(testDir, "doesNotExist");
-		RemovableDriveMonitor monitor = createMonitor(doesNotExist);
-		monitor.start(new Callback() {
-
-			public void driveInserted(File root) {
-				fail();
-			}
-
-			public void exceptionThrown(IOException e) {
-				fail();
-			}
-		});
-		monitor.stop();
-	}
-
-	@Test
-	public void testOneCallbackPerFile() throws Exception {
-		if (!(OsUtils.isLinux() || OsUtils.isMacLeopardOrNewer())) {
-			System.err.println("WARNING: Skipping test, can't run on this OS");
-			return;
-		}
-		// Create a callback that will wait for two files before stopping
-		final List<File> detected = new ArrayList<File>();
-		final CountDownLatch latch = new CountDownLatch(2);
-		final Callback callback = new Callback() {
-
-			public void driveInserted(File f) {
-				detected.add(f);
-				latch.countDown();
-			}
-
-			public void exceptionThrown(IOException e) {
-				fail();
-			}
-		};
-		// Create the monitor and start it
-		RemovableDriveMonitor monitor = createMonitor(testDir);
-		monitor.start(callback);
-		// Create two files in the test directory
-		File file1 = new File(testDir, "1");
-		File file2 = new File(testDir, "2");
-		assertTrue(file1.createNewFile());
-		assertTrue(file2.createNewFile());
-		// Wait for the monitor to detect the files
-		assertTrue(latch.await(5, SECONDS));
-		monitor.stop();
-		// Check that both files were detected
-		assertEquals(2, detected.size());
-		assertTrue(detected.contains(file1));
-		assertTrue(detected.contains(file2));
-	}
-
-	@After
-	public void tearDown() {
-		TestUtils.deleteTestDirectory(testDir);
-	}
-
-	private RemovableDriveMonitor createMonitor(final File dir) {
-		return new UnixRemovableDriveMonitor() {
-			protected String[] getPathsToWatch() {
-				return new String[] { dir.getPath() };
-			}
-		};
-	}
-}
+package org.briarproject.bramble.plugin.file;
+
+import org.briarproject.BriarTestCase;
+import org.briarproject.TestUtils;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.plugin.file.RemovableDriveMonitor.Callback;
+import org.briarproject.bramble.util.OsUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class UnixRemovableDriveMonitorTest extends BriarTestCase {
+
+	private final File testDir = TestUtils.getTestDirectory();
+
+	@Before
+	public void setUp() {
+		testDir.mkdirs();
+	}
+
+	@Test
+	public void testNonexistentDir() throws Exception {
+		if (!(OsUtils.isLinux() || OsUtils.isMacLeopardOrNewer())) {
+			System.err.println("WARNING: Skipping test, can't run on this OS");
+			return;
+		}
+		File doesNotExist = new File(testDir, "doesNotExist");
+		RemovableDriveMonitor monitor = createMonitor(doesNotExist);
+		@NotNullByDefault
+		Callback callback = new Callback() {
+
+			@Override
+			public void driveInserted(File root) {
+				fail();
+			}
+
+			@Override
+			public void exceptionThrown(IOException e) {
+				fail();
+			}
+		};
+		monitor.start(callback);
+		monitor.stop();
+	}
+
+	@Test
+	public void testOneCallbackPerFile() throws Exception {
+		if (!(OsUtils.isLinux() || OsUtils.isMacLeopardOrNewer())) {
+			System.err.println("WARNING: Skipping test, can't run on this OS");
+			return;
+		}
+		// Create a callback that will wait for two files before stopping
+		final List<File> detected = new ArrayList<>();
+		final CountDownLatch latch = new CountDownLatch(2);
+		@NotNullByDefault
+		final Callback callback = new Callback() {
+
+			@Override
+			public void driveInserted(File f) {
+				detected.add(f);
+				latch.countDown();
+			}
+
+			@Override
+			public void exceptionThrown(IOException e) {
+				fail();
+			}
+		};
+		// Create the monitor and start it
+		RemovableDriveMonitor monitor = createMonitor(testDir);
+		monitor.start(callback);
+		// Create two files in the test directory
+		File file1 = new File(testDir, "1");
+		File file2 = new File(testDir, "2");
+		assertTrue(file1.createNewFile());
+		assertTrue(file2.createNewFile());
+		// Wait for the monitor to detect the files
+		assertTrue(latch.await(5, SECONDS));
+		monitor.stop();
+		// Check that both files were detected
+		assertEquals(2, detected.size());
+		assertTrue(detected.contains(file1));
+		assertTrue(detected.contains(file2));
+	}
+
+	@After
+	public void tearDown() {
+		TestUtils.deleteTestDirectory(testDir);
+	}
+
+	private RemovableDriveMonitor createMonitor(final File dir) {
+		@NotNullByDefault
+		RemovableDriveMonitor monitor = new UnixRemovableDriveMonitor() {
+			@Override
+			protected String[] getPathsToWatch() {
+				return new String[] {dir.getPath()};
+			}
+		};
+		return monitor;
+	}
+}
diff --git a/briar-tests/src/org/briarproject/plugins/modem/CountryCodesTest.java b/briar-tests/src/org/briarproject/bramble/plugin/modem/CountryCodesTest.java
similarity index 98%
rename from briar-tests/src/org/briarproject/plugins/modem/CountryCodesTest.java
rename to briar-tests/src/org/briarproject/bramble/plugin/modem/CountryCodesTest.java
index 235b6e8067586d9fb21a14867d349706ef62dd0a..35aea6e15ca6c966c7dd13013b4579632e7fa86d 100644
--- a/briar-tests/src/org/briarproject/plugins/modem/CountryCodesTest.java
+++ b/briar-tests/src/org/briarproject/bramble/plugin/modem/CountryCodesTest.java
@@ -1,4 +1,4 @@
-package org.briarproject.plugins.modem;
+package org.briarproject.bramble.plugin.modem;
 
 import org.briarproject.BriarTestCase;
 import org.junit.Test;
diff --git a/briar-tests/src/org/briarproject/plugins/modem/ModemPluginTest.java b/briar-tests/src/org/briarproject/bramble/plugin/modem/ModemPluginTest.java
similarity index 96%
rename from briar-tests/src/org/briarproject/plugins/modem/ModemPluginTest.java
rename to briar-tests/src/org/briarproject/bramble/plugin/modem/ModemPluginTest.java
index af9c3298367498cf36f3246b72714b30fce38619..d50a54fae95b535cb76881e6a2fa97e7851d0bea 100644
--- a/briar-tests/src/org/briarproject/plugins/modem/ModemPluginTest.java
+++ b/briar-tests/src/org/briarproject/bramble/plugin/modem/ModemPluginTest.java
@@ -1,9 +1,9 @@
-package org.briarproject.plugins.modem;
+package org.briarproject.bramble.plugin.modem;
 
 import org.briarproject.BriarTestCase;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
-import org.briarproject.api.properties.TransportProperties;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
+import org.briarproject.bramble.api.properties.TransportProperties;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.junit.Test;
diff --git a/briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java b/briar-tests/src/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java
similarity index 92%
rename from briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java
rename to briar-tests/src/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java
index 2f8e349c4caeae61580035583e058b6d761bae0a..cd8e31d647c518d0e6633aeed9c9db927d5105e4 100644
--- a/briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java
+++ b/briar-tests/src/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java
@@ -1,16 +1,17 @@
-package org.briarproject.plugins.tcp;
+package org.briarproject.bramble.plugin.tcp;
 
 import org.briarproject.BriarTestCase;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.keyagreement.KeyAgreementConnection;
-import org.briarproject.api.keyagreement.KeyAgreementListener;
-import org.briarproject.api.plugins.Backoff;
-import org.briarproject.api.plugins.duplex.DuplexPlugin;
-import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
-import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
-import org.briarproject.api.properties.TransportProperties;
-import org.briarproject.api.settings.Settings;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
+import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.plugin.Backoff;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
+import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
+import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
+import org.briarproject.bramble.api.properties.TransportProperties;
+import org.briarproject.bramble.api.settings.Settings;
 import org.junit.Test;
 
 import java.io.IOException;
@@ -31,8 +32,8 @@ import java.util.concurrent.FutureTask;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.briarproject.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
-import static org.briarproject.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_LAN;
+import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
+import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_LAN;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -285,6 +286,7 @@ public class LanTcpPluginTest extends BriarTestCase {
 		return false;
 	}
 
+	@NotNullByDefault
 	private static class Callback implements DuplexPluginCallback {
 
 		private final Map<ContactId, TransportProperties> remote =
diff --git a/briar-tests/src/org/briarproject/properties/TransportPropertyManagerImplTest.java b/briar-tests/src/org/briarproject/bramble/properties/TransportPropertyManagerImplTest.java
similarity index 84%
rename from briar-tests/src/org/briarproject/properties/TransportPropertyManagerImplTest.java
rename to briar-tests/src/org/briarproject/bramble/properties/TransportPropertyManagerImplTest.java
index c5f69eee718ced237f8fe7dcd0b68e48cd12c7b3..510b2a98e3510bc54c2917ea0b1039309d9b33e1 100644
--- a/briar-tests/src/org/briarproject/properties/TransportPropertyManagerImplTest.java
+++ b/briar-tests/src/org/briarproject/bramble/properties/TransportPropertyManagerImplTest.java
@@ -1,4 +1,4 @@
-package org.briarproject.properties;
+package org.briarproject.bramble.properties;
 
 import org.briarproject.BriarTestCase;
 import org.junit.Test;
diff --git a/briar-tests/src/org/briarproject/properties/TransportPropertyValidatorTest.java b/briar-tests/src/org/briarproject/bramble/properties/TransportPropertyValidatorTest.java
similarity index 77%
rename from briar-tests/src/org/briarproject/properties/TransportPropertyValidatorTest.java
rename to briar-tests/src/org/briarproject/bramble/properties/TransportPropertyValidatorTest.java
index a7798148c2f1caf0ce1d4c5c7548b924c438ae83..3a67bb7f87da39515259e785a4d9a12317892d3c 100644
--- a/briar-tests/src/org/briarproject/properties/TransportPropertyValidatorTest.java
+++ b/briar-tests/src/org/briarproject/bramble/properties/TransportPropertyValidatorTest.java
@@ -1,26 +1,26 @@
-package org.briarproject.properties;
+package org.briarproject.bramble.properties;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestUtils;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.system.Clock;
 import org.jmock.Mockery;
 import org.junit.Test;
 
 import java.io.IOException;
 
-import static org.briarproject.api.TransportId.MAX_TRANSPORT_ID_LENGTH;
-import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTIES_PER_TRANSPORT;
+import static org.briarproject.bramble.api.plugin.TransportId.MAX_TRANSPORT_ID_LENGTH;
+import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MAX_PROPERTIES_PER_TRANSPORT;
 import static org.junit.Assert.assertEquals;
 
 public class TransportPropertyValidatorTest extends BriarTestCase {
diff --git a/briar-tests/src/org/briarproject/sync/PacketReaderImplTest.java b/briar-tests/src/org/briarproject/bramble/sync/PacketReaderImplTest.java
similarity index 90%
rename from briar-tests/src/org/briarproject/sync/PacketReaderImplTest.java
rename to briar-tests/src/org/briarproject/bramble/sync/PacketReaderImplTest.java
index 5bfc0971a289f2f7ca72fad708736e4f7a40b758..1652208d67b3f7e4b588bef7ff855247da4de55e 100644
--- a/briar-tests/src/org/briarproject/sync/PacketReaderImplTest.java
+++ b/briar-tests/src/org/briarproject/bramble/sync/PacketReaderImplTest.java
@@ -1,20 +1,20 @@
-package org.briarproject.sync;
+package org.briarproject.bramble.sync;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestUtils;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.UniqueId;
-import org.briarproject.util.ByteUtils;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.UniqueId;
+import org.briarproject.bramble.util.ByteUtils;
 import org.junit.Test;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 
-import static org.briarproject.api.sync.PacketTypes.ACK;
-import static org.briarproject.api.sync.PacketTypes.OFFER;
-import static org.briarproject.api.sync.PacketTypes.REQUEST;
-import static org.briarproject.api.sync.SyncConstants.MAX_PACKET_PAYLOAD_LENGTH;
-import static org.briarproject.api.sync.SyncConstants.PACKET_HEADER_LENGTH;
+import static org.briarproject.bramble.api.sync.PacketTypes.ACK;
+import static org.briarproject.bramble.api.sync.PacketTypes.OFFER;
+import static org.briarproject.bramble.api.sync.PacketTypes.REQUEST;
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_PACKET_PAYLOAD_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.PACKET_HEADER_LENGTH;
 import static org.junit.Assert.assertEquals;
 
 public class PacketReaderImplTest extends BriarTestCase {
diff --git a/briar-tests/src/org/briarproject/sync/SimplexOutgoingSessionTest.java b/briar-tests/src/org/briarproject/bramble/sync/SimplexOutgoingSessionTest.java
similarity index 89%
rename from briar-tests/src/org/briarproject/sync/SimplexOutgoingSessionTest.java
rename to briar-tests/src/org/briarproject/bramble/sync/SimplexOutgoingSessionTest.java
index 36e94594671087f312d9d0c443b5fb21b651a85f..d9c58531e2a397a71717b43618dd3440d4a79043 100644
--- a/briar-tests/src/org/briarproject/sync/SimplexOutgoingSessionTest.java
+++ b/briar-tests/src/org/briarproject/bramble/sync/SimplexOutgoingSessionTest.java
@@ -1,15 +1,15 @@
-package org.briarproject.sync;
+package org.briarproject.bramble.sync;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.ImmediateExecutor;
 import org.briarproject.TestUtils;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.sync.Ack;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.sync.PacketWriter;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.event.EventBus;
+import org.briarproject.bramble.api.sync.Ack;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.PacketWriter;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.junit.Test;
@@ -18,7 +18,7 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.concurrent.Executor;
 
-import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_IDS;
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_IDS;
 
 public class SimplexOutgoingSessionTest extends BriarTestCase {
 
diff --git a/briar-tests/src/org/briarproject/sync/ValidationManagerImplTest.java b/briar-tests/src/org/briarproject/bramble/sync/ValidationManagerImplTest.java
similarity index 97%
rename from briar-tests/src/org/briarproject/sync/ValidationManagerImplTest.java
rename to briar-tests/src/org/briarproject/bramble/sync/ValidationManagerImplTest.java
index 905ba25294b0075573157924cf587ffdacfab644..a436e8977fc53729db0e1273147e19a0c999851a 100644
--- a/briar-tests/src/org/briarproject/sync/ValidationManagerImplTest.java
+++ b/briar-tests/src/org/briarproject/bramble/sync/ValidationManagerImplTest.java
@@ -1,28 +1,28 @@
-package org.briarproject.sync;
+package org.briarproject.bramble.sync;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.ImmediateExecutor;
 import org.briarproject.TestUtils;
-import org.briarproject.api.UniqueId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.db.NoSuchGroupException;
-import org.briarproject.api.db.NoSuchMessageException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.MessageAddedEvent;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.InvalidMessageException;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageContext;
-import org.briarproject.api.sync.MessageFactory;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.sync.ValidationManager.IncomingMessageHook;
-import org.briarproject.api.sync.ValidationManager.MessageValidator;
-import org.briarproject.api.sync.ValidationManager.State;
-import org.briarproject.util.ByteUtils;
+import org.briarproject.bramble.api.UniqueId;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.db.NoSuchGroupException;
+import org.briarproject.bramble.api.db.NoSuchMessageException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.InvalidMessageException;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageContext;
+import org.briarproject.bramble.api.sync.MessageFactory;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.ValidationManager.IncomingMessageHook;
+import org.briarproject.bramble.api.sync.ValidationManager.MessageValidator;
+import org.briarproject.bramble.api.sync.ValidationManager.State;
+import org.briarproject.bramble.api.sync.event.MessageAddedEvent;
+import org.briarproject.bramble.util.ByteUtils;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.junit.Test;
@@ -33,10 +33,10 @@ import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.concurrent.Executor;
 
-import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
-import static org.briarproject.api.sync.ValidationManager.State.INVALID;
-import static org.briarproject.api.sync.ValidationManager.State.PENDING;
-import static org.briarproject.api.sync.ValidationManager.State.UNKNOWN;
+import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
+import static org.briarproject.bramble.api.sync.ValidationManager.State.INVALID;
+import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
+import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
 
 public class ValidationManagerImplTest extends BriarTestCase {
 
diff --git a/briar-tests/src/org/briarproject/system/LinuxSeedProviderTest.java b/briar-tests/src/org/briarproject/bramble/system/LinuxSeedProviderTest.java
similarity index 90%
rename from briar-tests/src/org/briarproject/system/LinuxSeedProviderTest.java
rename to briar-tests/src/org/briarproject/bramble/system/LinuxSeedProviderTest.java
index 8750d531c4c5935e4fb8f2143bd9eb42cb6f588c..ad9affb9a737d3e755604ad36263109c641a93f2 100644
--- a/briar-tests/src/org/briarproject/system/LinuxSeedProviderTest.java
+++ b/briar-tests/src/org/briarproject/bramble/system/LinuxSeedProviderTest.java
@@ -1,9 +1,9 @@
-package org.briarproject.system;
+package org.briarproject.bramble.system;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestUtils;
-import org.briarproject.api.Bytes;
-import org.briarproject.util.OsUtils;
+import org.briarproject.bramble.api.Bytes;
+import org.briarproject.bramble.util.OsUtils;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -13,7 +13,7 @@ import java.io.FileOutputStream;
 import java.util.HashSet;
 import java.util.Set;
 
-import static org.briarproject.api.system.SeedProvider.SEED_BYTES;
+import static org.briarproject.bramble.api.system.SeedProvider.SEED_BYTES;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -33,7 +33,7 @@ public class LinuxSeedProviderTest extends BriarTestCase {
 			System.err.println("WARNING: Skipping test, can't run on this OS");
 			return;
 		}
-		Set<Bytes> seeds = new HashSet<Bytes>();
+		Set<Bytes> seeds = new HashSet<>();
 		LinuxSeedProvider p = new LinuxSeedProvider();
 		for (int i = 0; i < 1000; i++) {
 			byte[] seed = p.getSeed();
diff --git a/briar-tests/src/org/briarproject/transport/KeyManagerImplTest.java b/briar-tests/src/org/briarproject/bramble/transport/KeyManagerImplTest.java
similarity index 87%
rename from briar-tests/src/org/briarproject/transport/KeyManagerImplTest.java
rename to briar-tests/src/org/briarproject/bramble/transport/KeyManagerImplTest.java
index 3ac7d5f1c75499e00a6be260b13baafc0dc5d35e..d3de3b87ae438af7ce3a4973cc7a49c08a6b8185 100644
--- a/briar-tests/src/org/briarproject/transport/KeyManagerImplTest.java
+++ b/briar-tests/src/org/briarproject/bramble/transport/KeyManagerImplTest.java
@@ -1,19 +1,19 @@
-package org.briarproject.transport;
+package org.briarproject.bramble.transport;
 
 import org.briarproject.BriarTestCase;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.ContactRemovedEvent;
-import org.briarproject.api.event.ContactStatusChangedEvent;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.plugins.PluginConfig;
-import org.briarproject.api.plugins.simplex.SimplexPluginFactory;
-import org.briarproject.api.transport.StreamContext;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
+import org.briarproject.bramble.api.contact.event.ContactStatusChangedEvent;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.plugin.PluginConfig;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
+import org.briarproject.bramble.api.transport.StreamContext;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.jmock.lib.concurrent.DeterministicExecutor;
@@ -27,7 +27,7 @@ import java.util.Collections;
 import static org.briarproject.TestUtils.getRandomBytes;
 import static org.briarproject.TestUtils.getRandomId;
 import static org.briarproject.TestUtils.getSecretKey;
-import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
 import static org.junit.Assert.assertEquals;
 
 public class KeyManagerImplTest extends BriarTestCase {
diff --git a/briar-tests/src/org/briarproject/transport/ReorderingWindowTest.java b/briar-tests/src/org/briarproject/bramble/transport/ReorderingWindowTest.java
similarity index 95%
rename from briar-tests/src/org/briarproject/transport/ReorderingWindowTest.java
rename to briar-tests/src/org/briarproject/bramble/transport/ReorderingWindowTest.java
index fc30420f09d67d8bc417d25603d9995c9f731d5d..827ba97e2840e3f6a945cfd8619f164e8541b90e 100644
--- a/briar-tests/src/org/briarproject/transport/ReorderingWindowTest.java
+++ b/briar-tests/src/org/briarproject/bramble/transport/ReorderingWindowTest.java
@@ -1,14 +1,14 @@
-package org.briarproject.transport;
+package org.briarproject.bramble.transport;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestUtils;
-import org.briarproject.transport.ReorderingWindow.Change;
+import org.briarproject.bramble.transport.ReorderingWindow.Change;
 import org.junit.Test;
 
 import java.util.Arrays;
 import java.util.Collections;
 
-import static org.briarproject.api.transport.TransportConstants.REORDERING_WINDOW_SIZE;
+import static org.briarproject.bramble.api.transport.TransportConstants.REORDERING_WINDOW_SIZE;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 
diff --git a/briar-tests/src/org/briarproject/transport/StreamReaderImplTest.java b/briar-tests/src/org/briarproject/bramble/transport/StreamReaderImplTest.java
similarity index 95%
rename from briar-tests/src/org/briarproject/transport/StreamReaderImplTest.java
rename to briar-tests/src/org/briarproject/bramble/transport/StreamReaderImplTest.java
index c186400cf6c4755461045ebee086a29fc8d6c354..cd01b5779c7a2753d7d3a6943113bbb1da8f7902 100644
--- a/briar-tests/src/org/briarproject/transport/StreamReaderImplTest.java
+++ b/briar-tests/src/org/briarproject/bramble/transport/StreamReaderImplTest.java
@@ -1,12 +1,12 @@
-package org.briarproject.transport;
+package org.briarproject.bramble.transport;
 
 import org.briarproject.BriarTestCase;
-import org.briarproject.api.crypto.StreamDecrypter;
+import org.briarproject.bramble.api.crypto.StreamDecrypter;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.junit.Test;
 
-import static org.briarproject.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
 import static org.junit.Assert.assertEquals;
 
 public class StreamReaderImplTest extends BriarTestCase {
diff --git a/briar-tests/src/org/briarproject/transport/StreamReaderWriterIntegrationTest.java b/briar-tests/src/org/briarproject/bramble/transport/StreamReaderWriterIntegrationTest.java
similarity index 80%
rename from briar-tests/src/org/briarproject/transport/StreamReaderWriterIntegrationTest.java
rename to briar-tests/src/org/briarproject/bramble/transport/StreamReaderWriterIntegrationTest.java
index bf013fd2defac7db76baa66276ea6f6f51abcc1b..8292f804f3bd2113bbdcf393a78fb69d376f7228 100644
--- a/briar-tests/src/org/briarproject/transport/StreamReaderWriterIntegrationTest.java
+++ b/briar-tests/src/org/briarproject/bramble/transport/StreamReaderWriterIntegrationTest.java
@@ -1,9 +1,9 @@
-package org.briarproject.transport;
+package org.briarproject.bramble.transport;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestUtils;
-import org.briarproject.api.crypto.StreamDecrypter;
-import org.briarproject.api.crypto.StreamEncrypter;
+import org.briarproject.bramble.api.crypto.StreamDecrypter;
+import org.briarproject.bramble.api.crypto.StreamEncrypter;
 import org.junit.Test;
 
 import java.io.ByteArrayInputStream;
@@ -12,10 +12,10 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 
-import static org.briarproject.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.MAC_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.STREAM_HEADER_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAC_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 
diff --git a/briar-tests/src/org/briarproject/transport/StreamWriterImplTest.java b/briar-tests/src/org/briarproject/bramble/transport/StreamWriterImplTest.java
similarity index 96%
rename from briar-tests/src/org/briarproject/transport/StreamWriterImplTest.java
rename to briar-tests/src/org/briarproject/bramble/transport/StreamWriterImplTest.java
index 6bf6e9dff3183e3a339846139670f61f8cdf4cfa..01e9c7c0e94ee9ae0027f318c2db853b31544500 100644
--- a/briar-tests/src/org/briarproject/transport/StreamWriterImplTest.java
+++ b/briar-tests/src/org/briarproject/bramble/transport/StreamWriterImplTest.java
@@ -1,12 +1,12 @@
-package org.briarproject.transport;
+package org.briarproject.bramble.transport;
 
 import org.briarproject.BriarTestCase;
-import org.briarproject.api.crypto.StreamEncrypter;
+import org.briarproject.bramble.api.crypto.StreamEncrypter;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.junit.Test;
 
-import static org.briarproject.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
 import static org.junit.Assert.assertEquals;
 
 public class StreamWriterImplTest extends BriarTestCase {
diff --git a/briar-tests/src/org/briarproject/transport/TestStreamDecrypter.java b/briar-tests/src/org/briarproject/bramble/transport/TestStreamDecrypter.java
similarity index 69%
rename from briar-tests/src/org/briarproject/transport/TestStreamDecrypter.java
rename to briar-tests/src/org/briarproject/bramble/transport/TestStreamDecrypter.java
index 985b000a35e9d71a544da2743002ef57d9894ce6..2823539d075e7f4f7cba80474d6aac7f35d6cef4 100644
--- a/briar-tests/src/org/briarproject/transport/TestStreamDecrypter.java
+++ b/briar-tests/src/org/briarproject/bramble/transport/TestStreamDecrypter.java
@@ -1,18 +1,20 @@
-package org.briarproject.transport;
+package org.briarproject.bramble.transport;
 
-import org.briarproject.api.crypto.StreamDecrypter;
-import org.briarproject.util.ByteUtils;
+import org.briarproject.bramble.api.crypto.StreamDecrypter;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.util.ByteUtils;
 
 import java.io.EOFException;
 import java.io.IOException;
 import java.io.InputStream;
 
-import static org.briarproject.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.MAC_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.MAX_FRAME_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.STREAM_HEADER_LENGTH;
-import static org.briarproject.util.ByteUtils.INT_16_BYTES;
+import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAC_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAX_FRAME_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_LENGTH;
+import static org.briarproject.bramble.util.ByteUtils.INT_16_BYTES;
 
+@NotNullByDefault
 class TestStreamDecrypter implements StreamDecrypter {
 
 	private final InputStream in;
@@ -25,6 +27,7 @@ class TestStreamDecrypter implements StreamDecrypter {
 		frame = new byte[MAX_FRAME_LENGTH];
 	}
 
+	@Override
 	public int readFrame(byte[] payload) throws IOException {
 		if (finalFrame) return -1;
 		if (readStreamHeader) readStreamHeader();
diff --git a/briar-tests/src/org/briarproject/transport/TestStreamEncrypter.java b/briar-tests/src/org/briarproject/bramble/transport/TestStreamEncrypter.java
similarity index 64%
rename from briar-tests/src/org/briarproject/transport/TestStreamEncrypter.java
rename to briar-tests/src/org/briarproject/bramble/transport/TestStreamEncrypter.java
index 5dbf9d3eeeb3ece17e53de8ee9ea5a592df36e94..4ff790b946b0f651cdc597d47870182d5b67f64d 100644
--- a/briar-tests/src/org/briarproject/transport/TestStreamEncrypter.java
+++ b/briar-tests/src/org/briarproject/bramble/transport/TestStreamEncrypter.java
@@ -1,16 +1,18 @@
-package org.briarproject.transport;
+package org.briarproject.bramble.transport;
 
-import org.briarproject.api.crypto.StreamEncrypter;
-import org.briarproject.util.ByteUtils;
+import org.briarproject.bramble.api.crypto.StreamEncrypter;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.util.ByteUtils;
 
 import java.io.IOException;
 import java.io.OutputStream;
 
-import static org.briarproject.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.MAC_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.STREAM_HEADER_LENGTH;
-import static org.briarproject.util.ByteUtils.INT_16_BYTES;
+import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAC_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_LENGTH;
+import static org.briarproject.bramble.util.ByteUtils.INT_16_BYTES;
 
+@NotNullByDefault
 class TestStreamEncrypter implements StreamEncrypter {
 
 	private final OutputStream out;
@@ -23,6 +25,7 @@ class TestStreamEncrypter implements StreamEncrypter {
 		this.tag = tag;
 	}
 
+	@Override
 	public void writeFrame(byte[] payload, int payloadLength,
 			int paddingLength, boolean finalFrame) throws IOException {
 		if (writeTagAndHeader) writeTagAndHeader();
@@ -36,6 +39,7 @@ class TestStreamEncrypter implements StreamEncrypter {
 		out.write(new byte[MAC_LENGTH]);
 	}
 
+	@Override
 	public void flush() throws IOException {
 		if (writeTagAndHeader) writeTagAndHeader();
 		out.flush();
diff --git a/briar-tests/src/org/briarproject/transport/TransportKeyManagerImplTest.java b/briar-tests/src/org/briarproject/bramble/transport/TransportKeyManagerImplTest.java
similarity index 95%
rename from briar-tests/src/org/briarproject/transport/TransportKeyManagerImplTest.java
rename to briar-tests/src/org/briarproject/bramble/transport/TransportKeyManagerImplTest.java
index 0f039dfdac7b73d56d920fe6321ceae13df9f0ec..71e646bf98df95ee5124cefa273d78a454825d9e 100644
--- a/briar-tests/src/org/briarproject/transport/TransportKeyManagerImplTest.java
+++ b/briar-tests/src/org/briarproject/bramble/transport/TransportKeyManagerImplTest.java
@@ -1,19 +1,19 @@
-package org.briarproject.transport;
+package org.briarproject.bramble.transport;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.RunAction;
 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.db.DatabaseComponent;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.system.Clock;
-import org.briarproject.api.transport.IncomingKeys;
-import org.briarproject.api.transport.OutgoingKeys;
-import org.briarproject.api.transport.StreamContext;
-import org.briarproject.api.transport.TransportKeys;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.bramble.api.transport.IncomingKeys;
+import org.briarproject.bramble.api.transport.OutgoingKeys;
+import org.briarproject.bramble.api.transport.StreamContext;
+import org.briarproject.bramble.api.transport.TransportKeys;
 import org.hamcrest.Description;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
@@ -32,10 +32,10 @@ import java.util.concurrent.Executor;
 import java.util.concurrent.ScheduledExecutorService;
 
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static org.briarproject.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
-import static org.briarproject.api.transport.TransportConstants.REORDERING_WINDOW_SIZE;
-import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH;
-import static org.briarproject.util.ByteUtils.MAX_32_BIT_UNSIGNED;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
+import static org.briarproject.bramble.api.transport.TransportConstants.REORDERING_WINDOW_SIZE;
+import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
+import static org.briarproject.bramble.util.ByteUtils.MAX_32_BIT_UNSIGNED;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
diff --git a/briar-tests/src/org/briarproject/util/ByteUtilsTest.java b/briar-tests/src/org/briarproject/bramble/util/ByteUtilsTest.java
similarity index 96%
rename from briar-tests/src/org/briarproject/util/ByteUtilsTest.java
rename to briar-tests/src/org/briarproject/bramble/util/ByteUtilsTest.java
index 11919c5fc60fcd1d270c534b8ea5849d70260584..54eebbce128b94ed3b4339884d0b3fbc2511e110 100644
--- a/briar-tests/src/org/briarproject/util/ByteUtilsTest.java
+++ b/briar-tests/src/org/briarproject/bramble/util/ByteUtilsTest.java
@@ -1,10 +1,10 @@
-package org.briarproject.util;
+package org.briarproject.bramble.util;
 
 import org.briarproject.BriarTestCase;
 import org.junit.Test;
 
-import static org.briarproject.util.ByteUtils.MAX_16_BIT_UNSIGNED;
-import static org.briarproject.util.ByteUtils.MAX_32_BIT_UNSIGNED;
+import static org.briarproject.bramble.util.ByteUtils.MAX_16_BIT_UNSIGNED;
+import static org.briarproject.bramble.util.ByteUtils.MAX_32_BIT_UNSIGNED;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
diff --git a/briar-tests/src/org/briarproject/util/StringUtilsTest.java b/briar-tests/src/org/briarproject/bramble/util/StringUtilsTest.java
similarity index 99%
rename from briar-tests/src/org/briarproject/util/StringUtilsTest.java
rename to briar-tests/src/org/briarproject/bramble/util/StringUtilsTest.java
index 92aeaf54c7331046128a7e26f784d4a610defd21..0814db61119b9adbcc40a85781e4d5d0b361e69f 100644
--- a/briar-tests/src/org/briarproject/util/StringUtilsTest.java
+++ b/briar-tests/src/org/briarproject/bramble/util/StringUtilsTest.java
@@ -1,4 +1,4 @@
-package org.briarproject.util;
+package org.briarproject.bramble.util;
 
 import org.briarproject.BriarTestCase;
 import org.junit.Test;
diff --git a/briar-tests/src/org/briarproject/blogs/BlogManagerImplTest.java b/briar-tests/src/org/briarproject/briar/blog/BlogManagerImplTest.java
similarity index 80%
rename from briar-tests/src/org/briarproject/blogs/BlogManagerImplTest.java
rename to briar-tests/src/org/briarproject/briar/blog/BlogManagerImplTest.java
index caf349af12d500eeaa43d841307acfe3628dd74a..3430dc39909d5190b68128db60e188a983bf9668 100644
--- a/briar-tests/src/org/briarproject/blogs/BlogManagerImplTest.java
+++ b/briar-tests/src/org/briarproject/briar/blog/BlogManagerImplTest.java
@@ -1,32 +1,32 @@
-package org.briarproject.blogs;
+package org.briarproject.briar.blog;
 
 import org.briarproject.BriarTestCase;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.blogs.Blog;
-import org.briarproject.api.blogs.BlogFactory;
-import org.briarproject.api.blogs.BlogPost;
-import org.briarproject.api.blogs.BlogPostFactory;
-import org.briarproject.api.blogs.BlogPostHeader;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataParser;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.BlogPostAddedEvent;
-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.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataParser;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.blog.Blog;
+import org.briarproject.briar.api.blog.BlogFactory;
+import org.briarproject.briar.api.blog.BlogPost;
+import org.briarproject.briar.api.blog.BlogPostFactory;
+import org.briarproject.briar.api.blog.BlogPostHeader;
+import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.junit.Test;
@@ -36,19 +36,19 @@ import java.util.Collections;
 
 import static org.briarproject.TestUtils.getRandomBytes;
 import static org.briarproject.TestUtils.getRandomId;
-import static org.briarproject.api.blogs.BlogConstants.KEY_AUTHOR;
-import static org.briarproject.api.blogs.BlogConstants.KEY_AUTHOR_ID;
-import static org.briarproject.api.blogs.BlogConstants.KEY_AUTHOR_NAME;
-import static org.briarproject.api.blogs.BlogConstants.KEY_PUBLIC_KEY;
-import static org.briarproject.api.blogs.BlogConstants.KEY_READ;
-import static org.briarproject.api.blogs.BlogConstants.KEY_TIMESTAMP;
-import static org.briarproject.api.blogs.BlogConstants.KEY_TIME_RECEIVED;
-import static org.briarproject.api.blogs.BlogConstants.KEY_TYPE;
-import static org.briarproject.api.blogs.MessageType.POST;
-import static org.briarproject.api.identity.Author.Status.VERIFIED;
-import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
-import static org.briarproject.api.sync.Group.Visibility.SHARED;
-import static org.briarproject.blogs.BlogManagerImpl.CLIENT_ID;
+import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_ID;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_NAME;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_PUBLIC_KEY;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_READ;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_TIMESTAMP;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_TIME_RECEIVED;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_TYPE;
+import static org.briarproject.briar.api.blog.BlogManager.CLIENT_ID;
+import static org.briarproject.briar.api.blog.MessageType.POST;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
diff --git a/briar-tests/src/org/briarproject/blogs/BlogPostValidatorTest.java b/briar-tests/src/org/briarproject/briar/blog/BlogPostValidatorTest.java
similarity index 79%
rename from briar-tests/src/org/briarproject/blogs/BlogPostValidatorTest.java
rename to briar-tests/src/org/briarproject/briar/blog/BlogPostValidatorTest.java
index 306b082a6bf55333d6345140a161f0fa76c6a438..56c8999bd9bdf5fcee08e05acc41d0ca2c4d0b00 100644
--- a/briar-tests/src/org/briarproject/blogs/BlogPostValidatorTest.java
+++ b/briar-tests/src/org/briarproject/briar/blog/BlogPostValidatorTest.java
@@ -1,27 +1,26 @@
-package org.briarproject.blogs;
+package org.briarproject.briar.blog;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestUtils;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.blogs.Blog;
-import org.briarproject.api.blogs.BlogFactory;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupFactory;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageFactory;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.system.Clock;
-import org.briarproject.system.SystemClock;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupFactory;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageFactory;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.bramble.system.SystemClock;
+import org.briarproject.briar.api.blog.Blog;
+import org.briarproject.briar.api.blog.BlogFactory;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.junit.Test;
@@ -29,22 +28,22 @@ import org.junit.Test;
 import java.io.IOException;
 import java.security.GeneralSecurityException;
 
-import static org.briarproject.api.blogs.BlogConstants.KEY_AUTHOR;
-import static org.briarproject.api.blogs.BlogConstants.KEY_AUTHOR_ID;
-import static org.briarproject.api.blogs.BlogConstants.KEY_AUTHOR_NAME;
-import static org.briarproject.api.blogs.BlogConstants.KEY_COMMENT;
-import static org.briarproject.api.blogs.BlogConstants.KEY_ORIGINAL_MSG_ID;
-import static org.briarproject.api.blogs.BlogConstants.KEY_ORIGINAL_PARENT_MSG_ID;
-import static org.briarproject.api.blogs.BlogConstants.KEY_PARENT_MSG_ID;
-import static org.briarproject.api.blogs.BlogConstants.KEY_PUBLIC_KEY;
-import static org.briarproject.api.blogs.BlogConstants.KEY_READ;
-import static org.briarproject.api.blogs.BlogPostFactory.SIGNING_LABEL_COMMENT;
-import static org.briarproject.api.blogs.BlogPostFactory.SIGNING_LABEL_POST;
-import static org.briarproject.api.blogs.MessageType.COMMENT;
-import static org.briarproject.api.blogs.MessageType.POST;
-import static org.briarproject.api.blogs.MessageType.WRAPPED_COMMENT;
-import static org.briarproject.api.blogs.MessageType.WRAPPED_POST;
-import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_ID;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_NAME;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_COMMENT;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_MSG_ID;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_PARENT_MSG_ID;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_PARENT_MSG_ID;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_PUBLIC_KEY;
+import static org.briarproject.briar.api.blog.BlogConstants.KEY_READ;
+import static org.briarproject.briar.api.blog.BlogPostFactory.SIGNING_LABEL_COMMENT;
+import static org.briarproject.briar.api.blog.BlogPostFactory.SIGNING_LABEL_POST;
+import static org.briarproject.briar.api.blog.MessageType.COMMENT;
+import static org.briarproject.briar.api.blog.MessageType.POST;
+import static org.briarproject.briar.api.blog.MessageType.WRAPPED_COMMENT;
+import static org.briarproject.briar.api.blog.MessageType.WRAPPED_POST;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 
diff --git a/briar-tests/src/org/briarproject/clients/MessageQueueManagerImplTest.java b/briar-tests/src/org/briarproject/briar/client/MessageQueueManagerImplTest.java
similarity index 93%
rename from briar-tests/src/org/briarproject/clients/MessageQueueManagerImplTest.java
rename to briar-tests/src/org/briarproject/briar/client/MessageQueueManagerImplTest.java
index 8e750a9c68fcfd56fee96beed40959d894087fd8..2c38258e2a42e7bf6570fed19551cf27e5faa4a3 100644
--- a/briar-tests/src/org/briarproject/clients/MessageQueueManagerImplTest.java
+++ b/briar-tests/src/org/briarproject/briar/client/MessageQueueManagerImplTest.java
@@ -1,29 +1,29 @@
-package org.briarproject.clients;
+package org.briarproject.briar.client;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.CaptureArgumentAction;
 import org.briarproject.TestUtils;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageQueueManager.IncomingQueueMessageHook;
-import org.briarproject.api.clients.MessageQueueManager.QueueMessageValidator;
-import org.briarproject.api.clients.QueueMessage;
-import org.briarproject.api.clients.QueueMessageFactory;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.InvalidMessageException;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageContext;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.sync.ValidationManager;
-import org.briarproject.api.sync.ValidationManager.IncomingMessageHook;
-import org.briarproject.api.sync.ValidationManager.MessageValidator;
-import org.briarproject.util.ByteUtils;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.InvalidMessageException;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageContext;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.ValidationManager;
+import org.briarproject.bramble.api.sync.ValidationManager.IncomingMessageHook;
+import org.briarproject.bramble.api.sync.ValidationManager.MessageValidator;
+import org.briarproject.bramble.util.ByteUtils;
+import org.briarproject.briar.api.client.MessageQueueManager.IncomingQueueMessageHook;
+import org.briarproject.briar.api.client.MessageQueueManager.QueueMessageValidator;
+import org.briarproject.briar.api.client.QueueMessage;
+import org.briarproject.briar.api.client.QueueMessageFactory;
 import org.hamcrest.Description;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
@@ -33,9 +33,9 @@ import org.junit.Test;
 
 import java.util.concurrent.atomic.AtomicReference;
 
-import static org.briarproject.api.clients.MessageQueueManager.QUEUE_STATE_KEY;
-import static org.briarproject.api.clients.QueueMessage.QUEUE_MESSAGE_HEADER_LENGTH;
-import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
+import static org.briarproject.briar.api.client.MessageQueueManager.QUEUE_STATE_KEY;
+import static org.briarproject.briar.api.client.QueueMessage.QUEUE_MESSAGE_HEADER_LENGTH;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertSame;
diff --git a/briar-tests/src/org/briarproject/clients/MessageTreeTest.java b/briar-tests/src/org/briarproject/briar/client/MessageTreeImplTest.java
similarity index 66%
rename from briar-tests/src/org/briarproject/clients/MessageTreeTest.java
rename to briar-tests/src/org/briarproject/briar/client/MessageTreeImplTest.java
index e198db4719ea2dca4b4952a9ff160dce44affbcc..e35af03566c3cf9cc840bf6c89f6538d18e1d523 100644
--- a/briar-tests/src/org/briarproject/clients/MessageTreeTest.java
+++ b/briar-tests/src/org/briarproject/briar/client/MessageTreeImplTest.java
@@ -1,20 +1,19 @@
-package org.briarproject.clients;
+package org.briarproject.briar.client;
 
 import org.briarproject.TestUtils;
-import org.briarproject.api.clients.MessageTree;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.MessageTree;
 import org.junit.Test;
 
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.logging.Logger;
 
-import static org.junit.Assert.assertEquals;
+import javax.annotation.Nullable;
 
-public class MessageTreeTest {
+import static org.junit.Assert.assertEquals;
 
-	private static final Logger LOG =
-			Logger.getLogger(MessageTreeTest.class.getName());
+public class MessageTreeImplTest {
 
 	private MessageTree<TestNode> tree;
 
@@ -49,9 +48,10 @@ public class MessageTreeTest {
 		nodes[3].setTimestamp(timestamp - 2);
 		nodes[2].setTimestamp(timestamp - 1);
 		// add all nodes except the last one
-		tree.add(Arrays.asList(Arrays.copyOf(nodes, nodes.length-1)));
-		tree.add(Collections.singletonList(nodes[nodes.length-1]));
-		TestNode[] sortedNodes = tree.depthFirstOrder().toArray(new TestNode[5]);
+		tree.add(Arrays.asList(Arrays.copyOf(nodes, nodes.length - 1)));
+		tree.add(Collections.singletonList(nodes[nodes.length - 1]));
+		TestNode[] sortedNodes =
+				tree.depthFirstOrder().toArray(new TestNode[5]);
 		assertEquals(nodes[4], sortedNodes[0]);
 		assertEquals(nodes[1], sortedNodes[1]);
 		assertEquals(nodes[0], sortedNodes[2]);
@@ -59,20 +59,11 @@ public class MessageTreeTest {
 		assertEquals(nodes[3], sortedNodes[4]);
 	}
 
-	private void printNodes(TestNode[] nodes, TestNode[] sortedNodes) {
-		for (int i = 0; i < sortedNodes.length; i++) {
-			for (int j = 0; j < nodes.length; j++) {
-				if (sortedNodes[i] == nodes[j]) {
-					LOG.info("index: " + j);
-					break;
-				}
-			}
-		}
-	}
-
-	class TestNode implements MessageTree.MessageNode {
+	@NotNullByDefault
+	private class TestNode implements MessageTree.MessageNode {
 
 		private final MessageId id = new MessageId(TestUtils.getRandomId());
+		@Nullable
 		private MessageId parentId;
 		private long timestamp;
 
@@ -82,6 +73,7 @@ public class MessageTreeTest {
 		}
 
 		@Override
+		@Nullable
 		public MessageId getParentId() {
 			return parentId;
 		}
@@ -101,11 +93,11 @@ public class MessageTreeTest {
 			return timestamp;
 		}
 
-		public void setParentId(MessageId parentId) {
+		private void setParentId(MessageId parentId) {
 			this.parentId = parentId;
 		}
 
-		public void setTimestamp(long timestamp) {
+		private void setTimestamp(long timestamp) {
 			this.timestamp = timestamp;
 		}
 	}
diff --git a/briar-tests/src/org/briarproject/forum/ForumManagerImplTest.java b/briar-tests/src/org/briarproject/briar/forum/ForumManagerImplTest.java
similarity index 86%
rename from briar-tests/src/org/briarproject/forum/ForumManagerImplTest.java
rename to briar-tests/src/org/briarproject/briar/forum/ForumManagerImplTest.java
index 0e72451229636910d491aea96840cdf547e56ae4..0a4a0ac6fd89be677b770a3a7e960f32af9310d5 100644
--- a/briar-tests/src/org/briarproject/forum/ForumManagerImplTest.java
+++ b/briar-tests/src/org/briarproject/briar/forum/ForumManagerImplTest.java
@@ -1,4 +1,4 @@
-package org.briarproject.forum;
+package org.briarproject.briar.forum;
 
 import org.briarproject.BriarTestCase;
 import org.junit.Test;
diff --git a/briar-tests/src/org/briarproject/forum/ForumPostValidatorTest.java b/briar-tests/src/org/briarproject/briar/forum/ForumPostValidatorTest.java
similarity index 93%
rename from briar-tests/src/org/briarproject/forum/ForumPostValidatorTest.java
rename to briar-tests/src/org/briarproject/briar/forum/ForumPostValidatorTest.java
index 52fcd5d721ff0a81d4b34e9a5fb762cff4617fb4..4eacdc503360ae59ad146f36a5dcd29a025aff48 100644
--- a/briar-tests/src/org/briarproject/forum/ForumPostValidatorTest.java
+++ b/briar-tests/src/org/briarproject/briar/forum/ForumPostValidatorTest.java
@@ -1,27 +1,27 @@
-package org.briarproject.forum;
+package org.briarproject.briar.forum;
 
 import org.briarproject.TestUtils;
 import org.briarproject.ValidatorTestCase;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.UniqueId;
-import org.briarproject.api.clients.BdfMessageContext;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.sync.InvalidMessageException;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.UniqueId;
+import org.briarproject.bramble.api.client.BdfMessageContext;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.sync.InvalidMessageException;
+import org.briarproject.bramble.api.sync.MessageId;
 import org.jmock.Expectations;
 import org.junit.Test;
 
 import java.security.GeneralSecurityException;
 import java.util.Collection;
 
-import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
-import static org.briarproject.api.forum.ForumPostFactory.SIGNING_LABEL_POST;
-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.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
+import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
+import static org.briarproject.briar.api.forum.ForumPostFactory.SIGNING_LABEL_POST;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
diff --git a/briar-tests/src/org/briarproject/introduction/IntroduceeManagerTest.java b/briar-tests/src/org/briarproject/briar/introduction/IntroduceeManagerTest.java
similarity index 72%
rename from briar-tests/src/org/briarproject/introduction/IntroduceeManagerTest.java
rename to briar-tests/src/org/briarproject/briar/introduction/IntroduceeManagerTest.java
index c33b308c665e0f5e9156f5277eb893607d15b300..c0de31ef2deb531118380d570a5eb5c34ece7808 100644
--- a/briar-tests/src/org/briarproject/introduction/IntroduceeManagerTest.java
+++ b/briar-tests/src/org/briarproject/briar/introduction/IntroduceeManagerTest.java
@@ -1,34 +1,34 @@
-package org.briarproject.introduction;
+package org.briarproject.briar.introduction;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestUtils;
-import org.briarproject.api.Bytes;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.SessionId;
-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.crypto.SecretKey;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.introduction.IntroduceeProtocolState;
-import org.briarproject.api.properties.TransportPropertyManager;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.Bytes;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.properties.TransportPropertyManager;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.introduction.IntroduceeProtocolState;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.jmock.lib.legacy.ClassImposteriser;
@@ -37,44 +37,44 @@ import org.junit.Test;
 import java.security.GeneralSecurityException;
 import java.security.SecureRandom;
 
-import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
-import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
-import static org.briarproject.api.introduction.IntroduceeProtocolState.AWAIT_REQUEST;
-import static org.briarproject.api.introduction.IntroductionConstants.ACCEPT;
-import static org.briarproject.api.introduction.IntroductionConstants.ADDED_CONTACT_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.ANSWERED;
-import static org.briarproject.api.introduction.IntroductionConstants.CONTACT;
-import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_ID_1;
-import static org.briarproject.api.introduction.IntroductionConstants.EXISTS;
-import static org.briarproject.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
-import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.INTRODUCER;
-import static org.briarproject.api.introduction.IntroductionConstants.LOCAL_AUTHOR_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.MAC;
-import static org.briarproject.api.introduction.IntroductionConstants.MAC_KEY;
-import static org.briarproject.api.introduction.IntroductionConstants.MAC_LENGTH;
-import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TIME;
-import static org.briarproject.api.introduction.IntroductionConstants.NAME;
-import static org.briarproject.api.introduction.IntroductionConstants.NONCE;
-import static org.briarproject.api.introduction.IntroductionConstants.NOT_OUR_RESPONSE;
-import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY;
-import static org.briarproject.api.introduction.IntroductionConstants.REMOTE_AUTHOR_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.REMOTE_AUTHOR_IS_US;
-import static org.briarproject.api.introduction.IntroductionConstants.ROLE;
-import static org.briarproject.api.introduction.IntroductionConstants.ROLE_INTRODUCEE;
-import static org.briarproject.api.introduction.IntroductionConstants.SESSION_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.SIGNATURE;
-import static org.briarproject.api.introduction.IntroductionConstants.STATE;
-import static org.briarproject.api.introduction.IntroductionConstants.STORAGE_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.TIME;
-import static org.briarproject.api.introduction.IntroductionConstants.TRANSPORT;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
-import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
-import static org.briarproject.introduction.IntroduceeManager.SIGNING_LABEL_RESPONSE;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
+import static org.briarproject.briar.api.introduction.IntroduceeProtocolState.AWAIT_REQUEST;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ACCEPT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ADDED_CONTACT_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ANSWERED;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.CONTACT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.CONTACT_ID_1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.EXISTS;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.INTRODUCER;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.LOCAL_AUTHOR_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MAC;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MAC_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MAC_LENGTH;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MESSAGE_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MESSAGE_TIME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.NAME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.NONCE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.NOT_OUR_RESPONSE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.PUBLIC_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.REMOTE_AUTHOR_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.REMOTE_AUTHOR_IS_US;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ROLE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ROLE_INTRODUCEE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.SESSION_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.SIGNATURE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.STATE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.STORAGE_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TIME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TRANSPORT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_ACK;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_REQUEST;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_RESPONSE;
+import static org.briarproject.briar.introduction.IntroduceeManager.SIGNING_LABEL_RESPONSE;
 import static org.hamcrest.Matchers.array;
 import static org.hamcrest.Matchers.samePropertyValuesAs;
 import static org.junit.Assert.assertFalse;
diff --git a/briar-tests/src/org/briarproject/introduction/IntroducerManagerTest.java b/briar-tests/src/org/briarproject/briar/introduction/IntroducerManagerTest.java
similarity index 60%
rename from briar-tests/src/org/briarproject/introduction/IntroducerManagerTest.java
rename to briar-tests/src/org/briarproject/briar/introduction/IntroducerManagerTest.java
index cf8640edab6989a49f8d5f89461c2afe4692186e..09c0474d9135257aa485f77edc225f952107d7fa 100644
--- a/briar-tests/src/org/briarproject/introduction/IntroducerManagerTest.java
+++ b/briar-tests/src/org/briarproject/briar/introduction/IntroducerManagerTest.java
@@ -1,25 +1,25 @@
-package org.briarproject.introduction;
+package org.briarproject.briar.introduction;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestUtils;
-import org.briarproject.api.Bytes;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.Bytes;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.system.Clock;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.jmock.lib.legacy.ClassImposteriser;
@@ -27,44 +27,44 @@ import org.junit.Test;
 
 import java.security.SecureRandom;
 
-import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
-import static org.briarproject.api.introduction.IntroducerProtocolState.AWAIT_RESPONSES;
-import static org.briarproject.api.introduction.IntroducerProtocolState.PREPARE_REQUESTS;
-import static org.briarproject.api.introduction.IntroductionConstants.AUTHOR_ID_1;
-import static org.briarproject.api.introduction.IntroductionConstants.AUTHOR_ID_2;
-import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_1;
-import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_2;
-import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_ID_1;
-import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_ID_2;
-import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID_1;
-import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID_2;
-import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TIME;
-import static org.briarproject.api.introduction.IntroductionConstants.NAME;
-import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY;
-import static org.briarproject.api.introduction.IntroductionConstants.ROLE;
-import static org.briarproject.api.introduction.IntroductionConstants.ROLE_INTRODUCER;
-import static org.briarproject.api.introduction.IntroductionConstants.SESSION_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.STATE;
-import static org.briarproject.api.introduction.IntroductionConstants.STORAGE_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.briar.api.introduction.IntroducerProtocolState.AWAIT_RESPONSES;
+import static org.briarproject.briar.api.introduction.IntroducerProtocolState.PREPARE_REQUESTS;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.AUTHOR_ID_1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.AUTHOR_ID_2;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.CONTACT_1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.CONTACT_2;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.CONTACT_ID_1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.CONTACT_ID_2;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID_1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID_2;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MESSAGE_TIME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.NAME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.PUBLIC_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ROLE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ROLE_INTRODUCER;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.SESSION_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.STATE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.STORAGE_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_REQUEST;
 import static org.junit.Assert.assertFalse;
 
 public class IntroducerManagerTest extends BriarTestCase {
 
-	final Mockery context;
-	final IntroducerManager introducerManager;
-	final CryptoComponent cryptoComponent;
-	final ClientHelper clientHelper;
-	final IntroductionGroupFactory introductionGroupFactory;
-	final MessageSender messageSender;
-	final Clock clock;
-	final Contact introducee1;
-	final Contact introducee2;
-	final Group localGroup0;
-	final Group introductionGroup1;
-	final Group introductionGroup2;
+	private final Mockery context;
+	private final IntroducerManager introducerManager;
+	private final CryptoComponent cryptoComponent;
+	private final ClientHelper clientHelper;
+	private final IntroductionGroupFactory introductionGroupFactory;
+	private final MessageSender messageSender;
+	private final Clock clock;
+	private final Contact introducee1;
+	private final Contact introducee2;
+	private final Group localGroup0;
+	private final Group introductionGroup1;
+	private final Group introductionGroup2;
 
 	public IntroducerManagerTest() {
 		context = new Mockery();
diff --git a/briar-tests/src/org/briarproject/introduction/IntroductionManagerImplTest.java b/briar-tests/src/org/briarproject/briar/introduction/IntroductionManagerImplTest.java
similarity index 78%
rename from briar-tests/src/org/briarproject/introduction/IntroductionManagerImplTest.java
rename to briar-tests/src/org/briarproject/briar/introduction/IntroductionManagerImplTest.java
index 463d4a8671a1a29efb2d282bc3cab5c6ecab4936..6d9841e2c780f26fd75f336bb32c4a9485da9cb3 100644
--- a/briar-tests/src/org/briarproject/introduction/IntroductionManagerImplTest.java
+++ b/briar-tests/src/org/briarproject/briar/introduction/IntroductionManagerImplTest.java
@@ -1,28 +1,28 @@
-package org.briarproject.introduction;
+package org.briarproject.briar.introduction;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestUtils;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageTracker;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataParser;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.sync.MessageStatus;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataParser;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.sync.MessageStatus;
+import org.briarproject.briar.api.client.MessageTracker;
+import org.briarproject.briar.api.client.SessionId;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.jmock.lib.legacy.ClassImposteriser;
@@ -32,16 +32,16 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Map;
 
-import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
-import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID_1;
-import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID_2;
-import static org.briarproject.api.introduction.IntroductionConstants.ROLE;
-import static org.briarproject.api.introduction.IntroductionConstants.ROLE_INTRODUCER;
-import static org.briarproject.api.introduction.IntroductionConstants.SESSION_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
-import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID_1;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID_2;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ROLE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ROLE_INTRODUCER;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.SESSION_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_REQUEST;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_RESPONSE;
 import static org.junit.Assert.assertFalse;
 
 public class IntroductionManagerImplTest extends BriarTestCase {
@@ -55,6 +55,7 @@ public class IntroductionManagerImplTest extends BriarTestCase {
 	private final MessageTracker messageTracker;
 	private final IntroductionGroupFactory introductionGroupFactory;
 	private final SessionId sessionId = new SessionId(TestUtils.getRandomId());
+	private final MessageId storageId = new MessageId(sessionId.getBytes());
 	private final long time = 42L;
 	private final Contact introducee1;
 	private final Contact introducee2;
@@ -157,7 +158,7 @@ public class IntroductionManagerImplTest extends BriarTestCase {
 			will(returnValue(introducee1));
 			oneOf(introductionGroupFactory).createIntroductionGroup(introducee1);
 			will(returnValue(introductionGroup1));
-			oneOf(clientHelper).getMessageMetadataAsDictionary(txn, sessionId);
+			oneOf(clientHelper).getMessageMetadataAsDictionary(txn, storageId);
 			will(returnValue(state));
 			oneOf(introduceeManager).acceptIntroduction(txn, state, time);
 			// track message
@@ -188,7 +189,7 @@ public class IntroductionManagerImplTest extends BriarTestCase {
 			will(returnValue(introducee1));
 			oneOf(introductionGroupFactory).createIntroductionGroup(introducee1);
 			will(returnValue(introductionGroup1));
-			oneOf(clientHelper).getMessageMetadataAsDictionary(txn, sessionId);
+			oneOf(clientHelper).getMessageMetadataAsDictionary(txn, storageId);
 			will(returnValue(state));
 			oneOf(introduceeManager).declineIntroduction(txn, state, time);
 			// track message
@@ -278,7 +279,7 @@ public class IntroductionManagerImplTest extends BriarTestCase {
 		txn = new Transaction(null, false);
 
 		context.checking(new Expectations() {{
-			oneOf(clientHelper).getMessageMetadataAsDictionary(txn, sessionId);
+			oneOf(clientHelper).getMessageMetadataAsDictionary(txn, storageId);
 			will(returnValue(state));
 			oneOf(introducerManager).incomingMessage(txn, state, msg);
 			// track message
diff --git a/briar-tests/src/org/briarproject/introduction/IntroductionValidatorTest.java b/briar-tests/src/org/briarproject/briar/introduction/IntroductionValidatorTest.java
similarity index 79%
rename from briar-tests/src/org/briarproject/introduction/IntroductionValidatorTest.java
rename to briar-tests/src/org/briarproject/briar/introduction/IntroductionValidatorTest.java
index 3c1be62abf21d0b5788901ef44b18821178e3819..5678cc61c452cd57c2729fd9a79cb8c1da25e6a9 100644
--- a/briar-tests/src/org/briarproject/introduction/IntroductionValidatorTest.java
+++ b/briar-tests/src/org/briarproject/briar/introduction/IntroductionValidatorTest.java
@@ -1,50 +1,50 @@
-package org.briarproject.introduction;
+package org.briarproject.briar.introduction;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestUtils;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.system.Clock;
-import org.briarproject.system.SystemClock;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.bramble.system.SystemClock;
+import org.briarproject.briar.api.client.SessionId;
 import org.jmock.Mockery;
 import org.junit.Test;
 
 import java.io.IOException;
 
-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.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
-import static org.briarproject.api.introduction.IntroductionConstants.ACCEPT;
-import static org.briarproject.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
-import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.MAC;
-import static org.briarproject.api.introduction.IntroductionConstants.MAC_LENGTH;
-import static org.briarproject.api.introduction.IntroductionConstants.MAX_INTRODUCTION_MESSAGE_LENGTH;
-import static org.briarproject.api.introduction.IntroductionConstants.MSG;
-import static org.briarproject.api.introduction.IntroductionConstants.NAME;
-import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY;
-import static org.briarproject.api.introduction.IntroductionConstants.SESSION_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.SIGNATURE;
-import static org.briarproject.api.introduction.IntroductionConstants.TIME;
-import static org.briarproject.api.introduction.IntroductionConstants.TRANSPORT;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ABORT;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
-import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
-import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
+import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
+import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.ACCEPT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MAC;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MAC_LENGTH;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MAX_INTRODUCTION_MESSAGE_LENGTH;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MSG;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.NAME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.PUBLIC_KEY;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.SESSION_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.SIGNATURE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TIME;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TRANSPORT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_ABORT;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_ACK;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_REQUEST;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_RESPONSE;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
diff --git a/briar-tests/src/org/briarproject/introduction/MessageSenderTest.java b/briar-tests/src/org/briarproject/briar/introduction/MessageSenderTest.java
similarity index 59%
rename from briar-tests/src/org/briarproject/introduction/MessageSenderTest.java
rename to briar-tests/src/org/briarproject/briar/introduction/MessageSenderTest.java
index 56415f41c99a5dd6c86d9027f4c189d938b72144..5c43548c43e5657a368398da830460d0eb592b8e 100644
--- a/briar-tests/src/org/briarproject/introduction/MessageSenderTest.java
+++ b/briar-tests/src/org/briarproject/briar/introduction/MessageSenderTest.java
@@ -1,34 +1,34 @@
-package org.briarproject.introduction;
+package org.briarproject.briar.introduction;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestUtils;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageQueueManager;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.system.Clock;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataEncoder;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.sync.ClientId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.client.MessageQueueManager;
+import org.briarproject.briar.api.client.SessionId;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.junit.Test;
 
-import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
-import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.MAC;
-import static org.briarproject.api.introduction.IntroductionConstants.SESSION_ID;
-import static org.briarproject.api.introduction.IntroductionConstants.SIGNATURE;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
-import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.MAC;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.SESSION_ID;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.SIGNATURE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE;
+import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_ACK;
 import static org.junit.Assert.assertFalse;
 
 public class MessageSenderTest extends BriarTestCase {
@@ -51,9 +51,8 @@ public class MessageSenderTest extends BriarTestCase {
 				context.mock(MessageQueueManager.class);
 		clock = context.mock(Clock.class);
 
-		messageSender =
-				new MessageSender(db, clientHelper, clock, metadataEncoder,
-						messageQueueManager);
+		messageSender = new MessageSender(db, clientHelper, clock,
+				metadataEncoder, messageQueueManager);
 	}
 
 	@Test
diff --git a/briar-tests/src/org/briarproject/messaging/MessagingManagerImplTest.java b/briar-tests/src/org/briarproject/briar/messaging/MessagingManagerImplTest.java
similarity index 85%
rename from briar-tests/src/org/briarproject/messaging/MessagingManagerImplTest.java
rename to briar-tests/src/org/briarproject/briar/messaging/MessagingManagerImplTest.java
index 9e9227806157ff5d9425367fb43f174c011f0bd4..f6ac2bf66e4d1447750f4ed19dc98ae00b0d6284 100644
--- a/briar-tests/src/org/briarproject/messaging/MessagingManagerImplTest.java
+++ b/briar-tests/src/org/briarproject/briar/messaging/MessagingManagerImplTest.java
@@ -1,4 +1,4 @@
-package org.briarproject.messaging;
+package org.briarproject.briar.messaging;
 
 import org.briarproject.BriarTestCase;
 import org.junit.Test;
diff --git a/briar-tests/src/org/briarproject/messaging/PrivateMessageValidatorTest.java b/briar-tests/src/org/briarproject/briar/messaging/PrivateMessageValidatorTest.java
similarity index 86%
rename from briar-tests/src/org/briarproject/messaging/PrivateMessageValidatorTest.java
rename to briar-tests/src/org/briarproject/briar/messaging/PrivateMessageValidatorTest.java
index 3d5fad97a6c95ea9335f8b67ebcaf116fd0104d4..88b9fcf201a93766d1c5f08ed2b73f3f094e3886 100644
--- a/briar-tests/src/org/briarproject/messaging/PrivateMessageValidatorTest.java
+++ b/briar-tests/src/org/briarproject/briar/messaging/PrivateMessageValidatorTest.java
@@ -1,15 +1,15 @@
-package org.briarproject.messaging;
+package org.briarproject.briar.messaging;
 
 import org.briarproject.TestUtils;
 import org.briarproject.ValidatorTestCase;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.BdfMessageContext;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.BdfMessageContext;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
 import org.junit.Test;
 
-import static org.briarproject.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
-import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
+import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
+import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 
diff --git a/briar-tests/src/org/briarproject/privategroup/GroupMessageValidatorTest.java b/briar-tests/src/org/briarproject/briar/privategroup/GroupMessageValidatorTest.java
similarity index 90%
rename from briar-tests/src/org/briarproject/privategroup/GroupMessageValidatorTest.java
rename to briar-tests/src/org/briarproject/briar/privategroup/GroupMessageValidatorTest.java
index cff74d31d34d043860c821705e297114a06cb253..88650c06f2a3668fb32665f0c9dd8077db1ab4cc 100644
--- a/briar-tests/src/org/briarproject/privategroup/GroupMessageValidatorTest.java
+++ b/briar-tests/src/org/briarproject/briar/privategroup/GroupMessageValidatorTest.java
@@ -1,18 +1,18 @@
-package org.briarproject.privategroup;
+package org.briarproject.briar.privategroup;
 
 import org.briarproject.ValidatorTestCase;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.BdfMessageContext;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.privategroup.MessageType;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.privategroup.PrivateGroupFactory;
-import org.briarproject.api.privategroup.invitation.GroupInvitationFactory;
-import org.briarproject.api.sync.InvalidMessageException;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.BdfMessageContext;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.sync.InvalidMessageException;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.privategroup.MessageType;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory;
 import org.jmock.Expectations;
 import org.junit.Test;
 
@@ -24,26 +24,26 @@ import java.util.Collections;
 import static org.briarproject.TestUtils.getRandomBytes;
 import static org.briarproject.TestUtils.getRandomId;
 import static org.briarproject.TestUtils.getRandomString;
-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.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
-import static org.briarproject.api.privategroup.GroupMessageFactory.SIGNING_LABEL_JOIN;
-import static org.briarproject.api.privategroup.GroupMessageFactory.SIGNING_LABEL_POST;
-import static org.briarproject.api.privategroup.MessageType.JOIN;
-import static org.briarproject.api.privategroup.MessageType.POST;
-import static org.briarproject.api.privategroup.PrivateGroupConstants.GROUP_SALT_LENGTH;
-import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH;
-import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH;
-import static org.briarproject.api.privategroup.invitation.GroupInvitationFactory.SIGNING_LABEL_INVITE;
-import static org.briarproject.privategroup.GroupConstants.KEY_INITIAL_JOIN_MSG;
-import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_ID;
-import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_NAME;
-import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_PUBLIC_KEY;
-import static org.briarproject.privategroup.GroupConstants.KEY_PARENT_MSG_ID;
-import static org.briarproject.privategroup.GroupConstants.KEY_PREVIOUS_MSG_ID;
-import static org.briarproject.privategroup.GroupConstants.KEY_READ;
-import static org.briarproject.privategroup.GroupConstants.KEY_TIMESTAMP;
-import static org.briarproject.privategroup.GroupConstants.KEY_TYPE;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
+import static org.briarproject.briar.api.privategroup.GroupMessageFactory.SIGNING_LABEL_JOIN;
+import static org.briarproject.briar.api.privategroup.GroupMessageFactory.SIGNING_LABEL_POST;
+import static org.briarproject.briar.api.privategroup.MessageType.JOIN;
+import static org.briarproject.briar.api.privategroup.MessageType.POST;
+import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.GROUP_SALT_LENGTH;
+import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH;
+import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH;
+import static org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory.SIGNING_LABEL_INVITE;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_INITIAL_JOIN_MSG;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_MEMBER_ID;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_MEMBER_NAME;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_MEMBER_PUBLIC_KEY;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_PARENT_MSG_ID;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_PREVIOUS_MSG_ID;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_READ;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_TIMESTAMP;
+import static org.briarproject.briar.privategroup.GroupConstants.KEY_TYPE;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
diff --git a/briar-tests/src/org/briarproject/privategroup/invitation/GroupInvitationManagerImplTest.java b/briar-tests/src/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java
similarity index 92%
rename from briar-tests/src/org/briarproject/privategroup/invitation/GroupInvitationManagerImplTest.java
rename to briar-tests/src/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java
index 8cd1b54b7569fb2dc996d448e1cb3202046148ce..c1557b9404714a4d66eb8ba1e7a17aa7ad43ef14 100644
--- a/briar-tests/src/org/briarproject/privategroup/invitation/GroupInvitationManagerImplTest.java
+++ b/briar-tests/src/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java
@@ -1,36 +1,35 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
 import org.briarproject.BriarMockTestCase;
 import org.briarproject.TestUtils;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.ContactGroupFactory;
-import org.briarproject.api.clients.MessageTracker;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataParser;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.privategroup.PrivateGroupFactory;
-import org.briarproject.api.privategroup.PrivateGroupManager;
-import org.briarproject.api.privategroup.invitation.GroupInvitationItem;
-import org.briarproject.api.privategroup.invitation.GroupInvitationRequest;
-import org.briarproject.api.privategroup.invitation.GroupInvitationResponse;
-import org.briarproject.api.sharing.InvitationMessage;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.jetbrains.annotations.Nullable;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.client.ContactGroupFactory;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.data.MetadataParser;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Metadata;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.Message;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.client.MessageTracker;
+import org.briarproject.briar.api.client.SessionId;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
+import org.briarproject.briar.api.privategroup.PrivateGroupManager;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationItem;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest;
+import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse;
+import org.briarproject.briar.api.sharing.InvitationMessage;
 import org.jmock.AbstractExpectations;
 import org.jmock.Expectations;
 import org.jmock.lib.legacy.ClassImposteriser;
@@ -42,20 +41,22 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
+import javax.annotation.Nullable;
+
 import static junit.framework.TestCase.fail;
 import static org.briarproject.TestUtils.getRandomBytes;
 import static org.briarproject.TestUtils.getRandomId;
 import static org.briarproject.TestUtils.getRandomString;
-import static org.briarproject.api.privategroup.PrivateGroupConstants.GROUP_SALT_LENGTH;
-import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH;
-import static org.briarproject.api.privategroup.invitation.GroupInvitationManager.CLIENT_ID;
-import static org.briarproject.api.sync.Group.Visibility.SHARED;
-import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
-import static org.briarproject.privategroup.invitation.GroupInvitationConstants.GROUP_KEY_CONTACT_ID;
-import static org.briarproject.privategroup.invitation.MessageType.ABORT;
-import static org.briarproject.privategroup.invitation.MessageType.INVITE;
-import static org.briarproject.privategroup.invitation.MessageType.JOIN;
-import static org.briarproject.privategroup.invitation.MessageType.LEAVE;
+import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
+import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
+import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.GROUP_SALT_LENGTH;
+import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH;
+import static org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager.CLIENT_ID;
+import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.GROUP_KEY_CONTACT_ID;
+import static org.briarproject.briar.privategroup.invitation.MessageType.ABORT;
+import static org.briarproject.briar.privategroup.invitation.MessageType.INVITE;
+import static org.briarproject.briar.privategroup.invitation.MessageType.JOIN;
+import static org.briarproject.briar.privategroup.invitation.MessageType.LEAVE;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
diff --git a/briar-tests/src/org/briarproject/privategroup/invitation/GroupInvitationValidatorTest.java b/briar-tests/src/org/briarproject/briar/privategroup/invitation/GroupInvitationValidatorTest.java
similarity index 92%
rename from briar-tests/src/org/briarproject/privategroup/invitation/GroupInvitationValidatorTest.java
rename to briar-tests/src/org/briarproject/briar/privategroup/invitation/GroupInvitationValidatorTest.java
index 76ed641b4219ef855da1143afc41eb669f9af59e..b230be881f424809c0dba72d9bc6d620e529f51e 100644
--- a/briar-tests/src/org/briarproject/privategroup/invitation/GroupInvitationValidatorTest.java
+++ b/briar-tests/src/org/briarproject/briar/privategroup/invitation/GroupInvitationValidatorTest.java
@@ -1,18 +1,18 @@
-package org.briarproject.privategroup.invitation;
+package org.briarproject.briar.privategroup.invitation;
 
 import org.briarproject.ValidatorTestCase;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.UniqueId;
-import org.briarproject.api.clients.BdfMessageContext;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.privategroup.PrivateGroupFactory;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.UniqueId;
+import org.briarproject.bramble.api.client.BdfMessageContext;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.briar.api.privategroup.PrivateGroup;
+import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
 import org.jmock.Expectations;
 import org.junit.Test;
 
@@ -21,17 +21,17 @@ import java.security.GeneralSecurityException;
 import static org.briarproject.TestUtils.getRandomBytes;
 import static org.briarproject.TestUtils.getRandomId;
 import static org.briarproject.TestUtils.getRandomString;
-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.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
-import static org.briarproject.api.privategroup.PrivateGroupConstants.GROUP_SALT_LENGTH;
-import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_INVITATION_MSG_LENGTH;
-import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH;
-import static org.briarproject.api.privategroup.invitation.GroupInvitationFactory.SIGNING_LABEL_INVITE;
-import static org.briarproject.privategroup.invitation.MessageType.ABORT;
-import static org.briarproject.privategroup.invitation.MessageType.INVITE;
-import static org.briarproject.privategroup.invitation.MessageType.JOIN;
-import static org.briarproject.privategroup.invitation.MessageType.LEAVE;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
+import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.GROUP_SALT_LENGTH;
+import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_INVITATION_MSG_LENGTH;
+import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH;
+import static org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory.SIGNING_LABEL_INVITE;
+import static org.briarproject.briar.privategroup.invitation.MessageType.ABORT;
+import static org.briarproject.briar.privategroup.invitation.MessageType.INVITE;
+import static org.briarproject.briar.privategroup.invitation.MessageType.JOIN;
+import static org.briarproject.briar.privategroup.invitation.MessageType.LEAVE;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
diff --git a/briar-tests/src/org/briarproject/sharing/ForumSharingValidatorTest.java b/briar-tests/src/org/briarproject/briar/sharing/ForumSharingValidatorTest.java
similarity index 88%
rename from briar-tests/src/org/briarproject/sharing/ForumSharingValidatorTest.java
rename to briar-tests/src/org/briarproject/briar/sharing/ForumSharingValidatorTest.java
index 7d3c6e22b25012af428b554a5c7018419643e53c..7c8423e2adda0e7da0083eef24424d3d7cf086c4 100644
--- a/briar-tests/src/org/briarproject/sharing/ForumSharingValidatorTest.java
+++ b/briar-tests/src/org/briarproject/briar/sharing/ForumSharingValidatorTest.java
@@ -1,32 +1,32 @@
-package org.briarproject.sharing;
+package org.briarproject.briar.sharing;
 
 import org.briarproject.TestUtils;
 import org.briarproject.ValidatorTestCase;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.UniqueId;
-import org.briarproject.api.clients.BdfMessageContext;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.UniqueId;
+import org.briarproject.bramble.api.client.BdfMessageContext;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfList;
+import org.briarproject.briar.api.client.SessionId;
 import org.junit.Test;
 
 import javax.annotation.Nullable;
 
-import static org.briarproject.api.forum.ForumConstants.FORUM_NAME;
-import static org.briarproject.api.forum.ForumConstants.FORUM_SALT;
-import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH;
-import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
-import static org.briarproject.api.sharing.SharingConstants.INVITATION_MSG;
-import static org.briarproject.api.sharing.SharingConstants.LOCAL;
-import static org.briarproject.api.sharing.SharingConstants.MAX_INVITATION_MESSAGE_LENGTH;
-import static org.briarproject.api.sharing.SharingConstants.SESSION_ID;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ACCEPT;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_DECLINE;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION;
-import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE;
-import static org.briarproject.api.sharing.SharingConstants.TIME;
-import static org.briarproject.api.sharing.SharingConstants.TYPE;
+import static org.briarproject.briar.api.forum.ForumConstants.FORUM_NAME;
+import static org.briarproject.briar.api.forum.ForumConstants.FORUM_SALT;
+import static org.briarproject.briar.api.forum.ForumConstants.FORUM_SALT_LENGTH;
+import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
+import static org.briarproject.briar.api.sharing.SharingConstants.INVITATION_MSG;
+import static org.briarproject.briar.api.sharing.SharingConstants.LOCAL;
+import static org.briarproject.briar.api.sharing.SharingConstants.MAX_INVITATION_MESSAGE_LENGTH;
+import static org.briarproject.briar.api.sharing.SharingConstants.SESSION_ID;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_ACCEPT;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_DECLINE;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION;
+import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE;
+import static org.briarproject.briar.api.sharing.SharingConstants.TIME;
+import static org.briarproject.briar.api.sharing.SharingConstants.TYPE;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 
diff --git a/briar-tests/src/org/briarproject/forum/SharingManagerImplTest.java b/briar-tests/src/org/briarproject/briar/sharing/SharingManagerImplTest.java
similarity index 85%
rename from briar-tests/src/org/briarproject/forum/SharingManagerImplTest.java
rename to briar-tests/src/org/briarproject/briar/sharing/SharingManagerImplTest.java
index bc014f56c1764e64e321e3aaa7a75bf70ed399cf..10306c4f522901e95b56a3b317c829e267012619 100644
--- a/briar-tests/src/org/briarproject/forum/SharingManagerImplTest.java
+++ b/briar-tests/src/org/briarproject/briar/sharing/SharingManagerImplTest.java
@@ -1,4 +1,4 @@
-package org.briarproject.forum;
+package org.briarproject.briar.sharing;
 
 import org.briarproject.BriarTestCase;
 import org.junit.Test;
diff --git a/build.gradle b/build.gradle
index eddf2bc6a583d821c4da4a361f51b04287ab3b81..5905facbe34083c2c1dcc216f91bbfe7e7fdfc8c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -17,6 +17,6 @@ buildscript {
 		classpath 'com.android.tools.build:gradle:2.2.2'
 		classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
 		classpath 'de.undercouch:gradle-download-task:2.1.0'
-		classpath files('briar-core/libs/gradle-witness.jar')
+		classpath files('libs/gradle-witness.jar')
 	}
 }
diff --git a/briar-core/libs/gradle-witness.jar b/libs/gradle-witness.jar
similarity index 100%
rename from briar-core/libs/gradle-witness.jar
rename to libs/gradle-witness.jar
diff --git a/settings.gradle b/settings.gradle
index b167af5b93487c3b27f3ab04efe7b0ab38337094..c6bb2b271208916854b576b3a79f46bb0a02fd3f 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,6 +1,8 @@
+include ':bramble-api', ':bramble-android'
+include ':bramble-core'
+include ':bramble-j2se'
 include ':briar-api'
 include ':briar-core'
-include ':briar-desktop'
 include ':briar-tests'
 include ':briar-android'
-include ':briar-android-tests'
\ No newline at end of file
+include ':briar-android-tests'