diff --git a/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java b/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java
index c5841d76e61d44500df89d1accab77f2570f36ec..d1ba7d858208ceea83441b838ca8093d30b6bca2 100644
--- a/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java
+++ b/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java
@@ -18,6 +18,8 @@ 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;
@@ -25,6 +27,7 @@ import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
 import org.briarproject.api.properties.TransportProperties;
 import org.briarproject.util.StringUtils;
 
+import java.io.Closeable;
 import java.io.IOException;
 import java.io.InputStream;
 import java.security.SecureRandom;
@@ -63,6 +66,8 @@ import static java.util.logging.Level.WARNING;
 import static org.briarproject.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_BLUETOOTH;
 import static org.briarproject.util.PrivacyUtils.scrubMacAddress;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 class DroidtoothPlugin implements DuplexPlugin {
 
 	// Share an ID with the J2SE Bluetooth plugin
@@ -221,7 +226,7 @@ class DroidtoothPlugin implements DuplexPlugin {
 		return UUID.fromString(uuid);
 	}
 
-	private void tryToClose(BluetoothServerSocket ss) {
+	private void tryToClose(@Nullable BluetoothServerSocket ss) {
 		try {
 			if (ss != null) ss.close();
 		} catch (IOException e) {
@@ -344,9 +349,9 @@ class DroidtoothPlugin implements DuplexPlugin {
 		}
 	}
 
-	private void tryToClose(BluetoothSocket s) {
+	private void tryToClose(@Nullable Closeable c) {
 		try {
-			if (s != null) s.close();
+			if (c != null) c.close();
 		} catch (IOException e) {
 			if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
 		}
@@ -424,7 +429,7 @@ class DroidtoothPlugin implements DuplexPlugin {
 	}
 
 	private void closeSockets(final List<Future<BluetoothSocket>> futures,
-			final BluetoothSocket chosen) {
+			@Nullable final BluetoothSocket chosen) {
 		ioExecutor.execute(new Runnable() {
 			@Override
 			public void run() {
@@ -458,6 +463,9 @@ class DroidtoothPlugin implements DuplexPlugin {
 	@Override
 	public KeyAgreementListener createKeyAgreementListener(byte[] commitment) {
 		if (!isRunning()) return null;
+		// There's no point listening if we can't discover our own address
+		String address = AndroidUtils.getBluetoothAddress(appContext, adapter);
+		if (address.isEmpty()) return null;
 		// No truncation necessary because COMMIT_LENGTH = 16
 		UUID uuid = UUID.nameUUIDFromBytes(commitment);
 		if (LOG.isLoggable(INFO)) LOG.info("Key agreement UUID " + uuid);
@@ -472,8 +480,7 @@ class DroidtoothPlugin implements DuplexPlugin {
 		}
 		BdfList descriptor = new BdfList();
 		descriptor.add(TRANSPORT_ID_BLUETOOTH);
-		String address = AndroidUtils.getBluetoothAddress(appContext, adapter);
-		if (!address.isEmpty()) descriptor.add(StringUtils.macToBytes(address));
+		descriptor.add(StringUtils.macToBytes(address));
 		return new BluetoothKeyAgreementListener(descriptor, ss);
 	}
 
@@ -488,7 +495,6 @@ class DroidtoothPlugin implements DuplexPlugin {
 			LOG.info("Invalid address in key agreement descriptor");
 			return null;
 		}
-		if (address == null) return null;
 		// No truncation necessary because COMMIT_LENGTH = 16
 		UUID uuid = UUID.nameUUIDFromBytes(commitment);
 		if (LOG.isLoggable(INFO))
@@ -498,9 +504,7 @@ class DroidtoothPlugin implements DuplexPlugin {
 		return new DroidtoothTransportConnection(this, s);
 	}
 
-	@Nullable
 	private String parseAddress(BdfList descriptor) throws FormatException {
-		if (descriptor.size() < 2) return null;
 		byte[] mac = descriptor.getRaw(1);
 		if (mac.length != 6) throw new FormatException();
 		return StringUtils.macToString(mac);
diff --git a/briar-android/src/org/briarproject/plugins/tcp/AndroidLanTcpPlugin.java b/briar-android/src/org/briarproject/plugins/tcp/AndroidLanTcpPlugin.java
index 598e914b6d695d1373fba80145c392e2abe32e7f..b96aefa0893fa8c2dcf1e87d02649500d9fc7841 100644
--- a/briar-android/src/org/briarproject/plugins/tcp/AndroidLanTcpPlugin.java
+++ b/briar-android/src/org/briarproject/plugins/tcp/AndroidLanTcpPlugin.java
@@ -7,16 +7,20 @@ 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 java.util.concurrent.Executor;
 import java.util.logging.Logger;
 
+import javax.annotation.Nullable;
+
 import static android.content.Context.CONNECTIVITY_SERVICE;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
 import static android.net.ConnectivityManager.TYPE_WIFI;
 
+@NotNullByDefault
 class AndroidLanTcpPlugin extends LanTcpPlugin {
 
 	private static final Logger LOG =
@@ -24,6 +28,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
 
 	private final Context appContext;
 
+	@Nullable
 	private volatile BroadcastReceiver networkStateReceiver = null;
 
 	AndroidLanTcpPlugin(Executor ioExecutor, Backoff backoff,
diff --git a/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java b/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java
index ee62791d2e9bbb8d7772c89bf1e11c5b389319cc..2a8b58991bcafe11f4b2e4ed24d33286aca18519 100644
--- a/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java
+++ b/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java
@@ -24,6 +24,7 @@ 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;
@@ -60,6 +61,7 @@ import java.util.logging.Logger;
 import java.util.regex.Pattern;
 import java.util.zip.ZipInputStream;
 
+import javax.annotation.Nullable;
 import javax.net.SocketFactory;
 
 import static android.content.Context.CONNECTIVITY_SERVICE;
@@ -76,6 +78,7 @@ 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;
 
+@NotNullByDefault
 class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
 
 	private static final String PROP_ONION = "onion";
@@ -104,9 +107,13 @@ 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,
@@ -289,7 +296,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
 		return appContext.getResources().getAssets().open("torrc");
 	}
 
-	private void tryToClose(Closeable c) {
+	private void tryToClose(@Nullable Closeable c) {
 		try {
 			if (c != null) c.close();
 		} catch (IOException e) {
@@ -297,7 +304,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
 		}
 	}
 
-	private void tryToClose(Socket s) {
+	private void tryToClose(@Nullable Socket s) {
 		try {
 			if (s != null) s.close();
 		} catch (IOException e) {
@@ -385,7 +392,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
 		});
 	}
 
-	private void tryToClose(ServerSocket ss) {
+	private void tryToClose(@Nullable ServerSocket ss) {
 		try {
 			if (ss != null) ss.close();
 		} catch (IOException e) {
diff --git a/briar-api/src/org/briarproject/api/plugins/Plugin.java b/briar-api/src/org/briarproject/api/plugins/Plugin.java
index 393fa27ea1737e86a8c794eacc3d4b506a7a6eb7..e54822cceccd94854febc9be2cc247bb9fd17f0e 100644
--- a/briar-api/src/org/briarproject/api/plugins/Plugin.java
+++ b/briar-api/src/org/briarproject/api/plugins/Plugin.java
@@ -2,28 +2,42 @@ package org.briarproject.api.plugins;
 
 import org.briarproject.api.TransportId;
 import org.briarproject.api.contact.ContactId;
+import org.briarproject.api.nullsafety.NotNullByDefault;
 
 import java.io.IOException;
 import java.util.Collection;
 
+@NotNullByDefault
 public interface Plugin {
 
-	/** Returns the plugin's transport identifier. */
+	/**
+	 * Returns the plugin's transport identifier.
+	 */
 	TransportId getId();
 
-	/** Returns the transport's maximum latency in milliseconds. */
+	/**
+	 * Returns the transport's maximum latency in milliseconds.
+	 */
 	int getMaxLatency();
 
-	/** Returns the transport's maximum idle time in milliseconds. */
+	/**
+	 * Returns the transport's maximum idle time in milliseconds.
+	 */
 	int getMaxIdleTime();
 
-	/** Starts the plugin and returns true if it started successfully. */
+	/**
+	 * Starts the plugin and returns true if it started successfully.
+	 */
 	boolean start() throws IOException;
 
-	/** Stops the plugin. */
+	/**
+	 * Stops the plugin.
+	 */
 	void stop() throws IOException;
 
-	/** Returns true if the plugin is running. */
+	/**
+	 * Returns true if the plugin is running.
+	 */
 	boolean isRunning();
 
 	/**
diff --git a/briar-api/src/org/briarproject/api/plugins/duplex/DuplexPlugin.java b/briar-api/src/org/briarproject/api/plugins/duplex/DuplexPlugin.java
index a77bd090ea4d65ec24338783ba2f74592769e74d..c45d5bab3b53ff69b5f712b7d0d8b71ddc3f2cd1 100644
--- a/briar-api/src/org/briarproject/api/plugins/duplex/DuplexPlugin.java
+++ b/briar-api/src/org/briarproject/api/plugins/duplex/DuplexPlugin.java
@@ -4,19 +4,28 @@ 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;
 
-/** An interface for transport plugins that support duplex communication. */
+import javax.annotation.Nullable;
+
+/**
+ * An interface for transport plugins that support duplex communication.
+ */
+@NotNullByDefault
 public interface DuplexPlugin extends Plugin {
 
 	/**
 	 * Attempts to create and return a connection to the given contact using
 	 * the current transport and configuration properties. Returns null if a
-	 * connection could not be created.
+	 * connection cannot be created.
 	 */
+	@Nullable
 	DuplexTransportConnection createConnection(ContactId c);
 
-	/** Returns true if the plugin supports exchanging invitations. */
+	/**
+	 * Returns true if the plugin supports exchanging invitations.
+	 */
 	boolean supportsInvitations();
 
 	/**
@@ -24,21 +33,27 @@ public interface DuplexPlugin extends Plugin {
 	 * peer. Returns null if no connection can be established within the given
 	 * time.
 	 */
+	@Nullable
 	DuplexTransportConnection createInvitationConnection(PseudoRandom r,
 			long timeout, boolean alice);
 
-	/** Returns true if the plugin supports short-range key agreement. */
+	/**
+	 * Returns true if the plugin supports short-range key agreement.
+	 */
 	boolean supportsKeyAgreement();
 
 	/**
-	 * Returns a listener that can be used to perform key agreement.
+	 * Attempts to create and return a listener that can be used to perform key
+	 * agreement. Returns null if a listener cannot be created.
 	 */
+	@Nullable
 	KeyAgreementListener createKeyAgreementListener(byte[] localCommitment);
 
 	/**
 	 * Attempts to connect to the remote peer specified in the given descriptor.
 	 * Returns null if no connection can be established within the given time.
 	 */
+	@Nullable
 	DuplexTransportConnection createKeyAgreementConnection(
 			byte[] remoteCommitment, BdfList descriptor, long timeout);
 }
diff --git a/briar-api/src/org/briarproject/api/plugins/simplex/SimplexPlugin.java b/briar-api/src/org/briarproject/api/plugins/simplex/SimplexPlugin.java
index 36e2ed438393090fa71cea2dde44f4b744298326..cf9f5ebec3543cad0407d9c25d0c72d44bffc831 100644
--- a/briar-api/src/org/briarproject/api/plugins/simplex/SimplexPlugin.java
+++ b/briar-api/src/org/briarproject/api/plugins/simplex/SimplexPlugin.java
@@ -1,24 +1,32 @@
 package org.briarproject.api.plugins.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;
 
-/** An interface for transport plugins that support simplex communication. */
+import javax.annotation.Nullable;
+
+/**
+ * An interface for transport plugins that support simplex communication.
+ */
+@NotNullByDefault
 public interface SimplexPlugin extends Plugin {
 
 	/**
 	 * Attempts to create and return a reader for the given contact using the
 	 * current transport and configuration properties. Returns null if a reader
-	 * could not be created.
+	 * cannot be created.
 	 */
+	@Nullable
 	TransportConnectionReader createReader(ContactId c);
 
 	/**
 	 * Attempts to create and return a writer for the given contact using the
 	 * current transport and configuration properties. Returns null if a writer
-	 * could not be created.
+	 * cannot be created.
 	 */
+	@Nullable
 	TransportConnectionWriter createWriter(ContactId c);
 }
diff --git a/briar-core/src/org/briarproject/plugins/file/FilePlugin.java b/briar-core/src/org/briarproject/plugins/file/FilePlugin.java
index 9819235539b04318dcef32152617f4e32f3b7254..108db3c7b25ef17715d87ab4357701e275cc1c73 100644
--- a/briar-core/src/org/briarproject/plugins/file/FilePlugin.java
+++ b/briar-core/src/org/briarproject/plugins/file/FilePlugin.java
@@ -1,6 +1,7 @@
 package org.briarproject.plugins.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;
@@ -17,10 +18,13 @@ import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
 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;
 
-public abstract class FilePlugin implements SimplexPlugin {
+@NotNullByDefault
+abstract class FilePlugin implements SimplexPlugin {
 
 	private static final Logger LOG =
 			Logger.getLogger(FilePlugin.class.getName());
@@ -32,6 +36,7 @@ public abstract class FilePlugin implements SimplexPlugin {
 
 	protected volatile boolean running = false;
 
+	@Nullable
 	protected abstract File chooseOutputDirectory();
 	protected abstract Collection<File> findFilesByName(String filename);
 	protected abstract void writerFinished(File f);
@@ -82,6 +87,7 @@ public abstract class FilePlugin implements SimplexPlugin {
 		return filename.toLowerCase(Locale.US).matches("[a-z]{8}\\.dat");
 	}
 
+	@Nullable
 	private TransportConnectionWriter createWriter(String filename) {
 		if (!running) return null;
 		File dir = chooseOutputDirectory();
diff --git a/briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java b/briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java
index 01928d373734ab2cf67a8fb985fba5bead24c30f..e3527f74dd52129501dbc42b183677c5b91a53d5 100644
--- a/briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java
+++ b/briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java
@@ -6,6 +6,7 @@ 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;
@@ -29,14 +30,13 @@ import java.util.concurrent.Callable;
 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;
 import static org.briarproject.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_LAN;
 import static org.briarproject.util.ByteUtils.MAX_16_BIT_UNSIGNED;
 import static org.briarproject.util.PrivacyUtils.scrubSocketAddress;
 
+@NotNullByDefault
 class LanTcpPlugin extends TcpPlugin {
 
 	static final TransportId ID = new TransportId("lan");
@@ -211,7 +211,6 @@ class LanTcpPlugin extends TcpPlugin {
 			LOG.info("Invalid IP/port in key agreement descriptor");
 			return null;
 		}
-		if (remote == null) return null;
 		if (!isConnectable(remote)) {
 			if (LOG.isLoggable(INFO)) {
 				SocketAddress local = socket.getLocalSocketAddress();
@@ -237,10 +236,8 @@ class LanTcpPlugin extends TcpPlugin {
 		}
 	}
 
-	@Nullable
 	private InetSocketAddress parseSocketAddress(BdfList descriptor)
 			throws FormatException {
-		if (descriptor.size() < 3) return null;
 		byte[] address = descriptor.getRaw(1);
 		int port = descriptor.getLong(2).intValue();
 		if (port < 1 || port > MAX_16_BIT_UNSIGNED) throw new FormatException();
diff --git a/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java b/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java
index 7227e1a0f4bd7ef627e655de8be7610696ef4416..76da5bf7dd8899d0fdf0da01cf8ae35180c49939 100644
--- a/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java
+++ b/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java
@@ -4,6 +4,8 @@ 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;
@@ -28,10 +30,14 @@ import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.logging.Logger;
 import java.util.regex.Pattern;
 
+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;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 abstract class TcpPlugin implements DuplexPlugin {
 
 	private static final Pattern DOTTED_QUAD =
@@ -141,7 +147,7 @@ abstract class TcpPlugin implements DuplexPlugin {
 		});
 	}
 
-	protected void tryToClose(ServerSocket ss) {
+	protected void tryToClose(@Nullable ServerSocket ss) {
 		try {
 			if (ss != null) ss.close();
 		} catch (IOException e) {
@@ -252,6 +258,7 @@ abstract class TcpPlugin implements DuplexPlugin {
 		return null;
 	}
 
+	@Nullable
 	protected InetSocketAddress parseSocketAddress(String ipPort) {
 		if (StringUtils.isNullOrEmpty(ipPort)) return null;
 		String[] split = ipPort.split(":");
diff --git a/briar-core/src/org/briarproject/plugins/tcp/WanTcpPlugin.java b/briar-core/src/org/briarproject/plugins/tcp/WanTcpPlugin.java
index 82c3221a5b65cf99311a255321dbf87b16cd173d..3f297d14825d9f5120bd15461f1a310ee86494b0 100644
--- a/briar-core/src/org/briarproject/plugins/tcp/WanTcpPlugin.java
+++ b/briar-core/src/org/briarproject/plugins/tcp/WanTcpPlugin.java
@@ -2,6 +2,8 @@ package org.briarproject.plugins.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;
@@ -14,6 +16,8 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.Executor;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 class WanTcpPlugin extends TcpPlugin {
 
 	static final TransportId ID = new TransportId("wan");
diff --git a/briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothPlugin.java b/briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothPlugin.java
index c6b607d32b6f3035d8d09a05907dec36ec304d43..c945ca8154803711a0cddf181c3ca5dd66a80403 100644
--- a/briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothPlugin.java
+++ b/briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothPlugin.java
@@ -7,6 +7,8 @@ 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;
@@ -48,6 +50,8 @@ import static java.util.logging.Level.WARNING;
 import static javax.bluetooth.DiscoveryAgent.GIAC;
 import static org.briarproject.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_BLUETOOTH;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 class BluetoothPlugin implements DuplexPlugin {
 
 	// Share an ID with the Android Bluetooth plugin
@@ -164,7 +168,7 @@ class BluetoothPlugin implements DuplexPlugin {
 		return uuid;
 	}
 
-	private void tryToClose(StreamConnectionNotifier ss) {
+	private void tryToClose(@Nullable StreamConnectionNotifier ss) {
 		try {
 			if (ss != null) ss.close();
 		} catch (IOException e) {
@@ -333,7 +337,7 @@ class BluetoothPlugin implements DuplexPlugin {
 	}
 
 	private void closeSockets(final List<Future<StreamConnection>> futures,
-			final StreamConnection chosen) {
+			@Nullable final StreamConnection chosen) {
 		ioExecutor.execute(new Runnable() {
 			@Override
 			public void run() {
@@ -388,7 +392,7 @@ class BluetoothPlugin implements DuplexPlugin {
 		BdfList descriptor = new BdfList();
 		descriptor.add(TRANSPORT_ID_BLUETOOTH);
 		String address = localDevice.getBluetoothAddress();
-		if (!address.isEmpty()) descriptor.add(StringUtils.macToBytes(address));
+		descriptor.add(StringUtils.macToBytes(address));
 		return new BluetoothKeyAgreementListener(descriptor, ss);
 	}
 
@@ -403,7 +407,6 @@ class BluetoothPlugin implements DuplexPlugin {
 			LOG.info("Invalid address in key agreement descriptor");
 			return null;
 		}
-		if (address == null) return null;
 		// No truncation necessary because COMMIT_LENGTH = 16
 		String uuid = UUID.nameUUIDFromBytes(commitment).toString();
 		if (LOG.isLoggable(INFO))
@@ -414,9 +417,7 @@ class BluetoothPlugin implements DuplexPlugin {
 		return new BluetoothTransportConnection(this, s);
 	}
 
-	@Nullable
 	private String parseAddress(BdfList descriptor) throws FormatException {
-		if (descriptor.size() < 2) return null;
 		byte[] mac = descriptor.getRaw(1);
 		if (mac.length != 6) throw new FormatException();
 		return StringUtils.macToString(mac);
diff --git a/briar-desktop/src/org/briarproject/plugins/file/RemovableDrivePlugin.java b/briar-desktop/src/org/briarproject/plugins/file/RemovableDrivePlugin.java
index 926f8d314800774f623b08688439bcc4dca36ca2..4a463eb3eb02c5a49b12f20fdc7a56e4e943e2e8 100644
--- a/briar-desktop/src/org/briarproject/plugins/file/RemovableDrivePlugin.java
+++ b/briar-desktop/src/org/briarproject/plugins/file/RemovableDrivePlugin.java
@@ -2,6 +2,7 @@ package org.briarproject.plugins.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 java.io.File;
@@ -15,6 +16,7 @@ import java.util.logging.Logger;
 
 import static java.util.logging.Level.WARNING;
 
+@NotNullByDefault
 class RemovableDrivePlugin extends FilePlugin
 implements RemovableDriveMonitor.Callback {
 
diff --git a/briar-desktop/src/org/briarproject/plugins/modem/ModemPlugin.java b/briar-desktop/src/org/briarproject/plugins/modem/ModemPlugin.java
index 4a32bf4618317c2f1224c12c8b2fe43a1ff055a0..fe3b89e2c32f99139694d4e7fe519366d796f342 100644
--- a/briar-desktop/src/org/briarproject/plugins/modem/ModemPlugin.java
+++ b/briar-desktop/src/org/briarproject/plugins/modem/ModemPlugin.java
@@ -5,6 +5,8 @@ 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;
@@ -22,6 +24,8 @@ 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("modem");
diff --git a/briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java b/briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java
index 33f8d3a908ddb96e5e64f146d782874f1215553c..2f8e349c4caeae61580035583e058b6d761bae0a 100644
--- a/briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java
+++ b/briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java
@@ -31,6 +31,7 @@ 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.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -188,7 +189,9 @@ public class LanTcpPluginTest extends BriarTestCase {
 				0, 0);
 		plugin.start();
 		assertTrue(callback.propertiesLatch.await(5, SECONDS));
-		KeyAgreementListener kal = plugin.createKeyAgreementListener(null);
+		KeyAgreementListener kal =
+				plugin.createKeyAgreementListener(new byte[COMMIT_LENGTH]);
+		assertNotNull(kal);
 		Callable<KeyAgreementConnection> c = kal.listen();
 		FutureTask<KeyAgreementConnection> f = new FutureTask<>(c);
 		new Thread(f).start();
@@ -258,8 +261,8 @@ public class LanTcpPluginTest extends BriarTestCase {
 		descriptor.add(local.getAddress().getAddress());
 		descriptor.add(local.getPort());
 		// Connect to the port
-		DuplexTransportConnection d =
-				plugin.createKeyAgreementConnection(null, descriptor, 5000);
+		DuplexTransportConnection d = plugin.createKeyAgreementConnection(
+				new byte[COMMIT_LENGTH], descriptor, 5000);
 		assertNotNull(d);
 		// Check that the connection was accepted
 		assertTrue(latch.await(5, SECONDS));