From ad6016d428a34a8648a7571dd56b4837b5238434 Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Wed, 23 Nov 2016 14:58:42 +0000
Subject: [PATCH 1/4] Updated java.library.path.

---
 .gitignore                                    |   2 +
 bramble-android/build.gradle                  | 104 ++++
 .../libs/jtorctl-briar.jar                    | Bin
 bramble-android/proguard-rules.txt            |  15 +
 bramble-android/src/main/AndroidManifest.xml  |  24 +
 .../bramble/BrambleAndroidModule.java         |  13 +
 .../bramble/api/system}/AndroidExecutor.java  |   2 +-
 .../bramble/plugin/AndroidPluginModule.java   |  35 +-
 .../plugin}/droidtooth/DroidtoothPlugin.java  |  48 +-
 .../droidtooth/DroidtoothPluginFactory.java   |  23 +-
 .../DroidtoothTransportConnection.java        |   8 +-
 .../plugin}/tcp/AndroidLanTcpPlugin.java      |   8 +-
 .../tcp/AndroidLanTcpPluginFactory.java       |  21 +-
 .../plugin}/tor/TorNetworkMetadata.java       |   8 +-
 .../bramble/plugin}/tor/TorPlugin.java        |  73 +--
 .../bramble/plugin}/tor/TorPluginFactory.java |  30 +-
 .../plugin}/tor/TorTransportConnection.java   |   8 +-
 .../bramble}/system/AndroidExecutorImpl.java  |   4 +-
 .../bramble}/system/AndroidLocationUtils.java |   9 +-
 .../bramble}/system/AndroidSeedProvider.java  |   7 +-
 .../bramble/system/AndroidSystemModule.java   |  33 ++
 .../bramble/util/AndroidUtils.java            |  70 +++
 .../src/main/res/raw}/torrc                   |   0
 .../src/main/res/values/strings.xml           |   3 +
 {briar-desktop => bramble-api}/.gitignore     |   0
 bramble-api/build.gradle                      |  22 +
 .../org/briarproject/bramble}/api/Bytes.java  |   8 +-
 .../bramble/api/FormatException.java          |   9 +
 .../briarproject/bramble}/api/StringMap.java  |   4 +-
 .../briarproject/bramble/api/UniqueId.java    |  20 +
 .../api/client}/BdfMessageContext.java        |   8 +-
 .../api/client/BdfMessageValidator.java       |  66 +++
 .../bramble/api/client}/ClientHelper.java     |  25 +-
 .../api/client/ContactGroupFactory.java       |  29 ++
 .../bramble}/api/contact/Contact.java         |  11 +-
 .../api/contact/ContactExchangeListener.java  |  20 +
 .../api/contact/ContactExchangeTask.java      |  22 +
 .../bramble}/api/contact/ContactId.java       |   8 +-
 .../bramble}/api/contact/ContactManager.java  |  50 +-
 .../api/contact/event/ContactAddedEvent.java  |  31 ++
 .../contact/event/ContactRemovedEvent.java    |  25 +
 .../event/ContactStatusChangedEvent.java      |  31 ++
 .../contact/event/ContactVerifiedEvent.java   |  26 +
 .../bramble}/api/crypto/CryptoComponent.java  |   6 +-
 .../bramble}/api/crypto/CryptoExecutor.java   |   2 +-
 .../bramble}/api/crypto/KeyPair.java          |  12 +-
 .../bramble}/api/crypto/KeyParser.java        |   5 +-
 .../bramble/api/crypto/MessageDigest.java     |  47 ++
 .../api/crypto/PasswordStrengthEstimator.java |   5 +-
 .../bramble/api/crypto/PrivateKey.java        |  15 +
 .../bramble/api/crypto/PseudoRandom.java      |  12 +
 .../bramble/api/crypto/PublicKey.java         |  15 +
 .../bramble}/api/crypto/SecretKey.java        |  11 +-
 .../bramble}/api/crypto/StreamDecrypter.java  |   8 +-
 .../api/crypto/StreamDecrypterFactory.java    |  12 +-
 .../bramble/api/crypto/StreamEncrypter.java   |  20 +
 .../api/crypto/StreamEncrypterFactory.java    |  12 +-
 .../bramble}/api/data/BdfDictionary.java      |   6 +-
 .../bramble}/api/data/BdfEntry.java           |   8 +-
 .../bramble}/api/data/BdfList.java            |  11 +-
 .../bramble}/api/data/BdfReader.java          |  28 +-
 .../bramble}/api/data/BdfReaderFactory.java   |   5 +-
 .../bramble}/api/data/BdfWriter.java          |  12 +-
 .../bramble/api/data/BdfWriterFactory.java    |  11 +
 .../bramble/api/data/MetadataEncoder.java     |  11 +
 .../bramble/api/data/MetadataParser.java      |  11 +
 .../bramble/api/data/ObjectReader.java        |  11 +
 .../api/db/ContactExistsException.java        |   3 +-
 .../bramble}/api/db/DatabaseComponent.java    |  56 ++-
 .../bramble}/api/db/DatabaseConfig.java       |  10 +-
 .../bramble}/api/db/DatabaseExecutor.java     |   7 +-
 .../bramble}/api/db/DbClosedException.java    |   3 +-
 .../bramble}/api/db/DbException.java          |   2 +-
 .../bramble}/api/db/Metadata.java             |   5 +-
 .../api/db/NoSuchContactException.java        |   3 +-
 .../bramble}/api/db/NoSuchGroupException.java |   3 +-
 .../api/db/NoSuchLocalAuthorException.java    |   3 +-
 .../api/db/NoSuchMessageException.java        |   3 +-
 .../api/db/NoSuchTransportException.java      |   3 +-
 .../bramble}/api/db/Transaction.java          |   7 +-
 .../briarproject/bramble/api/event/Event.java |   7 +
 .../bramble/api/event/EventBus.java           |  22 +
 .../bramble/api/event/EventListener.java      |  16 +
 .../bramble}/api/identity/Author.java         |  26 +-
 .../api/identity/AuthorConstants.java         |   6 +-
 .../bramble}/api/identity/AuthorFactory.java  |   5 +-
 .../bramble}/api/identity/AuthorId.java       |  11 +-
 .../bramble/api/identity/IdentityManager.java |  38 ++
 .../bramble}/api/identity/LocalAuthor.java    |  16 +-
 .../identity/event/LocalAuthorAddedEvent.java |  25 +
 .../event/LocalAuthorRemovedEvent.java        |  25 +
 .../api/invitation/InvitationConstants.java   |  20 +
 .../api/invitation/InvitationListener.java    |   2 +-
 .../api/invitation/InvitationState.java       |  16 +-
 .../api/invitation/InvitationTask.java        |  17 +-
 .../api/invitation/InvitationTaskFactory.java |  15 +
 .../keyagreement/KeyAgreementConnection.java  |  12 +-
 .../keyagreement/KeyAgreementConstants.java   |  36 ++
 .../keyagreement/KeyAgreementListener.java    |   4 +-
 .../api/keyagreement/KeyAgreementResult.java  |   8 +-
 .../api/keyagreement/KeyAgreementTask.java    |  13 +-
 .../keyagreement/KeyAgreementTaskFactory.java |  15 +
 .../bramble}/api/keyagreement/Payload.java    |   6 +-
 .../api/keyagreement/PayloadEncoder.java      |   9 +
 .../api/keyagreement/PayloadParser.java       |   4 +-
 .../api/keyagreement/RecordTypes.java         |   6 +-
 .../api/keyagreement/TransportDescriptor.java |   8 +-
 .../event/KeyAgreementAbortedEvent.java       |  24 +
 .../event/KeyAgreementFailedEvent.java        |   9 +
 .../event/KeyAgreementFinishedEvent.java      |  25 +
 .../event/KeyAgreementListeningEvent.java     |  25 +
 .../event/KeyAgreementStartedEvent.java       |   9 +
 .../event/KeyAgreementWaitingEvent.java       |   5 +-
 .../bramble}/api/lifecycle/IoExecutor.java    |   2 +-
 .../api/lifecycle/LifecycleManager.java       |  74 +++
 .../bramble}/api/lifecycle/Service.java       |   2 +-
 .../api/lifecycle/ServiceException.java       |   2 +-
 .../api/lifecycle/ShutdownManager.java        |   5 +-
 .../api/lifecycle/event/ShutdownEvent.java    |   9 +
 .../nullsafety/FieldsNotNullByDefault.java    |   2 +-
 .../nullsafety/MethodsNotNullByDefault.java   |   2 +-
 .../api/nullsafety/NotNullByDefault.java      |   2 +-
 .../ParametersNotNullByDefault.java           |   2 +-
 .../bramble/api/plugin}/Backoff.java          |   2 +-
 .../bramble/api/plugin}/BackoffFactory.java   |   2 +-
 .../api/plugin}/BluetoothConstants.java       |   4 +-
 .../api/plugin}/ConnectionManager.java        |   7 +-
 .../api/plugin}/ConnectionRegistry.java       |   7 +-
 .../bramble/api/plugin}/LanTcpConstants.java  |   4 +-
 .../bramble/api/plugin}/Plugin.java           |   7 +-
 .../bramble/api/plugin}/PluginCallback.java   |  35 +-
 .../bramble/api/plugin/PluginConfig.java      |  15 +
 .../bramble/api/plugin}/PluginManager.java    |   9 +-
 .../bramble/api/plugin}/TorConstants.java     |   6 +-
 .../plugin}/TransportConnectionReader.java    |  13 +-
 .../plugin}/TransportConnectionWriter.java    |  22 +-
 .../bramble/api/plugin}/TransportId.java      |   2 +-
 .../bramble/api/plugin}/WanTcpConstants.java  |   4 +-
 .../AbstractDuplexTransportConnection.java    |  18 +-
 .../api/plugin}/duplex/DuplexPlugin.java      |  16 +-
 .../plugin}/duplex/DuplexPluginCallback.java  |   8 +-
 .../plugin}/duplex/DuplexPluginFactory.java   |   9 +-
 .../duplex/DuplexTransportConnection.java     |  26 +
 .../plugin}/event/ConnectionClosedEvent.java  |  12 +-
 .../plugin}/event/ConnectionOpenedEvent.java  |  12 +-
 .../plugin}/event/ContactConnectedEvent.java  |  10 +-
 .../event/ContactDisconnectedEvent.java       |  10 +-
 .../plugin/event/TransportDisabledEvent.java  |  25 +
 .../plugin/event/TransportEnabledEvent.java   |  25 +
 .../api/plugin}/simplex/SimplexPlugin.java    |  12 +-
 .../plugin/simplex/SimplexPluginCallback.java |  19 +
 .../plugin}/simplex/SimplexPluginFactory.java |   9 +-
 .../api/properties/TransportProperties.java   |   6 +-
 .../TransportPropertyConstants.java           |  14 +
 .../properties/TransportPropertyManager.java  |  32 +-
 .../bramble/api/reliability/ReadHandler.java  |  11 +
 .../api/reliability/ReliabilityLayer.java     |  14 +-
 .../reliability/ReliabilityLayerFactory.java  |  12 +
 .../bramble/api/reliability/WriteHandler.java |  11 +
 .../bramble/api/reporting/DevConfig.java      |  12 +
 .../bramble/api/reporting/DevReporter.java    |  30 ++
 .../api/reporting/ReportingConstants.java     |   2 +-
 .../bramble/api/settings/Settings.java        |   6 +
 .../bramble/api/settings/SettingsManager.java |  19 +
 .../settings/event/SettingsUpdatedEvent.java  |  24 +
 .../briarproject/bramble}/api/sync/Ack.java   |  10 +-
 .../briarproject/bramble/api/sync/Client.java |  14 +
 .../bramble}/api/sync/ClientId.java           |   4 +-
 .../briarproject/bramble}/api/sync/Group.java |  14 +-
 .../bramble/api/sync/GroupFactory.java        |  12 +
 .../bramble}/api/sync/GroupId.java            |   9 +-
 .../api/sync/InvalidMessageException.java     |   6 +-
 .../bramble}/api/sync/Message.java            |  26 +-
 .../bramble}/api/sync/MessageContext.java     |   6 +-
 .../bramble}/api/sync/MessageFactory.java     |   4 +-
 .../bramble}/api/sync/MessageId.java          |   9 +-
 .../bramble}/api/sync/MessageStatus.java      |  20 +-
 .../briarproject/bramble}/api/sync/Offer.java |  10 +-
 .../bramble}/api/sync/PacketReader.java       |   9 +-
 .../bramble/api/sync/PacketReaderFactory.java |  11 +
 .../bramble}/api/sync/PacketTypes.java        |   6 +-
 .../bramble}/api/sync/PacketWriter.java       |   5 +-
 .../bramble/api/sync/PacketWriterFactory.java |  11 +
 .../bramble/api/sync/Request.java             |  22 +
 .../bramble/api/sync/SyncConstants.java       |  41 ++
 .../bramble}/api/sync/SyncSession.java        |   2 +-
 .../bramble}/api/sync/SyncSessionFactory.java |   6 +-
 .../bramble}/api/sync/ValidationManager.java  |  10 +-
 .../api/sync/event/GroupAddedEvent.java       |  25 +
 .../api/sync/event/GroupRemovedEvent.java     |  25 +
 .../event/GroupVisibilityUpdatedEvent.java    |  30 ++
 .../api/sync/event/MessageAddedEvent.java     |  50 ++
 .../api/sync/event/MessageRequestedEvent.java |  25 +
 .../api/sync/event/MessageSharedEvent.java    |  25 +
 .../sync}/event/MessageStateChangedEvent.java |  12 +-
 .../api/sync/event/MessageToAckEvent.java     |  26 +
 .../sync}/event/MessageToRequestEvent.java    |  10 +-
 .../api/sync/event/MessagesAckedEvent.java    |  35 ++
 .../api/sync}/event/MessagesSentEvent.java    |  16 +-
 .../bramble}/api/system/Clock.java            |  10 +-
 .../bramble}/api/system/LocationUtils.java    |   9 +-
 .../bramble}/api/system/Scheduler.java        |   2 +-
 .../bramble}/api/system/SeedProvider.java     |   8 +-
 .../bramble}/api/transport/IncomingKeys.java  |   6 +-
 .../bramble}/api/transport/KeyManager.java    |  16 +-
 .../bramble}/api/transport/OutgoingKeys.java  |   4 +-
 .../bramble}/api/transport/StreamContext.java |   8 +-
 .../api/transport/StreamReaderFactory.java    |  23 +
 .../api/transport/StreamWriterFactory.java    |  23 +
 .../api/transport/TransportConstants.java     |  49 +-
 .../bramble}/api/transport/TransportKeys.java |   8 +-
 .../bramble}/api/ui/UiCallback.java           |   3 +-
 .../briarproject/bramble}/util/ByteUtils.java |   6 +-
 .../briarproject/bramble}/util/IoUtils.java   |   9 +-
 .../briarproject/bramble}/util/OsUtils.java   |  18 +-
 .../bramble}/util/PrivacyUtils.java           |  23 +-
 .../bramble}/util/StringUtils.java            |   4 +-
 .../bramble/util/ValidationUtils.java         |  67 +++
 bramble-core/build.gradle                     |  19 +
 .../libs/weupnp-0.1.3-SNAPSHOT-briar.jar      | Bin
 .../bramble/BrambleCoreEagerSingletons.java   |  35 ++
 .../bramble/BrambleCoreModule.java            |  61 +++
 .../bramble/client}/ClientHelperImpl.java     |  48 +-
 .../bramble/client/ClientModule.java          |  36 ++
 .../client}/ContactGroupFactoryImpl.java      |  31 +-
 .../contact/ContactExchangeTaskImpl.java      |  76 +--
 .../bramble}/contact/ContactManagerImpl.java  |  29 +-
 .../bramble}/contact/ContactModule.java       |   6 +-
 .../bramble}/crypto/AsciiArmour.java          |   8 +-
 .../bramble}/crypto/AuthenticatedCipher.java  |  26 +-
 .../bramble}/crypto/Blake2sDigest.java        |   2 +-
 .../bramble}/crypto/CombinedSecureRandom.java |  11 +-
 .../bramble}/crypto/CryptoComponentImpl.java  |  48 +-
 .../bramble}/crypto/CryptoModule.java         |  19 +-
 .../bramble}/crypto/DigestWrapper.java        |   9 +-
 .../bramble}/crypto/DoubleDigest.java         |  17 +-
 .../crypto/EllipticCurveConstants.java        |  10 +-
 .../bramble}/crypto/FortunaGenerator.java     |  17 +-
 .../bramble}/crypto/FortunaSecureRandom.java  |  14 +-
 .../bramble}/crypto/FrameEncoder.java         |  16 +-
 .../bramble}/crypto/MessageEncrypter.java     |  19 +-
 .../crypto/PasswordStrengthEstimatorImpl.java |  10 +-
 .../bramble}/crypto/PseudoRandomImpl.java     |  14 +-
 .../bramble}/crypto/Sec1KeyParser.java        |  15 +-
 .../bramble}/crypto/Sec1PrivateKey.java       |  10 +-
 .../bramble}/crypto/Sec1PublicKey.java        |  10 +-
 .../bramble}/crypto/Sec1Utils.java            |   5 +-
 .../bramble/crypto/Signature.java             |  46 ++
 .../bramble}/crypto/SignatureImpl.java        |  17 +-
 .../crypto/StreamDecrypterFactoryImpl.java    |  14 +-
 .../bramble}/crypto/StreamDecrypterImpl.java  |  37 +-
 .../crypto/StreamEncrypterFactoryImpl.java    |  20 +-
 .../bramble}/crypto/StreamEncrypterImpl.java  |  39 +-
 .../XSalsa20Poly1305AuthenticatedCipher.java  |  28 +-
 .../bramble/data/BdfReaderFactoryImpl.java    |  26 +
 .../bramble}/data/BdfReaderImpl.java          |  80 ++-
 .../bramble/data/BdfWriterFactoryImpl.java    |  19 +
 .../bramble}/data/BdfWriterImpl.java          |  69 ++-
 .../bramble}/data/DataModule.java             |  11 +-
 .../bramble}/data/MetadataEncoderImpl.java    |  24 +-
 .../bramble}/data/MetadataParserImpl.java     |  22 +-
 .../org/briarproject/bramble}/data/Types.java |   2 +-
 .../briarproject/bramble}/db/Database.java    |  51 +-
 .../bramble}/db/DatabaseComponentImpl.java    | 124 ++---
 .../bramble}/db/DatabaseConstants.java        |  16 +-
 .../bramble}/db/DatabaseExecutorModule.java   |   6 +-
 .../bramble}/db/DatabaseModule.java           |  12 +-
 .../bramble/db/DbStateException.java          |   9 +
 .../bramble}/db/ExponentialBackoff.java       |   2 +-
 .../briarproject/bramble}/db/H2Database.java  |  22 +-
 .../bramble}/db/JdbcDatabase.java             |  86 ++--
 .../bramble}/event/EventBusImpl.java          |  16 +-
 .../bramble}/event/EventModule.java           |   4 +-
 .../bramble}/identity/AuthorFactoryImpl.java  |  26 +-
 .../bramble/identity/AuthorReader.java        |  36 ++
 .../identity/IdentityManagerImpl.java         |  50 +-
 .../bramble}/identity/IdentityModule.java     |  20 +-
 .../bramble}/invitation/AliceConnector.java   |  31 +-
 .../bramble}/invitation/BobConnector.java     |  32 +-
 .../bramble}/invitation/Connector.java        |  63 +--
 .../bramble}/invitation/ConnectorGroup.java   |  46 +-
 .../bramble/invitation/InvitationModule.java  |  16 +
 .../invitation/InvitationTaskFactoryImpl.java |  23 +-
 .../bramble/keyagreement/AbortException.java  |  24 +
 .../keyagreement/KeyAgreementConnector.java   |  39 +-
 .../keyagreement/KeyAgreementModule.java      |  24 +-
 .../keyagreement/KeyAgreementProtocol.java    |  16 +-
 .../KeyAgreementTaskFactoryImpl.java          |  30 +-
 .../keyagreement/KeyAgreementTaskImpl.java    |  40 +-
 .../keyagreement/KeyAgreementTransport.java   |  36 +-
 .../keyagreement/PayloadEncoderImpl.java      |  16 +-
 .../keyagreement/PayloadParserImpl.java       |  32 +-
 .../lifecycle/LifecycleManagerImpl.java       |  44 +-
 .../bramble}/lifecycle/LifecycleModule.java   |  20 +-
 .../lifecycle/ShutdownManagerImpl.java        |  13 +-
 .../bramble/plugin/BackoffFactoryImpl.java    |  18 +
 .../bramble/plugin}/BackoffImpl.java          |   9 +-
 .../plugin}/ConnectionManagerImpl.java        |  46 +-
 .../plugin}/ConnectionRegistryImpl.java       |  22 +-
 .../bramble/plugin}/PluginManagerImpl.java    |  71 +--
 .../bramble/plugin/PluginModule.java          |  22 +-
 .../briarproject/bramble/plugin}/Poller.java  |  46 +-
 .../bramble/plugin}/file/FilePlugin.java      |  19 +-
 .../plugin}/file/FileTransportReader.java     |   8 +-
 .../plugin}/file/FileTransportWriter.java     |  13 +-
 .../bramble/plugin}/tcp/LanTcpPlugin.java     |  36 +-
 .../plugin}/tcp/LanTcpPluginFactory.java      |  21 +-
 .../bramble/plugin}/tcp/MappingResult.java    |  21 +-
 .../bramble/plugin/tcp/PortMapper.java        |   9 +
 .../bramble/plugin}/tcp/PortMapperImpl.java   |  16 +-
 .../bramble/plugin}/tcp/TcpPlugin.java        |  36 +-
 .../plugin}/tcp/TcpTransportConnection.java   |  11 +-
 .../bramble/plugin}/tcp/WanTcpPlugin.java     |  27 +-
 .../plugin}/tcp/WanTcpPluginFactory.java      |  23 +-
 .../bramble}/properties/PropertiesModule.java |  30 +-
 .../TransportPropertyManagerImpl.java         |  58 ++-
 .../TransportPropertyValidator.java           |  58 +++
 .../bramble}/reliability/Ack.java             |  13 +-
 .../bramble}/reliability/Crc32.java           |   5 +-
 .../bramble}/reliability/Data.java            |  10 +-
 .../bramble}/reliability/Frame.java           |  11 +-
 .../bramble}/reliability/Receiver.java        |  39 +-
 .../reliability/ReceiverInputStream.java      |  14 +-
 .../ReliabilityLayerFactoryImpl.java          |  33 ++
 .../reliability/ReliabilityLayerImpl.java     |  23 +-
 .../reliability/ReliabilityModule.java        |  12 +-
 .../bramble}/reliability/Sender.java          |  16 +-
 .../reliability/SenderOutputStream.java       |   8 +-
 .../bramble}/reliability/SlipDecoder.java     |  10 +-
 .../bramble}/reliability/SlipEncoder.java     |  10 +-
 .../bramble}/reporting/DevReportServer.java   |  35 +-
 .../bramble}/reporting/DevReporterImpl.java   |  21 +-
 .../bramble/reporting/ReportingModule.java    |  20 +
 .../settings/SettingsManagerImpl.java         |  17 +-
 .../bramble}/settings/SettingsModule.java     |   7 +-
 .../bramble}/socks/SocksModule.java           |   6 +-
 .../bramble}/socks/SocksSocket.java           |   6 +-
 .../bramble}/socks/SocksSocketFactory.java    |   2 +-
 .../bramble}/sync/DuplexOutgoingSession.java  |  95 ++--
 .../bramble/sync/GroupFactoryImpl.java        |  31 ++
 .../bramble}/sync/IncomingSession.java        |  57 ++-
 .../bramble}/sync/MessageFactoryImpl.java     |  22 +-
 .../bramble/sync/PacketReaderFactoryImpl.java |  28 ++
 .../bramble}/sync/PacketReaderImpl.java       |  48 +-
 .../bramble/sync/PacketWriterFactoryImpl.java |  16 +
 .../bramble}/sync/PacketWriterImpl.java       |  39 +-
 .../bramble}/sync/SimplexOutgoingSession.java |  66 ++-
 .../bramble}/sync/SyncModule.java             |  29 +-
 .../bramble}/sync/SyncSessionFactoryImpl.java |  33 +-
 .../bramble}/sync/ThrowingRunnable.java       |   2 +-
 .../bramble}/sync/ValidationManagerImpl.java  |  52 +-
 .../bramble}/system/LinuxSeedProvider.java    |  12 +-
 .../bramble}/system/SystemClock.java          |  10 +-
 .../bramble}/system/SystemModule.java         |   8 +-
 .../bramble}/transport/KeyManagerImpl.java    |  44 +-
 .../transport/MutableIncomingKeys.java        |  12 +-
 .../transport/MutableOutgoingKeys.java        |  12 +-
 .../transport/MutableTransportKeys.java       |  11 +-
 .../bramble}/transport/ReorderingWindow.java  |  11 +-
 .../transport/StreamReaderFactoryImpl.java    |  18 +-
 .../bramble}/transport/StreamReaderImpl.java  |  16 +-
 .../transport/StreamWriterFactoryImpl.java    |  18 +-
 .../bramble}/transport/StreamWriterImpl.java  |  19 +-
 .../transport/TransportKeyManager.java        |  30 ++
 .../transport/TransportKeyManagerFactory.java |  12 +
 .../TransportKeyManagerFactoryImpl.java       |  18 +-
 .../transport/TransportKeyManagerImpl.java    |  39 +-
 .../bramble}/transport/TransportModule.java   |  18 +-
 bramble-j2se/build.gradle                     |  10 +
 .../libs/bluecove-2.1.1-SNAPSHOT-briar.jar    | Bin
 .../libs/bluecove-gpl-2.1.1-SNAPSHOT.jar      | Bin
 .../libs/jna-4.1.0.jar                        | Bin
 .../libs/jna-platform-4.1.0.jar               | Bin
 .../libs/jnotify-0.94.jar                     | Bin
 .../libs/jnotify-x86.dll                      | Bin
 .../libs/jnotify-x86_64.dll                   | Bin
 .../libs/jssc-0.9-briar.jar                   | Bin
 .../libs/libjnotify-amd64.so                  | Bin
 .../libs/libjnotify-i386.so                   | Bin
 .../libs/libjnotify.dylib                     | Bin
 .../libs/source/jssc-0.9-briar-source.jar     | Bin
 .../lifecycle/DesktopLifecycleModule.java     |   6 +-
 .../lifecycle/WindowsShutdownManagerImpl.java |  16 +-
 .../bramble/plugin/DesktopPluginModule.java   |  33 +-
 .../plugin}/bluetooth/BluetoothPlugin.java    |  48 +-
 .../bluetooth/BluetoothPluginFactory.java     |  21 +-
 .../BluetoothTransportConnection.java         |   8 +-
 .../plugin}/bluetooth/InvitationListener.java |  14 +-
 .../file/LinuxRemovableDriveFinder.java       |   8 +-
 .../file/LinuxRemovableDriveMonitor.java      |  12 +
 .../plugin}/file/MacRemovableDriveFinder.java |   8 +-
 .../plugin/file/MacRemovableDriveMonitor.java |  12 +
 .../file/PollingRemovableDriveMonitor.java    |  17 +-
 .../plugin}/file/RemovableDriveFinder.java    |   5 +-
 .../plugin}/file/RemovableDriveMonitor.java   |   5 +-
 .../plugin}/file/RemovableDrivePlugin.java    |  12 +-
 .../file/RemovableDrivePluginFactory.java     |  20 +-
 .../file/UnixRemovableDriveFinder.java        |  12 +-
 .../file/UnixRemovableDriveMonitor.java       |  35 +-
 .../file/WindowsRemovableDriveFinder.java     |   5 +-
 .../bramble/plugin}/modem/CountryCodes.java   |   5 +-
 .../bramble/plugin}/modem/Modem.java          |   5 +-
 .../bramble/plugin/modem/ModemFactory.java    |   9 +
 .../plugin}/modem/ModemFactoryImpl.java       |  14 +-
 .../bramble/plugin}/modem/ModemImpl.java      |  37 +-
 .../bramble/plugin}/modem/ModemPlugin.java    | 462 +++++++++---------
 .../plugin}/modem/ModemPluginFactory.java     |  88 ++--
 .../bramble/plugin}/modem/SerialPort.java     |   5 +-
 .../bramble/plugin}/modem/SerialPortImpl.java |  12 +-
 .../bramble/plugin/modem/SerialPortList.java  |   9 +
 .../plugin/modem/SerialPortListImpl.java      |  12 +
 .../system/DesktopSeedProviderModule.java     |   6 +-
 briar-android-tests/build.gradle              |   4 +-
 .../org/briarproject/BlogManagerTest.java     |  50 +-
 .../BlogSharingIntegrationTest.java           |  74 ++-
 .../briarproject/BriarIntegrationTest.java    | 141 +++---
 .../BriarIntegrationTestComponent.java        |  95 ++--
 .../org/briarproject/ForumManagerTest.java    |  37 +-
 .../ForumSharingIntegrationTest.java          |  89 ++--
 .../GroupInvitationIntegrationTest.java       |  47 +-
 .../MessageSizeIntegrationTest.java           |  45 +-
 .../MessageSizeIntegrationTestComponent.java  |  26 +-
 .../PrivateGroupIntegrationTest.java          |  59 ++-
 .../briarproject/PrivateGroupManagerTest.java |  75 ++-
 .../SimplexMessagingIntegrationTest.java      |  66 +--
 ...plexMessagingIntegrationTestComponent.java |  56 ++-
 .../org/briarproject/SyncIntegrationTest.java |  42 +-
 .../SyncIntegrationTestComponent.java         |   9 +-
 .../org/briarproject/TestDatabaseModule.java  |   7 +-
 .../org/briarproject/TestLifecycleModule.java |  31 +-
 .../briarproject/TestPluginConfigModule.java  |  23 +-
 .../briarproject/TestSeedProviderModule.java  |   2 +-
 .../IntroductionIntegrationTest.java          | 126 +++--
 .../IntroductionIntegrationTestComponent.java |  64 +++
 briar-android/.gitignore                      |   3 +-
 briar-android/build.gradle                    | 108 +---
 briar-android/proguard-rules.txt              |  70 +--
 .../{ => src/main}/AndroidManifest.xml        | 112 ++---
 .../{ => src/main}/assets/emoji_activity.png  | Bin
 .../main}/assets/emoji_animals_nature.png     | Bin
 .../{ => src/main}/assets/emoji_flags.png     | Bin
 .../main}/assets/emoji_food_drink.png         | Bin
 .../{ => src/main}/assets/emoji_objects.png   | Bin
 .../main}/assets/emoji_smiley_people.png      | Bin
 .../{ => src/main}/assets/emoji_symbols.png   | Bin
 .../main}/assets/emoji_travel_places.png      | Bin
 .../delight/android/identicons/Identicon.java |   0
 .../android/identicons/IdenticonDrawable.java |   0
 .../briar/android/AndroidComponent.java       | 147 ++++++
 .../briar/android/AndroidEagerSingletons.java |   8 +
 .../AndroidNotificationManagerImpl.java       |  83 ++--
 .../briar}/android/AppModule.java             |  45 +-
 .../briar}/android/BriarApplication.java      |   2 +-
 .../briar}/android/BriarApplicationImpl.java  |  16 +-
 .../briar}/android/BriarService.java          |  17 +-
 .../briar}/android/DestroyableContext.java    |   2 +-
 .../briar}/android/ReferenceManagerImpl.java  |  14 +-
 .../android/StartupFailureActivity.java       |   8 +-
 .../briar}/android/TestingConstants.java      |   4 +-
 .../android/activity/ActivityComponent.java   | 191 ++++++++
 .../android/activity}/ActivityModule.java     |  28 +-
 .../android/activity}/ActivityScope.java      |   2 +-
 .../briar/android/activity}/BaseActivity.java |  14 +-
 .../android/activity}/BriarActivity.java      |  11 +-
 .../activity}/BriarFragmentActivity.java      |  34 +-
 .../briar/android/blog}/BaseController.java   |  22 +-
 .../android/blog}/BaseControllerImpl.java     |  50 +-
 .../briar/android/blog}/BasePostFragment.java |  15 +-
 .../briar/android/blog}/BlogActivity.java     |  14 +-
 .../briar/android/blog}/BlogCommentItem.java  |   6 +-
 .../briar/android/blog}/BlogController.java   |  12 +-
 .../android/blog}/BlogControllerImpl.java     |  40 +-
 .../briar/android/blog}/BlogFragment.java     |  40 +-
 .../briar/android/blog}/BlogItem.java         |   4 +-
 .../briar/android/blog}/BlogModule.java       |   6 +-
 .../briar/android/blog}/BlogPostAdapter.java  |   6 +-
 .../briar/android/blog}/BlogPostFragment.java |  16 +-
 .../briar/android/blog}/BlogPostItem.java     |  14 +-
 .../android/blog}/BlogPostViewHolder.java     |  33 +-
 .../briar/android/blog}/FeedController.java   |  11 +-
 .../android/blog}/FeedControllerImpl.java     |  42 +-
 .../briar/android/blog}/FeedFragment.java     |  32 +-
 .../briar/android/blog}/FeedPostFragment.java |  20 +-
 .../briar/android/blog}/ReblogActivity.java   |  16 +-
 .../briar/android/blog}/ReblogFragment.java   |  34 +-
 .../briar/android/blog}/RssFeedAdapter.java   |  14 +-
 .../android/blog}/RssFeedImportActivity.java  |  16 +-
 .../android/blog}/RssFeedManageActivity.java  |  20 +-
 .../android/blog}/WriteBlogPostActivity.java  |  34 +-
 .../contact/BaseContactListAdapter.java       |   9 +-
 .../briar}/android/contact/ContactItem.java   |   6 +-
 .../contact/ContactItemViewHolder.java        |  13 +-
 .../android/contact/ContactListAdapter.java   |   4 +-
 .../android/contact/ContactListFragment.java  |  81 +--
 .../android/contact/ContactListItem.java      |   8 +-
 .../contact/ContactListItemViewHolder.java    |  21 +-
 .../briar}/android/contact/ContactModule.java |   2 +-
 .../android/contact/ConversationActivity.java | 130 ++---
 .../android/contact/ConversationAdapter.java  |  11 +-
 .../android/contact/ConversationItem.java     |  52 +-
 .../contact/ConversationItemViewHolder.java   |  12 +-
 .../contact/ConversationMessageInItem.java    |   8 +-
 .../contact/ConversationMessageOutItem.java   |   8 +-
 .../ConversationMessageOutViewHolder.java     |   2 +-
 .../contact/ConversationNoticeInItem.java     |  14 +-
 .../ConversationNoticeInViewHolder.java       |   8 +-
 .../contact/ConversationNoticeOutItem.java    |  14 +-
 .../ConversationNoticeOutViewHolder.java      |   8 +-
 .../android/contact/ConversationOutItem.java  |  18 +-
 .../ConversationOutItemViewHolder.java        |   6 +-
 .../contact/ConversationRequestItem.java      |  21 +-
 .../ConversationRequestViewHolder.java        |   8 +-
 .../BaseContactSelectorAdapter.java           |  10 +-
 .../BaseContactSelectorFragment.java          |  35 +-
 .../BaseSelectableContactHolder.java          |  15 +-
 .../ContactSelectorActivity.java              |  19 +-
 .../ContactSelectorAdapter.java               |   8 +-
 .../ContactSelectorController.java            |  19 +
 .../ContactSelectorControllerImpl.java        |  22 +-
 .../ContactSelectorFragment.java              |  10 +-
 .../ContactSelectorListener.java              |   8 +-
 .../SelectableContactHolder.java              |  12 +-
 .../SelectableContactItem.java                |   8 +-
 .../ActivityLifecycleController.java          |   2 +-
 .../android/controller/BriarController.java   |   4 +-
 .../controller/BriarControllerImpl.java       |  10 +-
 .../android/controller/ConfigController.java  |   8 +-
 .../controller/ConfigControllerImpl.java      |  12 +-
 .../android/controller/DbController.java      |   9 +
 .../android/controller/DbControllerImpl.java  |  10 +-
 .../controller/handler/ExceptionHandler.java  |   2 +-
 .../handler/ResultExceptionHandler.java       |   2 +-
 .../controller/handler/ResultHandler.java     |   2 +-
 .../handler/UiExceptionHandler.java           |   6 +-
 .../handler/UiResultExceptionHandler.java     |   6 +-
 .../controller/handler/UiResultHandler.java   |   4 +-
 .../android/forum/CreateForumActivity.java    |  25 +-
 .../briar}/android/forum/ForumActivity.java   |  34 +-
 .../briar/android/forum/ForumController.java  |  12 +
 .../android/forum/ForumControllerImpl.java    |  53 +-
 .../briar/android/forum/ForumItem.java        |  25 +
 .../android/forum/ForumListAdapter.java       |  20 +-
 .../android/forum/ForumListFragment.java      |  57 ++-
 .../briar}/android/forum/ForumListItem.java   |   8 +-
 .../briar}/android/forum/ForumModule.java     |   6 +-
 .../android/fragment/BaseEventFragment.java   |   6 +-
 .../briar}/android/fragment/BaseFragment.java |   9 +-
 .../introduction/ContactChooserFragment.java  |  30 +-
 .../introduction/IntroductionActivity.java    |  15 +-
 .../IntroductionMessageFragment.java          |  28 +-
 .../invitation/AddContactActivity.java        |  34 +-
 .../android/invitation/AddContactView.java    |   2 +-
 .../invitation/ChooseIdentityView.java        |   8 +-
 .../invitation/ConfirmationCodeView.java      |   5 +-
 .../briar}/android/invitation/ErrorView.java  |   8 +-
 .../invitation/InvitationCodeView.java        |   5 +-
 .../android/keyagreement}/CameraView.java     |   7 +-
 .../android/keyagreement/IntroFragment.java   |  24 +-
 .../keyagreement/KeyAgreementActivity.java    |  41 +-
 .../keyagreement}/PreviewConsumer.java        |   7 +-
 .../android/keyagreement}/QrCodeDecoder.java  |  15 +-
 .../android/keyagreement}/QrCodeUtils.java    |  11 +-
 .../keyagreement/ShowQrCodeFragment.java      |  58 +--
 .../login}/ChangePasswordActivity.java        |  24 +-
 .../android/login}/PasswordActivity.java      |  15 +-
 .../android/login/PasswordController.java     |  15 +
 .../login}/PasswordControllerImpl.java        |  17 +-
 .../briar/android/login}/SetupActivity.java   |  25 +-
 .../briar/android/login/SetupController.java  |  14 +
 .../android/login}/SetupControllerImpl.java   |  16 +-
 .../briar/android/login}/StrengthMeter.java   |  10 +-
 .../android/navdrawer}/NavDrawerActivity.java |  76 +--
 .../navdrawer/NavDrawerController.java        |  12 +
 .../navdrawer}/NavDrawerControllerImpl.java   |  27 +-
 .../navdrawer/TransportStateListener.java     |   9 +
 .../briar}/android/panic/ExitActivity.java    |   6 +-
 .../panic/PanicPreferencesActivity.java       |   8 +-
 .../panic/PanicPreferencesFragment.java       |   7 +-
 .../android/panic/PanicResponderActivity.java |  16 +-
 .../privategroup/VisibilityHelper.java        |   8 +-
 .../conversation/GroupActivity.java           |  44 +-
 .../conversation/GroupController.java         |  32 ++
 .../conversation/GroupControllerImpl.java     |  61 +--
 .../conversation/GroupConversationModule.java |   6 +-
 .../conversation/GroupMessageAdapter.java     |  18 +-
 .../conversation/GroupMessageItem.java        |  16 +-
 .../conversation/JoinMessageItem.java         |  15 +-
 .../JoinMessageItemViewHolder.java            |  28 +-
 .../creation/BaseGroupInviteActivity.java     |  23 +-
 .../creation/CreateGroupActivity.java         |  24 +-
 .../creation/CreateGroupController.java       |  23 +
 .../creation/CreateGroupControllerImpl.java   |  48 +-
 .../creation/CreateGroupFragment.java         |  10 +-
 .../creation/CreateGroupListener.java         |   4 +-
 .../creation/CreateGroupMessageFragment.java  |   8 +-
 .../creation/GroupCreateModule.java           |   6 +-
 .../creation/GroupInviteActivity.java         |  10 +-
 .../creation/GroupInviteFragment.java         |  21 +-
 .../invitation/GroupInvitationActivity.java   |  18 +-
 .../invitation/GroupInvitationAdapter.java    |   6 +-
 .../invitation/GroupInvitationController.java |  10 +
 .../GroupInvitationControllerImpl.java        |  34 +-
 .../invitation/GroupInvitationModule.java     |   4 +-
 .../invitation/GroupInvitationViewHolder.java |  30 ++
 .../android/privategroup/list/GroupItem.java  |  16 +-
 .../privategroup/list/GroupListAdapter.java   |  17 +-
 .../list/GroupListController.java             |  20 +-
 .../list/GroupListControllerImpl.java         |  54 +-
 .../privategroup/list/GroupListFragment.java  |  34 +-
 .../privategroup/list/GroupListModule.java    |   4 +-
 .../privategroup/list/GroupViewHolder.java    |  25 +-
 .../memberlist/GroupMemberListActivity.java   |  26 +-
 .../memberlist/GroupMemberListController.java |  15 +
 .../GroupMemberListControllerImpl.java        |  20 +-
 .../memberlist/GroupMemberModule.java         |   4 +-
 .../memberlist/MemberListAdapter.java         |   6 +-
 .../memberlist/MemberListItem.java            |  37 ++
 .../memberlist/MemberListItemHolder.java      |  16 +-
 .../reveal/GroupRevealModule.java             |   4 +-
 .../reveal/RevealContactsActivity.java        |  24 +-
 .../reveal/RevealContactsController.java      |  25 +
 .../reveal/RevealContactsControllerImpl.java  |  44 +-
 .../reveal/RevealContactsFragment.java        |  20 +-
 .../reveal/RevealableContactAdapter.java      |  10 +-
 .../reveal/RevealableContactItem.java         |  26 +
 .../reveal/RevealableContactViewHolder.java   |  22 +-
 .../android/reporting}/BriarReportPrimer.java |   6 +-
 .../android/reporting}/BriarReportSender.java |  12 +-
 .../reporting}/BriarReportSenderFactory.java  |   4 +-
 .../android/reporting}/DevReportActivity.java |   6 +-
 .../android/settings}/SettingsActivity.java   |  13 +-
 .../android/settings}/SettingsFragment.java   |  31 +-
 .../android/sharing/BaseMessageFragment.java  |  18 +-
 .../sharing/BlogInvitationActivity.java       |  14 +-
 .../sharing/BlogInvitationController.java     |   7 +
 .../sharing/BlogInvitationControllerImpl.java |  32 +-
 .../sharing/BlogSharingStatusActivity.java    |  21 +-
 .../sharing/ForumInvitationActivity.java      |  14 +-
 .../sharing/ForumInvitationController.java    |   7 +
 .../ForumInvitationControllerImpl.java        |  35 +-
 .../sharing/ForumSharingStatusActivity.java   |  21 +-
 .../android/sharing/InvitationActivity.java   |  27 +-
 .../android/sharing/InvitationAdapter.java    |   8 +-
 .../android/sharing/InvitationController.java |  28 ++
 .../sharing/InvitationControllerImpl.java     |  32 +-
 .../android/sharing/InvitationViewHolder.java |  13 +-
 .../briar}/android/sharing/ShareActivity.java |  24 +-
 .../android/sharing/ShareBlogActivity.java    |  20 +-
 .../android/sharing/ShareBlogController.java  |  18 +
 .../sharing/ShareBlogControllerImpl.java      |  34 +-
 .../android/sharing/ShareBlogFragment.java    |  18 +-
 .../sharing/ShareBlogMessageFragment.java     |   6 +-
 .../android/sharing/ShareForumActivity.java   |  20 +-
 .../android/sharing/ShareForumController.java |  18 +
 .../sharing/ShareForumControllerImpl.java     |  34 +-
 .../android/sharing/ShareForumFragment.java   |  18 +-
 .../sharing/ShareForumMessageFragment.java    |   6 +-
 .../sharing/SharingInvitationAdapter.java     |   7 +-
 .../sharing/SharingInvitationViewHolder.java  |  17 +-
 .../briar}/android/sharing/SharingModule.java |   6 +-
 .../sharing/SharingStatusActivity.java        |  16 +-
 .../android/sharing/SharingStatusAdapter.java |  10 +-
 .../android/splash}/ExpiredActivity.java      |   6 +-
 .../android/splash}/SplashScreenActivity.java |  16 +-
 .../threaded/BaseThreadItemViewHolder.java    |  12 +-
 .../android/threaded/NestedTreeList.java      |   8 +-
 .../briar}/android/threaded/ThreadItem.java   |  22 +-
 .../android/threaded/ThreadItemAdapter.java   |  16 +-
 .../android/threaded/ThreadListActivity.java  |  37 +-
 .../threaded/ThreadListController.java        |  23 +-
 .../threaded/ThreadListControllerImpl.java    |  46 +-
 .../threaded/ThreadPostViewHolder.java        |  10 +-
 .../briar}/android/util/BriarAdapter.java     |   5 +-
 .../briar/android/util/UiUtils.java}          |  77 +--
 .../briar}/android/util/UserFeedback.java     |   2 +-
 .../briar}/android/util/VersionedAdapter.java |   2 +-
 .../android/view/ArticleMovementMethod.java   |   2 +-
 .../briar}/android/view/AuthorView.java       |  23 +-
 .../android/view/BriarRecyclerView.java       |   9 +-
 .../view/BriarRecyclerViewBehavior.java       |   2 +-
 .../android/view/LargeTextInputView.java      |   8 +-
 .../briar}/android/view/TextAvatarView.java   |  15 +-
 .../briar}/android/view/TextInputView.java    |   7 +-
 .../android/view/TrustIndicatorView.java      |   8 +-
 .../android/widget/LinkDialogFragment.java    |   4 +-
 .../widget/PreferenceDividerDecoration.java   |  52 +-
 .../android}/AndroidNotificationManager.java  |   6 +-
 .../briar/api/android}/ReferenceManager.java  |   2 +-
 .../java}/org/thoughtcrime/securesms/LICENSE  |   0
 .../components/KeyboardAwareLinearLayout.java |   5 +-
 .../components/RepeatableImageKey.java        |   0
 .../components/emoji/AnimatingImageSpan.java  |   0
 .../components/emoji/EmojiDrawer.java         |   5 +-
 .../components/emoji/EmojiEditText.java       |   5 +-
 .../components/emoji/EmojiFilter.java         |   5 +-
 .../components/emoji/EmojiPageModel.java      |   3 +-
 .../components/emoji/EmojiPageView.java       |   5 +-
 .../components/emoji/EmojiPages.java          |   2 +-
 .../components/emoji/EmojiProvider.java       |   8 +-
 .../securesms/components/emoji/EmojiSpan.java |   2 +-
 .../components/emoji/EmojiTextView.java       |   3 +-
 .../components/emoji/EmojiToggle.java         |   5 +-
 .../securesms/components/emoji/EmojiView.java |   5 +-
 .../emoji/RecentEmojiPageModel.java           |  16 +-
 .../emoji/StaticEmojiPageModel.java           |   3 +-
 .../components/util/FutureTaskListener.java   |   0
 .../components/util/ListenableFutureTask.java |   4 +-
 .../util/BitmapDecodingException.java         |   0
 .../securesms/util/BitmapUtil.java            |   0
 .../main}/res/drawable-hdpi/ic_launcher.png   | Bin
 .../{ => src/main}/res/drawable-hdpi/logo.png | Bin
 .../main}/res/drawable-hdpi/msg_in.9.png      | Bin
 .../main}/res/drawable-hdpi/msg_in_top.9.png  | Bin
 .../main}/res/drawable-hdpi/msg_out.9.png     | Bin
 .../main}/res/drawable-hdpi/msg_out_top.9.png | Bin
 .../main}/res/drawable-hdpi/notice_in.9.png   | Bin
 .../res/drawable-hdpi/notice_in_bottom.9.png  | Bin
 .../main}/res/drawable-hdpi/notice_out.9.png  | Bin
 .../res/drawable-hdpi/notice_out_bottom.9.png | Bin
 .../ongoing_notification_icon.png             | Bin
 .../main}/res/drawable-ldpi/ic_launcher.png   | Bin
 .../{ => src/main}/res/drawable-ldpi/logo.png | Bin
 .../ongoing_notification_icon.png             | Bin
 .../main}/res/drawable-mdpi/ic_launcher.png   | Bin
 .../{ => src/main}/res/drawable-mdpi/logo.png | Bin
 .../main}/res/drawable-mdpi/msg_in.9.png      | Bin
 .../main}/res/drawable-mdpi/msg_in_top.9.png  | Bin
 .../main}/res/drawable-mdpi/msg_out.9.png     | Bin
 .../main}/res/drawable-mdpi/msg_out_top.9.png | Bin
 .../main}/res/drawable-mdpi/notice_in.9.png   | Bin
 .../res/drawable-mdpi/notice_in_bottom.9.png  | Bin
 .../main}/res/drawable-mdpi/notice_out.9.png  | Bin
 .../res/drawable-mdpi/notice_out_bottom.9.png | Bin
 .../ongoing_notification_icon.png             | Bin
 .../main}/res/drawable-xhdpi/ic_launcher.png  | Bin
 .../main}/res/drawable-xhdpi/logo.png         | Bin
 .../main}/res/drawable-xhdpi/msg_in.9.png     | Bin
 .../main}/res/drawable-xhdpi/msg_in_top.9.png | Bin
 .../main}/res/drawable-xhdpi/msg_out.9.png    | Bin
 .../res/drawable-xhdpi/msg_out_top.9.png      | Bin
 .../main}/res/drawable-xhdpi/notice_in.9.png  | Bin
 .../res/drawable-xhdpi/notice_in_bottom.9.png | Bin
 .../main}/res/drawable-xhdpi/notice_out.9.png | Bin
 .../drawable-xhdpi/notice_out_bottom.9.png    | Bin
 .../ongoing_notification_icon.png             | Bin
 .../main}/res/drawable-xxhdpi/msg_in.9.png    | Bin
 .../res/drawable-xxhdpi/msg_in_top.9.png      | Bin
 .../main}/res/drawable-xxhdpi/msg_out.9.png   | Bin
 .../res/drawable-xxhdpi/msg_out_top.9.png     | Bin
 .../main}/res/drawable-xxhdpi/notice_in.9.png | Bin
 .../drawable-xxhdpi/notice_in_bottom.9.png    | Bin
 .../res/drawable-xxhdpi/notice_out.9.png      | Bin
 .../drawable-xxhdpi/notice_out_bottom.9.png   | Bin
 .../res/drawable/action_delete_black.xml      |   0
 .../res/drawable/action_delete_white.xml      |   0
 .../res/drawable/alerts_and_states_error.xml  |   0
 .../{ => src/main}/res/drawable/blogs.xml     |   0
 .../{ => src/main}/res/drawable/bluetooth.xml |   0
 .../main}/res/drawable/border_explanation.xml |   0
 .../main}/res/drawable/border_spinner.xml     |   0
 .../main}/res/drawable/briar_logo_large.png   | Bin
 .../{ => src/main}/res/drawable/bubble.xml    |   0
 .../main}/res/drawable/bubble_problem.xml     |   0
 .../main}/res/drawable/bubble_white.xml       |   0
 .../main}/res/drawable/chevron48dp_down.xml   |   0
 .../main}/res/drawable/chevron48dp_up.xml     |   0
 .../main}/res/drawable/contact_connected.xml  |   0
 .../res/drawable/contact_disconnected.xml     |   0
 .../main}/res/drawable/contact_offline.xml    |   0
 .../main}/res/drawable/contact_online.xml     |   0
 .../res/drawable/forum_item_create_white.xml  |   0
 .../main}/res/drawable/ic_add_white.xml       |   0
 .../main}/res/drawable/ic_backspace_black.xml |   0
 .../main}/res/drawable/ic_check_white.xml     |   0
 .../res/drawable/ic_contact_introduction.xml  |   0
 .../main}/res/drawable/ic_contacts.xml        |   0
 .../main}/res/drawable/ic_emoji_activity.xml  |   0
 .../res/drawable/ic_emoji_animals_nature.xml  |   0
 .../main}/res/drawable/ic_emoji_emoticons.xml |   0
 .../main}/res/drawable/ic_emoji_flags.xml     |   0
 .../res/drawable/ic_emoji_food_drink.xml      |   0
 .../main}/res/drawable/ic_emoji_objects.xml   |   0
 .../main}/res/drawable/ic_emoji_recent.xml    |   0
 .../res/drawable/ic_emoji_smiley_people.xml   |   0
 .../main}/res/drawable/ic_emoji_symbols.xml   |   0
 .../main}/res/drawable/ic_emoji_toggle.xml    |   0
 .../res/drawable/ic_emoji_travel_places.xml   |   0
 .../res/drawable/ic_forums_black_24dp.xml     |   0
 .../{ => src/main}/res/drawable/ic_group.xml  |   0
 .../main}/res/drawable/ic_group_white.xml     |   0
 .../main}/res/drawable/ic_info_white.xml      |   0
 .../main}/res/drawable/ic_keyboard_black.xml  |   0
 .../res/drawable/ic_more_vert_accent.xml      |   0
 .../res/drawable/ic_our_identity_black.xml    |   0
 .../{ => src/main}/res/drawable/ic_repeat.xml |   0
 .../res/drawable/ic_settings_black_24dp.xml   |   0
 .../res/drawable/ic_signout_black_24dp.xml    |   0
 .../main}/res/drawable/ic_visibility.xml      |   0
 .../main}/res/drawable/ic_visibility_off.xml  |   0
 .../res/drawable/ic_visibility_white.xml      |   0
 .../drawable/introduction_notification.xml    |   0
 .../main}/res/drawable/introduction_white.xml |   0
 .../res/drawable/level_indicator_circle.xml   |   0
 .../main}/res/drawable/message_delivered.xml  |   0
 .../res/drawable/message_delivered_white.xml  |   0
 .../drawable/message_notification_icon.xml    |   0
 .../main}/res/drawable/message_sent.xml       |   0
 .../main}/res/drawable/message_sent_white.xml |   0
 .../main}/res/drawable/message_stored.xml     |   0
 .../res/drawable/message_stored_white.xml     |   0
 .../main}/res/drawable/navigation_accept.xml  |   0
 .../res/drawable/navigation_drawer_header.png | Bin
 .../res/drawable/qr_code_explanation.xml      |   0
 .../main}/res/drawable/qr_code_intro.xml      |   0
 .../main}/res/drawable/selector_chevron.xml   |   0
 .../res/drawable/social_send_now_white.xml    |   0
 .../main}/res/drawable/social_share_white.xml |   0
 .../main}/res/drawable/transport_bt.xml       |   0
 .../main}/res/drawable/transport_lan.xml      |   0
 .../main}/res/drawable/transport_tor.xml      |   0
 .../drawable/trust_indicator_anonymous.xml    |   0
 .../res/drawable/trust_indicator_unknown.xml  |   0
 .../drawable/trust_indicator_unverified.xml   |   0
 .../res/drawable/trust_indicator_verified.xml |   0
 .../layout-land/fragment_keyagreement_id.xml  |   0
 .../invitation_bluetooth_start.xml            |   0
 .../res/layout/activity_change_password.xml   |   4 +-
 .../res/layout/activity_conversation.xml      |   4 +-
 .../res/layout/activity_create_forum.xml      |   0
 .../main}/res/layout/activity_dev_report.xml  |   2 +-
 .../main}/res/layout/activity_expired.xml     |   0
 .../main}/res/layout/activity_forum.xml       |   4 +-
 .../layout/activity_fragment_container.xml    |   0
 .../main}/res/layout/activity_nav_drawer.xml  |   0
 .../res/layout/activity_panic_preferences.xml |   2 +-
 .../main}/res/layout/activity_password.xml    |   0
 .../main}/res/layout/activity_plain.xml       |   0
 .../res/layout/activity_reveal_contacts.xml   |   0
 .../res/layout/activity_rss_feed_import.xml   |   0
 .../res/layout/activity_rss_feed_manage.xml   |   2 +-
 .../main}/res/layout/activity_settings.xml    |   2 +-
 .../main}/res/layout/activity_setup.xml       |   4 +-
 .../res/layout/activity_sharing_status.xml    |   4 +-
 .../res/layout/activity_startup_failure.xml   |   0
 .../res/layout/activity_with_loading.xml      |   0
 .../res/layout/activity_write_blog_post.xml   |   4 +-
 .../{ => src/main}/res/layout/author_view.xml |   2 +-
 .../main}/res/layout/briar_recycler_view.xml  |   0
 .../res/layout/contact_avatar_status.xml      |   0
 .../main}/res/layout/emoji_drawer.xml         |   0
 .../main}/res/layout/emoji_grid_layout.xml    |   0
 .../main}/res/layout/fragment_blog.xml        |   4 +-
 .../main}/res/layout/fragment_blog_post.xml   |   0
 .../res/layout/fragment_blog_post_pager.xml   |   0
 .../res/layout/fragment_create_group.xml      |   0
 .../main}/res/layout/fragment_forum_list.xml  |   4 +-
 .../res/layout/fragment_keyagreement_id.xml   |   0
 .../res/layout/fragment_keyagreement_qr.xml   |   2 +-
 .../main}/res/layout/fragment_link_dialog.xml |   0
 .../main}/res/layout/fragment_message.xml     |   2 +-
 .../main}/res/layout/fragment_reblog.xml      |   2 +-
 .../main}/res/layout/introduction_message.xml |   2 +-
 ...invitation_bluetooth_confirmation_code.xml |   0
 .../invitation_bluetooth_invitation_code.xml  |   0
 .../res/layout/invitation_bluetooth_start.xml |   0
 .../main}/res/layout/invitation_error.xml     |   0
 .../{ => src/main}/res/layout/list.xml        |   2 +-
 .../main}/res/layout/list_item_blog.xml       |   2 +-
 .../res/layout/list_item_blog_comment.xml     |   2 +-
 .../main}/res/layout/list_item_blog_post.xml  |   4 +-
 .../main}/res/layout/list_item_contact.xml    |   0
 .../res/layout/list_item_contact_small.xml    |   0
 .../layout/list_item_conversation_msg_in.xml  |   0
 .../layout/list_item_conversation_msg_out.xml |   0
 .../list_item_conversation_notice_in.xml      |   0
 .../list_item_conversation_notice_out.xml     |   0
 .../layout/list_item_conversation_request.xml |   0
 .../main}/res/layout/list_item_crash.xml      |   0
 .../main}/res/layout/list_item_forum.xml      |   2 +-
 .../main}/res/layout/list_item_group.xml      |   2 +-
 .../layout/list_item_group_join_notice.xml    |   2 +-
 .../res/layout/list_item_group_member.xml     |   2 +-
 .../res/layout/list_item_invitations.xml      |   2 +-
 .../layout/list_item_revealable_contact.xml   |   0
 .../main}/res/layout/list_item_rss_feed.xml   |   0
 .../layout/list_item_selectable_contact.xml   |   0
 .../main}/res/layout/list_item_thread.xml     |   2 +-
 .../main}/res/layout/list_item_transport.xml  |   0
 .../main}/res/layout/navigation_header.xml    |   0
 .../main}/res/layout/navigation_menu.xml      |   0
 .../{ => src/main}/res/layout/splash.xml      |   0
 .../main}/res/layout/text_avatar_view.xml     |   0
 .../main}/res/layout/text_input_view.xml      |   0
 .../res/layout/text_input_view_large.xml      |   0
 .../main}/res/layout/transports_list.xml      |   0
 .../main}/res/layout/view_code_entry.xml      |   0
 .../main}/res/menu/blogs_blog_actions.xml     |   0
 .../main}/res/menu/blogs_feed_actions.xml     |   0
 .../main}/res/menu/contact_list_actions.xml   |   0
 .../res/menu/contact_selection_actions.xml    |   0
 .../main}/res/menu/conversation_actions.xml   |   0
 .../main}/res/menu/dev_report_actions.xml     |   0
 .../{ => src/main}/res/menu/forum_actions.xml |   0
 .../main}/res/menu/forum_list_actions.xml     |   0
 .../{ => src/main}/res/menu/group_actions.xml |   0
 .../main}/res/menu/group_reveal_actions.xml   |   0
 .../main}/res/menu/groups_list_actions.xml    |   0
 .../main}/res/menu/navigation_drawer.xml      |   0
 .../res/menu/rss_feed_manage_actions.xml      |   0
 .../{ => src/main}/res/values-de/strings.xml  |   0
 .../{ => src/main}/res/values-es/strings.xml  |   0
 .../{ => src/main}/res/values-it/strings.xml  |   0
 .../{ => src/main}/res/values-ms/strings.xml  |   0
 .../main}/res/values-pt-rBR/strings.xml       |   0
 .../{ => src/main}/res/values/arrays.xml      |   0
 .../{ => src/main}/res/values/attrs.xml       |   0
 .../{ => src/main}/res/values/color.xml       |   0
 .../{ => src/main}/res/values/dimens.xml      | 130 ++---
 .../{ => src/main}/res/values/emoji.xml       |   0
 .../{ => src/main}/res/values/strings.xml     |   0
 .../{ => src/main}/res/values/styles.xml      |   0
 .../{ => src/main}/res/values/themes.xml      |   0
 .../main}/res/xml/panic_preferences.xml       |   0
 .../{ => src/main}/res/xml/settings.xml       |   4 +-
 .../android/ActivityComponent.java            | 184 -------
 .../android/AndroidComponent.java             | 145 ------
 .../android/AndroidEagerSingletons.java       |   8 -
 .../ContactSelectorController.java            |  19 -
 .../android/controller/DbController.java      |   6 -
 .../controller/NavDrawerController.java       |   9 -
 .../controller/PasswordController.java        |  12 -
 .../android/controller/SetupController.java   |  12 -
 .../controller/TransportStateListener.java    |   9 -
 .../android/forum/ForumController.java        |  10 -
 .../briarproject/android/forum/ForumItem.java |  24 -
 .../conversation/GroupController.java         |  32 --
 .../creation/CreateGroupController.java       |  23 -
 .../invitation/GroupInvitationController.java |   8 -
 .../invitation/GroupInvitationViewHolder.java |  28 --
 .../memberlist/GroupMemberListController.java |  15 -
 .../memberlist/MemberListItem.java            |  39 --
 .../reveal/RevealContactsController.java      |  25 -
 .../reveal/RevealableContactItem.java         |  26 -
 .../sharing/BlogInvitationController.java     |   7 -
 .../sharing/ForumInvitationController.java    |   7 -
 .../android/sharing/InvitationController.java |  28 --
 .../android/sharing/ShareBlogController.java  |  18 -
 .../android/sharing/ShareForumController.java |  19 -
 .../system/AndroidSystemModule.java           |  33 --
 .../android/net/http/AndroidHttpClient.java   |   2 +-
 .../briar}/android/SetupActivityTest.java     |  25 +-
 .../briar}/android/TestBriarApplication.java  |   8 +-
 .../briar}/android/TestSetupActivity.java     |   5 +-
 .../android/forum/ForumActivityTest.java      |  22 +-
 .../android/forum/TestForumActivity.java      |  19 +-
 .../login}/ChangePasswordActivityTest.java    |  22 +-
 .../login}/TestChangePasswordActivity.java    |   5 +-
 briar-api/build.gradle                        |  22 +-
 .../briarproject/briar/api/blog}/Blog.java    |  12 +-
 .../briar/api/blog/BlogCommentHeader.java     |  46 ++
 .../briar/api/blog}/BlogConstants.java        |  20 +-
 .../briar/api/blog/BlogFactory.java           |  21 +
 .../briar/api/blog/BlogInvitationRequest.java |  31 ++
 .../api/blog/BlogInvitationResponse.java      |  21 +
 .../briar/api/blog/BlogManager.java           | 105 ++++
 .../briarproject/briar/api/blog/BlogPost.java |  20 +
 .../briar/api/blog/BlogPostFactory.java       |  54 ++
 .../briar/api/blog/BlogPostHeader.java        |  48 ++
 .../briar/api/blog/BlogSharingManager.java    |  10 +
 .../briar/api/blog}/BlogSharingMessage.java   |  30 +-
 .../briar/api/blog}/MessageType.java          |   3 +-
 .../BlogInvitationRequestReceivedEvent.java   |  21 +
 .../BlogInvitationResponseReceivedEvent.java  |  20 +
 .../api/blog}/event/BlogPostAddedEvent.java   |  16 +-
 .../briar/api/client}/BaseGroup.java          |   8 +-
 .../briar/api/client}/BaseMessageHeader.java  |  19 +-
 .../api/client}/MessageQueueManager.java      |  21 +-
 .../briar/api/client}/MessageTracker.java     |  16 +-
 .../briar/api/client}/MessageTree.java        |  19 +-
 .../briar/api/client}/NamedGroup.java         |   6 +-
 .../briar/api/client}/PostHeader.java         |  20 +-
 .../briar/api/client}/ProtocolEngine.java     |  22 +-
 .../api/client}/ProtocolStateException.java   |   9 +-
 .../briar/api/client}/QueueMessage.java       |  15 +-
 .../briar/api/client/QueueMessageFactory.java |  15 +
 .../briar/api/client/SessionId.java           |  24 +
 .../briar/api/client}/ThreadedMessage.java    |  14 +-
 .../briarproject/briar}/api/feed/Feed.java    |  57 ++-
 .../briar}/api/feed/FeedConstants.java        |   2 +-
 .../briar/api/feed/FeedManager.java           |  34 ++
 .../briarproject/briar}/api/forum/Forum.java  |  10 +-
 .../briar}/api/forum/ForumConstants.java      |  20 +-
 .../briar/api/forum/ForumFactory.java         |  18 +
 .../api/forum/ForumInvitationRequest.java     |  33 ++
 .../api/forum/ForumInvitationResponse.java    |  24 +
 .../briar}/api/forum/ForumManager.java        |  25 +-
 .../briar/api/forum/ForumPost.java            |  21 +
 .../briar/api/forum/ForumPostFactory.java     |  26 +
 .../briar/api/forum/ForumPostHeader.java      |  21 +
 .../briar}/api/forum/ForumSharingManager.java |   6 +-
 .../briar}/api/forum/ForumSharingMessage.java |  34 +-
 .../ForumInvitationRequestReceivedEvent.java  |  21 +
 .../ForumInvitationResponseReceivedEvent.java |  21 +
 .../forum}/event/ForumPostReceivedEvent.java  |  15 +-
 .../api/introduction/IntroduceeAction.java    |  19 +-
 .../introduction/IntroduceeProtocolState.java |  20 +-
 .../api/introduction/IntroducerAction.java    |  18 +-
 .../introduction/IntroducerProtocolState.java |  25 +-
 .../introduction/IntroductionConstants.java   |   4 +-
 .../api/introduction/IntroductionManager.java |  50 ++
 .../api/introduction/IntroductionMessage.java |  43 ++
 .../api/introduction/IntroductionRequest.java |  51 ++
 .../introduction/IntroductionResponse.java    |  43 ++
 .../event/IntroductionAbortedEvent.java       |  12 +-
 .../IntroductionRequestReceivedEvent.java     |  12 +-
 .../IntroductionResponseReceivedEvent.java    |  12 +-
 .../event/IntroductionSucceededEvent.java     |  22 +
 .../api/messaging/ConversationManager.java    |  39 ++
 .../api/messaging/MessagingConstants.java     |  11 +
 .../briar/api/messaging/MessagingManager.java |  47 ++
 .../briar}/api/messaging/PrivateMessage.java  |   6 +-
 .../api/messaging/PrivateMessageFactory.java  |  13 +
 .../api/messaging/PrivateMessageHeader.java   |  20 +
 .../event/PrivateMessageReceivedEvent.java    |  16 +-
 .../briar}/api/privategroup/GroupMember.java  |   8 +-
 .../briar/api/privategroup/GroupMessage.java  |  25 +
 .../api/privategroup/GroupMessageFactory.java |  63 +++
 .../api/privategroup/GroupMessageHeader.java  |  18 +-
 .../api/privategroup/JoinMessageHeader.java   |   7 +-
 .../briar}/api/privategroup/MessageType.java  |  11 +-
 .../briar}/api/privategroup/PrivateGroup.java |  14 +-
 .../privategroup/PrivateGroupConstants.java   |   4 +-
 .../api/privategroup/PrivateGroupFactory.java |  10 +-
 .../api/privategroup/PrivateGroupManager.java |  63 ++-
 .../briar}/api/privategroup/Visibility.java   |  11 +-
 .../ContactRelationshipRevealedEvent.java     |  11 +-
 .../event/GroupDissolvedEvent.java            |  27 +
 .../GroupInvitationRequestReceivedEvent.java  |  21 +
 .../GroupInvitationResponseReceivedEvent.java |  19 +
 .../event/GroupMessageAddedEvent.java         |  12 +-
 .../invitation/GroupInvitationFactory.java    |  16 +-
 .../invitation/GroupInvitationItem.java       |  10 +-
 .../invitation/GroupInvitationManager.java    |  24 +-
 .../invitation/GroupInvitationRequest.java    |  18 +-
 .../invitation/GroupInvitationResponse.java   |  14 +-
 .../briar/api/sharing/InvitationFactory.java  |  10 +
 .../briar}/api/sharing/InvitationItem.java    |   6 +-
 .../briar/api/sharing/InvitationMessage.java  |  36 ++
 .../briar/api/sharing/InvitationRequest.java  |  39 ++
 .../briar/api/sharing/InvitationResponse.java |  28 ++
 .../briar/api/sharing/Shareable.java          |  16 +
 .../briar}/api/sharing/SharingConstants.java  |   4 +-
 .../api/sharing/SharingInvitationItem.java    |   6 +-
 .../briar}/api/sharing/SharingManager.java    |  19 +-
 .../briar}/api/sharing/SharingMessage.java    |  54 +-
 .../event/InvitationRequestReceivedEvent.java |  16 +-
 .../InvitationResponseReceivedEvent.java      |  12 +-
 .../org/briarproject/api/FormatException.java |   9 -
 .../src/org/briarproject/api/UniqueId.java    |  12 -
 .../api/blogs/BlogCommentHeader.java          |  42 --
 .../briarproject/api/blogs/BlogFactory.java   |  18 -
 .../api/blogs/BlogInvitationRequest.java      |  27 -
 .../api/blogs/BlogInvitationResponse.java     |  20 -
 .../briarproject/api/blogs/BlogManager.java   |  70 ---
 .../org/briarproject/api/blogs/BlogPost.java  |  16 -
 .../api/blogs/BlogPostFactory.java            |  47 --
 .../api/blogs/BlogPostHeader.java             |  47 --
 .../api/blogs/BlogSharingManager.java         |  10 -
 .../org/briarproject/api/clients/Client.java  |  12 -
 .../api/clients/ContactGroupFactory.java      |  23 -
 .../api/clients/QueueMessageFactory.java      |  12 -
 .../briarproject/api/clients/SessionId.java   |  19 -
 .../api/contact/ContactExchangeListener.java  |  14 -
 .../api/contact/ContactExchangeTask.java      |  20 -
 .../api/crypto/MessageDigest.java             |  28 --
 .../briarproject/api/crypto/PrivateKey.java   |   8 -
 .../briarproject/api/crypto/PseudoRandom.java |   7 -
 .../briarproject/api/crypto/PublicKey.java    |   8 -
 .../api/crypto/StreamEncrypter.java           |  13 -
 .../api/data/BdfWriterFactory.java            |   8 -
 .../api/data/MetadataEncoder.java             |   9 -
 .../briarproject/api/data/MetadataParser.java |   9 -
 .../briarproject/api/data/ObjectReader.java   |   8 -
 .../event/BlogInvitationReceivedEvent.java    |  15 -
 .../BlogInvitationResponseReceivedEvent.java  |  14 -
 .../api/event/ContactAddedEvent.java          |  23 -
 .../api/event/ContactRemovedEvent.java        |  17 -
 .../api/event/ContactStatusChangedEvent.java  |  23 -
 .../api/event/ContactVerifiedEvent.java       |  18 -
 .../src/org/briarproject/api/event/Event.java |   6 -
 .../org/briarproject/api/event/EventBus.java  |  13 -
 .../briarproject/api/event/EventListener.java |  11 -
 .../event/ForumInvitationReceivedEvent.java   |  15 -
 .../ForumInvitationResponseReceivedEvent.java |  19 -
 .../api/event/GroupAddedEvent.java            |  17 -
 .../api/event/GroupDissolvedEvent.java        |  26 -
 .../GroupInvitationRequestReceivedEvent.java  |  15 -
 .../GroupInvitationResponseReceivedEvent.java |  13 -
 .../api/event/GroupRemovedEvent.java          |  17 -
 .../event/GroupVisibilityUpdatedEvent.java    |  20 -
 .../api/event/IntroductionSucceededEvent.java |  16 -
 .../api/event/KeyAgreementAbortedEvent.java   |  15 -
 .../api/event/KeyAgreementFailedEvent.java    |   6 -
 .../api/event/KeyAgreementFinishedEvent.java  |  17 -
 .../api/event/KeyAgreementListeningEvent.java |  17 -
 .../api/event/KeyAgreementStartedEvent.java   |   6 -
 .../api/event/LocalAuthorAddedEvent.java      |  17 -
 .../api/event/LocalAuthorRemovedEvent.java    |  17 -
 .../api/event/MessageAddedEvent.java          |  35 --
 .../api/event/MessageRequestedEvent.java      |  17 -
 .../api/event/MessageSharedEvent.java         |  17 -
 .../api/event/MessageToAckEvent.java          |  20 -
 .../api/event/MessagesAckedEvent.java         |  27 -
 .../api/event/SettingsUpdatedEvent.java       |  15 -
 .../briarproject/api/event/ShutdownEvent.java |   6 -
 .../api/event/TransportDisabledEvent.java     |  17 -
 .../api/event/TransportEnabledEvent.java      |  17 -
 .../briarproject/api/feed/FeedManager.java    |  24 -
 .../briarproject/api/forum/ForumFactory.java  |  11 -
 .../api/forum/ForumInvitationRequest.java     |  27 -
 .../api/forum/ForumInvitationResponse.java    |  20 -
 .../org/briarproject/api/forum/ForumPost.java |  21 -
 .../api/forum/ForumPostFactory.java           |  22 -
 .../api/forum/ForumPostHeader.java            |  14 -
 .../api/identity/IdentityManager.java         |  26 -
 .../api/introduction/IntroductionManager.java |  48 --
 .../api/introduction/IntroductionMessage.java |  42 --
 .../api/introduction/IntroductionRequest.java |  47 --
 .../introduction/IntroductionResponse.java    |  39 --
 .../api/invitation/InvitationConstants.java   |  11 -
 .../api/invitation/InvitationTaskFactory.java |   8 -
 .../keyagreement/KeyAgreementConstants.java   |  25 -
 .../keyagreement/KeyAgreementTaskFactory.java |   8 -
 .../api/keyagreement/KeyAgreementTaskId.java  |  18 -
 .../api/keyagreement/PayloadEncoder.java      |   6 -
 .../api/lifecycle/LifecycleManager.java       |  79 ---
 .../api/messaging/ConversationManager.java    |  38 --
 .../api/messaging/MessagingConstants.java     |  12 -
 .../api/messaging/MessagingManager.java       |  37 --
 .../api/messaging/PrivateMessageFactory.java  |  13 -
 .../api/messaging/PrivateMessageHeader.java   |  15 -
 .../api/plugins/PluginConfig.java             |  13 -
 .../duplex/DuplexTransportConnection.java     |  20 -
 .../simplex/SimplexPluginCallback.java        |  17 -
 .../api/privategroup/GroupMessage.java        |  25 -
 .../api/privategroup/GroupMessageFactory.java |  60 ---
 .../TransportPropertyConstants.java           |  10 -
 .../api/reliability/ReadHandler.java          |   8 -
 .../reliability/ReliabilityLayerFactory.java  |   7 -
 .../api/reliability/WriteHandler.java         |   8 -
 .../briarproject/api/reporting/DevConfig.java |  10 -
 .../api/reporting/DevReporter.java            |  27 -
 .../briarproject/api/settings/Settings.java   |   8 -
 .../api/settings/SettingsManager.java         |  15 -
 .../api/sharing/InvitationFactory.java        |  10 -
 .../api/sharing/InvitationMessage.java        |  35 --
 .../api/sharing/InvitationRequest.java        |  35 --
 .../api/sharing/InvitationResponse.java       |  24 -
 .../briarproject/api/sharing/Shareable.java   |  14 -
 .../briarproject/api/sync/GroupFactory.java   |   7 -
 .../api/sync/PacketReaderFactory.java         |   8 -
 .../api/sync/PacketWriterFactory.java         |   8 -
 .../org/briarproject/api/sync/Request.java    |  20 -
 .../briarproject/api/sync/SyncConstants.java  |  27 -
 .../api/transport/StreamReaderFactory.java    |  21 -
 .../api/transport/StreamWriterFactory.java    |  21 -
 briar-core/build.gradle                       |  11 +-
 .../briar/BriarCoreEagerSingletons.java       |  29 ++
 .../briarproject/briar/BriarCoreModule.java   |  38 ++
 .../briar/blog}/BlogFactoryImpl.java          |  31 +-
 .../briar/blog}/BlogManagerImpl.java          | 122 ++---
 .../briarproject/briar/blog/BlogModule.java}  |  30 +-
 .../briar/blog}/BlogPostFactoryImpl.java      |  52 +-
 .../briar/blog}/BlogPostValidator.java        |  91 ++--
 .../briar/client}/BdfIncomingMessageHook.java |  39 +-
 .../client/BdfQueueMessageValidator.java      |  71 +++
 .../briar/client/BriarClientModule.java       |  37 ++
 .../briar/client/ConversationClientImpl.java  |  46 ++
 .../client}/MessageQueueManagerImpl.java      |  55 ++-
 .../client/MessageTrackerConstants.java}      |   4 +-
 .../briar/client}/MessageTrackerImpl.java     |  40 +-
 .../briar/client}/MessageTreeImpl.java        |  28 +-
 .../client}/QueueMessageFactoryImpl.java      |  32 +-
 .../briar}/feed/FeedManagerImpl.java          | 109 +++--
 .../briarproject/briar}/feed/FeedModule.java  |   8 +-
 .../briar}/forum/ForumFactoryImpl.java        |  34 +-
 .../briar}/forum/ForumManagerImpl.java        |  91 ++--
 .../briar}/forum/ForumModule.java             |  30 +-
 .../briar/forum/ForumPostFactoryImpl.java     |  55 +++
 .../briar}/forum/ForumPostValidator.java      |  49 +-
 .../briar}/introduction/IntroduceeEngine.java | 133 ++---
 .../introduction/IntroduceeManager.java       | 198 ++++----
 .../briar}/introduction/IntroducerEngine.java | 149 +++---
 .../introduction/IntroducerManager.java       |  93 ++--
 .../IntroductionGroupFactory.java             |  30 ++
 .../introduction/IntroductionManagerImpl.java | 144 +++---
 .../introduction/IntroductionModule.java      |  62 +++
 .../introduction/IntroductionValidator.java   | 188 +++++++
 .../briar/introduction/MessageSender.java     | 125 +++++
 .../messaging/ConversationManagerImpl.java    |  24 +-
 .../messaging/MessagingManagerImpl.java       |  62 +--
 .../briar}/messaging/MessagingModule.java     |  31 +-
 .../messaging/PrivateMessageFactoryImpl.java  |  40 ++
 .../messaging/PrivateMessageValidator.java    |  46 ++
 .../briar}/privategroup/GroupConstants.java   |   4 +-
 .../privategroup/GroupMessageFactoryImpl.java |  32 +-
 .../privategroup/GroupMessageValidator.java   |  83 ++--
 .../privategroup/PrivateGroupFactoryImpl.java |  32 +-
 .../privategroup/PrivateGroupManagerImpl.java | 128 ++---
 .../privategroup/PrivateGroupModule.java      |  22 +-
 .../privategroup/invitation/AbortMessage.java |   8 +-
 .../invitation/AbstractProtocolEngine.java    |  62 +--
 .../invitation/CreatorProtocolEngine.java     |  54 +-
 .../invitation/CreatorSession.java            |  12 +-
 .../privategroup/invitation/CreatorState.java |   9 +-
 .../invitation/GroupInvitationConstants.java  |   2 +-
 .../GroupInvitationFactoryImpl.java           |  28 +-
 .../GroupInvitationManagerImpl.java           |  94 ++--
 .../invitation/GroupInvitationMessage.java    |   8 +-
 .../invitation/GroupInvitationModule.java     |  28 +-
 .../invitation/GroupInvitationValidator.java  |  62 +--
 .../invitation/InviteMessage.java             |  10 +-
 .../invitation/InviteeProtocolEngine.java     |  64 +--
 .../invitation/InviteeSession.java            |  12 +-
 .../privategroup/invitation/InviteeState.java |   9 +-
 .../privategroup/invitation/JoinMessage.java  |  10 +-
 .../privategroup/invitation/LeaveMessage.java |  10 +-
 .../privategroup/invitation/LocalAction.java  |   2 +-
 .../invitation/MessageEncoder.java            |  16 +-
 .../invitation/MessageEncoderImpl.java        |  44 +-
 .../invitation/MessageMetadata.java           |   9 +-
 .../invitation/MessageParser.java             |  16 +-
 .../invitation/MessageParserImpl.java         |  42 +-
 .../privategroup/invitation/MessageType.java  |   9 +-
 .../invitation/PeerProtocolEngine.java        |  54 +-
 .../privategroup/invitation/PeerSession.java  |  12 +-
 .../privategroup/invitation/PeerState.java    |   9 +-
 .../invitation/ProtocolEngine.java            |  10 +-
 .../invitation/ProtocolEngineFactory.java     |   4 +-
 .../invitation/ProtocolEngineFactoryImpl.java |  20 +-
 .../briar}/privategroup/invitation/Role.java  |   9 +-
 .../privategroup/invitation/Session.java      |   8 +-
 .../invitation/SessionEncoder.java            |  10 +
 .../invitation/SessionEncoderImpl.java        |  47 ++
 .../invitation/SessionParser.java             |  12 +-
 .../invitation/SessionParserImpl.java         |  38 +-
 .../briar/privategroup/invitation/State.java  |   6 +
 .../sharing/BlogInviteeSessionState.java      |  47 ++
 .../briar/sharing/BlogSharerSessionState.java |  49 ++
 .../sharing/BlogSharingManagerImpl.java       |  95 ++--
 .../briar/sharing/BlogSharingValidator.java   |  92 ++++
 .../sharing/ForumInviteeSessionState.java     |  47 ++
 .../sharing/ForumSharerSessionState.java      |  24 +-
 .../sharing/ForumSharingManagerImpl.java      |  83 ++--
 .../briar/sharing/ForumSharingValidator.java  |  89 ++++
 .../briar/sharing/InvitationFactory.java      |  11 +
 .../InvitationReceivedEventFactory.java       |  10 +
 ...nvitationResponseReceivedEventFactory.java |  10 +
 .../briar}/sharing/InviteeEngine.java         |  76 +--
 .../briar}/sharing/InviteeSessionState.java   |  50 +-
 .../sharing/InviteeSessionStateFactory.java   |  20 +
 .../briar/sharing/ShareableFactory.java       |  26 +
 .../briar}/sharing/SharerEngine.java          |  45 +-
 .../briar}/sharing/SharerSessionState.java    |  43 +-
 .../sharing/SharerSessionStateFactory.java    |  21 +
 .../briar}/sharing/SharingManagerImpl.java    | 179 +++----
 .../briar}/sharing/SharingModule.java         |  56 +--
 .../briar}/sharing/SharingSessionState.java   |  46 +-
 .../briarproject/briar}/util/HtmlUtils.java   |   8 +-
 .../org/briarproject/CoreEagerSingletons.java |  59 ---
 .../src/org/briarproject/CoreModule.java      |  86 ----
 .../clients/BdfMessageValidator.java          | 139 ------
 .../briarproject/clients/ClientsModule.java   |  60 ---
 .../clients/ConversationClientImpl.java       |  43 --
 .../org/briarproject/crypto/Signature.java    |  34 --
 .../data/BdfReaderFactoryImpl.java            |  21 -
 .../data/BdfWriterFactoryImpl.java            |  13 -
 .../org/briarproject/db/DbStateException.java |   9 -
 .../forum/ForumPostFactoryImpl.java           |  50 --
 .../briarproject/identity/AuthorReader.java   |  30 --
 .../IntroductionGroupFactory.java             |  30 --
 .../introduction/IntroductionModule.java      |  62 ---
 .../introduction/IntroductionValidator.java   | 183 -------
 .../introduction/MessageSender.java           | 125 -----
 .../invitation/InvitationModule.java          |  32 --
 .../keyagreement/AbortException.java          |  23 -
 .../messaging/PrivateMessageFactoryImpl.java  |  38 --
 .../messaging/PrivateMessageValidator.java    |  41 --
 .../plugins/BackoffFactoryImpl.java           |  13 -
 .../briarproject/plugins/tcp/PortMapper.java  |   6 -
 .../privategroup/invitation/InviteAction.java |  35 --
 .../invitation/SessionEncoder.java            |  10 -
 .../invitation/SessionEncoderImpl.java        |  47 --
 .../privategroup/invitation/State.java        |   6 -
 .../TransportPropertyValidator.java           |  53 --
 .../ReliabilityLayerFactoryImpl.java          |  28 --
 .../reporting/ReportingModule.java            |  20 -
 .../sharing/BlogInviteeSessionState.java      |  47 --
 .../sharing/BlogSharerSessionState.java       |  48 --
 .../sharing/BlogSharingValidator.java         |  88 ----
 .../sharing/ForumInviteeSessionState.java     |  43 --
 .../sharing/ForumSharingValidator.java        |  85 ----
 .../sharing/InvitationFactory.java            |   9 -
 .../InvitationReceivedEventFactory.java       |   8 -
 ...nvitationResponseReceivedEventFactory.java |   8 -
 .../sharing/InviteeSessionStateFactory.java   |  20 -
 .../sharing/ShareableFactory.java             |  24 -
 .../sharing/SharerSessionStateFactory.java    |  19 -
 .../briarproject/sync/GroupFactoryImpl.java   |  27 -
 .../sync/PacketReaderFactoryImpl.java         |  23 -
 .../sync/PacketWriterFactoryImpl.java         |  13 -
 .../transport/TransportKeyManager.java        |  24 -
 .../transport/TransportKeyManagerFactory.java |  10 -
 briar-desktop/build.gradle                    |  17 -
 .../file/LinuxRemovableDriveMonitor.java      |   9 -
 .../file/MacRemovableDriveMonitor.java        |   9 -
 .../plugins/modem/ModemFactory.java           |   6 -
 .../plugins/modem/SerialPortList.java         |   6 -
 .../plugins/modem/SerialPortListImpl.java     |   8 -
 briar-tests/build.gradle                      |   6 +-
 .../org/briarproject/ImmediateExecutor.java   |   4 +
 .../org/briarproject/TestDatabaseConfig.java  |   6 +-
 .../org/briarproject/TestSeedProvider.java    |   5 +-
 .../src/org/briarproject/TestUtils.java       |  14 +-
 .../org/briarproject/ValidatorTestCase.java   |  18 +-
 .../client}/BdfMessageValidatorTest.java      |  42 +-
 .../client}/ClientHelperImplTest.java         |  40 +-
 .../contact/ContactManagerImplTest.java       |  20 +-
 .../{ => bramble}/crypto/AsciiArmourTest.java |   2 +-
 .../crypto/Blake2sDigestTest.java             |   4 +-
 .../EllipticCurveMultiplicationTest.java      |   4 +-
 .../crypto/EllipticCurvePerformanceTest.java  |   6 +-
 .../crypto/FortunaGeneratorTest.java          |   2 +-
 .../crypto/FortunaSecureRandomTest.java       |  10 +-
 .../crypto/KeyAgreementTest.java              |  10 +-
 .../crypto/KeyDerivationTest.java             |  12 +-
 .../crypto/KeyEncodingAndParsingTest.java     |  14 +-
 .../{ => bramble}/crypto/MacTest.java         |   6 +-
 .../crypto/MessageEncrypterTest.java          |  11 +-
 .../crypto/PasswordBasedKdfTest.java          |   2 +-
 .../PasswordStrengthEstimatorImplTest.java    |   6 +-
 .../{ => bramble}/crypto/SignatureTest.java   |   6 +-
 .../crypto/StreamDecrypterImplTest.java       |  16 +-
 .../crypto/StreamEncrypterImplTest.java       |  12 +-
 .../crypto/TestAuthenticatedCipher.java       |  11 +-
 ...alsa20Poly1305AuthenticatedCipherTest.java |   6 +-
 .../{ => bramble}/data/BdfDictionaryTest.java |  16 +-
 .../{ => bramble}/data/BdfListTest.java       |  14 +-
 .../{ => bramble}/data/BdfReaderImplTest.java |  14 +-
 .../{ => bramble}/data/BdfWriterImplTest.java |  18 +-
 .../MetadataEncoderParserIntegrationTest.java |  31 +-
 .../{ => bramble}/db/BasicH2Test.java         |  17 +-
 .../db/DatabaseComponentImplTest.java         | 115 ++---
 .../db/ExponentialBackoffTest.java            |   2 +-
 .../{ => bramble}/db/H2DatabaseTest.java      |  65 ++-
 .../{ => bramble/db}/LockFairnessTest.java    |   3 +-
 .../db/TransactionIsolationTest.java          |   2 +-
 .../identity/IdentityManagerImplTest.java     |  28 +-
 .../KeyAgreementProtocolTest.java             |  16 +-
 .../lifecycle/ShutdownManagerImplTest.java    |  10 +-
 .../WindowsShutdownManagerImplTest.java       |  83 ++--
 .../plugin}/BackoffImplTest.java              |   2 +-
 .../plugin}/ConnectionRegistryImplTest.java   |  18 +-
 .../plugin}/PluginManagerImplTest.java        |  28 +-
 .../plugin}/PollerTest.java                   |  32 +-
 .../file/LinuxRemovableDriveFinderTest.java   |   2 +-
 .../file/MacRemovableDriveFinderTest.java     |   2 +-
 .../PollingRemovableDriveMonitorTest.java     |  16 +-
 .../file/RemovableDrivePluginTest.java        |  22 +-
 .../file/UnixRemovableDriveMonitorTest.java   | 213 ++++----
 .../plugin}/modem/CountryCodesTest.java       |   2 +-
 .../plugin}/modem/ModemPluginTest.java        |   8 +-
 .../plugin}/tcp/LanTcpPluginTest.java         |  28 +-
 .../TransportPropertyManagerImplTest.java     |   2 +-
 .../TransportPropertyValidatorTest.java       |  30 +-
 .../sync/PacketReaderImplTest.java            |  18 +-
 .../sync/SimplexOutgoingSessionTest.java      |  18 +-
 .../sync/ValidationManagerImplTest.java       |  50 +-
 .../system/LinuxSeedProviderTest.java         |  10 +-
 .../transport/KeyManagerImplTest.java         |  30 +-
 .../transport/ReorderingWindowTest.java       |   6 +-
 .../transport/StreamReaderImplTest.java       |   6 +-
 .../StreamReaderWriterIntegrationTest.java    |  14 +-
 .../transport/StreamWriterImplTest.java       |   6 +-
 .../transport/TestStreamDecrypter.java        |  19 +-
 .../transport/TestStreamEncrypter.java        |  18 +-
 .../TransportKeyManagerImplTest.java          |  32 +-
 .../{ => bramble}/util/ByteUtilsTest.java     |   6 +-
 .../{ => bramble}/util/StringUtilsTest.java   |   2 +-
 .../blog}/BlogManagerImplTest.java            |  80 +--
 .../blog}/BlogPostValidatorTest.java          |  73 ++-
 .../client}/MessageQueueManagerImplTest.java  |  50 +-
 .../client/MessageTreeImplTest.java}          |  42 +-
 .../forum/ForumManagerImplTest.java           |   2 +-
 .../forum/ForumPostValidatorTest.java         |  30 +-
 .../introduction/IntroduceeManagerTest.java   | 132 ++---
 .../introduction/IntroducerManagerTest.java   | 106 ++--
 .../IntroductionManagerImplTest.java          |  71 +--
 .../IntroductionValidatorTest.java            |  78 +--
 .../introduction/MessageSenderTest.java       |  53 +-
 .../messaging/MessagingManagerImplTest.java   |   2 +-
 .../PrivateMessageValidatorTest.java          |  14 +-
 .../GroupMessageValidatorTest.java            |  66 +--
 .../GroupInvitationManagerImplTest.java       |  81 +--
 .../GroupInvitationValidatorTest.java         |  48 +-
 .../sharing/ForumSharingValidatorTest.java    |  44 +-
 .../sharing}/SharingManagerImplTest.java      |   2 +-
 build.gradle                                  |   2 +-
 {briar-core/libs => libs}/gradle-witness.jar  | Bin
 settings.gradle                               |   6 +-
 1410 files changed, 15788 insertions(+), 13022 deletions(-)
 create mode 100644 bramble-android/build.gradle
 rename {briar-android => bramble-android}/libs/jtorctl-briar.jar (100%)
 create mode 100644 bramble-android/proguard-rules.txt
 create mode 100644 bramble-android/src/main/AndroidManifest.xml
 create mode 100644 bramble-android/src/main/java/org/briarproject/bramble/BrambleAndroidModule.java
 rename {briar-android/src/org/briarproject/android/api => bramble-android/src/main/java/org/briarproject/bramble/api/system}/AndroidExecutor.java (94%)
 rename briar-android/src/org/briarproject/plugins/AndroidPluginsModule.java => bramble-android/src/main/java/org/briarproject/bramble/plugin/AndroidPluginModule.java (55%)
 rename {briar-android/src/org/briarproject/plugins => bramble-android/src/main/java/org/briarproject/bramble/plugin}/droidtooth/DroidtoothPlugin.java (92%)
 rename {briar-android/src/org/briarproject/plugins => bramble-android/src/main/java/org/briarproject/bramble/plugin}/droidtooth/DroidtoothPluginFactory.java (67%)
 rename {briar-android/src/org/briarproject/plugins => bramble-android/src/main/java/org/briarproject/bramble/plugin}/droidtooth/DroidtoothTransportConnection.java (72%)
 rename {briar-android/src/org/briarproject/plugins => bramble-android/src/main/java/org/briarproject/bramble/plugin}/tcp/AndroidLanTcpPlugin.java (90%)
 rename {briar-android/src/org/briarproject/plugins => bramble-android/src/main/java/org/briarproject/bramble/plugin}/tcp/AndroidLanTcpPluginFactory.java (66%)
 rename {briar-android/src/org/briarproject/plugins => bramble-android/src/main/java/org/briarproject/bramble/plugin}/tor/TorNetworkMetadata.java (64%)
 rename {briar-android/src/org/briarproject/plugins => bramble-android/src/main/java/org/briarproject/bramble/plugin}/tor/TorPlugin.java (91%)
 rename {briar-android/src/org/briarproject/plugins => bramble-android/src/main/java/org/briarproject/bramble/plugin}/tor/TorPluginFactory.java (72%)
 rename {briar-android/src/org/briarproject/plugins => bramble-android/src/main/java/org/briarproject/bramble/plugin}/tor/TorTransportConnection.java (71%)
 rename {briar-android/src/org/briarproject => bramble-android/src/main/java/org/briarproject/bramble}/system/AndroidExecutorImpl.java (94%)
 rename {briar-android/src/org/briarproject => bramble-android/src/main/java/org/briarproject/bramble}/system/AndroidLocationUtils.java (90%)
 rename {briar-android/src/org/briarproject => bramble-android/src/main/java/org/briarproject/bramble}/system/AndroidSeedProvider.java (85%)
 create mode 100644 bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSystemModule.java
 create mode 100644 bramble-android/src/main/java/org/briarproject/bramble/util/AndroidUtils.java
 rename {briar-android/assets => bramble-android/src/main/res/raw}/torrc (100%)
 create mode 100644 bramble-android/src/main/res/values/strings.xml
 rename {briar-desktop => bramble-api}/.gitignore (100%)
 create mode 100644 bramble-api/build.gradle
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/Bytes.java (87%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/FormatException.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/StringMap.java (89%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/UniqueId.java
 rename {briar-api/src/org/briarproject/api/clients => bramble-api/src/main/java/org/briarproject/bramble/api/client}/BdfMessageContext.java (75%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/client/BdfMessageValidator.java
 rename {briar-api/src/org/briarproject/api/clients => bramble-api/src/main/java/org/briarproject/bramble/api/client}/ClientHelper.java (82%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/client/ContactGroupFactory.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/contact/Contact.java (74%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactExchangeListener.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactExchangeTask.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/contact/ContactId.java (69%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/contact/ContactManager.java (61%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/contact/event/ContactAddedEvent.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/contact/event/ContactRemovedEvent.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/contact/event/ContactStatusChangedEvent.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/contact/event/ContactVerifiedEvent.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/crypto/CryptoComponent.java (97%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/crypto/CryptoExecutor.java (94%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/crypto/KeyPair.java (56%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/crypto/KeyParser.java (65%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/crypto/MessageDigest.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/crypto/PasswordStrengthEstimator.java (71%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PrivateKey.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PseudoRandom.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PublicKey.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/crypto/SecretKey.java (52%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/crypto/StreamDecrypter.java (61%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/crypto/StreamDecrypterFactory.java (54%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/crypto/StreamEncrypter.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/crypto/StreamEncrypterFactory.java (54%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/data/BdfDictionary.java (97%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/data/BdfEntry.java (75%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/data/BdfList.java (96%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/data/BdfReader.java (90%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/data/BdfReaderFactory.java (57%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/data/BdfWriter.java (93%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfWriterFactory.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/data/MetadataEncoder.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/data/MetadataParser.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/data/ObjectReader.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/db/ContactExistsException.java (84%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/db/DatabaseComponent.java (90%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/db/DatabaseConfig.java (54%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/db/DatabaseExecutor.java (86%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/db/DbClosedException.java (77%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/db/DbException.java (75%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/db/Metadata.java (67%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/db/NoSuchContactException.java (86%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/db/NoSuchGroupException.java (86%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/db/NoSuchLocalAuthorException.java (86%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/db/NoSuchMessageException.java (86%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/db/NoSuchTransportException.java (86%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/db/Transaction.java (90%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/event/Event.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/event/EventBus.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/event/EventListener.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/identity/Author.java (64%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/identity/AuthorConstants.java (88%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/identity/AuthorFactory.java (57%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/identity/AuthorId.java (64%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/identity/IdentityManager.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/identity/LocalAuthor.java (62%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/identity/event/LocalAuthorAddedEvent.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/identity/event/LocalAuthorRemovedEvent.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/invitation/InvitationConstants.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/invitation/InvitationListener.java (96%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/invitation/InvitationState.java (83%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/invitation/InvitationTask.java (64%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/invitation/InvitationTaskFactory.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/keyagreement/KeyAgreementConnection.java (53%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementConstants.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/keyagreement/KeyAgreementListener.java (88%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/keyagreement/KeyAgreementResult.java (74%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/keyagreement/KeyAgreementTask.java (60%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementTaskFactory.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/keyagreement/Payload.java (83%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/PayloadEncoder.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/keyagreement/PayloadParser.java (53%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/keyagreement/RecordTypes.java (50%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/keyagreement/TransportDescriptor.java (64%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementAbortedEvent.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementFailedEvent.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementFinishedEvent.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementListeningEvent.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/event/KeyAgreementStartedEvent.java
 rename {briar-api/src/org/briarproject/api => bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement}/event/KeyAgreementWaitingEvent.java (60%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/lifecycle/IoExecutor.java (94%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/LifecycleManager.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/lifecycle/Service.java (87%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/lifecycle/ServiceException.java (83%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/lifecycle/ShutdownManager.java (73%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/event/ShutdownEvent.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/nullsafety/FieldsNotNullByDefault.java (93%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/nullsafety/MethodsNotNullByDefault.java (94%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/nullsafety/NotNullByDefault.java (95%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/nullsafety/ParametersNotNullByDefault.java (94%)
 rename {briar-api/src/org/briarproject/api/plugins => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/Backoff.java (87%)
 rename {briar-api/src/org/briarproject/api/plugins => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/BackoffFactory.java (71%)
 rename {briar-api/src/org/briarproject/api/plugins => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/BluetoothConstants.java (71%)
 rename {briar-api/src/org/briarproject/api/plugins => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/ConnectionManager.java (66%)
 rename {briar-api/src/org/briarproject/api/plugins => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/ConnectionRegistry.java (71%)
 rename {briar-api/src/org/briarproject/api/plugins => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/LanTcpConstants.java (57%)
 rename {briar-api/src/org/briarproject/api/plugins => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/Plugin.java (86%)
 rename {briar-api/src/org/briarproject/api/plugins => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/PluginCallback.java (65%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/plugin/PluginConfig.java
 rename {briar-api/src/org/briarproject/api/plugins => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/PluginManager.java (76%)
 rename {briar-api/src/org/briarproject/api/plugins => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/TorConstants.java (63%)
 rename {briar-api/src/org/briarproject/api/plugins => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/TransportConnectionReader.java (71%)
 rename {briar-api/src/org/briarproject/api/plugins => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/TransportConnectionWriter.java (65%)
 rename {briar-api/src/org/briarproject/api => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/TransportId.java (94%)
 rename {briar-api/src/org/briarproject/api/plugins => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/WanTcpConstants.java (57%)
 rename {briar-api/src/org/briarproject/api/plugins => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/duplex/AbstractDuplexTransportConnection.java (82%)
 rename {briar-api/src/org/briarproject/api/plugins => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/duplex/DuplexPlugin.java (78%)
 rename {briar-api/src/org/briarproject/api/plugins => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/duplex/DuplexPluginCallback.java (54%)
 rename {briar-api/src/org/briarproject/api/plugins => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/duplex/DuplexPluginFactory.java (64%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/DuplexTransportConnection.java
 rename {briar-api/src/org/briarproject/api => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/event/ConnectionClosedEvent.java (60%)
 rename {briar-api/src/org/briarproject/api => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/event/ConnectionOpenedEvent.java (60%)
 rename {briar-api/src/org/briarproject/api => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/event/ContactConnectedEvent.java (54%)
 rename {briar-api/src/org/briarproject/api => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/event/ContactDisconnectedEvent.java (54%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/TransportDisabledEvent.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/TransportEnabledEvent.java
 rename {briar-api/src/org/briarproject/api/plugins => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/simplex/SimplexPlugin.java (65%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/plugin/simplex/SimplexPluginCallback.java
 rename {briar-api/src/org/briarproject/api/plugins => bramble-api/src/main/java/org/briarproject/bramble/api/plugin}/simplex/SimplexPluginFactory.java (64%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/properties/TransportProperties.java (56%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/properties/TransportPropertyConstants.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/properties/TransportPropertyManager.java (60%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/reliability/ReadHandler.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/reliability/ReliabilityLayer.java (73%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/reliability/ReliabilityLayerFactory.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/reliability/WriteHandler.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/reporting/DevConfig.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/reporting/DevReporter.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/reporting/ReportingConstants.java (93%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/settings/Settings.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/settings/SettingsManager.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/settings/event/SettingsUpdatedEvent.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/sync/Ack.java (54%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/sync/Client.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/sync/ClientId.java (85%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/sync/Group.java (78%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/sync/GroupFactory.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/sync/GroupId.java (67%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/sync/InvalidMessageException.java (72%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/sync/Message.java (63%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/sync/MessageContext.java (80%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/sync/MessageFactory.java (61%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/sync/MessageId.java (67%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/sync/MessageStatus.java (62%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/sync/Offer.java (57%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/sync/PacketReader.java (76%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/sync/PacketReaderFactory.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/sync/PacketTypes.java (53%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/sync/PacketWriter.java (69%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/sync/PacketWriterFactory.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/sync/Request.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncConstants.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/sync/SyncSession.java (90%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/sync/SyncSessionFactory.java (67%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/sync/ValidationManager.java (89%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/GroupAddedEvent.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/GroupRemovedEvent.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/GroupVisibilityUpdatedEvent.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessageAddedEvent.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessageRequestedEvent.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessageSharedEvent.java
 rename {briar-api/src/org/briarproject/api => bramble-api/src/main/java/org/briarproject/bramble/api/sync}/event/MessageStateChangedEvent.java (59%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessageToAckEvent.java
 rename {briar-api/src/org/briarproject/api => bramble-api/src/main/java/org/briarproject/bramble/api/sync}/event/MessageToRequestEvent.java (53%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/MessagesAckedEvent.java
 rename {briar-api/src/org/briarproject/api => bramble-api/src/main/java/org/briarproject/bramble/api/sync}/event/MessagesSentEvent.java (51%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/system/Clock.java (60%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/system/LocationUtils.java (67%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/system/Scheduler.java (94%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/system/SeedProvider.java (50%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/transport/IncomingKeys.java (84%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/transport/KeyManager.java (73%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/transport/OutgoingKeys.java (89%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/transport/StreamContext.java (78%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/transport/StreamReaderFactory.java
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/transport/StreamWriterFactory.java
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/transport/TransportConstants.java (54%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/transport/TransportKeys.java (86%)
 rename {briar-api/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/api/ui/UiCallback.java (94%)
 rename {briar-core/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/util/ByteUtils.java (96%)
 rename {briar-core/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/util/IoUtils.java (84%)
 rename {briar-core/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/util/OsUtils.java (65%)
 rename {briar-core/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/util/PrivacyUtils.java (76%)
 rename {briar-core/src/org/briarproject => bramble-api/src/main/java/org/briarproject/bramble}/util/StringUtils.java (97%)
 create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/util/ValidationUtils.java
 create mode 100644 bramble-core/build.gradle
 rename {briar-core => bramble-core}/libs/weupnp-0.1.3-SNAPSHOT-briar.jar (100%)
 create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/BrambleCoreEagerSingletons.java
 create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/BrambleCoreModule.java
 rename {briar-core/src/org/briarproject/clients => bramble-core/src/main/java/org/briarproject/bramble/client}/ClientHelperImpl.java (88%)
 create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/client/ClientModule.java
 rename {briar-core/src/org/briarproject/clients => bramble-core/src/main/java/org/briarproject/bramble/client}/ContactGroupFactoryImpl.java (66%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/contact/ContactExchangeTaskImpl.java (79%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/contact/ContactManagerImpl.java (83%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/contact/ContactModule.java (75%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/AsciiArmour.java (72%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/AuthenticatedCipher.java (66%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/Blake2sDigest.java (99%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/CombinedSecureRandom.java (79%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/CryptoComponentImpl.java (94%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/CryptoModule.java (81%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/DigestWrapper.java (80%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/DoubleDigest.java (81%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/EllipticCurveConstants.java (91%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/FortunaGenerator.java (90%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/FortunaSecureRandom.java (85%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/FrameEncoder.java (72%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/MessageEncrypter.java (94%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/PasswordStrengthEstimatorImpl.java (80%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/PseudoRandomImpl.java (57%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/Sec1KeyParser.java (91%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/Sec1PrivateKey.java (69%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/Sec1PublicKey.java (68%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/Sec1Utils.java (77%)
 create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/crypto/Signature.java
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/SignatureImpl.java (83%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/StreamDecrypterFactoryImpl.java (65%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/StreamDecrypterImpl.java (76%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/StreamEncrypterFactoryImpl.java (68%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/StreamEncrypterImpl.java (76%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/crypto/XSalsa20Poly1305AuthenticatedCipher.java (83%)
 create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderFactoryImpl.java
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/data/BdfReaderImpl.java (84%)
 create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterFactoryImpl.java
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/data/BdfWriterImpl.java (70%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/data/DataModule.java (67%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/data/MetadataEncoderImpl.java (73%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/data/MetadataParserImpl.java (72%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/data/Types.java (90%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/db/Database.java (93%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/db/DatabaseComponentImpl.java (87%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/db/DatabaseConstants.java (54%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/db/DatabaseExecutorModule.java (90%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/db/DatabaseModule.java (62%)
 create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/db/DbStateException.java
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/db/ExponentialBackoff.java (96%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/db/H2Database.java (79%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/db/JdbcDatabase.java (96%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/event/EventBusImpl.java (55%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/event/EventModule.java (68%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/identity/AuthorFactoryImpl.java (65%)
 create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/identity/AuthorReader.java
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/identity/IdentityManagerImpl.java (59%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/identity/IdentityModule.java (57%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/invitation/AliceConnector.java (79%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/invitation/BobConnector.java (79%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/invitation/Connector.java (66%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/invitation/ConnectorGroup.java (83%)
 create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/invitation/InvitationModule.java
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/invitation/InvitationTaskFactoryImpl.java (61%)
 create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/keyagreement/AbortException.java
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/keyagreement/KeyAgreementConnector.java (85%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/keyagreement/KeyAgreementModule.java (55%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/keyagreement/KeyAgreementProtocol.java (89%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/keyagreement/KeyAgreementTaskFactoryImpl.java (53%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/keyagreement/KeyAgreementTaskImpl.java (73%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/keyagreement/KeyAgreementTransport.java (69%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/keyagreement/PayloadEncoderImpl.java (64%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/keyagreement/PayloadParserImpl.java (61%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/lifecycle/LifecycleManagerImpl.java (82%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/lifecycle/LifecycleModule.java (73%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/lifecycle/ShutdownManagerImpl.java (75%)
 create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/plugin/BackoffFactoryImpl.java
 rename {briar-core/src/org/briarproject/plugins => bramble-core/src/main/java/org/briarproject/bramble/plugin}/BackoffImpl.java (76%)
 rename {briar-core/src/org/briarproject/plugins => bramble-core/src/main/java/org/briarproject/bramble/plugin}/ConnectionManagerImpl.java (91%)
 rename {briar-core/src/org/briarproject/plugins => bramble-core/src/main/java/org/briarproject/bramble/plugin}/ConnectionRegistryImpl.java (84%)
 rename {briar-core/src/org/briarproject/plugins => bramble-core/src/main/java/org/briarproject/bramble/plugin}/PluginManagerImpl.java (83%)
 rename briar-core/src/org/briarproject/plugins/PluginsModule.java => bramble-core/src/main/java/org/briarproject/bramble/plugin/PluginModule.java (70%)
 rename {briar-core/src/org/briarproject/plugins => bramble-core/src/main/java/org/briarproject/bramble/plugin}/Poller.java (80%)
 rename {briar-core/src/org/briarproject/plugins => bramble-core/src/main/java/org/briarproject/bramble/plugin}/file/FilePlugin.java (85%)
 rename {briar-core/src/org/briarproject/plugins => bramble-core/src/main/java/org/briarproject/bramble/plugin}/file/FileTransportReader.java (79%)
 rename {briar-core/src/org/briarproject/plugins => bramble-core/src/main/java/org/briarproject/bramble/plugin}/file/FileTransportWriter.java (81%)
 rename {briar-core/src/org/briarproject/plugins => bramble-core/src/main/java/org/briarproject/bramble/plugin}/tcp/LanTcpPlugin.java (88%)
 rename {briar-core/src/org/briarproject/plugins => bramble-core/src/main/java/org/briarproject/bramble/plugin}/tcp/LanTcpPluginFactory.java (63%)
 rename {briar-core/src/org/briarproject/plugins => bramble-core/src/main/java/org/briarproject/bramble/plugin}/tcp/MappingResult.java (50%)
 create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/PortMapper.java
 rename {briar-core/src/org/briarproject/plugins => bramble-core/src/main/java/org/briarproject/bramble/plugin}/tcp/PortMapperImpl.java (84%)
 rename {briar-core/src/org/briarproject/plugins => bramble-core/src/main/java/org/briarproject/bramble/plugin}/tcp/TcpPlugin.java (89%)
 rename {briar-core/src/org/briarproject/plugins => bramble-core/src/main/java/org/briarproject/bramble/plugin}/tcp/TcpTransportConnection.java (66%)
 rename {briar-core/src/org/briarproject/plugins => bramble-core/src/main/java/org/briarproject/bramble/plugin}/tcp/WanTcpPlugin.java (78%)
 rename {briar-core/src/org/briarproject/plugins => bramble-core/src/main/java/org/briarproject/bramble/plugin}/tcp/WanTcpPluginFactory.java (64%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/properties/PropertiesModule.java (54%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/properties/TransportPropertyManagerImpl.java (83%)
 create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/properties/TransportPropertyValidator.java
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/reliability/Ack.java (54%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/reliability/Crc32.java (80%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/reliability/Data.java (70%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/reliability/Frame.java (79%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/reliability/Receiver.java (86%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/reliability/ReceiverInputStream.java (76%)
 create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/reliability/ReliabilityLayerFactoryImpl.java
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/reliability/ReliabilityLayerImpl.java (85%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/reliability/ReliabilityModule.java (56%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/reliability/Sender.java (94%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/reliability/SenderOutputStream.java (91%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/reliability/SlipDecoder.java (86%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/reliability/SlipEncoder.java (78%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/reporting/DevReportServer.java (87%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/reporting/DevReporterImpl.java (82%)
 create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/reporting/ReportingModule.java
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/settings/SettingsManagerImpl.java (61%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/settings/SettingsModule.java (53%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/socks/SocksModule.java (63%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/socks/SocksSocket.java (96%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/socks/SocksSocketFactory.java (96%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/sync/DuplexOutgoingSession.java (79%)
 create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/sync/GroupFactoryImpl.java
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/sync/IncomingSession.java (74%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/sync/MessageFactoryImpl.java (65%)
 create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/sync/PacketReaderFactoryImpl.java
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/sync/PacketReaderImpl.java (73%)
 create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/sync/PacketWriterFactoryImpl.java
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/sync/PacketWriterImpl.java (59%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/sync/SimplexOutgoingSession.java (75%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/sync/SyncModule.java (63%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/sync/SyncSessionFactoryImpl.java (66%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/sync/ThrowingRunnable.java (66%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/sync/ValidationManagerImpl.java (91%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/system/LinuxSeedProvider.java (86%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/system/SystemClock.java (59%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/system/SystemModule.java (78%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/transport/KeyManagerImpl.java (77%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/transport/MutableIncomingKeys.java (70%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/transport/MutableOutgoingKeys.java (69%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/transport/MutableTransportKeys.java (76%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/transport/ReorderingWindow.java (90%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/transport/StreamReaderFactoryImpl.java (60%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/transport/StreamReaderImpl.java (72%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/transport/StreamWriterFactoryImpl.java (61%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/transport/StreamWriterImpl.java (72%)
 create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManager.java
 create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerFactory.java
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/transport/TransportKeyManagerFactoryImpl.java (64%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/transport/TransportKeyManagerImpl.java (88%)
 rename {briar-core/src/org/briarproject => bramble-core/src/main/java/org/briarproject/bramble}/transport/TransportModule.java (67%)
 create mode 100644 bramble-j2se/build.gradle
 rename {briar-desktop => bramble-j2se}/libs/bluecove-2.1.1-SNAPSHOT-briar.jar (100%)
 rename {briar-desktop => bramble-j2se}/libs/bluecove-gpl-2.1.1-SNAPSHOT.jar (100%)
 rename {briar-desktop => bramble-j2se}/libs/jna-4.1.0.jar (100%)
 rename {briar-desktop => bramble-j2se}/libs/jna-platform-4.1.0.jar (100%)
 rename {briar-desktop => bramble-j2se}/libs/jnotify-0.94.jar (100%)
 rename {briar-desktop => bramble-j2se}/libs/jnotify-x86.dll (100%)
 rename {briar-desktop => bramble-j2se}/libs/jnotify-x86_64.dll (100%)
 rename {briar-desktop => bramble-j2se}/libs/jssc-0.9-briar.jar (100%)
 rename {briar-desktop => bramble-j2se}/libs/libjnotify-amd64.so (100%)
 rename {briar-desktop => bramble-j2se}/libs/libjnotify-i386.so (100%)
 rename {briar-desktop => bramble-j2se}/libs/libjnotify.dylib (100%)
 rename {briar-desktop => bramble-j2se}/libs/source/jssc-0.9-briar-source.jar (100%)
 rename {briar-desktop/src/org/briarproject => bramble-j2se/src/main/java/org/briarproject/bramble}/lifecycle/DesktopLifecycleModule.java (68%)
 rename {briar-desktop/src/org/briarproject => bramble-j2se/src/main/java/org/briarproject/bramble}/lifecycle/WindowsShutdownManagerImpl.java (95%)
 rename briar-desktop/src/org/briarproject/plugins/DesktopPluginsModule.java => bramble-j2se/src/main/java/org/briarproject/bramble/plugin/DesktopPluginModule.java (55%)
 rename {briar-desktop/src/org/briarproject/plugins => bramble-j2se/src/main/java/org/briarproject/bramble/plugin}/bluetooth/BluetoothPlugin.java (90%)
 rename {briar-desktop/src/org/briarproject/plugins => bramble-j2se/src/main/java/org/briarproject/bramble/plugin}/bluetooth/BluetoothPluginFactory.java (64%)
 rename {briar-desktop/src/org/briarproject/plugins => bramble-j2se/src/main/java/org/briarproject/bramble/plugin}/bluetooth/BluetoothTransportConnection.java (72%)
 rename {briar-desktop/src/org/briarproject/plugins => bramble-j2se/src/main/java/org/briarproject/bramble/plugin}/bluetooth/InvitationListener.java (93%)
 rename {briar-desktop/src/org/briarproject/plugins => bramble-j2se/src/main/java/org/briarproject/bramble/plugin}/file/LinuxRemovableDriveFinder.java (76%)
 create mode 100644 bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/LinuxRemovableDriveMonitor.java
 rename {briar-desktop/src/org/briarproject/plugins => bramble-j2se/src/main/java/org/briarproject/bramble/plugin}/file/MacRemovableDriveFinder.java (74%)
 create mode 100644 bramble-j2se/src/main/java/org/briarproject/bramble/plugin/file/MacRemovableDriveMonitor.java
 rename {briar-desktop/src/org/briarproject/plugins => bramble-j2se/src/main/java/org/briarproject/bramble/plugin}/file/PollingRemovableDriveMonitor.java (85%)
 rename {briar-desktop/src/org/briarproject/plugins => bramble-j2se/src/main/java/org/briarproject/bramble/plugin}/file/RemovableDriveFinder.java (57%)
 rename {briar-desktop/src/org/briarproject/plugins => bramble-j2se/src/main/java/org/briarproject/bramble/plugin}/file/RemovableDriveMonitor.java (67%)
 rename {briar-desktop/src/org/briarproject/plugins => bramble-j2se/src/main/java/org/briarproject/bramble/plugin}/file/RemovableDrivePlugin.java (89%)
 rename {briar-desktop/src/org/briarproject/plugins => bramble-j2se/src/main/java/org/briarproject/bramble/plugin}/file/RemovableDrivePluginFactory.java (73%)
 rename {briar-desktop/src/org/briarproject/plugins => bramble-j2se/src/main/java/org/briarproject/bramble/plugin}/file/UnixRemovableDriveFinder.java (82%)
 rename {briar-desktop/src/org/briarproject/plugins => bramble-j2se/src/main/java/org/briarproject/bramble/plugin}/file/UnixRemovableDriveMonitor.java (78%)
 rename {briar-desktop/src/org/briarproject/plugins => bramble-j2se/src/main/java/org/briarproject/bramble/plugin}/file/WindowsRemovableDriveFinder.java (86%)
 rename {briar-desktop/src/org/briarproject/plugins => bramble-j2se/src/main/java/org/briarproject/bramble/plugin}/modem/CountryCodes.java (99%)
 rename {briar-desktop/src/org/briarproject/plugins => bramble-j2se/src/main/java/org/briarproject/bramble/plugin}/modem/Modem.java (90%)
 create mode 100644 bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/ModemFactory.java
 rename {briar-desktop/src/org/briarproject/plugins => bramble-j2se/src/main/java/org/briarproject/bramble/plugin}/modem/ModemFactoryImpl.java (61%)
 rename {briar-desktop/src/org/briarproject/plugins => bramble-j2se/src/main/java/org/briarproject/bramble/plugin}/modem/ModemImpl.java (94%)
 rename {briar-desktop/src/org/briarproject/plugins => bramble-j2se/src/main/java/org/briarproject/bramble/plugin}/modem/ModemPlugin.java (84%)
 rename {briar-desktop/src/org/briarproject/plugins => bramble-j2se/src/main/java/org/briarproject/bramble/plugin}/modem/ModemPluginFactory.java (59%)
 rename {briar-desktop/src/org/briarproject/plugins => bramble-j2se/src/main/java/org/briarproject/bramble/plugin}/modem/SerialPort.java (78%)
 rename {briar-desktop/src/org/briarproject/plugins => bramble-j2se/src/main/java/org/briarproject/bramble/plugin}/modem/SerialPortImpl.java (89%)
 create mode 100644 bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/SerialPortList.java
 create mode 100644 bramble-j2se/src/main/java/org/briarproject/bramble/plugin/modem/SerialPortListImpl.java
 rename {briar-desktop/src/org/briarproject => bramble-j2se/src/main/java/org/briarproject/bramble}/system/DesktopSeedProviderModule.java (64%)
 rename {briar-tests/src => briar-android-tests/src/test/java}/org/briarproject/TestDatabaseModule.java (74%)
 rename {briar-tests/src => briar-android-tests/src/test/java}/org/briarproject/TestLifecycleModule.java (63%)
 rename briar-tests/src/org/briarproject/TestPluginsModule.java => briar-android-tests/src/test/java/org/briarproject/TestPluginConfigModule.java (58%)
 rename {briar-tests/src => briar-android-tests/src/test/java}/org/briarproject/TestSeedProviderModule.java (81%)
 rename briar-android-tests/src/test/java/org/briarproject/{ => briar}/introduction/IntroductionIntegrationTest.java (85%)
 create mode 100644 briar-android-tests/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTestComponent.java
 rename briar-android/{ => src/main}/AndroidManifest.xml (76%)
 rename briar-android/{ => src/main}/assets/emoji_activity.png (100%)
 rename briar-android/{ => src/main}/assets/emoji_animals_nature.png (100%)
 rename briar-android/{ => src/main}/assets/emoji_flags.png (100%)
 rename briar-android/{ => src/main}/assets/emoji_food_drink.png (100%)
 rename briar-android/{ => src/main}/assets/emoji_objects.png (100%)
 rename briar-android/{ => src/main}/assets/emoji_smiley_people.png (100%)
 rename briar-android/{ => src/main}/assets/emoji_symbols.png (100%)
 rename briar-android/{ => src/main}/assets/emoji_travel_places.png (100%)
 rename briar-android/src/{ => main/java}/im/delight/android/identicons/Identicon.java (100%)
 rename briar-android/src/{ => main/java}/im/delight/android/identicons/IdenticonDrawable.java (100%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/AndroidEagerSingletons.java
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/AndroidNotificationManagerImpl.java (90%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/AppModule.java (67%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/BriarApplication.java (84%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/BriarApplicationImpl.java (83%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/BriarService.java (91%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/DestroyableContext.java (70%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/ReferenceManagerImpl.java (88%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/StartupFailureActivity.java (80%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/TestingConstants.java (87%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java
 rename briar-android/src/{org/briarproject/android => main/java/org/briarproject/briar/android/activity}/ActivityModule.java (65%)
 rename briar-android/src/{org/briarproject/android => main/java/org/briarproject/briar/android/activity}/ActivityScope.java (79%)
 rename briar-android/src/{org/briarproject/android => main/java/org/briarproject/briar/android/activity}/BaseActivity.java (85%)
 rename briar-android/src/{org/briarproject/android => main/java/org/briarproject/briar/android/activity}/BriarActivity.java (87%)
 rename briar-android/src/{org/briarproject/android => main/java/org/briarproject/briar/android/activity}/BriarFragmentActivity.java (68%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/BaseController.java (59%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/BaseControllerImpl.java (83%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/BasePostFragment.java (83%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/BlogActivity.java (76%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/BlogCommentItem.java (90%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/BlogController.java (55%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/BlogControllerImpl.java (75%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/BlogFragment.java (87%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/BlogItem.java (79%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/BlogModule.java (71%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/BlogPostAdapter.java (90%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/BlogPostFragment.java (77%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/BlogPostItem.java (79%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/BlogPostViewHolder.java (83%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/FeedController.java (60%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/FeedControllerImpl.java (74%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/FeedFragment.java (87%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/FeedPostFragment.java (75%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/ReblogActivity.java (79%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/ReblogFragment.java (79%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/RssFeedAdapter.java (89%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/RssFeedImportActivity.java (91%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/RssFeedManageActivity.java (88%)
 rename briar-android/src/{org/briarproject/android/blogs => main/java/org/briarproject/briar/android/blog}/WriteBlogPostActivity.java (80%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/BaseContactListAdapter.java (87%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/ContactItem.java (62%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/ContactItemViewHolder.java (78%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/ContactListAdapter.java (93%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/ContactListFragment.java (77%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/ContactListItem.java (79%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/ContactListItemViewHolder.java (71%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/ContactModule.java (56%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/ConversationActivity.java (86%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/ConversationAdapter.java (93%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/ConversationItem.java (83%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/ConversationItemViewHolder.java (72%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/ConversationMessageInItem.java (69%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/ConversationMessageOutItem.java (67%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/ConversationMessageOutViewHolder.java (83%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/ConversationNoticeInItem.java (67%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/ConversationNoticeInViewHolder.java (82%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/ConversationNoticeOutItem.java (66%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/ConversationNoticeOutViewHolder.java (83%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/ConversationOutItem.java (59%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/ConversationOutItemViewHolder.java (87%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/ConversationRequestItem.java (67%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contact/ConversationRequestViewHolder.java (85%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contactselection/BaseContactSelectorAdapter.java (69%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contactselection/BaseContactSelectorFragment.java (74%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contactselection/BaseSelectableContactHolder.java (71%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contactselection/ContactSelectorActivity.java (83%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contactselection/ContactSelectorAdapter.java (76%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/contactselection/ContactSelectorController.java
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contactselection/ContactSelectorControllerImpl.java (72%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contactselection/ContactSelectorFragment.java (83%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contactselection/ContactSelectorListener.java (50%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contactselection/SelectableContactHolder.java (62%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/contactselection/SelectableContactItem.java (68%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/controller/ActivityLifecycleController.java (79%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/controller/BriarController.java (60%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/controller/BriarControllerImpl.java (87%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/controller/ConfigController.java (54%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/controller/ConfigControllerImpl.java (75%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/controller/DbController.java
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/controller/DbControllerImpl.java (74%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/controller/handler/ExceptionHandler.java (61%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/controller/handler/ResultExceptionHandler.java (68%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/controller/handler/ResultHandler.java (52%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/controller/handler/UiExceptionHandler.java (77%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/controller/handler/UiResultExceptionHandler.java (76%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/controller/handler/UiResultHandler.java (80%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/forum/CreateForumActivity.java (83%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/forum/ForumActivity.java (83%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/forum/ForumController.java
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/forum/ForumControllerImpl.java (70%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/forum/ForumItem.java
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/forum/ForumListAdapter.java (87%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/forum/ForumListFragment.java (80%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/forum/ForumListItem.java (76%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/forum/ForumModule.java (64%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/fragment/BaseEventFragment.java (68%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/fragment/BaseFragment.java (90%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/introduction/ContactChooserFragment.java (80%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/introduction/IntroductionActivity.java (86%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/introduction/IntroductionMessageFragment.java (88%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/invitation/AddContactActivity.java (91%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/invitation/AddContactView.java (88%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/invitation/ChooseIdentityView.java (84%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/invitation/ConfirmationCodeView.java (97%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/invitation/ErrorView.java (88%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/invitation/InvitationCodeView.java (97%)
 rename briar-android/src/{org/briarproject/android/view => main/java/org/briarproject/briar/android/keyagreement}/CameraView.java (98%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/keyagreement/IntroFragment.java (73%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/keyagreement/KeyAgreementActivity.java (76%)
 rename briar-android/src/{org/briarproject/android/util => main/java/org/briarproject/briar/android/keyagreement}/PreviewConsumer.java (52%)
 rename briar-android/src/{org/briarproject/android/util => main/java/org/briarproject/briar/android/keyagreement}/QrCodeDecoder.java (84%)
 rename briar-android/src/{org/briarproject/android/util => main/java/org/briarproject/briar/android/keyagreement}/QrCodeUtils.java (84%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/keyagreement/ShowQrCodeFragment.java (83%)
 rename briar-android/src/{org/briarproject/android => main/java/org/briarproject/briar/android/login}/ChangePasswordActivity.java (87%)
 rename briar-android/src/{org/briarproject/android => main/java/org/briarproject/briar/android/login}/PasswordActivity.java (89%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/login/PasswordController.java
 rename briar-android/src/{org/briarproject/android/controller => main/java/org/briarproject/briar/android/login}/PasswordControllerImpl.java (81%)
 rename briar-android/src/{org/briarproject/android => main/java/org/briarproject/briar/android/login}/SetupActivity.java (85%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/login/SetupController.java
 rename briar-android/src/{org/briarproject/android/controller => main/java/org/briarproject/briar/android/login}/SetupControllerImpl.java (70%)
 rename briar-android/src/{org/briarproject/android/util => main/java/org/briarproject/briar/android/login}/StrengthMeter.java (85%)
 rename briar-android/src/{org/briarproject/android => main/java/org/briarproject/briar/android/navdrawer}/NavDrawerActivity.java (82%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerController.java
 rename briar-android/src/{org/briarproject/android/controller => main/java/org/briarproject/briar/android/navdrawer}/NavDrawerControllerImpl.java (69%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/navdrawer/TransportStateListener.java
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/panic/ExitActivity.java (74%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/panic/PanicPreferencesActivity.java (78%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/panic/PanicPreferencesFragment.java (98%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/panic/PanicResponderActivity.java (85%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/VisibilityHelper.java (79%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/conversation/GroupActivity.java (85%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupController.java
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/conversation/GroupControllerImpl.java (75%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/conversation/GroupConversationModule.java (62%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/conversation/GroupMessageAdapter.java (76%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/conversation/GroupMessageItem.java (65%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/conversation/JoinMessageItem.java (68%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/conversation/JoinMessageItemViewHolder.java (72%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/creation/BaseGroupInviteActivity.java (65%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/creation/CreateGroupActivity.java (73%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupController.java
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/creation/CreateGroupControllerImpl.java (80%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/creation/CreateGroupFragment.java (86%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/creation/CreateGroupListener.java (58%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/creation/CreateGroupMessageFragment.java (71%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/creation/GroupCreateModule.java (54%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/creation/GroupInviteActivity.java (71%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/creation/GroupInviteFragment.java (53%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/invitation/GroupInvitationActivity.java (54%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/invitation/GroupInvitationAdapter.java (75%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/privategroup/invitation/GroupInvitationController.java
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/invitation/GroupInvitationControllerImpl.java (61%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/invitation/GroupInvitationModule.java (69%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/privategroup/invitation/GroupInvitationViewHolder.java
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/list/GroupItem.java (74%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/list/GroupListAdapter.java (78%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/list/GroupListController.java (57%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/list/GroupListControllerImpl.java (76%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/list/GroupListFragment.java (84%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/list/GroupListModule.java (67%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/list/GroupViewHolder.java (82%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/memberlist/GroupMemberListActivity.java (69%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/GroupMemberListController.java
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/memberlist/GroupMemberListControllerImpl.java (70%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/memberlist/GroupMemberModule.java (69%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/memberlist/MemberListAdapter.java (88%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItem.java
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/memberlist/MemberListItemHolder.java (66%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/reveal/GroupRevealModule.java (69%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/reveal/RevealContactsActivity.java (83%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealContactsController.java
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/reveal/RevealContactsControllerImpl.java (75%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/reveal/RevealContactsFragment.java (67%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/reveal/RevealableContactAdapter.java (77%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealableContactItem.java
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/privategroup/reveal/RevealableContactViewHolder.java (54%)
 rename briar-android/src/{org/briarproject/android/report => main/java/org/briarproject/briar/android/reporting}/BriarReportPrimer.java (97%)
 rename briar-android/src/{org/briarproject/android/report => main/java/org/briarproject/briar/android/reporting}/BriarReportSender.java (80%)
 rename briar-android/src/{org/briarproject/android/report => main/java/org/briarproject/briar/android/reporting}/BriarReportSenderFactory.java (83%)
 rename briar-android/src/{org/briarproject/android/report => main/java/org/briarproject/briar/android/reporting}/DevReportActivity.java (98%)
 rename briar-android/src/{org/briarproject/android => main/java/org/briarproject/briar/android/settings}/SettingsActivity.java (73%)
 rename briar-android/src/{org/briarproject/android/fragment => main/java/org/briarproject/briar/android/settings}/SettingsFragment.java (93%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/BaseMessageFragment.java (81%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/BlogInvitationActivity.java (61%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/sharing/BlogInvitationController.java
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/BlogInvitationControllerImpl.java (63%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/BlogSharingStatusActivity.java (61%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/ForumInvitationActivity.java (61%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/sharing/ForumInvitationController.java
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/ForumInvitationControllerImpl.java (60%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/ForumSharingStatusActivity.java (61%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/InvitationActivity.java (80%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/InvitationAdapter.java (85%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/sharing/InvitationController.java
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/InvitationControllerImpl.java (72%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/InvitationViewHolder.java (84%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/ShareActivity.java (66%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/ShareBlogActivity.java (68%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareBlogController.java
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/ShareBlogControllerImpl.java (59%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/ShareBlogFragment.java (56%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/ShareBlogMessageFragment.java (87%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/ShareForumActivity.java (68%)
 create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/sharing/ShareForumController.java
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/ShareForumControllerImpl.java (59%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/ShareForumFragment.java (56%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/ShareForumMessageFragment.java (87%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/SharingInvitationAdapter.java (75%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/SharingInvitationViewHolder.java (64%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/SharingModule.java (84%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/SharingStatusActivity.java (90%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/sharing/SharingStatusAdapter.java (68%)
 rename briar-android/src/{org/briarproject/android => main/java/org/briarproject/briar/android/splash}/ExpiredActivity.java (69%)
 rename briar-android/src/{org/briarproject/android => main/java/org/briarproject/briar/android/splash}/SplashScreenActivity.java (78%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/threaded/BaseThreadItemViewHolder.java (90%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/threaded/NestedTreeList.java (80%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/threaded/ThreadItem.java (70%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/threaded/ThreadItemAdapter.java (95%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/threaded/ThreadListActivity.java (88%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/threaded/ThreadListController.java (57%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/threaded/ThreadListControllerImpl.java (84%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/threaded/ThreadPostViewHolder.java (89%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/util/BriarAdapter.java (97%)
 rename briar-android/src/{org/briarproject/android/util/AndroidUtils.java => main/java/org/briarproject/briar/android/util/UiUtils.java} (61%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/util/UserFeedback.java (52%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/util/VersionedAdapter.java (95%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/view/ArticleMovementMethod.java (97%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/view/AuthorView.java (89%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/view/BriarRecyclerView.java (96%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/view/BriarRecyclerViewBehavior.java (96%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/view/LargeTextInputView.java (94%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/view/TextAvatarView.java (90%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/view/TextInputView.java (98%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/view/TrustIndicatorView.java (85%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/widget/LinkDialogFragment.java (96%)
 rename briar-android/src/{org/briarproject => main/java/org/briarproject/briar}/android/widget/PreferenceDividerDecoration.java (77%)
 rename briar-android/src/{org/briarproject/android/api => main/java/org/briarproject/briar/api/android}/AndroidNotificationManager.java (87%)
 rename briar-android/src/{org/briarproject/android/api => main/java/org/briarproject/briar/api/android}/ReferenceManager.java (94%)
 rename briar-android/src/{ => main/java}/org/thoughtcrime/securesms/LICENSE (100%)
 rename briar-android/src/{ => main/java}/org/thoughtcrime/securesms/components/KeyboardAwareLinearLayout.java (99%)
 rename briar-android/src/{ => main/java}/org/thoughtcrime/securesms/components/RepeatableImageKey.java (100%)
 rename briar-android/src/{ => main/java}/org/thoughtcrime/securesms/components/emoji/AnimatingImageSpan.java (100%)
 rename briar-android/src/{ => main/java}/org/thoughtcrime/securesms/components/emoji/EmojiDrawer.java (98%)
 rename briar-android/src/{ => main/java}/org/thoughtcrime/securesms/components/emoji/EmojiEditText.java (95%)
 rename briar-android/src/{ => main/java}/org/thoughtcrime/securesms/components/emoji/EmojiFilter.java (91%)
 rename briar-android/src/{ => main/java}/org/thoughtcrime/securesms/components/emoji/EmojiPageModel.java (87%)
 rename briar-android/src/{ => main/java}/org/thoughtcrime/securesms/components/emoji/EmojiPageView.java (97%)
 rename briar-android/src/{ => main/java}/org/thoughtcrime/securesms/components/emoji/EmojiPages.java (98%)
 rename briar-android/src/{ => main/java}/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java (97%)
 rename briar-android/src/{ => main/java}/org/thoughtcrime/securesms/components/emoji/EmojiSpan.java (97%)
 rename briar-android/src/{ => main/java}/org/thoughtcrime/securesms/components/emoji/EmojiTextView.java (98%)
 rename briar-android/src/{ => main/java}/org/thoughtcrime/securesms/components/emoji/EmojiToggle.java (94%)
 rename briar-android/src/{ => main/java}/org/thoughtcrime/securesms/components/emoji/EmojiView.java (97%)
 rename briar-android/src/{ => main/java}/org/thoughtcrime/securesms/components/emoji/RecentEmojiPageModel.java (87%)
 rename briar-android/src/{ => main/java}/org/thoughtcrime/securesms/components/emoji/StaticEmojiPageModel.java (97%)
 rename briar-android/src/{ => main/java}/org/thoughtcrime/securesms/components/util/FutureTaskListener.java (100%)
 rename briar-android/src/{ => main/java}/org/thoughtcrime/securesms/components/util/ListenableFutureTask.java (98%)
 rename briar-android/src/{ => main/java}/org/thoughtcrime/securesms/util/BitmapDecodingException.java (100%)
 rename briar-android/src/{ => main/java}/org/thoughtcrime/securesms/util/BitmapUtil.java (100%)
 rename briar-android/{ => src/main}/res/drawable-hdpi/ic_launcher.png (100%)
 rename briar-android/{ => src/main}/res/drawable-hdpi/logo.png (100%)
 rename briar-android/{ => src/main}/res/drawable-hdpi/msg_in.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-hdpi/msg_in_top.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-hdpi/msg_out.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-hdpi/msg_out_top.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-hdpi/notice_in.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-hdpi/notice_in_bottom.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-hdpi/notice_out.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-hdpi/notice_out_bottom.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-hdpi/ongoing_notification_icon.png (100%)
 rename briar-android/{ => src/main}/res/drawable-ldpi/ic_launcher.png (100%)
 rename briar-android/{ => src/main}/res/drawable-ldpi/logo.png (100%)
 rename briar-android/{ => src/main}/res/drawable-ldpi/ongoing_notification_icon.png (100%)
 rename briar-android/{ => src/main}/res/drawable-mdpi/ic_launcher.png (100%)
 rename briar-android/{ => src/main}/res/drawable-mdpi/logo.png (100%)
 rename briar-android/{ => src/main}/res/drawable-mdpi/msg_in.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-mdpi/msg_in_top.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-mdpi/msg_out.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-mdpi/msg_out_top.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-mdpi/notice_in.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-mdpi/notice_in_bottom.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-mdpi/notice_out.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-mdpi/notice_out_bottom.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-mdpi/ongoing_notification_icon.png (100%)
 rename briar-android/{ => src/main}/res/drawable-xhdpi/ic_launcher.png (100%)
 rename briar-android/{ => src/main}/res/drawable-xhdpi/logo.png (100%)
 rename briar-android/{ => src/main}/res/drawable-xhdpi/msg_in.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-xhdpi/msg_in_top.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-xhdpi/msg_out.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-xhdpi/msg_out_top.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-xhdpi/notice_in.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-xhdpi/notice_in_bottom.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-xhdpi/notice_out.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-xhdpi/notice_out_bottom.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-xhdpi/ongoing_notification_icon.png (100%)
 rename briar-android/{ => src/main}/res/drawable-xxhdpi/msg_in.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-xxhdpi/msg_in_top.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-xxhdpi/msg_out.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-xxhdpi/msg_out_top.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-xxhdpi/notice_in.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-xxhdpi/notice_in_bottom.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-xxhdpi/notice_out.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable-xxhdpi/notice_out_bottom.9.png (100%)
 rename briar-android/{ => src/main}/res/drawable/action_delete_black.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/action_delete_white.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/alerts_and_states_error.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/blogs.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/bluetooth.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/border_explanation.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/border_spinner.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/briar_logo_large.png (100%)
 rename briar-android/{ => src/main}/res/drawable/bubble.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/bubble_problem.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/bubble_white.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/chevron48dp_down.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/chevron48dp_up.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/contact_connected.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/contact_disconnected.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/contact_offline.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/contact_online.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/forum_item_create_white.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_add_white.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_backspace_black.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_check_white.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_contact_introduction.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_contacts.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_emoji_activity.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_emoji_animals_nature.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_emoji_emoticons.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_emoji_flags.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_emoji_food_drink.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_emoji_objects.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_emoji_recent.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_emoji_smiley_people.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_emoji_symbols.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_emoji_toggle.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_emoji_travel_places.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_forums_black_24dp.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_group.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_group_white.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_info_white.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_keyboard_black.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_more_vert_accent.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_our_identity_black.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_repeat.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_settings_black_24dp.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_signout_black_24dp.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_visibility.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_visibility_off.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/ic_visibility_white.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/introduction_notification.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/introduction_white.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/level_indicator_circle.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/message_delivered.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/message_delivered_white.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/message_notification_icon.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/message_sent.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/message_sent_white.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/message_stored.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/message_stored_white.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/navigation_accept.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/navigation_drawer_header.png (100%)
 rename briar-android/{ => src/main}/res/drawable/qr_code_explanation.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/qr_code_intro.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/selector_chevron.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/social_send_now_white.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/social_share_white.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/transport_bt.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/transport_lan.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/transport_tor.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/trust_indicator_anonymous.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/trust_indicator_unknown.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/trust_indicator_unverified.xml (100%)
 rename briar-android/{ => src/main}/res/drawable/trust_indicator_verified.xml (100%)
 rename briar-android/{ => src/main}/res/layout-land/fragment_keyagreement_id.xml (100%)
 rename briar-android/{ => src/main}/res/layout-land/invitation_bluetooth_start.xml (100%)
 rename briar-android/{ => src/main}/res/layout/activity_change_password.xml (97%)
 rename briar-android/{ => src/main}/res/layout/activity_conversation.xml (94%)
 rename briar-android/{ => src/main}/res/layout/activity_create_forum.xml (100%)
 rename briar-android/{ => src/main}/res/layout/activity_dev_report.xml (99%)
 rename briar-android/{ => src/main}/res/layout/activity_expired.xml (100%)
 rename briar-android/{ => src/main}/res/layout/activity_forum.xml (87%)
 rename briar-android/{ => src/main}/res/layout/activity_fragment_container.xml (100%)
 rename briar-android/{ => src/main}/res/layout/activity_nav_drawer.xml (100%)
 rename briar-android/{ => src/main}/res/layout/activity_panic_preferences.xml (81%)
 rename briar-android/{ => src/main}/res/layout/activity_password.xml (100%)
 rename briar-android/{ => src/main}/res/layout/activity_plain.xml (100%)
 rename briar-android/{ => src/main}/res/layout/activity_reveal_contacts.xml (100%)
 rename briar-android/{ => src/main}/res/layout/activity_rss_feed_import.xml (100%)
 rename briar-android/{ => src/main}/res/layout/activity_rss_feed_manage.xml (88%)
 rename briar-android/{ => src/main}/res/layout/activity_settings.xml (82%)
 rename briar-android/{ => src/main}/res/layout/activity_setup.xml (97%)
 rename briar-android/{ => src/main}/res/layout/activity_sharing_status.xml (92%)
 rename briar-android/{ => src/main}/res/layout/activity_startup_failure.xml (100%)
 rename briar-android/{ => src/main}/res/layout/activity_with_loading.xml (100%)
 rename briar-android/{ => src/main}/res/layout/activity_write_blog_post.xml (87%)
 rename briar-android/{ => src/main}/res/layout/author_view.xml (97%)
 rename briar-android/{ => src/main}/res/layout/briar_recycler_view.xml (100%)
 rename briar-android/{ => src/main}/res/layout/contact_avatar_status.xml (100%)
 rename briar-android/{ => src/main}/res/layout/emoji_drawer.xml (100%)
 rename briar-android/{ => src/main}/res/layout/emoji_grid_layout.xml (100%)
 rename briar-android/{ => src/main}/res/layout/fragment_blog.xml (76%)
 rename briar-android/{ => src/main}/res/layout/fragment_blog_post.xml (100%)
 rename briar-android/{ => src/main}/res/layout/fragment_blog_post_pager.xml (100%)
 rename briar-android/{ => src/main}/res/layout/fragment_create_group.xml (100%)
 rename briar-android/{ => src/main}/res/layout/fragment_forum_list.xml (77%)
 rename briar-android/{ => src/main}/res/layout/fragment_keyagreement_id.xml (100%)
 rename briar-android/{ => src/main}/res/layout/fragment_keyagreement_qr.xml (98%)
 rename briar-android/{ => src/main}/res/layout/fragment_link_dialog.xml (100%)
 rename briar-android/{ => src/main}/res/layout/fragment_message.xml (86%)
 rename briar-android/{ => src/main}/res/layout/fragment_reblog.xml (95%)
 rename briar-android/{ => src/main}/res/layout/introduction_message.xml (98%)
 rename briar-android/{ => src/main}/res/layout/invitation_bluetooth_confirmation_code.xml (100%)
 rename briar-android/{ => src/main}/res/layout/invitation_bluetooth_invitation_code.xml (100%)
 rename briar-android/{ => src/main}/res/layout/invitation_bluetooth_start.xml (100%)
 rename briar-android/{ => src/main}/res/layout/invitation_error.xml (100%)
 rename briar-android/{ => src/main}/res/layout/list.xml (83%)
 rename briar-android/{ => src/main}/res/layout/list_item_blog.xml (98%)
 rename briar-android/{ => src/main}/res/layout/list_item_blog_comment.xml (96%)
 rename briar-android/{ => src/main}/res/layout/list_item_blog_post.xml (96%)
 rename briar-android/{ => src/main}/res/layout/list_item_contact.xml (100%)
 rename briar-android/{ => src/main}/res/layout/list_item_contact_small.xml (100%)
 rename briar-android/{ => src/main}/res/layout/list_item_conversation_msg_in.xml (100%)
 rename briar-android/{ => src/main}/res/layout/list_item_conversation_msg_out.xml (100%)
 rename briar-android/{ => src/main}/res/layout/list_item_conversation_notice_in.xml (100%)
 rename briar-android/{ => src/main}/res/layout/list_item_conversation_notice_out.xml (100%)
 rename briar-android/{ => src/main}/res/layout/list_item_conversation_request.xml (100%)
 rename briar-android/{ => src/main}/res/layout/list_item_crash.xml (100%)
 rename briar-android/{ => src/main}/res/layout/list_item_forum.xml (98%)
 rename briar-android/{ => src/main}/res/layout/list_item_group.xml (98%)
 rename briar-android/{ => src/main}/res/layout/list_item_group_join_notice.xml (98%)
 rename briar-android/{ => src/main}/res/layout/list_item_group_member.xml (97%)
 rename briar-android/{ => src/main}/res/layout/list_item_invitations.xml (98%)
 rename briar-android/{ => src/main}/res/layout/list_item_revealable_contact.xml (100%)
 rename briar-android/{ => src/main}/res/layout/list_item_rss_feed.xml (100%)
 rename briar-android/{ => src/main}/res/layout/list_item_selectable_contact.xml (100%)
 rename briar-android/{ => src/main}/res/layout/list_item_thread.xml (98%)
 rename briar-android/{ => src/main}/res/layout/list_item_transport.xml (100%)
 rename briar-android/{ => src/main}/res/layout/navigation_header.xml (100%)
 rename briar-android/{ => src/main}/res/layout/navigation_menu.xml (100%)
 rename briar-android/{ => src/main}/res/layout/splash.xml (100%)
 rename briar-android/{ => src/main}/res/layout/text_avatar_view.xml (100%)
 rename briar-android/{ => src/main}/res/layout/text_input_view.xml (100%)
 rename briar-android/{ => src/main}/res/layout/text_input_view_large.xml (100%)
 rename briar-android/{ => src/main}/res/layout/transports_list.xml (100%)
 rename briar-android/{ => src/main}/res/layout/view_code_entry.xml (100%)
 rename briar-android/{ => src/main}/res/menu/blogs_blog_actions.xml (100%)
 rename briar-android/{ => src/main}/res/menu/blogs_feed_actions.xml (100%)
 rename briar-android/{ => src/main}/res/menu/contact_list_actions.xml (100%)
 rename briar-android/{ => src/main}/res/menu/contact_selection_actions.xml (100%)
 rename briar-android/{ => src/main}/res/menu/conversation_actions.xml (100%)
 rename briar-android/{ => src/main}/res/menu/dev_report_actions.xml (100%)
 rename briar-android/{ => src/main}/res/menu/forum_actions.xml (100%)
 rename briar-android/{ => src/main}/res/menu/forum_list_actions.xml (100%)
 rename briar-android/{ => src/main}/res/menu/group_actions.xml (100%)
 rename briar-android/{ => src/main}/res/menu/group_reveal_actions.xml (100%)
 rename briar-android/{ => src/main}/res/menu/groups_list_actions.xml (100%)
 rename briar-android/{ => src/main}/res/menu/navigation_drawer.xml (100%)
 rename briar-android/{ => src/main}/res/menu/rss_feed_manage_actions.xml (100%)
 rename briar-android/{ => src/main}/res/values-de/strings.xml (100%)
 rename briar-android/{ => src/main}/res/values-es/strings.xml (100%)
 rename briar-android/{ => src/main}/res/values-it/strings.xml (100%)
 rename briar-android/{ => src/main}/res/values-ms/strings.xml (100%)
 rename briar-android/{ => src/main}/res/values-pt-rBR/strings.xml (100%)
 rename briar-android/{ => src/main}/res/values/arrays.xml (100%)
 rename briar-android/{ => src/main}/res/values/attrs.xml (100%)
 rename briar-android/{ => src/main}/res/values/color.xml (100%)
 rename briar-android/{ => src/main}/res/values/dimens.xml (97%)
 rename briar-android/{ => src/main}/res/values/emoji.xml (100%)
 rename briar-android/{ => src/main}/res/values/strings.xml (100%)
 rename briar-android/{ => src/main}/res/values/styles.xml (100%)
 rename briar-android/{ => src/main}/res/values/themes.xml (100%)
 rename briar-android/{ => src/main}/res/xml/panic_preferences.xml (100%)
 rename briar-android/{ => src/main}/res/xml/settings.xml (93%)
 delete mode 100644 briar-android/src/org/briarproject/android/ActivityComponent.java
 delete mode 100644 briar-android/src/org/briarproject/android/AndroidComponent.java
 delete mode 100644 briar-android/src/org/briarproject/android/AndroidEagerSingletons.java
 delete mode 100644 briar-android/src/org/briarproject/android/contactselection/ContactSelectorController.java
 delete mode 100644 briar-android/src/org/briarproject/android/controller/DbController.java
 delete mode 100644 briar-android/src/org/briarproject/android/controller/NavDrawerController.java
 delete mode 100644 briar-android/src/org/briarproject/android/controller/PasswordController.java
 delete mode 100644 briar-android/src/org/briarproject/android/controller/SetupController.java
 delete mode 100644 briar-android/src/org/briarproject/android/controller/TransportStateListener.java
 delete mode 100644 briar-android/src/org/briarproject/android/forum/ForumController.java
 delete mode 100644 briar-android/src/org/briarproject/android/forum/ForumItem.java
 delete mode 100644 briar-android/src/org/briarproject/android/privategroup/conversation/GroupController.java
 delete mode 100644 briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupController.java
 delete mode 100644 briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationController.java
 delete mode 100644 briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationViewHolder.java
 delete mode 100644 briar-android/src/org/briarproject/android/privategroup/memberlist/GroupMemberListController.java
 delete mode 100644 briar-android/src/org/briarproject/android/privategroup/memberlist/MemberListItem.java
 delete mode 100644 briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsController.java
 delete mode 100644 briar-android/src/org/briarproject/android/privategroup/reveal/RevealableContactItem.java
 delete mode 100644 briar-android/src/org/briarproject/android/sharing/BlogInvitationController.java
 delete mode 100644 briar-android/src/org/briarproject/android/sharing/ForumInvitationController.java
 delete mode 100644 briar-android/src/org/briarproject/android/sharing/InvitationController.java
 delete mode 100644 briar-android/src/org/briarproject/android/sharing/ShareBlogController.java
 delete mode 100644 briar-android/src/org/briarproject/android/sharing/ShareForumController.java
 delete mode 100644 briar-android/src/org/briarproject/system/AndroidSystemModule.java
 rename briar-android/{ => src}/test/java/android/net/http/AndroidHttpClient.java (71%)
 rename briar-android/{test/java/org/briarproject => src/test/java/org/briarproject/briar}/android/SetupActivityTest.java (90%)
 rename briar-android/{test/java/org/briarproject => src/test/java/org/briarproject/briar}/android/TestBriarApplication.java (75%)
 rename briar-android/{test/java/org/briarproject => src/test/java/org/briarproject/briar}/android/TestSetupActivity.java (67%)
 rename briar-android/{test/java/org/briarproject => src/test/java/org/briarproject/briar}/android/forum/ForumActivityTest.java (85%)
 rename briar-android/{test/java/org/briarproject => src/test/java/org/briarproject/briar}/android/forum/TestForumActivity.java (61%)
 rename briar-android/{test/java/org/briarproject/android => src/test/java/org/briarproject/briar/android/login}/ChangePasswordActivityTest.java (92%)
 rename briar-android/{test/java/org/briarproject/android => src/test/java/org/briarproject/briar/android/login}/TestChangePasswordActivity.java (79%)
 rename briar-api/src/{org/briarproject/api/blogs => main/java/org/briarproject/briar/api/blog}/Blog.java (64%)
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/blog/BlogCommentHeader.java
 rename briar-api/src/{org/briarproject/api/blogs => main/java/org/briarproject/briar/api/blog}/BlogConstants.java (72%)
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/blog/BlogFactory.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/blog/BlogInvitationRequest.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/blog/BlogInvitationResponse.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/blog/BlogManager.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/blog/BlogPost.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/blog/BlogPostFactory.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/blog/BlogPostHeader.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/blog/BlogSharingManager.java
 rename briar-api/src/{org/briarproject/api/blogs => main/java/org/briarproject/briar/api/blog}/BlogSharingMessage.java (62%)
 rename briar-api/src/{org/briarproject/api/blogs => main/java/org/briarproject/briar/api/blog}/MessageType.java (91%)
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/blog/event/BlogInvitationRequestReceivedEvent.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/blog/event/BlogInvitationResponseReceivedEvent.java
 rename briar-api/src/{org/briarproject/api => main/java/org/briarproject/briar/api/blog}/event/BlogPostAddedEvent.java (52%)
 rename briar-api/src/{org/briarproject/api/clients => main/java/org/briarproject/briar/api/client}/BaseGroup.java (71%)
 rename briar-api/src/{org/briarproject/api/clients => main/java/org/briarproject/briar/api/client}/BaseMessageHeader.java (61%)
 rename briar-api/src/{org/briarproject/api/clients => main/java/org/briarproject/briar/api/client}/MessageQueueManager.java (78%)
 rename briar-api/src/{org/briarproject/api/clients => main/java/org/briarproject/briar/api/client}/MessageTracker.java (79%)
 rename briar-api/src/{org/briarproject/api/clients => main/java/org/briarproject/briar/api/client}/MessageTree.java (64%)
 rename briar-api/src/{org/briarproject/api/clients => main/java/org/briarproject/briar/api/client}/NamedGroup.java (76%)
 rename briar-api/src/{org/briarproject/api/clients => main/java/org/briarproject/briar/api/client}/PostHeader.java (56%)
 rename briar-api/src/{org/briarproject/api/clients => main/java/org/briarproject/briar/api/client}/ProtocolEngine.java (64%)
 rename briar-api/src/{org/briarproject/api/clients => main/java/org/briarproject/briar/api/client}/ProtocolStateException.java (51%)
 rename briar-api/src/{org/briarproject/api/clients => main/java/org/briarproject/briar/api/client}/QueueMessage.java (52%)
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/client/QueueMessageFactory.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/client/SessionId.java
 rename briar-api/src/{org/briarproject/api/clients => main/java/org/briarproject/briar/api/client}/ThreadedMessage.java (57%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/feed/Feed.java (65%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/feed/FeedConstants.java (94%)
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/feed/FeedManager.java
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/forum/Forum.java (55%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/forum/ForumConstants.java (57%)
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/forum/ForumFactory.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/forum/ForumInvitationRequest.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/forum/ForumInvitationResponse.java
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/forum/ForumManager.java (75%)
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/forum/ForumPost.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/forum/ForumPostFactory.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/forum/ForumPostHeader.java
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/forum/ForumSharingManager.java (50%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/forum/ForumSharingMessage.java (56%)
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/forum/event/ForumInvitationRequestReceivedEvent.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/forum/event/ForumInvitationResponseReceivedEvent.java
 rename briar-api/src/{org/briarproject/api => main/java/org/briarproject/briar/api/forum}/event/ForumPostReceivedEvent.java (51%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/introduction/IntroduceeAction.java (62%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/introduction/IntroduceeProtocolState.java (68%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/introduction/IntroducerAction.java (62%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/introduction/IntroducerProtocolState.java (70%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/introduction/IntroductionConstants.java (94%)
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionManager.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionMessage.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionRequest.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/introduction/IntroductionResponse.java
 rename briar-api/src/{org/briarproject/api => main/java/org/briarproject/briar/api/introduction}/event/IntroductionAbortedEvent.java (52%)
 rename briar-api/src/{org/briarproject/api => main/java/org/briarproject/briar/api/introduction}/event/IntroductionRequestReceivedEvent.java (57%)
 rename briar-api/src/{org/briarproject/api => main/java/org/briarproject/briar/api/introduction}/event/IntroductionResponseReceivedEvent.java (58%)
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/introduction/event/IntroductionSucceededEvent.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/messaging/ConversationManager.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/messaging/MessagingConstants.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/messaging/MessagingManager.java
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/messaging/PrivateMessage.java (62%)
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/messaging/PrivateMessageFactory.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/messaging/PrivateMessageHeader.java
 rename briar-api/src/{org/briarproject/api => main/java/org/briarproject/briar/api/messaging}/event/PrivateMessageReceivedEvent.java (55%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/privategroup/GroupMember.java (69%)
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMessage.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMessageFactory.java
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/privategroup/GroupMessageHeader.java (52%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/privategroup/JoinMessageHeader.java (80%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/privategroup/MessageType.java (58%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/privategroup/PrivateGroup.java (52%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/privategroup/PrivateGroupConstants.java (79%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/privategroup/PrivateGroupFactory.java (64%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/privategroup/PrivateGroupManager.java (59%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/privategroup/Visibility.java (57%)
 rename briar-api/src/{org/briarproject/api/privategroup => main/java/org/briarproject/briar/api/privategroup/event}/ContactRelationshipRevealedEvent.java (64%)
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/privategroup/event/GroupDissolvedEvent.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/privategroup/event/GroupInvitationRequestReceivedEvent.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/privategroup/event/GroupInvitationResponseReceivedEvent.java
 rename briar-api/src/{org/briarproject/api => main/java/org/briarproject/briar/api/privategroup}/event/GroupMessageAddedEvent.java (62%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/privategroup/invitation/GroupInvitationFactory.java (59%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/privategroup/invitation/GroupInvitationItem.java (55%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/privategroup/invitation/GroupInvitationManager.java (75%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/privategroup/invitation/GroupInvitationRequest.java (63%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/privategroup/invitation/GroupInvitationResponse.java (52%)
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationFactory.java
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/sharing/InvitationItem.java (77%)
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationMessage.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationRequest.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationResponse.java
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/sharing/Shareable.java
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/sharing/SharingConstants.java (91%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/sharing/SharingInvitationItem.java (74%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/sharing/SharingManager.java (73%)
 rename briar-api/src/{org/briarproject => main/java/org/briarproject/briar}/api/sharing/SharingMessage.java (62%)
 rename briar-api/src/{org/briarproject/api => main/java/org/briarproject/briar/api/sharing}/event/InvitationRequestReceivedEvent.java (50%)
 rename briar-api/src/{org/briarproject/api => main/java/org/briarproject/briar/api/sharing}/event/InvitationResponseReceivedEvent.java (55%)
 delete mode 100644 briar-api/src/org/briarproject/api/FormatException.java
 delete mode 100644 briar-api/src/org/briarproject/api/UniqueId.java
 delete mode 100644 briar-api/src/org/briarproject/api/blogs/BlogCommentHeader.java
 delete mode 100644 briar-api/src/org/briarproject/api/blogs/BlogFactory.java
 delete mode 100644 briar-api/src/org/briarproject/api/blogs/BlogInvitationRequest.java
 delete mode 100644 briar-api/src/org/briarproject/api/blogs/BlogInvitationResponse.java
 delete mode 100644 briar-api/src/org/briarproject/api/blogs/BlogManager.java
 delete mode 100644 briar-api/src/org/briarproject/api/blogs/BlogPost.java
 delete mode 100644 briar-api/src/org/briarproject/api/blogs/BlogPostFactory.java
 delete mode 100644 briar-api/src/org/briarproject/api/blogs/BlogPostHeader.java
 delete mode 100644 briar-api/src/org/briarproject/api/blogs/BlogSharingManager.java
 delete mode 100644 briar-api/src/org/briarproject/api/clients/Client.java
 delete mode 100644 briar-api/src/org/briarproject/api/clients/ContactGroupFactory.java
 delete mode 100644 briar-api/src/org/briarproject/api/clients/QueueMessageFactory.java
 delete mode 100644 briar-api/src/org/briarproject/api/clients/SessionId.java
 delete mode 100644 briar-api/src/org/briarproject/api/contact/ContactExchangeListener.java
 delete mode 100644 briar-api/src/org/briarproject/api/contact/ContactExchangeTask.java
 delete mode 100644 briar-api/src/org/briarproject/api/crypto/MessageDigest.java
 delete mode 100644 briar-api/src/org/briarproject/api/crypto/PrivateKey.java
 delete mode 100644 briar-api/src/org/briarproject/api/crypto/PseudoRandom.java
 delete mode 100644 briar-api/src/org/briarproject/api/crypto/PublicKey.java
 delete mode 100644 briar-api/src/org/briarproject/api/crypto/StreamEncrypter.java
 delete mode 100644 briar-api/src/org/briarproject/api/data/BdfWriterFactory.java
 delete mode 100644 briar-api/src/org/briarproject/api/data/MetadataEncoder.java
 delete mode 100644 briar-api/src/org/briarproject/api/data/MetadataParser.java
 delete mode 100644 briar-api/src/org/briarproject/api/data/ObjectReader.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/BlogInvitationReceivedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/BlogInvitationResponseReceivedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/ContactAddedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/ContactRemovedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/ContactStatusChangedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/ContactVerifiedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/Event.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/EventBus.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/EventListener.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/ForumInvitationReceivedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/ForumInvitationResponseReceivedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/GroupAddedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/GroupDissolvedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/GroupInvitationRequestReceivedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/GroupInvitationResponseReceivedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/GroupRemovedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/GroupVisibilityUpdatedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/IntroductionSucceededEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/KeyAgreementAbortedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/KeyAgreementFailedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/KeyAgreementFinishedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/KeyAgreementListeningEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/KeyAgreementStartedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/LocalAuthorAddedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/LocalAuthorRemovedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/MessageAddedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/MessageRequestedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/MessageSharedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/MessageToAckEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/MessagesAckedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/SettingsUpdatedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/ShutdownEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/TransportDisabledEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/event/TransportEnabledEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/feed/FeedManager.java
 delete mode 100644 briar-api/src/org/briarproject/api/forum/ForumFactory.java
 delete mode 100644 briar-api/src/org/briarproject/api/forum/ForumInvitationRequest.java
 delete mode 100644 briar-api/src/org/briarproject/api/forum/ForumInvitationResponse.java
 delete mode 100644 briar-api/src/org/briarproject/api/forum/ForumPost.java
 delete mode 100644 briar-api/src/org/briarproject/api/forum/ForumPostFactory.java
 delete mode 100644 briar-api/src/org/briarproject/api/forum/ForumPostHeader.java
 delete mode 100644 briar-api/src/org/briarproject/api/identity/IdentityManager.java
 delete mode 100644 briar-api/src/org/briarproject/api/introduction/IntroductionManager.java
 delete mode 100644 briar-api/src/org/briarproject/api/introduction/IntroductionMessage.java
 delete mode 100644 briar-api/src/org/briarproject/api/introduction/IntroductionRequest.java
 delete mode 100644 briar-api/src/org/briarproject/api/introduction/IntroductionResponse.java
 delete mode 100644 briar-api/src/org/briarproject/api/invitation/InvitationConstants.java
 delete mode 100644 briar-api/src/org/briarproject/api/invitation/InvitationTaskFactory.java
 delete mode 100644 briar-api/src/org/briarproject/api/keyagreement/KeyAgreementConstants.java
 delete mode 100644 briar-api/src/org/briarproject/api/keyagreement/KeyAgreementTaskFactory.java
 delete mode 100644 briar-api/src/org/briarproject/api/keyagreement/KeyAgreementTaskId.java
 delete mode 100644 briar-api/src/org/briarproject/api/keyagreement/PayloadEncoder.java
 delete mode 100644 briar-api/src/org/briarproject/api/lifecycle/LifecycleManager.java
 delete mode 100644 briar-api/src/org/briarproject/api/messaging/ConversationManager.java
 delete mode 100644 briar-api/src/org/briarproject/api/messaging/MessagingConstants.java
 delete mode 100644 briar-api/src/org/briarproject/api/messaging/MessagingManager.java
 delete mode 100644 briar-api/src/org/briarproject/api/messaging/PrivateMessageFactory.java
 delete mode 100644 briar-api/src/org/briarproject/api/messaging/PrivateMessageHeader.java
 delete mode 100644 briar-api/src/org/briarproject/api/plugins/PluginConfig.java
 delete mode 100644 briar-api/src/org/briarproject/api/plugins/duplex/DuplexTransportConnection.java
 delete mode 100644 briar-api/src/org/briarproject/api/plugins/simplex/SimplexPluginCallback.java
 delete mode 100644 briar-api/src/org/briarproject/api/privategroup/GroupMessage.java
 delete mode 100644 briar-api/src/org/briarproject/api/privategroup/GroupMessageFactory.java
 delete mode 100644 briar-api/src/org/briarproject/api/properties/TransportPropertyConstants.java
 delete mode 100644 briar-api/src/org/briarproject/api/reliability/ReadHandler.java
 delete mode 100644 briar-api/src/org/briarproject/api/reliability/ReliabilityLayerFactory.java
 delete mode 100644 briar-api/src/org/briarproject/api/reliability/WriteHandler.java
 delete mode 100644 briar-api/src/org/briarproject/api/reporting/DevConfig.java
 delete mode 100644 briar-api/src/org/briarproject/api/reporting/DevReporter.java
 delete mode 100644 briar-api/src/org/briarproject/api/settings/Settings.java
 delete mode 100644 briar-api/src/org/briarproject/api/settings/SettingsManager.java
 delete mode 100644 briar-api/src/org/briarproject/api/sharing/InvitationFactory.java
 delete mode 100644 briar-api/src/org/briarproject/api/sharing/InvitationMessage.java
 delete mode 100644 briar-api/src/org/briarproject/api/sharing/InvitationRequest.java
 delete mode 100644 briar-api/src/org/briarproject/api/sharing/InvitationResponse.java
 delete mode 100644 briar-api/src/org/briarproject/api/sharing/Shareable.java
 delete mode 100644 briar-api/src/org/briarproject/api/sync/GroupFactory.java
 delete mode 100644 briar-api/src/org/briarproject/api/sync/PacketReaderFactory.java
 delete mode 100644 briar-api/src/org/briarproject/api/sync/PacketWriterFactory.java
 delete mode 100644 briar-api/src/org/briarproject/api/sync/Request.java
 delete mode 100644 briar-api/src/org/briarproject/api/sync/SyncConstants.java
 delete mode 100644 briar-api/src/org/briarproject/api/transport/StreamReaderFactory.java
 delete mode 100644 briar-api/src/org/briarproject/api/transport/StreamWriterFactory.java
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/BriarCoreEagerSingletons.java
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/BriarCoreModule.java
 rename briar-core/src/{org/briarproject/blogs => main/java/org/briarproject/briar/blog}/BlogFactoryImpl.java (60%)
 rename briar-core/src/{org/briarproject/blogs => main/java/org/briarproject/briar/blog}/BlogManagerImpl.java (82%)
 rename briar-core/src/{org/briarproject/blogs/BlogsModule.java => main/java/org/briarproject/briar/blog/BlogModule.java} (66%)
 rename briar-core/src/{org/briarproject/blogs => main/java/org/briarproject/briar/blog}/BlogPostFactoryImpl.java (76%)
 rename briar-core/src/{org/briarproject/blogs => main/java/org/briarproject/briar/blog}/BlogPostValidator.java (74%)
 rename briar-core/src/{org/briarproject/clients => main/java/org/briarproject/briar/client}/BdfIncomingMessageHook.java (66%)
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/client/BdfQueueMessageValidator.java
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/client/BriarClientModule.java
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/client/ConversationClientImpl.java
 rename briar-core/src/{org/briarproject/clients => main/java/org/briarproject/briar/client}/MessageQueueManagerImpl.java (83%)
 rename briar-core/src/{org/briarproject/clients/BdfConstants.java => main/java/org/briarproject/briar/client/MessageTrackerConstants.java} (69%)
 rename briar-core/src/{org/briarproject/clients => main/java/org/briarproject/briar/client}/MessageTrackerImpl.java (74%)
 rename briar-core/src/{org/briarproject/clients => main/java/org/briarproject/briar/client}/MessageTreeImpl.java (78%)
 rename briar-core/src/{org/briarproject/clients => main/java/org/briarproject/briar/client}/QueueMessageFactoryImpl.java (63%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/feed/FeedManagerImpl.java (81%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/feed/FeedModule.java (70%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/forum/ForumFactoryImpl.java (53%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/forum/ForumManagerImpl.java (75%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/forum/ForumModule.java (59%)
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/forum/ForumPostFactoryImpl.java
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/forum/ForumPostValidator.java (59%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/introduction/IntroduceeEngine.java (69%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/introduction/IntroduceeManager.java (71%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/introduction/IntroducerEngine.java (68%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/introduction/IntroducerManager.java (57%)
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionGroupFactory.java
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/introduction/IntroductionManagerImpl.java (75%)
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionModule.java
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionValidator.java
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/introduction/MessageSender.java
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/messaging/ConversationManagerImpl.java (64%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/messaging/MessagingManagerImpl.java (75%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/messaging/MessagingModule.java (64%)
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/messaging/PrivateMessageFactoryImpl.java
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/messaging/PrivateMessageValidator.java
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/GroupConstants.java (83%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/GroupMessageFactoryImpl.java (74%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/GroupMessageValidator.java (69%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/PrivateGroupFactoryImpl.java (64%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/PrivateGroupManagerImpl.java (81%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/PrivateGroupModule.java (66%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/AbortMessage.java (56%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/AbstractProtocolEngine.java (79%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/CreatorProtocolEngine.java (82%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/CreatorSession.java (68%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/CreatorState.java (62%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/GroupInvitationConstants.java (93%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/GroupInvitationFactoryImpl.java (61%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/GroupInvitationManagerImpl.java (86%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/GroupInvitationMessage.java (75%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/GroupInvitationModule.java (72%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/GroupInvitationValidator.java (67%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/InviteMessage.java (77%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/InviteeProtocolEngine.java (83%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/InviteeSession.java (68%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/InviteeState.java (63%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/JoinMessage.java (66%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/LeaveMessage.java (66%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/LocalAction.java (50%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/MessageEncoder.java (70%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/MessageEncoderImpl.java (65%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/MessageMetadata.java (78%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/MessageParser.java (62%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/MessageParserImpl.java (69%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/MessageType.java (58%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/PeerProtocolEngine.java (86%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/PeerSession.java (66%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/PeerState.java (63%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/ProtocolEngine.java (75%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/ProtocolEngineFactory.java (64%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/ProtocolEngineFactoryImpl.java (78%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/Role.java (55%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/Session.java (84%)
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/SessionEncoder.java
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/SessionEncoderImpl.java
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/SessionParser.java (58%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/privategroup/invitation/SessionParserImpl.java (62%)
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/State.java
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/sharing/BlogInviteeSessionState.java
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharerSessionState.java
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/sharing/BlogSharingManagerImpl.java (77%)
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharingValidator.java
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/sharing/ForumInviteeSessionState.java
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/sharing/ForumSharerSessionState.java (54%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/sharing/ForumSharingManagerImpl.java (77%)
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/sharing/ForumSharingValidator.java
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/sharing/InvitationFactory.java
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/sharing/InvitationReceivedEventFactory.java
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/sharing/InvitationResponseReceivedEventFactory.java
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/sharing/InviteeEngine.java (74%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/sharing/InviteeSessionState.java (60%)
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/sharing/InviteeSessionStateFactory.java
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/sharing/ShareableFactory.java
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/sharing/SharerEngine.java (81%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/sharing/SharerSessionState.java (64%)
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/sharing/SharerSessionStateFactory.java
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/sharing/SharingManagerImpl.java (84%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/sharing/SharingModule.java (60%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/sharing/SharingSessionState.java (63%)
 rename briar-core/src/{org/briarproject => main/java/org/briarproject/briar}/util/HtmlUtils.java (54%)
 delete mode 100644 briar-core/src/org/briarproject/CoreEagerSingletons.java
 delete mode 100644 briar-core/src/org/briarproject/CoreModule.java
 delete mode 100644 briar-core/src/org/briarproject/clients/BdfMessageValidator.java
 delete mode 100644 briar-core/src/org/briarproject/clients/ClientsModule.java
 delete mode 100644 briar-core/src/org/briarproject/clients/ConversationClientImpl.java
 delete mode 100644 briar-core/src/org/briarproject/crypto/Signature.java
 delete mode 100644 briar-core/src/org/briarproject/data/BdfReaderFactoryImpl.java
 delete mode 100644 briar-core/src/org/briarproject/data/BdfWriterFactoryImpl.java
 delete mode 100644 briar-core/src/org/briarproject/db/DbStateException.java
 delete mode 100644 briar-core/src/org/briarproject/forum/ForumPostFactoryImpl.java
 delete mode 100644 briar-core/src/org/briarproject/identity/AuthorReader.java
 delete mode 100644 briar-core/src/org/briarproject/introduction/IntroductionGroupFactory.java
 delete mode 100644 briar-core/src/org/briarproject/introduction/IntroductionModule.java
 delete mode 100644 briar-core/src/org/briarproject/introduction/IntroductionValidator.java
 delete mode 100644 briar-core/src/org/briarproject/introduction/MessageSender.java
 delete mode 100644 briar-core/src/org/briarproject/invitation/InvitationModule.java
 delete mode 100644 briar-core/src/org/briarproject/keyagreement/AbortException.java
 delete mode 100644 briar-core/src/org/briarproject/messaging/PrivateMessageFactoryImpl.java
 delete mode 100644 briar-core/src/org/briarproject/messaging/PrivateMessageValidator.java
 delete mode 100644 briar-core/src/org/briarproject/plugins/BackoffFactoryImpl.java
 delete mode 100644 briar-core/src/org/briarproject/plugins/tcp/PortMapper.java
 delete mode 100644 briar-core/src/org/briarproject/privategroup/invitation/InviteAction.java
 delete mode 100644 briar-core/src/org/briarproject/privategroup/invitation/SessionEncoder.java
 delete mode 100644 briar-core/src/org/briarproject/privategroup/invitation/SessionEncoderImpl.java
 delete mode 100644 briar-core/src/org/briarproject/privategroup/invitation/State.java
 delete mode 100644 briar-core/src/org/briarproject/properties/TransportPropertyValidator.java
 delete mode 100644 briar-core/src/org/briarproject/reliability/ReliabilityLayerFactoryImpl.java
 delete mode 100644 briar-core/src/org/briarproject/reporting/ReportingModule.java
 delete mode 100644 briar-core/src/org/briarproject/sharing/BlogInviteeSessionState.java
 delete mode 100644 briar-core/src/org/briarproject/sharing/BlogSharerSessionState.java
 delete mode 100644 briar-core/src/org/briarproject/sharing/BlogSharingValidator.java
 delete mode 100644 briar-core/src/org/briarproject/sharing/ForumInviteeSessionState.java
 delete mode 100644 briar-core/src/org/briarproject/sharing/ForumSharingValidator.java
 delete mode 100644 briar-core/src/org/briarproject/sharing/InvitationFactory.java
 delete mode 100644 briar-core/src/org/briarproject/sharing/InvitationReceivedEventFactory.java
 delete mode 100644 briar-core/src/org/briarproject/sharing/InvitationResponseReceivedEventFactory.java
 delete mode 100644 briar-core/src/org/briarproject/sharing/InviteeSessionStateFactory.java
 delete mode 100644 briar-core/src/org/briarproject/sharing/ShareableFactory.java
 delete mode 100644 briar-core/src/org/briarproject/sharing/SharerSessionStateFactory.java
 delete mode 100644 briar-core/src/org/briarproject/sync/GroupFactoryImpl.java
 delete mode 100644 briar-core/src/org/briarproject/sync/PacketReaderFactoryImpl.java
 delete mode 100644 briar-core/src/org/briarproject/sync/PacketWriterFactoryImpl.java
 delete mode 100644 briar-core/src/org/briarproject/transport/TransportKeyManager.java
 delete mode 100644 briar-core/src/org/briarproject/transport/TransportKeyManagerFactory.java
 delete mode 100644 briar-desktop/build.gradle
 delete mode 100644 briar-desktop/src/org/briarproject/plugins/file/LinuxRemovableDriveMonitor.java
 delete mode 100644 briar-desktop/src/org/briarproject/plugins/file/MacRemovableDriveMonitor.java
 delete mode 100644 briar-desktop/src/org/briarproject/plugins/modem/ModemFactory.java
 delete mode 100644 briar-desktop/src/org/briarproject/plugins/modem/SerialPortList.java
 delete mode 100644 briar-desktop/src/org/briarproject/plugins/modem/SerialPortListImpl.java
 rename briar-tests/src/org/briarproject/{clients => bramble/client}/BdfMessageValidatorTest.java (80%)
 rename briar-tests/src/org/briarproject/{clients => bramble/client}/ClientHelperImplTest.java (90%)
 rename briar-tests/src/org/briarproject/{ => bramble}/contact/ContactManagerImplTest.java (89%)
 rename briar-tests/src/org/briarproject/{ => bramble}/crypto/AsciiArmourTest.java (97%)
 rename briar-tests/src/org/briarproject/{ => bramble}/crypto/Blake2sDigestTest.java (98%)
 rename briar-tests/src/org/briarproject/{ => bramble}/crypto/EllipticCurveMultiplicationTest.java (97%)
 rename briar-tests/src/org/briarproject/{ => bramble}/crypto/EllipticCurvePerformanceTest.java (97%)
 rename briar-tests/src/org/briarproject/{ => bramble}/crypto/FortunaGeneratorTest.java (98%)
 rename briar-tests/src/org/briarproject/{ => bramble}/crypto/FortunaSecureRandomTest.java (85%)
 rename briar-tests/src/org/briarproject/{ => bramble}/crypto/KeyAgreementTest.java (84%)
 rename briar-tests/src/org/briarproject/{ => bramble}/crypto/KeyDerivationTest.java (95%)
 rename briar-tests/src/org/briarproject/{ => bramble}/crypto/KeyEncodingAndParsingTest.java (93%)
 rename briar-tests/src/org/briarproject/{ => bramble}/crypto/MacTest.java (91%)
 rename briar-tests/src/org/briarproject/{ => bramble}/crypto/MessageEncrypterTest.java (77%)
 rename briar-tests/src/org/briarproject/{ => bramble}/crypto/PasswordBasedKdfTest.java (97%)
 rename briar-tests/src/org/briarproject/{ => bramble}/crypto/PasswordStrengthEstimatorImplTest.java (80%)
 rename briar-tests/src/org/briarproject/{ => bramble}/crypto/SignatureTest.java (96%)
 rename briar-tests/src/org/briarproject/{ => bramble}/crypto/StreamDecrypterImplTest.java (91%)
 rename briar-tests/src/org/briarproject/{ => bramble}/crypto/StreamEncrypterImplTest.java (96%)
 rename briar-tests/src/org/briarproject/{ => bramble}/crypto/TestAuthenticatedCipher.java (75%)
 rename briar-tests/src/org/briarproject/{ => bramble}/crypto/XSalsa20Poly1305AuthenticatedCipherTest.java (96%)
 rename briar-tests/src/org/briarproject/{ => bramble}/data/BdfDictionaryTest.java (89%)
 rename briar-tests/src/org/briarproject/{ => bramble}/data/BdfListTest.java (96%)
 rename briar-tests/src/org/briarproject/{ => bramble}/data/BdfReaderImplTest.java (97%)
 rename briar-tests/src/org/briarproject/{ => bramble}/data/BdfWriterImplTest.java (94%)
 rename briar-tests/src/org/briarproject/{ => bramble}/data/MetadataEncoderParserIntegrationTest.java (85%)
 rename briar-tests/src/org/briarproject/{ => bramble}/db/BasicH2Test.java (96%)
 rename briar-tests/src/org/briarproject/{ => bramble}/db/DatabaseComponentImplTest.java (93%)
 rename briar-tests/src/org/briarproject/{ => bramble}/db/ExponentialBackoffTest.java (98%)
 rename briar-tests/src/org/briarproject/{ => bramble}/db/H2DatabaseTest.java (96%)
 rename briar-tests/src/org/briarproject/{ => bramble/db}/LockFairnessTest.java (98%)
 rename briar-tests/src/org/briarproject/{ => bramble}/db/TransactionIsolationTest.java (99%)
 rename briar-tests/src/org/briarproject/{ => bramble}/identity/IdentityManagerImplTest.java (79%)
 rename briar-tests/src/org/briarproject/{ => bramble}/keyagreement/KeyAgreementProtocolTest.java (96%)
 rename briar-tests/src/org/briarproject/{ => bramble}/lifecycle/ShutdownManagerImplTest.java (81%)
 rename briar-tests/src/org/briarproject/{ => bramble}/lifecycle/WindowsShutdownManagerImplTest.java (80%)
 rename briar-tests/src/org/briarproject/{plugins => bramble/plugin}/BackoffImplTest.java (97%)
 rename briar-tests/src/org/briarproject/{plugins => bramble/plugin}/ConnectionRegistryImplTest.java (87%)
 rename briar-tests/src/org/briarproject/{plugins => bramble/plugin}/PluginManagerImplTest.java (82%)
 rename briar-tests/src/org/briarproject/{plugins => bramble/plugin}/PollerTest.java (92%)
 rename briar-tests/src/org/briarproject/{plugins => bramble/plugin}/file/LinuxRemovableDriveFinderTest.java (95%)
 rename briar-tests/src/org/briarproject/{plugins => bramble/plugin}/file/MacRemovableDriveFinderTest.java (94%)
 rename briar-tests/src/org/briarproject/{plugins => bramble/plugin}/file/PollingRemovableDriveMonitorTest.java (88%)
 rename briar-tests/src/org/briarproject/{plugins => bramble/plugin}/file/RemovableDrivePluginTest.java (94%)
 rename briar-tests/src/org/briarproject/{plugins => bramble/plugin}/file/UnixRemovableDriveMonitorTest.java (80%)
 rename briar-tests/src/org/briarproject/{plugins => bramble/plugin}/modem/CountryCodesTest.java (98%)
 rename briar-tests/src/org/briarproject/{plugins => bramble/plugin}/modem/ModemPluginTest.java (96%)
 rename briar-tests/src/org/briarproject/{plugins => bramble/plugin}/tcp/LanTcpPluginTest.java (92%)
 rename briar-tests/src/org/briarproject/{ => bramble}/properties/TransportPropertyManagerImplTest.java (84%)
 rename briar-tests/src/org/briarproject/{ => bramble}/properties/TransportPropertyValidatorTest.java (77%)
 rename briar-tests/src/org/briarproject/{ => bramble}/sync/PacketReaderImplTest.java (90%)
 rename briar-tests/src/org/briarproject/{ => bramble}/sync/SimplexOutgoingSessionTest.java (89%)
 rename briar-tests/src/org/briarproject/{ => bramble}/sync/ValidationManagerImplTest.java (97%)
 rename briar-tests/src/org/briarproject/{ => bramble}/system/LinuxSeedProviderTest.java (90%)
 rename briar-tests/src/org/briarproject/{ => bramble}/transport/KeyManagerImplTest.java (87%)
 rename briar-tests/src/org/briarproject/{ => bramble}/transport/ReorderingWindowTest.java (95%)
 rename briar-tests/src/org/briarproject/{ => bramble}/transport/StreamReaderImplTest.java (95%)
 rename briar-tests/src/org/briarproject/{ => bramble}/transport/StreamReaderWriterIntegrationTest.java (80%)
 rename briar-tests/src/org/briarproject/{ => bramble}/transport/StreamWriterImplTest.java (96%)
 rename briar-tests/src/org/briarproject/{ => bramble}/transport/TestStreamDecrypter.java (69%)
 rename briar-tests/src/org/briarproject/{ => bramble}/transport/TestStreamEncrypter.java (64%)
 rename briar-tests/src/org/briarproject/{ => bramble}/transport/TransportKeyManagerImplTest.java (95%)
 rename briar-tests/src/org/briarproject/{ => bramble}/util/ByteUtilsTest.java (96%)
 rename briar-tests/src/org/briarproject/{ => bramble}/util/StringUtilsTest.java (99%)
 rename briar-tests/src/org/briarproject/{blogs => briar/blog}/BlogManagerImplTest.java (80%)
 rename briar-tests/src/org/briarproject/{blogs => briar/blog}/BlogPostValidatorTest.java (79%)
 rename briar-tests/src/org/briarproject/{clients => briar/client}/MessageQueueManagerImplTest.java (93%)
 rename briar-tests/src/org/briarproject/{clients/MessageTreeTest.java => briar/client/MessageTreeImplTest.java} (66%)
 rename briar-tests/src/org/briarproject/{ => briar}/forum/ForumManagerImplTest.java (86%)
 rename briar-tests/src/org/briarproject/{ => briar}/forum/ForumPostValidatorTest.java (93%)
 rename briar-tests/src/org/briarproject/{ => briar}/introduction/IntroduceeManagerTest.java (72%)
 rename briar-tests/src/org/briarproject/{ => briar}/introduction/IntroducerManagerTest.java (60%)
 rename briar-tests/src/org/briarproject/{ => briar}/introduction/IntroductionManagerImplTest.java (78%)
 rename briar-tests/src/org/briarproject/{ => briar}/introduction/IntroductionValidatorTest.java (79%)
 rename briar-tests/src/org/briarproject/{ => briar}/introduction/MessageSenderTest.java (59%)
 rename briar-tests/src/org/briarproject/{ => briar}/messaging/MessagingManagerImplTest.java (85%)
 rename briar-tests/src/org/briarproject/{ => briar}/messaging/PrivateMessageValidatorTest.java (86%)
 rename briar-tests/src/org/briarproject/{ => briar}/privategroup/GroupMessageValidatorTest.java (90%)
 rename briar-tests/src/org/briarproject/{ => briar}/privategroup/invitation/GroupInvitationManagerImplTest.java (92%)
 rename briar-tests/src/org/briarproject/{ => briar}/privategroup/invitation/GroupInvitationValidatorTest.java (92%)
 rename briar-tests/src/org/briarproject/{ => briar}/sharing/ForumSharingValidatorTest.java (88%)
 rename briar-tests/src/org/briarproject/{forum => briar/sharing}/SharingManagerImplTest.java (85%)
 rename {briar-core/libs => libs}/gradle-witness.jar (100%)

diff --git a/.gitignore b/.gitignore
index a436295bea..bf85d9ca13 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,5 @@ local.properties
 .gradle
 build/
 *.iml
+.gitignore
+src/test/
diff --git a/bramble-android/build.gradle b/bramble-android/build.gradle
new file mode 100644
index 0000000000..d161cee904
--- /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 0000000000..30918ebc48
--- /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 0000000000..eeb86de52b
--- /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 0000000000..dd5e9c3942
--- /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 7ea06bc2bd..facb76382e 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 4d49a13ac7..1f0055ae71 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 3d964ecbe5..ccd0fdf41f 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 ff166ea4f2..f612ad9e72 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 60520b563c..bebae98ef7 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 b96aefa089..b3daa5f136 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 74f98c17a8..311219a665 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 ae23856472..e6151d5740 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 2a8b58991b..4d9ddbcbcd 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 c85405f676..2f479d4ef8 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 f44669188e..1763784104 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 ba6bee3657..f07b2d721f 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 e5907c9c00..226064d6f2 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 ea40d43fef..52d15db5e3 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 0000000000..e5976ff995
--- /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 0000000000..15edba9c49
--- /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 0000000000..e0b5cd4739
--- /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 0000000000..138b9484c4
--- /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 7fce90ad70..5c9b61f408 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 0000000000..357deaf7d5
--- /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 299f8f3f12..aeb9823a17 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 0000000000..efa69358ff
--- /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 6eceac96d0..4cc02f3a24 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 0000000000..63f3418570
--- /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 32af81f627..74aea4ac4c 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 0000000000..d68f115fdc
--- /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 4de12c21c8..1d921e8017 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 0000000000..66a79c1e25
--- /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 0000000000..3ee8d70af4
--- /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 736597a388..9e11e55578 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 5203da3004..f864fa7f37 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 0000000000..a8c67dd060
--- /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 0000000000..703c87a85c
--- /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 0000000000..99211f6817
--- /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 0000000000..d2db5985ea
--- /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 60a606889a..a1573ec7a9 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 f1002e66b9..96c815ca7c 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 9af5da4cfd..16843b5aed 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 89258be5e7..7f416d31ac 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 0000000000..f55e169d0e
--- /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 93d27a6b32..0fdb4a8ba5 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 0000000000..edf478c40e
--- /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 0000000000..8e61027d6f
--- /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 0000000000..e5cc522ca6
--- /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 9c34e91a05..319f9305b6 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 9f217c1386..131fb74969 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 0d75a94287..b07c3239a1 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 0000000000..7a1e3ed77b
--- /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 6c94ee7f0c..7434013374 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 cae6f728d6..704e1e312e 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 6b3176ee71..d915a85d2f 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 39b7bd89e9..8f1d47e4ec 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 531806beb8..a2a3ec9e9e 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 f8a53c1fbf..7eb1847ba1 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 df0eb676df..8e0e11d73f 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 0000000000..669c5dfa38
--- /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 0000000000..fe9864a7e6
--- /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 0000000000..94428e0e5c
--- /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 0000000000..acbf1434da
--- /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 8e27d9cc8b..6b51ce5b67 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 d2a0b28210..1de66e9342 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 3233f68730..6a8aa19aa6 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 5421f451f8..256be229ad 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 c8fbf68233..218c0a0b1e 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 f111f9517b..a56f03302d 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 b70df227f9..0b70a067f4 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 9c2f5400b9..d24ae11f0c 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 89222f58c7..c40a64f3e6 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 91f4aabe91..3ce99c1db2 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 d7a5909e93..7f8b3ca5b4 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 d68a2cc30b..68ac567ce9 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 9d6d473c9d..e228c84ec4 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 0000000000..b93f209ea0
--- /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 0000000000..af00f8b1ba
--- /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 0000000000..6dd330eada
--- /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 de15869d3e..7e89a7a7bf 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 58fd9c4a84..0699f972dc 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 2c474b7cd7..aaf151dc17 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 00f35db0e9..c035a0ce08 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 0000000000..bb584fec45
--- /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 cdcfdc788a..ae217b19fd 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 0000000000..a12d232f26
--- /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 0000000000..31c93c3005
--- /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 0000000000..f7c6ed3319
--- /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 67af91ae43..acf545f1a7 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 e99ac16d06..456230837c 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 d188de5a59..b09d940f30 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 0000000000..76f94908a3
--- /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 7dfa3bc689..8a381ae09e 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 0000000000..76204bdfbe
--- /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 41b18a7de3..42fda82f9f 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 3f772ca287..9d7ac20c22 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 443ef42bd6..f5d5150c44 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 0000000000..40d875cc9d
--- /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 14cb82421f..c554d24e93 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 0000000000..4744d46400
--- /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 0ada113f36..90403669d4 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 ef1d2ff51f..36f3359f53 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 7b61d74ffd..329bf27ab9 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 0000000000..b0b8bf2c3c
--- /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 0000000000..e8f3dff795
--- /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 0000000000..81950fbcb2
--- /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 0000000000..6d8da3aeff
--- /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 0000000000..289077cb86
--- /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 473c6538ad..d671804d2a 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 1bffc3c3cc..c63e6a8c7f 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 0000000000..2c680b1018
--- /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 5489435a4a..fcdcab9128 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 55a0b939ab..932f0b2255 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 27550c7e8a..78e2ee60b2 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 0000000000..ba0c4d37f0
--- /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 bdfd8f523b..54d04f43fd 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 417e792de0..9fbfe4f0b0 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 29ae96b7cc..23fd38c7e7 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 ac5de25e25..eb183de2eb 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 927e8a737b..0158108d2a 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 4633ba3a5d..0a60b5626b 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 3708df560a..b8660d0f71 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 da7940187a..c29e5721eb 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 6afc50acec..776e050742 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 6ea2ceb514..056d537132 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 e54822ccec..89cd78640a 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 6e3d0e4fa6..954db7b149 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 0000000000..5518b7c6bc
--- /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 3f1fcf31a2..1056a6438c 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 27624c7a8d..28f3e438e3 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 e2b2855dea..941bb59d8a 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 d75522f1bb..a066f6422e 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 b0ad34b094..352e946a0a 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 cf8f649486..abb11b9a6c 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 575e43dc68..cdad526129 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 c45d5bab3b..f2c2027f90 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 eb88626b88..00f1acdc65 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 914402e3ca..9a3aa28b25 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 0000000000..f235e240b2
--- /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 29030edcc4..05c4cbdd71 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 2143eb37a0..ba21c185d8 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 0f0f90bac9..46f6b46bc9 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 2cef4d167b..77b1764840 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 0000000000..1d415ca9fd
--- /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 0000000000..7064c9b9ab
--- /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 cf9f5ebec3..3778918c25 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 0000000000..d36a5d5e88
--- /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 38277550ab..a2c12b5f75 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 512f3917c9..dee9586f4c 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 0000000000..9a46624e54
--- /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 b7da722fdb..98e889a128 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 0000000000..6a8176516c
--- /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 13d41f646d..bdf066bee4 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 0000000000..89a06a07ff
--- /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 0000000000..395e208a77
--- /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 0000000000..3418299af1
--- /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 0000000000..1d671525ff
--- /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 28dca8bca4..e5f28b6ba9 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 0000000000..9c9806ea7b
--- /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 0000000000..c8283640b5
--- /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 0000000000..8886574bb2
--- /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 21486a4ae2..8c56067d80 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 0000000000..956d876a34
--- /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 7101b31069..ee2b3b0ad9 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 9ffd3b9cac..009ef7dbd2 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 0000000000..999e1f9366
--- /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 8a5ed3fe71..bea1186f13 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 fa8b669ca7..577d4916e0 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 049807ac4b..3d4216270f 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 ce78942213..c11f630e4b 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 191770e2c2..e85b15d7df 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 3543460f64..3a1075dd9c 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 ec1df8cc48..86b9065aee 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 dc107ed4ab..b70df3dbae 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 e8893fbf9d..65708e0a0c 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 0000000000..9eb84fa549
--- /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 214af877a3..537cb7e594 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 a7e89bb64a..8741c55539 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 0000000000..9afab7d5ca
--- /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 0000000000..0f03fed252
--- /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 0000000000..23f22beb1e
--- /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 2937881417..9a860d13fe 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 db5954ffed..19b38cb8a3 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 b35a0bd8fd..d80042b415 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 0000000000..3ff5b795c6
--- /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 0000000000..9804547169
--- /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 0000000000..1bcca2c66f
--- /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 0000000000..960dddc661
--- /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 0000000000..eab1405425
--- /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 0000000000..e3745fd90e
--- /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 4ad29e0102..450512e53b 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 0000000000..cc35d59a95
--- /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 812fb0ad37..e1a7fb969f 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 0000000000..fb1b1dd21d
--- /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 8066c196f6..1f392417db 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 1fcb250d6b..a2ee764452 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 33057e839b..61a83d95c0 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 0b1e225da2..67466cdb03 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 886fa2df3c..2d5c147f16 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 6ee30759e5..ef444561f6 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 8ee0578a86..97afdc133e 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 08a06d2d9c..202c46e6a0 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 d9dbe9cd15..b5205999be 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 0000000000..44e31a671b
--- /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 0000000000..134bde50e7
--- /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 9166bcf0ca..5bd47f0a0a 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 ec550b52a6..40aeed9a3b 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 e3608950fc..c5ad6d1fc2 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 061a4780db..61b2378292 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 cb76c9d5fe..eb682e1679 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 547db92e1a..66ee8f256c 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 c2bf426287..50c4e792a2 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 af622cc270..4cfe34ee98 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 0000000000..fffacae0c3
--- /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/build.gradle b/bramble-core/build.gradle
new file mode 100644
index 0000000000..a281b0bd10
--- /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 0000000000..e7a211e294
--- /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 0000000000..250b8be2aa
--- /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 bca3812f35..55847365f4 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 0000000000..c5ec20f835
--- /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 f5cbaf8e9d..0690553479 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 ec825052cc..e33b1deb0c 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 c0d13a44f8..c4c3152b7a 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 800b8e57f9..2cb610972c 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 5e00461d47..2bf79875ef 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 fe4f8bee00..b70358e5da 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 33f3545d59..a8e132a9b1 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 9e8631fd3b..82c9d50d60 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 b18cea9f82..879ee25954 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 aa97444837..accfaf5279 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 01b7272f72..077a4012ad 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 1d1fdd99d1..3740472043 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 76be537299..e4b4b04e88 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 688a03dee4..2c4ef3ef68 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 ce3aeeaf86..62e609c96b 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 68219c7a66..b56119b24e 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 c8a8d974f7..82f3948b65 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 ca55efa07d..ad1a0148d8 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 2786b2994f..fb02df0471 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 a3bc7c71ee..edc36c6641 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 ff38772074..89e297c433 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 f85a34b8d7..a7fd114e81 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 926bcbc69b..f87d727009 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 0000000000..f5684a7dd7
--- /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 e7c7c6394a..2a4f870477 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 c134872b33..49fd6ba2ec 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 bfd961c92b..22c522d3d5 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 af5606d440..4feff3ece8 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 955bfc7d38..cb708eb4cf 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 8143b696ad..7bac148f2d 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 0000000000..959c5582d9
--- /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 d1fe25794f..96f7adea7e 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 0000000000..252ed843c0
--- /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 2b497dd02f..e9979e9ffc 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 b83293104f..7ddf2be0fa 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 d6cc64b145..7605b1da74 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 f387b2d0c5..6dd44196c1 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 6cc701d28f..e897cc6c36 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 0d2327200d..93e7bf8c68 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 e09ed8f2c4..8d9be17094 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 68e3ca1ef3..080a8ce8e2 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 d0a3bae872..7865faf364 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 39b1e49dbe..a6f3a11748 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 0000000000..83ed9a93ff
--- /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 bbb5bc112c..0e2f89bcfa 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 27099f15ba..32596eede3 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 4131ec9f4e..54238266b2 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 ca007e10ad..f2b3468475 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 e7f92f0379..3cd8bcdefb 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 b745f5e003..5d4dc0de67 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 0000000000..fbef759389
--- /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 e01e13c4d2..11e8220c9c 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 3caa856fcc..3fe6b9ab26 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 73e49a132e..871db9b4ce 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 80cca62503..d87a9334a0 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 6afcedf067..0fb91aa8a4 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 a88163f52b..103dd03c63 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 0000000000..0c6dbcfac5
--- /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 5c18deddc0..19bd8c6b9d 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 0000000000..5cae0d7466
--- /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 ee5c0e10dd..ad3015bb4d 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 9f6a529028..9875387db9 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 f67a85ecd6..1c56c2d149 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 aafde49b3b..4d9dc00cf6 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 e502676987..af180b89e2 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 25a18962ba..2044f2b65d 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 ac1a647d13..b6c3481eed 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 c0ee0064fe..5b4df07c48 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 fa66b14fde..da3536bebd 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 67c94c1a84..2db4307235 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 3779db2583..1b5e4ad6aa 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 0000000000..7640a95715
--- /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 175c0d35ff..a4522cbb4c 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 c85c5f016d..3714e420ff 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 7b687f9355..5c4b5d4221 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 010e75da58..45eeb2d44c 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 d7e6925e55..43ed215557 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 a904bbfe6d..f315bda9e8 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 108db3c7b2..17b61358d2 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 ed6219797c..df5d5b9086 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 94e83fe5b8..2752f7c8be 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 f60a0a743c..36c06d4853 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 2818666b0b..a15277c223 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 3e86a9668a..aa9c271f55 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 0000000000..3d12a84b81
--- /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 5e135419bf..2156bd10d1 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 76da5bf7dd..1708e918fe 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 7d8d33a9ae..97afa37434 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 f51767af60..fe30457285 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 f1fd78bcf5..42deaaffc4 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 cea2c7504e..0078beba5b 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 62b4be0c03..1fe72cdfc1 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 0000000000..f0431254b9
--- /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 1f5352c629..737e32fd53 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 1b456fb777..b4cf7bc25d 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 09edb4e619..ab33b67cd4 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 65d9a4c81a..6e5d1969c5 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 b45dcfafe7..c5c5de2e28 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 ac520f1912..6c0b838b97 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 0000000000..fbe4b18233
--- /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 5058984731..b6b60ef9d6 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 092f218b34..a4431a4225 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 06d5e3efc8..3062780994 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 715fadaff2..b90494b529 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 3ad966a79b..b4ca04c94d 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 2051f63049..1d77108453 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 e8e0ffa97f..5490c7ee09 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 e9df705828..919b6f240c 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 0000000000..1996ea86b7
--- /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 cfd20daf23..5663f8e8b1 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 b9edc99515..3c0900d73e 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 eaaa3c4d62..1fe9f31c6f 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 7c627daef9..2265966265 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 dfcd973597..adc5265fb9 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 a4c8f499f2..c8b306fdaa 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 0000000000..18065fc104
--- /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 b434bb6430..4c64a17f50 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 c245ea53b8..d94eb7c4be 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 0000000000..914bbf1f51
--- /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 abe24fa6b4..414f7e8120 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 0000000000..343819390f
--- /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 9bcbe570f3..62e702e415 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 a2caf77c5e..c2a1bc64e4 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 2cbbac5d79..44703c8b39 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 6fac0012f6..c337bf94ac 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 5532a8fc0f..55d966d31c 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 c4be29aa40..7e7aa865fb 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 6481b4a5f2..e4141a4179 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 3117b0a503..b1737ad805 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 40ca8037c9..a052b4d54c 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 a6c8f1be12..11e459eaf9 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 6be3d1823d..3f2f94a5ca 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 d8163e4f2b..aaafec13bd 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 65861974e7..ebaef9973a 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 c1baca01b7..f81d57fa6d 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 48179153f5..0d2e9cfb73 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 87a90eb796..770592c739 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 4335273db3..77dc7657d7 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 2fad041439..142ca19ff7 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 0000000000..6aa6d360fe
--- /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 0000000000..64907dc412
--- /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 55818bfdcc..d212a027b9 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 72d0e444db..9c1582425c 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 461e1d8dcb..5b33073147 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/build.gradle b/bramble-j2se/build.gradle
new file mode 100644
index 0000000000..d61f5dcdcd
--- /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 79525935a0..de9ca4bdb6 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 764f25f600..aac6a02199 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 912a0a7d7a..616f966110 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 81d5588abe..091aa9425b 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 fbe51e342f..e8dc0a754a 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 a68dd001f2..4a8849c7b0 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 38d9ce3c61..0a389134b3 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 124e0819fa..df922489ff 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 0000000000..6807f606f6
--- /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 a35c7af9a2..8bd9b92d16 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 0000000000..fb3b1acd49
--- /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 a09508582f..335051a821 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 efac800070..bae6193569 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 169dbc1408..1145c5687f 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 a5dba602e0..5a5e99a2bf 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 e2db0717d7..1b53e250e5 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 0931f6f443..c5626fdb94 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 bfe731d87c..8fcc0a539a 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 c67783ca8d..abdbbf0bf9 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 0ffb166c83..674d9f6b23 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 72c3a85d64..a25acbad5f 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 0000000000..81866a9ac8
--- /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 ee2aef1e09..78b8eff8b4 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 59fc18930b..4aff1d94c1 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 ae08ea3973..5169e5d5dc 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 690b3c7d78..1a3a1f24af 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 6d9f602313..b21100c7d7 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 3722e23182..f3e1aff06e 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 0000000000..918bcd6f3b
--- /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 0000000000..b2375d0d4d
--- /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 8ed175a8b2..d603f7a134 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 914bb06ff9..82a778db64 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 85803e837e..8226a135b1 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 2ceea6e9f2..538cf3ccf9 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 fcd3205e73..73efbf9ba1 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 7d4cdf2a8a..ddca97605e 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 3d5c827d0f..72c8fc0e43 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 249354bd21..40e3f0103f 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 198a3039d6..7c350c6301 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 b63c070dc8..78a57af54c 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 fe53046406..5921a61410 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 f1b96df29f..7e435710e6 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 4e1dbc0cd2..8b00a35f52 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 cc98b42c03..68515bd0fd 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 9de8e9c5ea..91536eccad 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 07a671747d..ef6ed72abb 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 69710bd5a6..f20e66c8ee 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 be401e4e28..b978c8deae 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 b97bb8251d..16407ea418 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 b7cf4209ee..416d5f1085 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 a239ba7d8d..1d449284fa 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 1fb7ef6738..099a510418 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 0000000000..1f6dcb7fd8
--- /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 f30761ae88..2efc20c365 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/build.gradle b/briar-android/build.gradle
index 113bb63dfb..48ee85bf19 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 feac1c8ba7..88fb5b29b5 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 16189e3751..dec1fbc3a8 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 0000000000..e038fb7fd9
--- /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 0000000000..00a2c70776
--- /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 2e01bdcab0..3f1dc6d096 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 f0f1954e42..667b4ee291 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 cd28990adc..bf78cecfa1 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 c78ff2dfcc..07f3f6c4b1 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 4707a41a14..f7eabd5086 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 75faa0d104..26d9281435 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 d5959a622e..99fa824980 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 b258369391..51ee125d53 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 26ae948520..5739b5e76c 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 0000000000..432cd87947
--- /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 0402ef56fc..2a00be5ccf 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 a6ceb30ab7..c3ea7520ae 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 02395fbf10..699985ee6d 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 9d162b62d6..c590eaddb4 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 7044355301..5b18421dfd 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 6b81243ec6..3d43ffce97 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 04d9e2d164..41dbf65569 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 8717acac1f..a6be4cd3fd 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 a52d443766..700ecf40ae 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 b463e31302..2ef640d37b 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 ba02cacd1c..c58e41e74e 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 abc5108e94..43877cc3df 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 a7273fd61f..10dd6d7201 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 691f9cb754..f0ea9b48dc 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 f4392e90a4..01e80dcb64 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 ae67d9cfce..febca0327d 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 2a0ecf1929..8c9f4ae21c 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 debcfd5446..d8561ad4d0 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 784e60b7f3..5187537d9e 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 76ab1baa23..4c28281ca3 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 1c5cee0ca2..1d02c8fdc1 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 e829c08962..0eee3cd8bc 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 73ec81a3ea..799c170a9e 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 8f04dc1db2..94194d682d 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 1c9655336a..d9093a79da 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 aa92468158..3052e3694f 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 2150b31bad..7e20858182 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 ecffd0cd20..5229018572 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 6dccc16856..1217d94b71 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 22e8391485..fb89f85d1b 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 eaa7f66c57..720a9d6df3 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 46a81762b6..3791c6c343 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 707ceeacdd..5eb17f7439 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 a14bbc0d57..af242e9454 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 18e4946c16..d6e839afa6 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 acbd27d82d..649e3782f9 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 b9bf00e24d..8dce03cbc4 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 02779ce442..7d832eff82 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 d280bdaee7..b8f1bb78a7 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 1a2c118e24..faf43cf5e3 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 58a42951b9..e58ed523c9 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 23d8571366..4022f2f68c 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 ee2d1a11b9..082071c23b 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 83d58dcee4..6c119a6c57 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 0e70e66312..efbc6e4f7e 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 7e5a60824d..db6bbd89b3 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 78cddf3a76..637c928b93 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 c0bdf7fcf7..504137ada8 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 469f4b0f44..e2aff0e342 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 4c10ba4024..8e5bf264da 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 f0a1cb08b4..3dd8dd721b 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 4aa5fc3cba..663e0394d2 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 c9e287b867..f6252717e0 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 fc1f400f29..1c9294fe29 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 d0b57f1328..e0fe9a688e 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 d61545f96e..2eaaecbafe 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 1b681679d1..39144d3d68 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 0000000000..778a038533
--- /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 aa198e35fe..3cd744d154 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 0e24b157d0..07908ac8b8 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 b844c35f64..ec9cb0040d 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 0ab5ecc4d6..b4435d6cf0 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 b11da75a10..d2a53a2a42 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 96d0cf4f02..edcb7456be 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 cbb61cde1e..38c1ca93b8 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 f49d6485f7..3d15ff7a2f 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 7ce5233033..d6bc554f6e 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 33ca325326..0af60bb981 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 0000000000..8f9fc3be1f
--- /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 c13576819e..eaeb7a06ec 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 6d8719a648..d283a39f65 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 b8346a565f..a3cd15adf7 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 601ff294d5..5d11a6a919 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 90db65fcd3..98ea082ee3 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 8fd4ab4fc9..d3ee2d7c83 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 6516ff7151..89bd919d4d 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 4c90245999..86822c7a2a 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 0fe164367f..ad961043d4 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 0000000000..8b99ab1741
--- /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 7cc859614d..3b9f91f617 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 0000000000..51070e9068
--- /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 040b81662b..46d8007fbe 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 9fb886f435..5b40f28dc7 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 281eb64b41..5341d3f1f8 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 9b665673be..06ebbd1f9f 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 cf78840532..6e8d1ddd46 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 594cd841fc..8a5923119a 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 20fbd08714..79f78b7cb9 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 8e9d5c389e..2b66f8e2ec 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 f5c9c32a63..c50db5a157 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 543b2c988d..b3e42e085f 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 6a6b300be3..3ca73869a2 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 8527a67a70..3e6819da3d 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 bfb2cc338c..2bd953a9b6 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 fa0f8fc33e..ab01e333c7 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 60c221798e..bfc7272a66 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 962b846674..89bb71a94a 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 6ce313f372..db37ed9330 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 8a075f151d..7d786bf2ca 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 fbe2b67269..9e5d7a5e92 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 0e9530c087..e69dc2da71 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 57a092eeb2..43286f6fd5 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 073a97132f..f20bb4d78c 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 4c93924ea8..6b6c717feb 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 751b6adcdb..3606f077f1 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 0000000000..209b5ac4a7
--- /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 9ea926474c..ac01eba475 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 0dcce3d72a..be3627dc8f 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 0000000000..5e72acb931
--- /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 356137008c..f413ca7361 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 83fb20b8f1..b740c14319 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 b84afd8b96..e2edf7c98d 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 0000000000..424fdb1add
--- /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 fb75cfce2a..26d945baae 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 0000000000..592263b6c8
--- /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 363270f26f..bd027c39c0 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 7fbd2ff97a..9c19c78b10 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 f62dc03852..9251b85b30 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 ba8583fcac..f79030e7fa 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 678fde3256..6c9de8c760 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 438c061120..e0502432ff 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 0000000000..c3e03c1031
--- /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 7cea3d521f..431c66a59b 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 8595b461c3..6fa1023756 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 4c94438e07..dbf8c7b96f 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 47104e8828..79ca011d28 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 c48f781a08..dfdd920223 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 bf8b229841..5fe8cf3996 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 2f7125331b..d115020db9 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 461989c81c..df6c245395 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 0000000000..37f7b92a84
--- /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 051f5a20f9..2a694c55a2 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 7f21508e38..d0adfef241 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 3347be1586..7485acfe8c 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 a261ce0167..b4c3fc6707 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 a553cb0ed4..fc51ac8e91 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 71ce496677..794a12069f 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 6e8eab6092..44e03ab61f 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 658a611d4d..a6dd2dd4ea 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 9c818b6807..540b15df56 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 0000000000..0cb87e9873
--- /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 68a8690791..b3b3f4c590 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 b6998cd195..9f3278da45 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 0000000000..a270de3690
--- /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 ded8051817..03a9d40b07 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 b5588e3440..a42bf3a78a 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 433c415ecd..e61e3c835c 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 f756f6ffcb..4c0febda6c 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 6627514bee..2c7e29b5a3 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 2bf5c56543..fcf9c09d17 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 7f3031aec9..af676fc019 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 a3523f8559..182a336d00 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 0000000000..b2d20c35e5
--- /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 8a91bee96e..4acd6b458e 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 e92d2e9478..97758b5793 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 be28f8e8bc..5eddb41e3a 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 0000000000..b055075364
--- /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 2bf488a412..5b82c5e8b0 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 dad020c3f6..b2f23bf208 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 3a7bd88ee8..029d770a5a 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 0000000000..52c38546b5
--- /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 985708f2ed..279b80710a 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 df34de80ff..f2648ed12d 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 c84303e788..1ac55740e4 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 0000000000..48ae57ecd0
--- /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 3fa6a3484c..585e2f622b 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 355690a3de..5e046e0155 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 9594cf5842..69654f983e 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 6c413781fe..c474f4a894 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 0d142757e1..82c21c0891 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 bb783a0651..022963eea3 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 60fab261fa..a9b9f6690b 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 631c4ff866..67532a44a0 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 54ffa984dd..e49b632780 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 0000000000..c56f96a238
--- /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 8b1a318484..66adb424c4 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 fed2c2a5af..ab60768c67 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 37dccd4426..59fb3683b7 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 0000000000..650cf1939e
--- /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 38274956ac..14e669f424 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 be51ab2cf4..fc59fd9cfd 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 b398fbd824..1f755fe366 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 5afd24c07c..1b3a4fecc6 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 0000000000..f4e3949c04
--- /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 b1b52aca58..0c0a9f426d 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 2c8337c13c..80adcfce29 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 8924d5300a..6db3a0694d 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 4303f3415f..f395eda7be 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 0000000000..55ed2b46c4
--- /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 33e21f3d15..401b88ecb0 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 f055b4fb63..ab0d97e1c0 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 ccee4d8fec..a963664fa0 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 51689bc2f3..f32a49cc8b 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 0000000000..eedf45dfc0
--- /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 73eba81b67..93a16307b2 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 9ed8c9e58c..c7bdd59fda 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 a3faeb630d..8a30df49ea 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 2964c9b930..58732021af 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 b10672468f..28c03f473e 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 de632f6b13..50bcceb2ba 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 4e62598ae5..543aaf6cd8 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 539d9f81f2..b751b9b2f8 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 65e4c60769..3569cc70b8 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 12d29096b8..6b40803d0c 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 af8e800b33..6bdbb9c773 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 aec3c58beb..d4fd06b7c3 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 e4c055e2b3..39d00f98f2 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 76b062508a..a22316a353 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 615a3bf9d8..2c2d20793f 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 19e339ea4f..942a61d680 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 f0c286aedd..a2db5242d9 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 bffd1d6eae..87152b0d7c 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 091dcc8a1b..889fd57f5c 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 6a0e6b9da3..3e65fc6421 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 3c259458e5..c02134a758 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 26df190cd2..de900512bc 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 d02ca1081e..3eebcb05ea 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 748d485165..4c3ee59442 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 40f455404d..1f32f5a75f 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 cfaa352cd4..c2226ec516 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 124361158b..6b03684493 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 2f5a2cfb2c..36ee3b4133 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 5eda031674..033747179f 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 5a88acdf68..918755eb6c 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 ffee887f63..1370574f37 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 a848d3b1c2..50835db2dd 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 6a199a0feb..5161fe860d 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 8f1cd93b01..e29b1d9551 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 096dd0c691..c3e6050c59 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 69234600f6..44c959184d 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 a8a25671ed..980e29cda6 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 603544869f..3afc44c2fe 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 2e0b899d54..eeaf124094 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 fa5e97c8ee..9344319cd2 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 0544de13af..1427b5df98 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 2ea99864e9..09778df1fa 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 6168ee2733..7cab093d85 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 8cb9ecc09c..024f318c05 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 d1f4722432..75e79bb271 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 c4f064d2ad..50217e3b77 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 1c16d9c877..89d086ef79 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 688ee3ae7a..4f9c9b94c6 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 1283148846..d9651770df 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 6e5887f2bf..e2c54958e8 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 cc05097fde..1e624c91d6 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 6670afeffa..90f52efcf2 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 81c7e4a2bb..3f26d7a010 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 78aaeb88da..233f8b1a29 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 8c9a0c4681..76c14b4aa7 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 4e629ca51b..4ef0a41576 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 fe77e491df..b1120debd9 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 48d2b7263a..ee9153f477 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 b8e5fe6406..a70a8c31e9 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 6f389e1de2..ad614ab534 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 bfc1c777a2..df5e36a9e7 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 ca4fb45205..6b09a7ff6c 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 c83c2f3b5f..1aaf28183f 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 168ff34a45..7f74c6577e 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 e6f8237cf6..c0305e2503 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 3240557289..61531fd227 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 0fbe7cede5..8f7a01284e 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 a04a430373..214056cf4d 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 4c521522a7..3cab8e948b 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 96c2033a3f..a0fef3ea7b 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 5c4df7bd17..50bd1a18af 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 20ed6fc9f6..d0b1122648 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 71d6ceec17..23b7fd283c 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 14640f3387..f02ed68c7d 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 6419c14b35..ce7afa1477 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 3757cc7e7c..dbc3cb060a 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-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/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 0fd1c3aff1..d8327da7da 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 3251942580..5c865755d7 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 01f39081f5..0000000000
--- 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 0a8feb9111..0000000000
--- 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 4a6cc4046d..0000000000
--- 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 e0d9cac7ab..0000000000
--- 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 f0c186bf34..0000000000
--- 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 869ec8bc09..0000000000
--- 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 64e4d4df00..0000000000
--- 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 947d6991ab..0000000000
--- 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 3bb1c0a883..0000000000
--- 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 9b1fba5641..0000000000
--- 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 9c64f4ebf3..0000000000
--- 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 523abc1b9b..0000000000
--- 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 2434ccd7d2..0000000000
--- 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 54318f31b2..0000000000
--- 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 25aef8ce8d..0000000000
--- 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 0f657d2d9c..0000000000
--- 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 42b001db73..0000000000
--- 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 dcc67f6aab..0000000000
--- 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 493fbda2e5..0000000000
--- 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 ebd447369e..0000000000
--- 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 74ee19ee27..0000000000
--- 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 a79d0347ad..0000000000
--- 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 7e51d99fed..0000000000
--- 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 1ad94416a3..0000000000
--- 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 99ca8fb7ab..0000000000
--- 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 f2cf7a3463..e83fb8177a 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 05a57f9ee1..d6c445eb85 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 6250040a19..bc6016caaa 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 bb4598752b..d9c78c8004 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 cedacc77d0..6b4d135b4b 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 7d4ff2f7d2..faa4faa10d 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 54ea446e82..d163c8c509 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 21d57e4fb3..3298c0e9be 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 18e5784e8a..f3f2257c0d 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 3de97f5ea8..b7e1d240fe 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 0000000000..70fded2813
--- /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 19adcefbdd..28df61f745 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 0000000000..4b0a89cf37
--- /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 0000000000..505a5a064b
--- /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 0000000000..664126aba9
--- /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 0000000000..8b596d6b65
--- /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 0000000000..53037b732c
--- /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 0000000000..4a64c27323
--- /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 0000000000..cf01dfc571
--- /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 0000000000..87f669bef0
--- /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 f97799ac53..811bf32e85 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 9be155679c..e717886b76 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 0000000000..957daaf7de
--- /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 0000000000..0b9ae90051
--- /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 c00e4efbff..77d9892cb8 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 f4f7636e14..d26b8190f4 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 b77ac908d4..4707ba8caa 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 0766e5e4be..75418bf7c2 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 6351491c74..44c26fef4d 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 14481f2a56..cca70884e3 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 176a50858d..2bd0a06680 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 7ffed63645..1935e27f64 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 1958deaf0d..281d9af86f 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 f7b072abfc..a879e912d8 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 0979c3d194..c41b6da2b6 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 0000000000..ac458a8a89
--- /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 0000000000..d569bdfec8
--- /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 34cd35a2bf..37b0dc86f2 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 502923c4b0..b36a8a70b1 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 bc98ad7eea..8be05d5681 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 0000000000..5d31b448a0
--- /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 f73cd049af..98cabde3e1 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 048f6c3c71..cca6c913e1 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 0000000000..1b14a06bef
--- /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 0000000000..25a544510d
--- /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 0000000000..4d65cf1c4e
--- /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 75c9b9eafc..f00a926af4 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 0000000000..fe35ca6ddc
--- /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 0000000000..a6ff14554e
--- /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 0000000000..01c76a5e77
--- /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 b2f99acf61..85bdf53da8 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 e93a39c6b8..c8a08752e5 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 0000000000..a737e1a443
--- /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 0000000000..60567907a1
--- /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 b300f9ee27..0aef3a23f5 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 324ba5bb61..68881b9dc0 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 8b46a0c1f6..e696181a01 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 d20433876a..7123c7eb26 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 61bcf38327..b3d89864e4 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 4e0e058283..a0ee65e00b 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 0000000000..2b707d9f18
--- /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 0000000000..680a955ff1
--- /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 0000000000..428528260c
--- /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 0000000000..22df6eba89
--- /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 b5d821655a..5855275918 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 58473e08c8..9fe4871e22 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 2938c40db6..2cd3d1c29d 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 0000000000..88998789c2
--- /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 0000000000..8e8ddac0dd
--- /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 0000000000..f515e60e6a
--- /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 0000000000..c2b80fc462
--- /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 90c14e54ad..2fe86deab9 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 0000000000..95db155f10
--- /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 0000000000..bc0003177f
--- /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 e1ddbfd194..d82bff8f6c 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 2638dfe706..fca0a05814 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 0000000000..7f57e1c124
--- /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 0000000000..0de8ada873
--- /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 9789a59e0a..f75183010f 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 ae83be9327..74619a80c1 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 8b5cf7d578..9927ae4f2d 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 6bb6fdbe9e..37303c868e 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 def6c3f69b..c9496a1b3f 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 e4a13eeb78..8413f0d1f9 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 b5665dc23f..aa4b7d4582 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 4ff09c3ed4..c8c97c1bad 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 2fd1203158..08fd42b3d8 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 0000000000..030bd266fa
--- /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 0000000000..6ce0ff1acc
--- /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 0000000000..705c93074d
--- /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 d0c05c105a..91d363779b 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 fdde77abe3..f539a04124 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 7fb91d6acd..215e3b756d 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 21a25e5933..6fc4c57e44 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 d98bcad2e1..bf8110c6b3 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 ba41a8b25e..3a72271560 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 0000000000..eab12f7414
--- /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 c81a4730d8..34735e7940 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 0000000000..495e9d489c
--- /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 0000000000..9d961f9058
--- /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 0000000000..ce94524c56
--- /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 0000000000..409e4ba218
--- /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 de49d674a9..53f4557e45 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 04b69f49e9..e04a38cf25 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 783e3ba3eb..e4cff4876e 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 3078d86b4e..23340ac1c0 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 f9bcfe1a5c..1491240136 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 63f41be02d..ac9ebce868 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 0cbbb8535d..0000000000
--- 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 72c78d1032..0000000000
--- 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 a5d2e4e9df..0000000000
--- 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 f730f43674..0000000000
--- 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 3fc41b9ddc..0000000000
--- 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 3798ea75e2..0000000000
--- 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 6b0f28ec16..0000000000
--- 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 73c787b29d..0000000000
--- 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 4f8292720a..0000000000
--- 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 dc191078df..0000000000
--- 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 10ee0ff842..0000000000
--- 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 28954c238a..0000000000
--- 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 705934de6d..0000000000
--- 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 cea02f230f..0000000000
--- 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 c9730730bf..0000000000
--- 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 50bf543c71..0000000000
--- 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 0d85850f6f..0000000000
--- 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 342733c2d8..0000000000
--- 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 0fd491e1e6..0000000000
--- 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 1edaa2b258..0000000000
--- 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 f192be90f4..0000000000
--- 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 a332743bb1..0000000000
--- 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 f7ede18908..0000000000
--- 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 4b2e3ab8e4..0000000000
--- 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 798ad5df9c..0000000000
--- 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 81f02902c1..0000000000
--- 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 2089e6c5d0..0000000000
--- 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 6043885ada..0000000000
--- 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 0b2e5017cc..0000000000
--- 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 f76c9a7eca..0000000000
--- 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 ddbdbd5db0..0000000000
--- 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 2507dee4ef..0000000000
--- 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 9a7a8b6484..0000000000
--- 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 0b49d81e6d..0000000000
--- 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 89598d79e1..0000000000
--- 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 416979d2e4..0000000000
--- 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 f4669f9462..0000000000
--- 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 d900388bc4..0000000000
--- 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 5b8a3224d3..0000000000
--- 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 1fc2599c22..0000000000
--- 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 a72fd313af..0000000000
--- 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 25838e6101..0000000000
--- 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 368865217c..0000000000
--- 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 dfbf3a3193..0000000000
--- 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 5e217f7f4d..0000000000
--- 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 97313a276b..0000000000
--- 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 f2afe349eb..0000000000
--- 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 df3b2cbac5..0000000000
--- 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 a12a9c459a..0000000000
--- 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 5f0aeb3cd4..0000000000
--- 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 5e69ccf7a2..0000000000
--- 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 dca0212fdc..0000000000
--- 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 f2dd84be0b..0000000000
--- 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 840c7cc42d..0000000000
--- 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 8afaed4e74..0000000000
--- 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 fc6a7fca30..0000000000
--- 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 ef25719aaa..0000000000
--- 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 b4d65fbb69..0000000000
--- 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 1efb575fdf..0000000000
--- 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 7a72d83587..0000000000
--- 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 a643cc429b..0000000000
--- 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 ee3b716cc9..0000000000
--- 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 5d4c8d5542..0000000000
--- 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 54969d97cb..0000000000
--- 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 205b4c6ecd..0000000000
--- 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 d5b8d9b356..0000000000
--- 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 b98d23448c..0000000000
--- 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 9a27c3e38b..0000000000
--- 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 a7e7e3db73..0000000000
--- 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 e2d968bfa1..0000000000
--- 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 4a2910dc23..0000000000
--- 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 bcb2ce3349..0000000000
--- 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 fda0ab037a..0000000000
--- 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 feea2d8126..0000000000
--- 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 9961a2b994..0000000000
--- 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 f823fcacdb..0000000000
--- 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 434f9cb71a..0000000000
--- 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 31876c1027..0000000000
--- 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 c0795ccdeb..0000000000
--- 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 69ecc3016a..0000000000
--- 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 98750b5518..0000000000
--- 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 78c7c4a759..0000000000
--- 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 0191ce61a6..0000000000
--- 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 706e453732..0000000000
--- 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 7fda14476e..0000000000
--- 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 8440fe4add..0000000000
--- 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 51f15da58b..0000000000
--- 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 513f80c7be..0000000000
--- 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 220e958fc0..0000000000
--- 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 fd0171094b..0000000000
--- 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 44b7b3344c..0000000000
--- 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 f98e87f13a..0000000000
--- 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 22bdbe0d99..0000000000
--- 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 b6f4ccbf89..0000000000
--- 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 dfcbb9c1a9..0000000000
--- 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 43fe1e5666..0000000000
--- 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 05166529b7..0000000000
--- 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 1f8548d384..0000000000
--- 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 4e6e4858f0..0000000000
--- 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 23ed952b96..0000000000
--- 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 0e2d24ee65..0000000000
--- 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 144b06dde1..0000000000
--- 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 02187cb8f5..0000000000
--- 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 5e48269d2f..0000000000
--- 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 51befe31fe..0000000000
--- 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 af6d2321f8..0000000000
--- 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 78229ef202..0000000000
--- 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 8e8544b525..0000000000
--- 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 7a23fa6e9a..0000000000
--- 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 9ffd0987f5..f4b3040f17 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 0000000000..b8980daa2d
--- /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 0000000000..a9a7bfc506
--- /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 aed543f533..26c1eb108c 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 ecc5991fa3..deab371d79 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 0ba7eaa0d5..4a6fde0806 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 52cbc72a76..b8fd8b7e32 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 4b7dd148e3..33fb0bddf7 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 41c4021334..19d8142c1a 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 0000000000..48fd665a10
--- /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 0000000000..52ecdb50aa
--- /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 0000000000..9e47fa3a3f
--- /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 d666598509..5e68e713c2 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 6f81491854..ca689fc1ca 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 0d5328eee6..bd230dca8e 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 0ef7c230ab..982bcd2e76 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 d64cbb5713..9b207cbaa3 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 55a413cde3..1cbc8e677f 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 2845370a4b..d47a088b88 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 f258222341..5570d52542 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 b4d7d84cba..348fe52100 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 0cc501d0af..8e742a7550 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 0000000000..2c26fa3667
--- /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 b7d2f70660..527960530a 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 4115fe0c09..e7c213d999 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 e0227b6bc4..588f539653 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 0f180a622f..ea08aebd77 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 a7ecd00cbe..07e031c632 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 0000000000..8aadc03d72
--- /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 8bdae86880..6b3884138f 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 0000000000..a4c3b8e293
--- /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 0000000000..3b71d42d58
--- /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 0000000000..7848aaf3dc
--- /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 2a480850a6..6d310756ca 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 90fbe5c79f..28a4726b06 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 243042dbc4..87aed0765b 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 0000000000..d3b73f8b5b
--- /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 0000000000..a93218210d
--- /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 b1e203aa7a..684ecb401e 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 71d6ebbeef..5c2b9fc8de 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 76f5b6b374..94089cdb5e 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 183bcbd7b7..4a19e68ebb 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 94febea167..91d66bd5a5 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 0ec50e101c..883664e036 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 7dd247ee1c..23d69d0746 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 6eb230247f..36c00ffb10 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 d31e88aa28..ef5f7e85f5 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 62b6a05f73..f152158248 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 a759ee7f34..4afe89c4d8 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 7cfe17f2dd..c55bc19f4f 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 502d4f0761..d527674737 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 6873a910db..4c57e9aff3 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 9ab719cb04..9344d52135 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 5e2733806d..1c2ecc00ef 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 175a593c49..125588cabc 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 b286e8c09c..b1847aafa1 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 231af01351..d1bf5bd608 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 12730ccbdc..cade5865cb 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 3299d747ea..7fa69e6af9 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 7b9c7df179..77d6e3eef3 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 86abb687e4..cf323fe810 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 3d2532ab18..dbd13810ff 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 7ced5fbaa1..4312e519d5 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 18180fe81a..17e0843d71 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 503a5e79db..92c62748df 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 c2e39d4606..9e6a7ad9db 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 13837cb36c..b31ff7d317 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 a8f04a2874..090d2e193c 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 7eaebba496..c1908735fd 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 2a6517dde4..e0e1b56c07 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 eda52e5de7..94f9d19afe 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 1908548f54..b0833260d2 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 95e5882de7..00ddc95b7f 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 ed48f12241..af3bbe8167 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 2e84f63b57..b79794276c 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 1cd5c76889..040ab401a8 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 0000000000..876a53feae
--- /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 0000000000..78e36bf3a5
--- /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 8f488298b0..baf0de80e2 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 c8e468db39..e8813b6dcd 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 0000000000..46df85efdc
--- /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 0000000000..564eec6cc7
--- /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 0000000000..bc4b34b5e5
--- /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 c28ad5792d..b68187b078 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 0000000000..9dbcecd082
--- /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 0000000000..d6a462982f
--- /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 1403b75a67..12280066eb 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 2946230747..e564f7bcc6 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 0000000000..7be98da26b
--- /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 0000000000..4b55d3c6b9
--- /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 0000000000..b440daf8cf
--- /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 0000000000..31ca766b26
--- /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 96af6e3207..a8a5a16fd6 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 ec77dfe82d..cb90748f70 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 0000000000..3a0e3813e9
--- /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 0000000000..2d18d56ced
--- /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 3ddb177606..476580f915 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 a7406f0b1b..597c88c688 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 0000000000..a0a36f8f89
--- /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 fbb0276f2a..4c99ceb54a 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 da616a43d7..f56e6b8ca8 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 6864df09ed..048d56a584 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 e9c338401b..bc20e85995 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 314543a313..0000000000
--- 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 aee24de22f..0000000000
--- 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 7007247665..0000000000
--- 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 cd8e17538a..0000000000
--- 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 a19e939fc5..0000000000
--- 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 78379f693b..0000000000
--- 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 0f1196c661..0000000000
--- 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 f98f9c871d..0000000000
--- 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 f324faf258..0000000000
--- 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 70a545e1f9..0000000000
--- 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 16be01ae63..0000000000
--- 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 8cdd9d0f58..0000000000
--- 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 14a92654ef..0000000000
--- 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 d22163227f..0000000000
--- 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 bfa8138d8f..0000000000
--- 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 b4262bca0d..0000000000
--- 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 670bbc3ee1..0000000000
--- 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 cb68389c7b..0000000000
--- 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 9eeae24096..0000000000
--- 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 1c3e5eceef..0000000000
--- 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 292d37a9d8..0000000000
--- 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 f43af230a8..0000000000
--- 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 5ba2cb48c5..0000000000
--- 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 32f85534a5..0000000000
--- 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 6c112668ac..0000000000
--- 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 14aef6715d..0000000000
--- 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 7aee1db755..0000000000
--- 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 333b3afca0..0000000000
--- 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 8298333ff1..0000000000
--- 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 aa48bf498c..0000000000
--- 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 3244abca1a..0000000000
--- 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 79c732e932..0000000000
--- 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 471446b6f4..0000000000
--- 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 2c2d32c293..0000000000
--- 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 9172656e9f..0000000000
--- 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 ea5cdd91ab..0000000000
--- 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 0a514f5192..0000000000
--- 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 6f961270da..0000000000
--- 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 d045114fc4..0000000000
--- 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 e5ee94a2d3..0000000000
--- 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 aad376cc40..0000000000
--- 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 b5da5e653a..0000000000
--- 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 56ed6b9ca5..0000000000
--- 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 ca1021a0c1..0000000000
--- 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 56f489dc1c..0000000000
--- 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 bc3967416a..0000000000
--- 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 11ff779133..0000000000
--- 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 f70c7cdab4..0000000000
--- 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 469263085c..0000000000
--- 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 9d6ad8d782..0000000000
--- 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 fa7ddcd949..3100969668 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 ce02678854..424e6674b2 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 af847ec2cf..0d366e8677 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 39014d239b..a6d761a4c9 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 562d27685d..6e28dce8cf 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 f7a7693fda..0ece8f562d 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 1714b261b3..c14032271d 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 ccea806ff2..818db58b61 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 d7ebb8302c..99243107e4 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 e07f3e6c39..21fb4e3102 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 843e6857a9..cd6494a400 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 6ee9690895..241e57c6ae 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 7f18689e84..b9e695eda6 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 9946ea4640..44f986b7e6 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 260c38cd85..86e302ec0c 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 2990e8f460..00cb0e7982 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 28276a4311..3d80762e06 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 b7abf54fb4..350354bf0e 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 c63fa66c29..8b9e59bab4 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 351fa48af4..ea36d9ca36 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 98ae7854d0..5d070af0d0 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 249ed4a165..3eea773aa4 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 36d7185408..7971809ddc 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 fb60f2cb29..50d6c10c2b 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 4dccd6739f..bb542662c5 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 7d7acd74d9..dd7982795a 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 6d45fc9757..8c19201f9f 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 06ead4cdfc..5aabfdd609 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 1cced78ffd..7fd85878f6 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 5d74a63d56..7520fdebd3 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 aa04a43aa7..c2856e5b0d 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 3139ad5983..953c99a1fd 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 1802fe2ca2..a5658ed956 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 d61f0cce93..62b7cc0834 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 2fb80dd065..376d7e54a7 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 5f1270265b..faf91edcd4 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 7daaf557e0..947e802bd4 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 b01f5770a9..77b849b60e 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 ec73a0c1a5..afcc1db3ab 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 63f52e82f3..8efc0f535c 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 3af216ebf4..7fb1598542 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 a4156c6d1b..28b72a852b 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 81e48b5614..894dc4e480 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 b18634e0aa..c455cd82f6 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 b8c9e4f6a2..ad4e4b665f 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 5531177d1b..3cdbcf8a67 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 6505284e7a..9de331d42f 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 43e9910418..3050581d5d 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 69e5595251..d2bd29cd4e 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 cd6d4c2f89..25a2a1b16b 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 06ac33bfc8..6b49f7d703 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 235b6e8067..35aea6e15c 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 af9c329836..d50a54fae9 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 2f8e349c4c..cd8e31d647 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 c5f69eee71..510b2a98e3 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 a7798148c2..3a67bb7f87 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 5bfc0971a2..1652208d67 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 36e9459467..d9c58531e2 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 905ba25294..a436e8977f 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 8750d531c4..ad9affb9a7 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 3ac7d5f1c7..d3de3b87ae 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 fc30420f09..827ba97e28 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 c186400cf6..cd01b5779c 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 bf013fd2de..8292f804f3 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 6bf6e9dff3..01e9c7c0e9 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 985b000a35..2823539d07 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 5dbf9d3eee..4ff790b946 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 0f039dfdac..71e646bf98 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 11919c5fc6..54eebbce12 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 92aeaf54c7..0814db6111 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 caf349af12..3430dc3990 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 306b082a6b..56c8999bd9 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 8e750a9c68..2c38258e2a 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 e198db4719..e35af03566 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 0e72451229..0a4a0ac6fd 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 52fcd5d721..4eacdc5033 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 c33b308c66..c0de31ef2d 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 cf8640edab..09c0474d91 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 463d4a8671..6d9841e2c7 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 3c1be62abf..5678cc61c4 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 56415f41c9..5c43548c43 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 9e92278061..f6ac2bf66e 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 3d5fad97a6..88b9fcf201 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 cff74d31d3..88650c06f2 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 8cd1b54b75..c1557b9404 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 76ed641b42..b230be881f 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 7d3c6e22b2..7c8423e2ad 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 bc014f56c1..10306c4f52 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 eddf2bc6a5..5905facbe3 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 b167af5b93..c6bb2b2712 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'
-- 
GitLab


From 906dd1bd062771addd53bc173a04af27c49685f5 Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Thu, 1 Dec 2016 10:08:46 +0000
Subject: [PATCH 2/4] Added .gitignore files for new modules.

---
 bramble-android/.gitignore | 5 +++++
 bramble-core/.gitignore    | 3 +++
 bramble-j2se/.gitignore    | 3 +++
 3 files changed, 11 insertions(+)
 create mode 100644 bramble-android/.gitignore
 create mode 100644 bramble-core/.gitignore
 create mode 100644 bramble-j2se/.gitignore

diff --git a/bramble-android/.gitignore b/bramble-android/.gitignore
new file mode 100644
index 0000000000..6653bfd64f
--- /dev/null
+++ b/bramble-android/.gitignore
@@ -0,0 +1,5 @@
+bin
+gen
+build
+.settings
+src/main/res/raw/*.zip
diff --git a/bramble-core/.gitignore b/bramble-core/.gitignore
new file mode 100644
index 0000000000..eeb02632a0
--- /dev/null
+++ b/bramble-core/.gitignore
@@ -0,0 +1,3 @@
+bin
+build
+.settings
diff --git a/bramble-j2se/.gitignore b/bramble-j2se/.gitignore
new file mode 100644
index 0000000000..eeb02632a0
--- /dev/null
+++ b/bramble-j2se/.gitignore
@@ -0,0 +1,3 @@
+bin
+build
+.settings
-- 
GitLab


From f25d33b0c8ffe150075a08b6c9bd61d8aa8434d5 Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Thu, 1 Dec 2016 10:18:42 +0000
Subject: [PATCH 3/4] Move stray resources to the right place.

---
 briar-android/{ => src/main}/res/values-fr/strings.xml | 0
 briar-android/{ => src/main}/res/values-sq/strings.xml | 0
 2 files changed, 0 insertions(+), 0 deletions(-)
 rename briar-android/{ => src/main}/res/values-fr/strings.xml (100%)
 rename briar-android/{ => src/main}/res/values-sq/strings.xml (100%)

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-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
-- 
GitLab


From 2d7cb7b27940f9dc3812926312f870c855015fa5 Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Thu, 1 Dec 2016 10:19:24 +0000
Subject: [PATCH 4/4] Updated Transifex config.

---
 briar-android/.tx/config | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/briar-android/.tx/config b/briar-android/.tx/config
index 893ff42a84..df6373eaa2 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
-- 
GitLab