From dce70f487ce5dbb881665a8a40b36e58072e8895 Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Wed, 8 Jan 2014 15:45:02 +0000
Subject: [PATCH] Merged clock and os packages, moved events into their own
 package.

---
 .../sf/briar/android/AndroidFileUtils.java    |  2 +-
 .../net/sf/briar/android/AndroidModule.java   |  2 +-
 .../android/contact/ContactListActivity.java  | 16 +++---
 .../android/contact/ConversationActivity.java | 14 ++---
 .../briar/android/groups/GroupActivity.java   | 14 ++---
 .../android/groups/GroupListActivity.java     | 18 +++----
 .../android/groups/ManageGroupsActivity.java  | 14 ++---
 .../plugins/droidtooth/DroidtoothPlugin.java  |  2 +-
 .../droidtooth/DroidtoothPluginFactory.java   |  4 +-
 .../briar/plugins/tcp/DroidLanTcpPlugin.java  |  2 +-
 .../plugins/tcp/DroidLanTcpPluginFactory.java |  4 +-
 .../sf/briar/api/db/DatabaseComponent.java    |  6 +--
 .../sf/briar/api/db/event/DatabaseEvent.java  |  6 ---
 .../briar/api/db/event/DatabaseListener.java  |  7 ---
 .../db/event/LocalTransportsUpdatedEvent.java |  9 ----
 .../api/{db => }/event/ContactAddedEvent.java |  4 +-
 .../{db => }/event/ContactRemovedEvent.java   |  4 +-
 .../src/net/sf/briar/api/event/Event.java     |  6 +++
 .../net/sf/briar/api/event/EventListener.java |  7 +++
 .../{db => }/event/LocalAuthorAddedEvent.java |  4 +-
 .../event/LocalAuthorRemovedEvent.java        |  4 +-
 .../event/LocalSubscriptionsUpdatedEvent.java |  4 +-
 .../event/LocalTransportsUpdatedEvent.java    |  9 ++++
 .../api/{db => }/event/MessageAddedEvent.java |  4 +-
 .../{db => }/event/MessageExpiredEvent.java   |  4 +-
 .../{db => }/event/MessageRequestedEvent.java |  4 +-
 .../api/{db => }/event/MessageToAckEvent.java |  6 +--
 .../{db => }/event/MessageToRequestEvent.java |  4 +-
 .../RemoteRetentionTimeUpdatedEvent.java      |  4 +-
 .../RemoteSubscriptionsUpdatedEvent.java      |  4 +-
 .../event/RemoteTransportsUpdatedEvent.java   |  4 +-
 .../event/SubscriptionAddedEvent.java         |  4 +-
 .../event/SubscriptionRemovedEvent.java       |  4 +-
 .../{db => }/event/TransportAddedEvent.java   |  6 +--
 .../{db => }/event/TransportRemovedEvent.java |  4 +-
 .../sf/briar/api/{clock => system}/Clock.java |  2 +-
 .../briar/api/{os => system}/FileUtils.java   |  2 +-
 .../api/{clock => system}/SystemClock.java    |  2 +-
 .../api/{clock => system}/SystemTimer.java    |  2 +-
 .../sf/briar/api/{clock => system}/Timer.java |  2 +-
 .../net/sf/briar/db/DatabaseCleanerImpl.java  |  2 +-
 .../sf/briar/db/DatabaseComponentImpl.java    | 54 +++++++++----------
 .../src/net/sf/briar/db/DatabaseModule.java   |  6 +--
 .../src/net/sf/briar/db/H2Database.java       |  4 +-
 .../src/net/sf/briar/db/JdbcDatabase.java     |  2 +-
 .../sf/briar/invitation/AliceConnector.java   |  2 +-
 .../net/sf/briar/invitation/BobConnector.java |  2 +-
 .../net/sf/briar/invitation/Connector.java    |  2 +-
 .../sf/briar/invitation/ConnectorGroup.java   |  2 +-
 .../invitation/InvitationTaskFactoryImpl.java |  2 +-
 .../briar/messaging/MessageVerifierImpl.java  |  2 +-
 .../messaging/duplex/DuplexConnection.java    | 30 +++++------
 .../src/net/sf/briar/plugins/PollerImpl.java  |  2 +-
 .../net/sf/briar/plugins/file/FilePlugin.java |  2 +-
 .../sf/briar/plugins/tcp/LanTcpPlugin.java    |  2 +-
 .../plugins/tcp/LanTcpPluginFactory.java      |  4 +-
 .../net/sf/briar/reliability/Receiver.java    |  2 +-
 .../ReliabilityLayerFactoryImpl.java          |  4 +-
 .../reliability/ReliabilityLayerImpl.java     |  2 +-
 .../src/net/sf/briar/reliability/Sender.java  |  2 +-
 .../briar/{clock => system}/ClockModule.java  | 10 ++--
 .../sf/briar/transport/KeyManagerImpl.java    | 18 +++----
 .../briar/plugins/DesktopPluginsModule.java   |  2 +-
 .../plugins/bluetooth/BluetoothPlugin.java    |  2 +-
 .../bluetooth/BluetoothPluginFactory.java     |  4 +-
 .../plugins/file/RemovableDrivePlugin.java    |  2 +-
 .../file/RemovableDrivePluginFactory.java     |  2 +-
 .../briar/plugins/modem/ModemFactoryImpl.java |  4 +-
 .../net/sf/briar/plugins/modem/ModemImpl.java |  2 +-
 .../briar/{os => system}/DesktopOsModule.java |  4 +-
 .../briar/{os => system}/FileUtilsImpl.java   |  4 +-
 .../net/sf/briar/ProtocolIntegrationTest.java |  2 +-
 .../src/net/sf/briar/TestDatabaseModule.java  |  2 +-
 .../src/net/sf/briar/TestFileUtils.java       |  2 +-
 .../sf/briar/db/DatabaseCleanerImplTest.java  |  4 +-
 .../briar/db/DatabaseComponentImplTest.java   |  2 +-
 .../sf/briar/db/DatabaseComponentTest.java    | 44 +++++++--------
 .../src/net/sf/briar/db/H2DatabaseTest.java   |  2 +-
 .../net/sf/briar/messaging/ConstantsTest.java |  2 +-
 .../OutgoingSimplexConnectionTest.java        |  2 +-
 .../SimplexMessagingIntegrationTest.java      | 12 ++---
 .../bluetooth/BluetoothClientTest.java        |  2 +-
 .../bluetooth/BluetoothServerTest.java        |  2 +-
 .../file/RemovableDrivePluginTest.java        |  2 +-
 .../briar/plugins/tcp/LanTcpClientTest.java   |  4 +-
 .../briar/plugins/tcp/LanTcpPluginTest.java   |  4 +-
 .../briar/plugins/tcp/LanTcpServerTest.java   |  4 +-
 .../briar/transport/KeyManagerImplTest.java   | 42 +++++++--------
 .../transport/KeyRotationIntegrationTest.java | 34 ++++++------
 89 files changed, 288 insertions(+), 288 deletions(-)
 delete mode 100644 briar-api/src/net/sf/briar/api/db/event/DatabaseEvent.java
 delete mode 100644 briar-api/src/net/sf/briar/api/db/event/DatabaseListener.java
 delete mode 100644 briar-api/src/net/sf/briar/api/db/event/LocalTransportsUpdatedEvent.java
 rename briar-api/src/net/sf/briar/api/{db => }/event/ContactAddedEvent.java (75%)
 rename briar-api/src/net/sf/briar/api/{db => }/event/ContactRemovedEvent.java (75%)
 create mode 100644 briar-api/src/net/sf/briar/api/event/Event.java
 create mode 100644 briar-api/src/net/sf/briar/api/event/EventListener.java
 rename briar-api/src/net/sf/briar/api/{db => }/event/LocalAuthorAddedEvent.java (74%)
 rename briar-api/src/net/sf/briar/api/{db => }/event/LocalAuthorRemovedEvent.java (74%)
 rename briar-api/src/net/sf/briar/api/{db => }/event/LocalSubscriptionsUpdatedEvent.java (81%)
 create mode 100644 briar-api/src/net/sf/briar/api/event/LocalTransportsUpdatedEvent.java
 rename briar-api/src/net/sf/briar/api/{db => }/event/MessageAddedEvent.java (87%)
 rename briar-api/src/net/sf/briar/api/{db => }/event/MessageExpiredEvent.java (61%)
 rename briar-api/src/net/sf/briar/api/{db => }/event/MessageRequestedEvent.java (76%)
 rename briar-api/src/net/sf/briar/api/{db => }/event/MessageToAckEvent.java (61%)
 rename briar-api/src/net/sf/briar/api/{db => }/event/MessageToRequestEvent.java (77%)
 rename briar-api/src/net/sf/briar/api/{db => }/event/RemoteRetentionTimeUpdatedEvent.java (76%)
 rename briar-api/src/net/sf/briar/api/{db => }/event/RemoteSubscriptionsUpdatedEvent.java (74%)
 rename briar-api/src/net/sf/briar/api/{db => }/event/RemoteTransportsUpdatedEvent.java (84%)
 rename briar-api/src/net/sf/briar/api/{db => }/event/SubscriptionAddedEvent.java (73%)
 rename briar-api/src/net/sf/briar/api/{db => }/event/SubscriptionRemovedEvent.java (73%)
 rename briar-api/src/net/sf/briar/api/{db => }/event/TransportAddedEvent.java (69%)
 rename briar-api/src/net/sf/briar/api/{db => }/event/TransportRemovedEvent.java (76%)
 rename briar-api/src/net/sf/briar/api/{clock => system}/Clock.java (90%)
 rename briar-api/src/net/sf/briar/api/{os => system}/FileUtils.java (79%)
 rename briar-api/src/net/sf/briar/api/{clock => system}/SystemClock.java (88%)
 rename briar-api/src/net/sf/briar/api/{clock => system}/SystemTimer.java (94%)
 rename briar-api/src/net/sf/briar/api/{clock => system}/Timer.java (95%)
 rename briar-core/src/net/sf/briar/{clock => system}/ClockModule.java (52%)
 rename briar-desktop/src/net/sf/briar/{os => system}/DesktopOsModule.java (73%)
 rename briar-desktop/src/net/sf/briar/{os => system}/FileUtilsImpl.java (72%)

diff --git a/briar-android/src/net/sf/briar/android/AndroidFileUtils.java b/briar-android/src/net/sf/briar/android/AndroidFileUtils.java
index 9d52ae01e8..a7c286e04c 100644
--- a/briar-android/src/net/sf/briar/android/AndroidFileUtils.java
+++ b/briar-android/src/net/sf/briar/android/AndroidFileUtils.java
@@ -3,7 +3,7 @@ package net.sf.briar.android;
 import java.io.File;
 import java.io.IOException;
 
-import net.sf.briar.api.os.FileUtils;
+import net.sf.briar.api.system.FileUtils;
 import android.os.Build;
 import android.os.StatFs;
 
diff --git a/briar-android/src/net/sf/briar/android/AndroidModule.java b/briar-android/src/net/sf/briar/android/AndroidModule.java
index 1a584579a5..a25cf96dc2 100644
--- a/briar-android/src/net/sf/briar/android/AndroidModule.java
+++ b/briar-android/src/net/sf/briar/android/AndroidModule.java
@@ -23,12 +23,12 @@ import net.sf.briar.api.crypto.CryptoComponent;
 import net.sf.briar.api.db.DatabaseConfig;
 import net.sf.briar.api.lifecycle.LifecycleManager;
 import net.sf.briar.api.lifecycle.ShutdownManager;
-import net.sf.briar.api.os.FileUtils;
 import net.sf.briar.api.plugins.PluginExecutor;
 import net.sf.briar.api.plugins.duplex.DuplexPluginConfig;
 import net.sf.briar.api.plugins.duplex.DuplexPluginFactory;
 import net.sf.briar.api.plugins.simplex.SimplexPluginConfig;
 import net.sf.briar.api.plugins.simplex.SimplexPluginFactory;
+import net.sf.briar.api.system.FileUtils;
 import net.sf.briar.api.ui.UiCallback;
 import net.sf.briar.plugins.droidtooth.DroidtoothPluginFactory;
 import net.sf.briar.plugins.tcp.DroidLanTcpPluginFactory;
diff --git a/briar-android/src/net/sf/briar/android/contact/ContactListActivity.java b/briar-android/src/net/sf/briar/android/contact/ContactListActivity.java
index 1b64b76352..2fb503234b 100644
--- a/briar-android/src/net/sf/briar/android/contact/ContactListActivity.java
+++ b/briar-android/src/net/sf/briar/android/contact/ContactListActivity.java
@@ -29,12 +29,12 @@ import net.sf.briar.api.db.DatabaseComponent;
 import net.sf.briar.api.db.DbException;
 import net.sf.briar.api.db.MessageHeader;
 import net.sf.briar.api.db.NoSuchContactException;
-import net.sf.briar.api.db.event.ContactAddedEvent;
-import net.sf.briar.api.db.event.ContactRemovedEvent;
-import net.sf.briar.api.db.event.DatabaseEvent;
-import net.sf.briar.api.db.event.DatabaseListener;
-import net.sf.briar.api.db.event.MessageAddedEvent;
-import net.sf.briar.api.db.event.MessageExpiredEvent;
+import net.sf.briar.api.event.ContactAddedEvent;
+import net.sf.briar.api.event.ContactRemovedEvent;
+import net.sf.briar.api.event.Event;
+import net.sf.briar.api.event.EventListener;
+import net.sf.briar.api.event.MessageAddedEvent;
+import net.sf.briar.api.event.MessageExpiredEvent;
 import net.sf.briar.api.lifecycle.LifecycleManager;
 import net.sf.briar.api.messaging.GroupId;
 import net.sf.briar.api.transport.ConnectionListener;
@@ -51,7 +51,7 @@ import android.widget.LinearLayout;
 import android.widget.ListView;
 
 public class ContactListActivity extends RoboActivity
-implements OnClickListener, OnItemClickListener, DatabaseListener,
+implements OnClickListener, OnItemClickListener, EventListener,
 ConnectionListener {
 
 	private static final Logger LOG =
@@ -219,7 +219,7 @@ ConnectionListener {
 		startActivity(i);
 	}
 
-	public void eventOccurred(DatabaseEvent e) {
+	public void eventOccurred(Event e) {
 		if(e instanceof ContactAddedEvent) {
 			loadContacts();
 		} else if(e instanceof ContactRemovedEvent) {
diff --git a/briar-android/src/net/sf/briar/android/contact/ConversationActivity.java b/briar-android/src/net/sf/briar/android/contact/ConversationActivity.java
index 29d3223287..d4ae17170c 100644
--- a/briar-android/src/net/sf/briar/android/contact/ConversationActivity.java
+++ b/briar-android/src/net/sf/briar/android/contact/ConversationActivity.java
@@ -25,11 +25,11 @@ import net.sf.briar.api.db.DatabaseComponent;
 import net.sf.briar.api.db.DbException;
 import net.sf.briar.api.db.MessageHeader;
 import net.sf.briar.api.db.NoSuchContactException;
-import net.sf.briar.api.db.event.ContactRemovedEvent;
-import net.sf.briar.api.db.event.DatabaseEvent;
-import net.sf.briar.api.db.event.DatabaseListener;
-import net.sf.briar.api.db.event.MessageAddedEvent;
-import net.sf.briar.api.db.event.MessageExpiredEvent;
+import net.sf.briar.api.event.ContactRemovedEvent;
+import net.sf.briar.api.event.Event;
+import net.sf.briar.api.event.EventListener;
+import net.sf.briar.api.event.MessageAddedEvent;
+import net.sf.briar.api.event.MessageExpiredEvent;
 import net.sf.briar.api.lifecycle.LifecycleManager;
 import net.sf.briar.api.messaging.GroupId;
 import roboguice.activity.RoboActivity;
@@ -44,7 +44,7 @@ import android.widget.LinearLayout;
 import android.widget.ListView;
 
 public class ConversationActivity extends RoboActivity
-implements DatabaseListener, OnClickListener, OnItemClickListener {
+implements EventListener, OnClickListener, OnItemClickListener {
 
 	private static final Logger LOG =
 			Logger.getLogger(ConversationActivity.class.getName());
@@ -196,7 +196,7 @@ implements DatabaseListener, OnClickListener, OnItemClickListener {
 		db.removeListener(this);
 	}
 
-	public void eventOccurred(DatabaseEvent e) {
+	public void eventOccurred(Event e) {
 		if(e instanceof ContactRemovedEvent) {
 			ContactRemovedEvent c = (ContactRemovedEvent) e;
 			if(c.getContactId().equals(contactId)) {
diff --git a/briar-android/src/net/sf/briar/android/groups/GroupActivity.java b/briar-android/src/net/sf/briar/android/groups/GroupActivity.java
index fef29b665a..d42d33e254 100644
--- a/briar-android/src/net/sf/briar/android/groups/GroupActivity.java
+++ b/briar-android/src/net/sf/briar/android/groups/GroupActivity.java
@@ -27,11 +27,11 @@ import net.sf.briar.api.db.DatabaseComponent;
 import net.sf.briar.api.db.DbException;
 import net.sf.briar.api.db.MessageHeader;
 import net.sf.briar.api.db.NoSuchSubscriptionException;
-import net.sf.briar.api.db.event.DatabaseEvent;
-import net.sf.briar.api.db.event.DatabaseListener;
-import net.sf.briar.api.db.event.MessageAddedEvent;
-import net.sf.briar.api.db.event.MessageExpiredEvent;
-import net.sf.briar.api.db.event.SubscriptionRemovedEvent;
+import net.sf.briar.api.event.Event;
+import net.sf.briar.api.event.EventListener;
+import net.sf.briar.api.event.MessageAddedEvent;
+import net.sf.briar.api.event.MessageExpiredEvent;
+import net.sf.briar.api.event.SubscriptionRemovedEvent;
 import net.sf.briar.api.lifecycle.LifecycleManager;
 import net.sf.briar.api.messaging.GroupId;
 import roboguice.activity.RoboActivity;
@@ -45,7 +45,7 @@ import android.widget.ImageButton;
 import android.widget.LinearLayout;
 import android.widget.ListView;
 
-public class GroupActivity extends RoboActivity implements DatabaseListener,
+public class GroupActivity extends RoboActivity implements EventListener,
 OnClickListener, OnItemClickListener {
 
 	private static final Logger LOG =
@@ -186,7 +186,7 @@ OnClickListener, OnItemClickListener {
 		db.removeListener(this);
 	}
 
-	public void eventOccurred(DatabaseEvent e) {
+	public void eventOccurred(Event e) {
 		if(e instanceof MessageAddedEvent) {
 			if(((MessageAddedEvent) e).getGroup().getId().equals(groupId)) {
 				if(LOG.isLoggable(INFO)) LOG.info("Message added, reloading");
diff --git a/briar-android/src/net/sf/briar/android/groups/GroupListActivity.java b/briar-android/src/net/sf/briar/android/groups/GroupListActivity.java
index 0689eba6d0..8ff3f80e93 100644
--- a/briar-android/src/net/sf/briar/android/groups/GroupListActivity.java
+++ b/briar-android/src/net/sf/briar/android/groups/GroupListActivity.java
@@ -31,13 +31,13 @@ import net.sf.briar.api.db.DatabaseComponent;
 import net.sf.briar.api.db.DbException;
 import net.sf.briar.api.db.MessageHeader;
 import net.sf.briar.api.db.NoSuchSubscriptionException;
-import net.sf.briar.api.db.event.DatabaseEvent;
-import net.sf.briar.api.db.event.DatabaseListener;
-import net.sf.briar.api.db.event.MessageAddedEvent;
-import net.sf.briar.api.db.event.MessageExpiredEvent;
-import net.sf.briar.api.db.event.RemoteSubscriptionsUpdatedEvent;
-import net.sf.briar.api.db.event.SubscriptionAddedEvent;
-import net.sf.briar.api.db.event.SubscriptionRemovedEvent;
+import net.sf.briar.api.event.Event;
+import net.sf.briar.api.event.EventListener;
+import net.sf.briar.api.event.MessageAddedEvent;
+import net.sf.briar.api.event.MessageExpiredEvent;
+import net.sf.briar.api.event.RemoteSubscriptionsUpdatedEvent;
+import net.sf.briar.api.event.SubscriptionAddedEvent;
+import net.sf.briar.api.event.SubscriptionRemovedEvent;
 import net.sf.briar.api.lifecycle.LifecycleManager;
 import net.sf.briar.api.messaging.Group;
 import net.sf.briar.api.messaging.GroupId;
@@ -54,7 +54,7 @@ import android.widget.LinearLayout;
 import android.widget.ListView;
 
 public class GroupListActivity extends RoboFragmentActivity
-implements DatabaseListener, OnClickListener, OnItemClickListener {
+implements EventListener, OnClickListener, OnItemClickListener {
 
 	private static final Logger LOG =
 			Logger.getLogger(GroupListActivity.class.getName());
@@ -238,7 +238,7 @@ implements DatabaseListener, OnClickListener, OnItemClickListener {
 		db.removeListener(this);
 	}
 
-	public void eventOccurred(DatabaseEvent e) {
+	public void eventOccurred(Event e) {
 		if(e instanceof MessageAddedEvent) {
 			Group g = ((MessageAddedEvent) e).getGroup();
 			if(groups.containsKey(g.getId())) {
diff --git a/briar-android/src/net/sf/briar/android/groups/ManageGroupsActivity.java b/briar-android/src/net/sf/briar/android/groups/ManageGroupsActivity.java
index 282fa6d29f..9c265d573d 100644
--- a/briar-android/src/net/sf/briar/android/groups/ManageGroupsActivity.java
+++ b/briar-android/src/net/sf/briar/android/groups/ManageGroupsActivity.java
@@ -16,11 +16,11 @@ import net.sf.briar.android.util.ListLoadingProgressBar;
 import net.sf.briar.api.android.DatabaseUiExecutor;
 import net.sf.briar.api.db.DatabaseComponent;
 import net.sf.briar.api.db.DbException;
-import net.sf.briar.api.db.event.DatabaseEvent;
-import net.sf.briar.api.db.event.DatabaseListener;
-import net.sf.briar.api.db.event.RemoteSubscriptionsUpdatedEvent;
-import net.sf.briar.api.db.event.SubscriptionAddedEvent;
-import net.sf.briar.api.db.event.SubscriptionRemovedEvent;
+import net.sf.briar.api.event.Event;
+import net.sf.briar.api.event.EventListener;
+import net.sf.briar.api.event.RemoteSubscriptionsUpdatedEvent;
+import net.sf.briar.api.event.SubscriptionAddedEvent;
+import net.sf.briar.api.event.SubscriptionRemovedEvent;
 import net.sf.briar.api.lifecycle.LifecycleManager;
 import net.sf.briar.api.messaging.Group;
 import net.sf.briar.api.messaging.GroupStatus;
@@ -33,7 +33,7 @@ import android.widget.AdapterView.OnItemClickListener;
 import android.widget.ListView;
 
 public class ManageGroupsActivity extends RoboFragmentActivity
-implements DatabaseListener, OnItemClickListener {
+implements EventListener, OnItemClickListener {
 
 	private static final Logger LOG =
 			Logger.getLogger(ManageGroupsActivity.class.getName());
@@ -111,7 +111,7 @@ implements DatabaseListener, OnItemClickListener {
 		db.removeListener(this);
 	}
 
-	public void eventOccurred(DatabaseEvent e) {
+	public void eventOccurred(Event e) {
 		if(e instanceof RemoteSubscriptionsUpdatedEvent) {
 			if(LOG.isLoggable(INFO))
 				LOG.info("Remote subscriptions changed, reloading");
diff --git a/briar-android/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java b/briar-android/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java
index 407daedd68..417f7c931e 100644
--- a/briar-android/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java
+++ b/briar-android/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java
@@ -28,11 +28,11 @@ import net.sf.briar.api.ContactId;
 import net.sf.briar.api.TransportId;
 import net.sf.briar.api.TransportProperties;
 import net.sf.briar.api.android.AndroidExecutor;
-import net.sf.briar.api.clock.Clock;
 import net.sf.briar.api.crypto.PseudoRandom;
 import net.sf.briar.api.plugins.duplex.DuplexPlugin;
 import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
 import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
+import net.sf.briar.api.system.Clock;
 import net.sf.briar.util.LatchedReference;
 import net.sf.briar.util.StringUtils;
 import android.bluetooth.BluetoothAdapter;
diff --git a/briar-android/src/net/sf/briar/plugins/droidtooth/DroidtoothPluginFactory.java b/briar-android/src/net/sf/briar/plugins/droidtooth/DroidtoothPluginFactory.java
index 6599601c31..384f129b62 100644
--- a/briar-android/src/net/sf/briar/plugins/droidtooth/DroidtoothPluginFactory.java
+++ b/briar-android/src/net/sf/briar/plugins/droidtooth/DroidtoothPluginFactory.java
@@ -5,11 +5,11 @@ import java.util.concurrent.Executor;
 
 import net.sf.briar.api.TransportId;
 import net.sf.briar.api.android.AndroidExecutor;
-import net.sf.briar.api.clock.Clock;
-import net.sf.briar.api.clock.SystemClock;
 import net.sf.briar.api.plugins.duplex.DuplexPlugin;
 import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
 import net.sf.briar.api.plugins.duplex.DuplexPluginFactory;
+import net.sf.briar.api.system.Clock;
+import net.sf.briar.api.system.SystemClock;
 import android.content.Context;
 
 public class DroidtoothPluginFactory implements DuplexPluginFactory {
diff --git a/briar-android/src/net/sf/briar/plugins/tcp/DroidLanTcpPlugin.java b/briar-android/src/net/sf/briar/plugins/tcp/DroidLanTcpPlugin.java
index 9853c23aa6..20bcd3867d 100644
--- a/briar-android/src/net/sf/briar/plugins/tcp/DroidLanTcpPlugin.java
+++ b/briar-android/src/net/sf/briar/plugins/tcp/DroidLanTcpPlugin.java
@@ -4,10 +4,10 @@ import static android.content.Context.WIFI_SERVICE;
 
 import java.util.concurrent.Executor;
 
-import net.sf.briar.api.clock.Clock;
 import net.sf.briar.api.crypto.PseudoRandom;
 import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
 import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
+import net.sf.briar.api.system.Clock;
 import android.content.Context;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiManager.MulticastLock;
diff --git a/briar-android/src/net/sf/briar/plugins/tcp/DroidLanTcpPluginFactory.java b/briar-android/src/net/sf/briar/plugins/tcp/DroidLanTcpPluginFactory.java
index 32ca3261a7..ad7b298687 100644
--- a/briar-android/src/net/sf/briar/plugins/tcp/DroidLanTcpPluginFactory.java
+++ b/briar-android/src/net/sf/briar/plugins/tcp/DroidLanTcpPluginFactory.java
@@ -3,11 +3,11 @@ package net.sf.briar.plugins.tcp;
 import java.util.concurrent.Executor;
 
 import net.sf.briar.api.TransportId;
-import net.sf.briar.api.clock.Clock;
-import net.sf.briar.api.clock.SystemClock;
 import net.sf.briar.api.plugins.duplex.DuplexPlugin;
 import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
 import net.sf.briar.api.plugins.duplex.DuplexPluginFactory;
+import net.sf.briar.api.system.Clock;
+import net.sf.briar.api.system.SystemClock;
 import android.content.Context;
 
 public class DroidLanTcpPluginFactory implements DuplexPluginFactory {
diff --git a/briar-api/src/net/sf/briar/api/db/DatabaseComponent.java b/briar-api/src/net/sf/briar/api/db/DatabaseComponent.java
index 4d3ab18080..43e1d38769 100644
--- a/briar-api/src/net/sf/briar/api/db/DatabaseComponent.java
+++ b/briar-api/src/net/sf/briar/api/db/DatabaseComponent.java
@@ -12,7 +12,7 @@ import net.sf.briar.api.LocalAuthor;
 import net.sf.briar.api.TransportConfig;
 import net.sf.briar.api.TransportId;
 import net.sf.briar.api.TransportProperties;
-import net.sf.briar.api.db.event.DatabaseListener;
+import net.sf.briar.api.event.EventListener;
 import net.sf.briar.api.messaging.Ack;
 import net.sf.briar.api.messaging.Group;
 import net.sf.briar.api.messaging.GroupId;
@@ -43,10 +43,10 @@ public interface DatabaseComponent {
 	void close() throws DbException, IOException;
 
 	/** Adds a listener to be notified when database events occur. */
-	void addListener(DatabaseListener d);
+	void addListener(EventListener d);
 
 	/** Removes a listener. */
-	void removeListener(DatabaseListener d);
+	void removeListener(EventListener d);
 
 	/**
 	 * Stores a contact associated with the given local and remote pseudonyms,
diff --git a/briar-api/src/net/sf/briar/api/db/event/DatabaseEvent.java b/briar-api/src/net/sf/briar/api/db/event/DatabaseEvent.java
deleted file mode 100644
index 2316bdef35..0000000000
--- a/briar-api/src/net/sf/briar/api/db/event/DatabaseEvent.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package net.sf.briar.api.db.event;
-
-/** An abstract superclass for database events. */
-public abstract class DatabaseEvent {
-
-}
diff --git a/briar-api/src/net/sf/briar/api/db/event/DatabaseListener.java b/briar-api/src/net/sf/briar/api/db/event/DatabaseListener.java
deleted file mode 100644
index 58605bee12..0000000000
--- a/briar-api/src/net/sf/briar/api/db/event/DatabaseListener.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package net.sf.briar.api.db.event;
-
-/** An interface for receiving notifications when database events occur. */
-public interface DatabaseListener {
-
-	void eventOccurred(DatabaseEvent e);
-}
diff --git a/briar-api/src/net/sf/briar/api/db/event/LocalTransportsUpdatedEvent.java b/briar-api/src/net/sf/briar/api/db/event/LocalTransportsUpdatedEvent.java
deleted file mode 100644
index c60c23b83b..0000000000
--- a/briar-api/src/net/sf/briar/api/db/event/LocalTransportsUpdatedEvent.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package net.sf.briar.api.db.event;
-
-/**
- * An event that is broadcast when the local transport properties are
- * updated.
- */
-public class LocalTransportsUpdatedEvent extends DatabaseEvent {
-
-}
diff --git a/briar-api/src/net/sf/briar/api/db/event/ContactAddedEvent.java b/briar-api/src/net/sf/briar/api/event/ContactAddedEvent.java
similarity index 75%
rename from briar-api/src/net/sf/briar/api/db/event/ContactAddedEvent.java
rename to briar-api/src/net/sf/briar/api/event/ContactAddedEvent.java
index 84cc5f2988..9e1cc4dfc1 100644
--- a/briar-api/src/net/sf/briar/api/db/event/ContactAddedEvent.java
+++ b/briar-api/src/net/sf/briar/api/event/ContactAddedEvent.java
@@ -1,9 +1,9 @@
-package net.sf.briar.api.db.event;
+package net.sf.briar.api.event;
 
 import net.sf.briar.api.ContactId;
 
 /** An event that is broadcast when a contact is added. */
-public class ContactAddedEvent extends DatabaseEvent {
+public class ContactAddedEvent extends Event {
 
 	private final ContactId contactId;
 
diff --git a/briar-api/src/net/sf/briar/api/db/event/ContactRemovedEvent.java b/briar-api/src/net/sf/briar/api/event/ContactRemovedEvent.java
similarity index 75%
rename from briar-api/src/net/sf/briar/api/db/event/ContactRemovedEvent.java
rename to briar-api/src/net/sf/briar/api/event/ContactRemovedEvent.java
index 74eed60299..e4ad51c5a4 100644
--- a/briar-api/src/net/sf/briar/api/db/event/ContactRemovedEvent.java
+++ b/briar-api/src/net/sf/briar/api/event/ContactRemovedEvent.java
@@ -1,9 +1,9 @@
-package net.sf.briar.api.db.event;
+package net.sf.briar.api.event;
 
 import net.sf.briar.api.ContactId;
 
 /** An event that is broadcast when a contact is removed. */
-public class ContactRemovedEvent extends DatabaseEvent {
+public class ContactRemovedEvent extends Event {
 
 	private final ContactId contactId;
 
diff --git a/briar-api/src/net/sf/briar/api/event/Event.java b/briar-api/src/net/sf/briar/api/event/Event.java
new file mode 100644
index 0000000000..6101944524
--- /dev/null
+++ b/briar-api/src/net/sf/briar/api/event/Event.java
@@ -0,0 +1,6 @@
+package net.sf.briar.api.event;
+
+/** An abstract superclass for events. */
+public abstract class Event {
+
+}
diff --git a/briar-api/src/net/sf/briar/api/event/EventListener.java b/briar-api/src/net/sf/briar/api/event/EventListener.java
new file mode 100644
index 0000000000..9db96a3d5e
--- /dev/null
+++ b/briar-api/src/net/sf/briar/api/event/EventListener.java
@@ -0,0 +1,7 @@
+package net.sf.briar.api.event;
+
+/** An interface for receiving notifications when events occur. */
+public interface EventListener {
+
+	void eventOccurred(Event e);
+}
diff --git a/briar-api/src/net/sf/briar/api/db/event/LocalAuthorAddedEvent.java b/briar-api/src/net/sf/briar/api/event/LocalAuthorAddedEvent.java
similarity index 74%
rename from briar-api/src/net/sf/briar/api/db/event/LocalAuthorAddedEvent.java
rename to briar-api/src/net/sf/briar/api/event/LocalAuthorAddedEvent.java
index 1d9c305437..2bd6c4fe27 100644
--- a/briar-api/src/net/sf/briar/api/db/event/LocalAuthorAddedEvent.java
+++ b/briar-api/src/net/sf/briar/api/event/LocalAuthorAddedEvent.java
@@ -1,9 +1,9 @@
-package net.sf.briar.api.db.event;
+package net.sf.briar.api.event;
 
 import net.sf.briar.api.AuthorId;
 
 /** An event that is broadcast when a local pseudonym is added. */
-public class LocalAuthorAddedEvent extends DatabaseEvent {
+public class LocalAuthorAddedEvent extends Event {
 
 	private final AuthorId authorId;
 
diff --git a/briar-api/src/net/sf/briar/api/db/event/LocalAuthorRemovedEvent.java b/briar-api/src/net/sf/briar/api/event/LocalAuthorRemovedEvent.java
similarity index 74%
rename from briar-api/src/net/sf/briar/api/db/event/LocalAuthorRemovedEvent.java
rename to briar-api/src/net/sf/briar/api/event/LocalAuthorRemovedEvent.java
index cf4e18e758..1166697936 100644
--- a/briar-api/src/net/sf/briar/api/db/event/LocalAuthorRemovedEvent.java
+++ b/briar-api/src/net/sf/briar/api/event/LocalAuthorRemovedEvent.java
@@ -1,9 +1,9 @@
-package net.sf.briar.api.db.event;
+package net.sf.briar.api.event;
 
 import net.sf.briar.api.AuthorId;
 
 /** An event that is broadcast when a local pseudonym is removed. */
-public class LocalAuthorRemovedEvent extends DatabaseEvent {
+public class LocalAuthorRemovedEvent extends Event {
 
 	private final AuthorId authorId;
 
diff --git a/briar-api/src/net/sf/briar/api/db/event/LocalSubscriptionsUpdatedEvent.java b/briar-api/src/net/sf/briar/api/event/LocalSubscriptionsUpdatedEvent.java
similarity index 81%
rename from briar-api/src/net/sf/briar/api/db/event/LocalSubscriptionsUpdatedEvent.java
rename to briar-api/src/net/sf/briar/api/event/LocalSubscriptionsUpdatedEvent.java
index fcd2ddeb66..934eee61e1 100644
--- a/briar-api/src/net/sf/briar/api/db/event/LocalSubscriptionsUpdatedEvent.java
+++ b/briar-api/src/net/sf/briar/api/event/LocalSubscriptionsUpdatedEvent.java
@@ -1,4 +1,4 @@
-package net.sf.briar.api.db.event;
+package net.sf.briar.api.event;
 
 import java.util.Collection;
 
@@ -8,7 +8,7 @@ import net.sf.briar.api.ContactId;
  * An event that is broadcast when the set of subscriptions visible to one or
  * more contacts is updated.
  */
-public class LocalSubscriptionsUpdatedEvent extends DatabaseEvent {
+public class LocalSubscriptionsUpdatedEvent extends Event {
 
 	private final Collection<ContactId> affected;
 
diff --git a/briar-api/src/net/sf/briar/api/event/LocalTransportsUpdatedEvent.java b/briar-api/src/net/sf/briar/api/event/LocalTransportsUpdatedEvent.java
new file mode 100644
index 0000000000..a3be88940f
--- /dev/null
+++ b/briar-api/src/net/sf/briar/api/event/LocalTransportsUpdatedEvent.java
@@ -0,0 +1,9 @@
+package net.sf.briar.api.event;
+
+/**
+ * An event that is broadcast when the local transport properties are
+ * updated.
+ */
+public class LocalTransportsUpdatedEvent extends Event {
+
+}
diff --git a/briar-api/src/net/sf/briar/api/db/event/MessageAddedEvent.java b/briar-api/src/net/sf/briar/api/event/MessageAddedEvent.java
similarity index 87%
rename from briar-api/src/net/sf/briar/api/db/event/MessageAddedEvent.java
rename to briar-api/src/net/sf/briar/api/event/MessageAddedEvent.java
index 8f04e5d141..ba7e54c1e0 100644
--- a/briar-api/src/net/sf/briar/api/db/event/MessageAddedEvent.java
+++ b/briar-api/src/net/sf/briar/api/event/MessageAddedEvent.java
@@ -1,10 +1,10 @@
-package net.sf.briar.api.db.event;
+package net.sf.briar.api.event;
 
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.messaging.Group;
 
 /** An event that is broadcast when a message is added to the database. */
-public class MessageAddedEvent extends DatabaseEvent {
+public class MessageAddedEvent extends Event {
 
 	private final Group group;
 	private final ContactId contactId;
diff --git a/briar-api/src/net/sf/briar/api/db/event/MessageExpiredEvent.java b/briar-api/src/net/sf/briar/api/event/MessageExpiredEvent.java
similarity index 61%
rename from briar-api/src/net/sf/briar/api/db/event/MessageExpiredEvent.java
rename to briar-api/src/net/sf/briar/api/event/MessageExpiredEvent.java
index 5f130f78a7..e7252d08c5 100644
--- a/briar-api/src/net/sf/briar/api/db/event/MessageExpiredEvent.java
+++ b/briar-api/src/net/sf/briar/api/event/MessageExpiredEvent.java
@@ -1,9 +1,9 @@
-package net.sf.briar.api.db.event;
+package net.sf.briar.api.event;
 
 /**
  * An event that is broadcast when one or messages expire from the database,
  * potentially changing the database's retention time.
  */
-public class MessageExpiredEvent extends DatabaseEvent {
+public class MessageExpiredEvent extends Event {
 
 }
diff --git a/briar-api/src/net/sf/briar/api/db/event/MessageRequestedEvent.java b/briar-api/src/net/sf/briar/api/event/MessageRequestedEvent.java
similarity index 76%
rename from briar-api/src/net/sf/briar/api/db/event/MessageRequestedEvent.java
rename to briar-api/src/net/sf/briar/api/event/MessageRequestedEvent.java
index f735994036..3aef09fc42 100644
--- a/briar-api/src/net/sf/briar/api/db/event/MessageRequestedEvent.java
+++ b/briar-api/src/net/sf/briar/api/event/MessageRequestedEvent.java
@@ -1,9 +1,9 @@
-package net.sf.briar.api.db.event;
+package net.sf.briar.api.event;
 
 import net.sf.briar.api.ContactId;
 
 /** An event that is broadcast when a message is requested by a contact. */
-public class MessageRequestedEvent extends DatabaseEvent {
+public class MessageRequestedEvent extends Event {
 
 	private final ContactId contactId;
 
diff --git a/briar-api/src/net/sf/briar/api/db/event/MessageToAckEvent.java b/briar-api/src/net/sf/briar/api/event/MessageToAckEvent.java
similarity index 61%
rename from briar-api/src/net/sf/briar/api/db/event/MessageToAckEvent.java
rename to briar-api/src/net/sf/briar/api/event/MessageToAckEvent.java
index 6050acd881..b0edcb03e4 100644
--- a/briar-api/src/net/sf/briar/api/db/event/MessageToAckEvent.java
+++ b/briar-api/src/net/sf/briar/api/event/MessageToAckEvent.java
@@ -1,12 +1,12 @@
-package net.sf.briar.api.db.event;
+package net.sf.briar.api.event;
 
 import net.sf.briar.api.ContactId;
 
 /**
- * An event that is broadcast when a message is received or offered from a
+ * 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 DatabaseEvent {
+public class MessageToAckEvent extends Event {
 
 	private final ContactId contactId;
 
diff --git a/briar-api/src/net/sf/briar/api/db/event/MessageToRequestEvent.java b/briar-api/src/net/sf/briar/api/event/MessageToRequestEvent.java
similarity index 77%
rename from briar-api/src/net/sf/briar/api/db/event/MessageToRequestEvent.java
rename to briar-api/src/net/sf/briar/api/event/MessageToRequestEvent.java
index 196ff5b714..da4cf6e5d1 100644
--- a/briar-api/src/net/sf/briar/api/db/event/MessageToRequestEvent.java
+++ b/briar-api/src/net/sf/briar/api/event/MessageToRequestEvent.java
@@ -1,4 +1,4 @@
-package net.sf.briar.api.db.event;
+package net.sf.briar.api.event;
 
 import net.sf.briar.api.ContactId;
 
@@ -6,7 +6,7 @@ import net.sf.briar.api.ContactId;
  * An event that is broadcast when a message is offered by a contact and needs
  * to be requested.
  */
-public class MessageToRequestEvent extends DatabaseEvent {
+public class MessageToRequestEvent extends Event {
 
 	private final ContactId contactId;
 
diff --git a/briar-api/src/net/sf/briar/api/db/event/RemoteRetentionTimeUpdatedEvent.java b/briar-api/src/net/sf/briar/api/event/RemoteRetentionTimeUpdatedEvent.java
similarity index 76%
rename from briar-api/src/net/sf/briar/api/db/event/RemoteRetentionTimeUpdatedEvent.java
rename to briar-api/src/net/sf/briar/api/event/RemoteRetentionTimeUpdatedEvent.java
index 35beb8e4d1..3fd53d51ea 100644
--- a/briar-api/src/net/sf/briar/api/db/event/RemoteRetentionTimeUpdatedEvent.java
+++ b/briar-api/src/net/sf/briar/api/event/RemoteRetentionTimeUpdatedEvent.java
@@ -1,4 +1,4 @@
-package net.sf.briar.api.db.event;
+package net.sf.briar.api.event;
 
 import net.sf.briar.api.ContactId;
 
@@ -6,7 +6,7 @@ import net.sf.briar.api.ContactId;
  * An event that is broadcast when the retention time of a contact's database
  * changes.
  */
-public class RemoteRetentionTimeUpdatedEvent extends DatabaseEvent {
+public class RemoteRetentionTimeUpdatedEvent extends Event {
 
 	private final ContactId contactId;
 
diff --git a/briar-api/src/net/sf/briar/api/db/event/RemoteSubscriptionsUpdatedEvent.java b/briar-api/src/net/sf/briar/api/event/RemoteSubscriptionsUpdatedEvent.java
similarity index 74%
rename from briar-api/src/net/sf/briar/api/db/event/RemoteSubscriptionsUpdatedEvent.java
rename to briar-api/src/net/sf/briar/api/event/RemoteSubscriptionsUpdatedEvent.java
index 54436e52e4..945fd2829d 100644
--- a/briar-api/src/net/sf/briar/api/db/event/RemoteSubscriptionsUpdatedEvent.java
+++ b/briar-api/src/net/sf/briar/api/event/RemoteSubscriptionsUpdatedEvent.java
@@ -1,9 +1,9 @@
-package net.sf.briar.api.db.event;
+package net.sf.briar.api.event;
 
 import net.sf.briar.api.ContactId;
 
 /**  An event that is broadcast when a contact's subscriptions are updated. */
-public class RemoteSubscriptionsUpdatedEvent extends DatabaseEvent {
+public class RemoteSubscriptionsUpdatedEvent extends Event {
 
 	private final ContactId contactId;
 
diff --git a/briar-api/src/net/sf/briar/api/db/event/RemoteTransportsUpdatedEvent.java b/briar-api/src/net/sf/briar/api/event/RemoteTransportsUpdatedEvent.java
similarity index 84%
rename from briar-api/src/net/sf/briar/api/db/event/RemoteTransportsUpdatedEvent.java
rename to briar-api/src/net/sf/briar/api/event/RemoteTransportsUpdatedEvent.java
index b2f66008a9..843686e1f3 100644
--- a/briar-api/src/net/sf/briar/api/db/event/RemoteTransportsUpdatedEvent.java
+++ b/briar-api/src/net/sf/briar/api/event/RemoteTransportsUpdatedEvent.java
@@ -1,4 +1,4 @@
-package net.sf.briar.api.db.event;
+package net.sf.briar.api.event;
 
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.TransportId;
@@ -7,7 +7,7 @@ import net.sf.briar.api.TransportId;
  * An event that is broadcast when a contact's remote transport properties
  * are updated.
  */
-public class RemoteTransportsUpdatedEvent extends DatabaseEvent {
+public class RemoteTransportsUpdatedEvent extends Event {
 
 	private final ContactId contactId;
 	private final TransportId transportId;
diff --git a/briar-api/src/net/sf/briar/api/db/event/SubscriptionAddedEvent.java b/briar-api/src/net/sf/briar/api/event/SubscriptionAddedEvent.java
similarity index 73%
rename from briar-api/src/net/sf/briar/api/db/event/SubscriptionAddedEvent.java
rename to briar-api/src/net/sf/briar/api/event/SubscriptionAddedEvent.java
index 1955d8f9df..0ca97fdf71 100644
--- a/briar-api/src/net/sf/briar/api/db/event/SubscriptionAddedEvent.java
+++ b/briar-api/src/net/sf/briar/api/event/SubscriptionAddedEvent.java
@@ -1,9 +1,9 @@
-package net.sf.briar.api.db.event;
+package net.sf.briar.api.event;
 
 import net.sf.briar.api.messaging.Group;
 
 /** An event that is broadcast when the user subscribes to a group. */
-public class SubscriptionAddedEvent extends DatabaseEvent {
+public class SubscriptionAddedEvent extends Event {
 
 	private final Group group;
 
diff --git a/briar-api/src/net/sf/briar/api/db/event/SubscriptionRemovedEvent.java b/briar-api/src/net/sf/briar/api/event/SubscriptionRemovedEvent.java
similarity index 73%
rename from briar-api/src/net/sf/briar/api/db/event/SubscriptionRemovedEvent.java
rename to briar-api/src/net/sf/briar/api/event/SubscriptionRemovedEvent.java
index 2957304efc..a1afb7b3d7 100644
--- a/briar-api/src/net/sf/briar/api/db/event/SubscriptionRemovedEvent.java
+++ b/briar-api/src/net/sf/briar/api/event/SubscriptionRemovedEvent.java
@@ -1,9 +1,9 @@
-package net.sf.briar.api.db.event;
+package net.sf.briar.api.event;
 
 import net.sf.briar.api.messaging.Group;
 
 /** An event that is broadcast when the user unsubscribes from a group. */
-public class SubscriptionRemovedEvent extends DatabaseEvent {
+public class SubscriptionRemovedEvent extends Event {
 
 	private final Group group;
 
diff --git a/briar-api/src/net/sf/briar/api/db/event/TransportAddedEvent.java b/briar-api/src/net/sf/briar/api/event/TransportAddedEvent.java
similarity index 69%
rename from briar-api/src/net/sf/briar/api/db/event/TransportAddedEvent.java
rename to briar-api/src/net/sf/briar/api/event/TransportAddedEvent.java
index f1e7dc62c9..bd4d18d41f 100644
--- a/briar-api/src/net/sf/briar/api/db/event/TransportAddedEvent.java
+++ b/briar-api/src/net/sf/briar/api/event/TransportAddedEvent.java
@@ -1,9 +1,9 @@
-package net.sf.briar.api.db.event;
+package net.sf.briar.api.event;
 
 import net.sf.briar.api.TransportId;
 
-/** An event that is broadcast when a transport is added to the database. */
-public class TransportAddedEvent extends DatabaseEvent {
+/** An event that is broadcast when a transport is added. */
+public class TransportAddedEvent extends Event {
 
 	private final TransportId transportId;
 	private final long maxLatency;
diff --git a/briar-api/src/net/sf/briar/api/db/event/TransportRemovedEvent.java b/briar-api/src/net/sf/briar/api/event/TransportRemovedEvent.java
similarity index 76%
rename from briar-api/src/net/sf/briar/api/db/event/TransportRemovedEvent.java
rename to briar-api/src/net/sf/briar/api/event/TransportRemovedEvent.java
index b5e4ee0f0e..4b16b8ccfa 100644
--- a/briar-api/src/net/sf/briar/api/db/event/TransportRemovedEvent.java
+++ b/briar-api/src/net/sf/briar/api/event/TransportRemovedEvent.java
@@ -1,9 +1,9 @@
-package net.sf.briar.api.db.event;
+package net.sf.briar.api.event;
 
 import net.sf.briar.api.TransportId;
 
 /** An event that is broadcast when a transport is removed. */
-public class TransportRemovedEvent extends DatabaseEvent {
+public class TransportRemovedEvent extends Event {
 
 	private final TransportId transportId;
 
diff --git a/briar-api/src/net/sf/briar/api/clock/Clock.java b/briar-api/src/net/sf/briar/api/system/Clock.java
similarity index 90%
rename from briar-api/src/net/sf/briar/api/clock/Clock.java
rename to briar-api/src/net/sf/briar/api/system/Clock.java
index f78c60dc47..805d017c66 100644
--- a/briar-api/src/net/sf/briar/api/clock/Clock.java
+++ b/briar-api/src/net/sf/briar/api/system/Clock.java
@@ -1,4 +1,4 @@
-package net.sf.briar.api.clock;
+package net.sf.briar.api.system;
 
 /**
  * An interface for time-related system functions that allows them to be
diff --git a/briar-api/src/net/sf/briar/api/os/FileUtils.java b/briar-api/src/net/sf/briar/api/system/FileUtils.java
similarity index 79%
rename from briar-api/src/net/sf/briar/api/os/FileUtils.java
rename to briar-api/src/net/sf/briar/api/system/FileUtils.java
index d52d4ca6eb..63bd408eeb 100644
--- a/briar-api/src/net/sf/briar/api/os/FileUtils.java
+++ b/briar-api/src/net/sf/briar/api/system/FileUtils.java
@@ -1,4 +1,4 @@
-package net.sf.briar.api.os;
+package net.sf.briar.api.system;
 
 import java.io.File;
 import java.io.IOException;
diff --git a/briar-api/src/net/sf/briar/api/clock/SystemClock.java b/briar-api/src/net/sf/briar/api/system/SystemClock.java
similarity index 88%
rename from briar-api/src/net/sf/briar/api/clock/SystemClock.java
rename to briar-api/src/net/sf/briar/api/system/SystemClock.java
index d6fb2cdb07..94100b342a 100644
--- a/briar-api/src/net/sf/briar/api/clock/SystemClock.java
+++ b/briar-api/src/net/sf/briar/api/system/SystemClock.java
@@ -1,4 +1,4 @@
-package net.sf.briar.api.clock;
+package net.sf.briar.api.system;
 
 /** Default clock implementation. */
 public class SystemClock implements Clock {
diff --git a/briar-api/src/net/sf/briar/api/clock/SystemTimer.java b/briar-api/src/net/sf/briar/api/system/SystemTimer.java
similarity index 94%
rename from briar-api/src/net/sf/briar/api/clock/SystemTimer.java
rename to briar-api/src/net/sf/briar/api/system/SystemTimer.java
index b220e3026b..6a068698d0 100644
--- a/briar-api/src/net/sf/briar/api/clock/SystemTimer.java
+++ b/briar-api/src/net/sf/briar/api/system/SystemTimer.java
@@ -1,4 +1,4 @@
-package net.sf.briar.api.clock;
+package net.sf.briar.api.system;
 
 import java.util.TimerTask;
 
diff --git a/briar-api/src/net/sf/briar/api/clock/Timer.java b/briar-api/src/net/sf/briar/api/system/Timer.java
similarity index 95%
rename from briar-api/src/net/sf/briar/api/clock/Timer.java
rename to briar-api/src/net/sf/briar/api/system/Timer.java
index 9e5cae3213..d5ad5620b7 100644
--- a/briar-api/src/net/sf/briar/api/clock/Timer.java
+++ b/briar-api/src/net/sf/briar/api/system/Timer.java
@@ -1,4 +1,4 @@
-package net.sf.briar.api.clock;
+package net.sf.briar.api.system;
 
 import java.util.TimerTask;
 
diff --git a/briar-core/src/net/sf/briar/db/DatabaseCleanerImpl.java b/briar-core/src/net/sf/briar/db/DatabaseCleanerImpl.java
index 10a1a554bd..573adc6144 100644
--- a/briar-core/src/net/sf/briar/db/DatabaseCleanerImpl.java
+++ b/briar-core/src/net/sf/briar/db/DatabaseCleanerImpl.java
@@ -8,9 +8,9 @@ import java.util.logging.Logger;
 
 import javax.inject.Inject;
 
-import net.sf.briar.api.clock.Timer;
 import net.sf.briar.api.db.DbClosedException;
 import net.sf.briar.api.db.DbException;
+import net.sf.briar.api.system.Timer;
 
 class DatabaseCleanerImpl extends TimerTask implements DatabaseCleaner {
 
diff --git a/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java b/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java
index 79f39e86c9..b5c5c623b1 100644
--- a/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java
+++ b/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java
@@ -30,7 +30,6 @@ import net.sf.briar.api.LocalAuthor;
 import net.sf.briar.api.TransportConfig;
 import net.sf.briar.api.TransportId;
 import net.sf.briar.api.TransportProperties;
-import net.sf.briar.api.clock.Clock;
 import net.sf.briar.api.db.ContactExistsException;
 import net.sf.briar.api.db.DatabaseComponent;
 import net.sf.briar.api.db.DbException;
@@ -41,26 +40,26 @@ import net.sf.briar.api.db.NoSuchLocalAuthorException;
 import net.sf.briar.api.db.NoSuchMessageException;
 import net.sf.briar.api.db.NoSuchSubscriptionException;
 import net.sf.briar.api.db.NoSuchTransportException;
-import net.sf.briar.api.db.event.ContactAddedEvent;
-import net.sf.briar.api.db.event.ContactRemovedEvent;
-import net.sf.briar.api.db.event.DatabaseEvent;
-import net.sf.briar.api.db.event.DatabaseListener;
-import net.sf.briar.api.db.event.LocalAuthorAddedEvent;
-import net.sf.briar.api.db.event.LocalAuthorRemovedEvent;
-import net.sf.briar.api.db.event.LocalSubscriptionsUpdatedEvent;
-import net.sf.briar.api.db.event.LocalTransportsUpdatedEvent;
-import net.sf.briar.api.db.event.MessageAddedEvent;
-import net.sf.briar.api.db.event.MessageExpiredEvent;
-import net.sf.briar.api.db.event.MessageRequestedEvent;
-import net.sf.briar.api.db.event.MessageToAckEvent;
-import net.sf.briar.api.db.event.MessageToRequestEvent;
-import net.sf.briar.api.db.event.RemoteRetentionTimeUpdatedEvent;
-import net.sf.briar.api.db.event.RemoteSubscriptionsUpdatedEvent;
-import net.sf.briar.api.db.event.RemoteTransportsUpdatedEvent;
-import net.sf.briar.api.db.event.SubscriptionAddedEvent;
-import net.sf.briar.api.db.event.SubscriptionRemovedEvent;
-import net.sf.briar.api.db.event.TransportAddedEvent;
-import net.sf.briar.api.db.event.TransportRemovedEvent;
+import net.sf.briar.api.event.ContactAddedEvent;
+import net.sf.briar.api.event.ContactRemovedEvent;
+import net.sf.briar.api.event.Event;
+import net.sf.briar.api.event.EventListener;
+import net.sf.briar.api.event.LocalAuthorAddedEvent;
+import net.sf.briar.api.event.LocalAuthorRemovedEvent;
+import net.sf.briar.api.event.LocalSubscriptionsUpdatedEvent;
+import net.sf.briar.api.event.LocalTransportsUpdatedEvent;
+import net.sf.briar.api.event.MessageAddedEvent;
+import net.sf.briar.api.event.MessageExpiredEvent;
+import net.sf.briar.api.event.MessageRequestedEvent;
+import net.sf.briar.api.event.MessageToAckEvent;
+import net.sf.briar.api.event.MessageToRequestEvent;
+import net.sf.briar.api.event.RemoteRetentionTimeUpdatedEvent;
+import net.sf.briar.api.event.RemoteSubscriptionsUpdatedEvent;
+import net.sf.briar.api.event.RemoteTransportsUpdatedEvent;
+import net.sf.briar.api.event.SubscriptionAddedEvent;
+import net.sf.briar.api.event.SubscriptionRemovedEvent;
+import net.sf.briar.api.event.TransportAddedEvent;
+import net.sf.briar.api.event.TransportRemovedEvent;
 import net.sf.briar.api.lifecycle.ShutdownManager;
 import net.sf.briar.api.messaging.Ack;
 import net.sf.briar.api.messaging.Group;
@@ -76,6 +75,7 @@ import net.sf.briar.api.messaging.SubscriptionAck;
 import net.sf.briar.api.messaging.SubscriptionUpdate;
 import net.sf.briar.api.messaging.TransportAck;
 import net.sf.briar.api.messaging.TransportUpdate;
+import net.sf.briar.api.system.Clock;
 import net.sf.briar.api.transport.Endpoint;
 import net.sf.briar.api.transport.TemporarySecret;
 
@@ -117,8 +117,8 @@ DatabaseCleaner.Callback {
 	private final ShutdownManager shutdown;
 	private final Clock clock;
 
-	private final Collection<DatabaseListener> listeners =
-			new CopyOnWriteArrayList<DatabaseListener>();
+	private final Collection<EventListener> listeners =
+			new CopyOnWriteArrayList<EventListener>();
 
 	private final Object spaceLock = new Object();
 	private long bytesStoredSinceLastCheck = 0; // Locking: spaceLock
@@ -174,11 +174,11 @@ DatabaseCleaner.Callback {
 		}
 	}
 
-	public void addListener(DatabaseListener d) {
+	public void addListener(EventListener d) {
 		listeners.add(d);
 	}
 
-	public void removeListener(DatabaseListener d) {
+	public void removeListener(EventListener d) {
 		listeners.remove(d);
 	}
 
@@ -237,8 +237,8 @@ DatabaseCleaner.Callback {
 	}
 
 	/** Notifies all listeners of a database event. */
-	private void callListeners(DatabaseEvent e) {
-		for(DatabaseListener d : listeners) d.eventOccurred(e);
+	private void callListeners(Event e) {
+		for(EventListener d : listeners) d.eventOccurred(e);
 	}
 
 	public void addEndpoint(Endpoint ep) throws DbException {
diff --git a/briar-core/src/net/sf/briar/db/DatabaseModule.java b/briar-core/src/net/sf/briar/db/DatabaseModule.java
index 165f986e8f..921845cf54 100644
--- a/briar-core/src/net/sf/briar/db/DatabaseModule.java
+++ b/briar-core/src/net/sf/briar/db/DatabaseModule.java
@@ -12,14 +12,14 @@ import java.util.concurrent.ThreadPoolExecutor;
 
 import javax.inject.Singleton;
 
-import net.sf.briar.api.clock.Clock;
-import net.sf.briar.api.clock.SystemClock;
 import net.sf.briar.api.db.DatabaseComponent;
 import net.sf.briar.api.db.DatabaseConfig;
 import net.sf.briar.api.db.DatabaseExecutor;
 import net.sf.briar.api.lifecycle.LifecycleManager;
 import net.sf.briar.api.lifecycle.ShutdownManager;
-import net.sf.briar.api.os.FileUtils;
+import net.sf.briar.api.system.Clock;
+import net.sf.briar.api.system.FileUtils;
+import net.sf.briar.api.system.SystemClock;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.Provides;
diff --git a/briar-core/src/net/sf/briar/db/H2Database.java b/briar-core/src/net/sf/briar/db/H2Database.java
index 2255e8e74e..0f6b67f973 100644
--- a/briar-core/src/net/sf/briar/db/H2Database.java
+++ b/briar-core/src/net/sf/briar/db/H2Database.java
@@ -10,10 +10,10 @@ import java.util.Properties;
 
 import javax.inject.Inject;
 
-import net.sf.briar.api.clock.Clock;
 import net.sf.briar.api.db.DatabaseConfig;
 import net.sf.briar.api.db.DbException;
-import net.sf.briar.api.os.FileUtils;
+import net.sf.briar.api.system.Clock;
+import net.sf.briar.api.system.FileUtils;
 import net.sf.briar.util.StringUtils;
 
 /** Contains all the H2-specific code for the database. */
diff --git a/briar-core/src/net/sf/briar/db/JdbcDatabase.java b/briar-core/src/net/sf/briar/db/JdbcDatabase.java
index a896416c98..5e7e008eec 100644
--- a/briar-core/src/net/sf/briar/db/JdbcDatabase.java
+++ b/briar-core/src/net/sf/briar/db/JdbcDatabase.java
@@ -32,7 +32,6 @@ import net.sf.briar.api.LocalAuthor;
 import net.sf.briar.api.TransportConfig;
 import net.sf.briar.api.TransportId;
 import net.sf.briar.api.TransportProperties;
-import net.sf.briar.api.clock.Clock;
 import net.sf.briar.api.db.DbClosedException;
 import net.sf.briar.api.db.DbException;
 import net.sf.briar.api.db.MessageHeader;
@@ -47,6 +46,7 @@ import net.sf.briar.api.messaging.SubscriptionAck;
 import net.sf.briar.api.messaging.SubscriptionUpdate;
 import net.sf.briar.api.messaging.TransportAck;
 import net.sf.briar.api.messaging.TransportUpdate;
+import net.sf.briar.api.system.Clock;
 import net.sf.briar.api.transport.Endpoint;
 import net.sf.briar.api.transport.TemporarySecret;
 
diff --git a/briar-core/src/net/sf/briar/invitation/AliceConnector.java b/briar-core/src/net/sf/briar/invitation/AliceConnector.java
index 3fe1c54917..d33787b88b 100644
--- a/briar-core/src/net/sf/briar/invitation/AliceConnector.java
+++ b/briar-core/src/net/sf/briar/invitation/AliceConnector.java
@@ -15,7 +15,6 @@ import net.sf.briar.api.AuthorFactory;
 import net.sf.briar.api.LocalAuthor;
 import net.sf.briar.api.TransportId;
 import net.sf.briar.api.TransportProperties;
-import net.sf.briar.api.clock.Clock;
 import net.sf.briar.api.crypto.CryptoComponent;
 import net.sf.briar.api.crypto.KeyManager;
 import net.sf.briar.api.crypto.PseudoRandom;
@@ -28,6 +27,7 @@ import net.sf.briar.api.serial.Reader;
 import net.sf.briar.api.serial.ReaderFactory;
 import net.sf.briar.api.serial.Writer;
 import net.sf.briar.api.serial.WriterFactory;
+import net.sf.briar.api.system.Clock;
 import net.sf.briar.api.transport.ConnectionDispatcher;
 import net.sf.briar.api.transport.ConnectionReader;
 import net.sf.briar.api.transport.ConnectionReaderFactory;
diff --git a/briar-core/src/net/sf/briar/invitation/BobConnector.java b/briar-core/src/net/sf/briar/invitation/BobConnector.java
index 4d05f92f7c..ebd8fbfddd 100644
--- a/briar-core/src/net/sf/briar/invitation/BobConnector.java
+++ b/briar-core/src/net/sf/briar/invitation/BobConnector.java
@@ -15,7 +15,6 @@ import net.sf.briar.api.AuthorFactory;
 import net.sf.briar.api.LocalAuthor;
 import net.sf.briar.api.TransportId;
 import net.sf.briar.api.TransportProperties;
-import net.sf.briar.api.clock.Clock;
 import net.sf.briar.api.crypto.CryptoComponent;
 import net.sf.briar.api.crypto.KeyManager;
 import net.sf.briar.api.crypto.PseudoRandom;
@@ -28,6 +27,7 @@ import net.sf.briar.api.serial.Reader;
 import net.sf.briar.api.serial.ReaderFactory;
 import net.sf.briar.api.serial.Writer;
 import net.sf.briar.api.serial.WriterFactory;
+import net.sf.briar.api.system.Clock;
 import net.sf.briar.api.transport.ConnectionDispatcher;
 import net.sf.briar.api.transport.ConnectionReader;
 import net.sf.briar.api.transport.ConnectionReaderFactory;
diff --git a/briar-core/src/net/sf/briar/invitation/Connector.java b/briar-core/src/net/sf/briar/invitation/Connector.java
index a1c7fe27fd..a2486ba146 100644
--- a/briar-core/src/net/sf/briar/invitation/Connector.java
+++ b/briar-core/src/net/sf/briar/invitation/Connector.java
@@ -30,7 +30,6 @@ import net.sf.briar.api.LocalAuthor;
 import net.sf.briar.api.TransportId;
 import net.sf.briar.api.TransportProperties;
 import net.sf.briar.api.UniqueId;
-import net.sf.briar.api.clock.Clock;
 import net.sf.briar.api.crypto.CryptoComponent;
 import net.sf.briar.api.crypto.KeyManager;
 import net.sf.briar.api.crypto.KeyPair;
@@ -50,6 +49,7 @@ import net.sf.briar.api.serial.Reader;
 import net.sf.briar.api.serial.ReaderFactory;
 import net.sf.briar.api.serial.Writer;
 import net.sf.briar.api.serial.WriterFactory;
+import net.sf.briar.api.system.Clock;
 import net.sf.briar.api.transport.ConnectionDispatcher;
 import net.sf.briar.api.transport.ConnectionReaderFactory;
 import net.sf.briar.api.transport.ConnectionWriterFactory;
diff --git a/briar-core/src/net/sf/briar/invitation/ConnectorGroup.java b/briar-core/src/net/sf/briar/invitation/ConnectorGroup.java
index c196597524..0dc6a39bc4 100644
--- a/briar-core/src/net/sf/briar/invitation/ConnectorGroup.java
+++ b/briar-core/src/net/sf/briar/invitation/ConnectorGroup.java
@@ -18,7 +18,6 @@ import net.sf.briar.api.AuthorId;
 import net.sf.briar.api.LocalAuthor;
 import net.sf.briar.api.TransportId;
 import net.sf.briar.api.TransportProperties;
-import net.sf.briar.api.clock.Clock;
 import net.sf.briar.api.crypto.CryptoComponent;
 import net.sf.briar.api.crypto.KeyManager;
 import net.sf.briar.api.crypto.PseudoRandom;
@@ -32,6 +31,7 @@ import net.sf.briar.api.plugins.PluginManager;
 import net.sf.briar.api.plugins.duplex.DuplexPlugin;
 import net.sf.briar.api.serial.ReaderFactory;
 import net.sf.briar.api.serial.WriterFactory;
+import net.sf.briar.api.system.Clock;
 import net.sf.briar.api.transport.ConnectionDispatcher;
 import net.sf.briar.api.transport.ConnectionReaderFactory;
 import net.sf.briar.api.transport.ConnectionWriterFactory;
diff --git a/briar-core/src/net/sf/briar/invitation/InvitationTaskFactoryImpl.java b/briar-core/src/net/sf/briar/invitation/InvitationTaskFactoryImpl.java
index b798adc75e..8adad86d8d 100644
--- a/briar-core/src/net/sf/briar/invitation/InvitationTaskFactoryImpl.java
+++ b/briar-core/src/net/sf/briar/invitation/InvitationTaskFactoryImpl.java
@@ -4,7 +4,6 @@ import javax.inject.Inject;
 
 import net.sf.briar.api.AuthorFactory;
 import net.sf.briar.api.AuthorId;
-import net.sf.briar.api.clock.Clock;
 import net.sf.briar.api.crypto.CryptoComponent;
 import net.sf.briar.api.crypto.KeyManager;
 import net.sf.briar.api.db.DatabaseComponent;
@@ -14,6 +13,7 @@ import net.sf.briar.api.messaging.GroupFactory;
 import net.sf.briar.api.plugins.PluginManager;
 import net.sf.briar.api.serial.ReaderFactory;
 import net.sf.briar.api.serial.WriterFactory;
+import net.sf.briar.api.system.Clock;
 import net.sf.briar.api.transport.ConnectionDispatcher;
 import net.sf.briar.api.transport.ConnectionReaderFactory;
 import net.sf.briar.api.transport.ConnectionWriterFactory;
diff --git a/briar-core/src/net/sf/briar/messaging/MessageVerifierImpl.java b/briar-core/src/net/sf/briar/messaging/MessageVerifierImpl.java
index cf9f755fdb..e68995aa7e 100644
--- a/briar-core/src/net/sf/briar/messaging/MessageVerifierImpl.java
+++ b/briar-core/src/net/sf/briar/messaging/MessageVerifierImpl.java
@@ -7,7 +7,6 @@ import java.security.GeneralSecurityException;
 import javax.inject.Inject;
 
 import net.sf.briar.api.Author;
-import net.sf.briar.api.clock.Clock;
 import net.sf.briar.api.crypto.CryptoComponent;
 import net.sf.briar.api.crypto.KeyParser;
 import net.sf.briar.api.crypto.MessageDigest;
@@ -17,6 +16,7 @@ import net.sf.briar.api.messaging.Message;
 import net.sf.briar.api.messaging.MessageId;
 import net.sf.briar.api.messaging.MessageVerifier;
 import net.sf.briar.api.messaging.UnverifiedMessage;
+import net.sf.briar.api.system.Clock;
 
 class MessageVerifierImpl implements MessageVerifier {
 
diff --git a/briar-core/src/net/sf/briar/messaging/duplex/DuplexConnection.java b/briar-core/src/net/sf/briar/messaging/duplex/DuplexConnection.java
index be616e9652..2b20048fca 100644
--- a/briar-core/src/net/sf/briar/messaging/duplex/DuplexConnection.java
+++ b/briar-core/src/net/sf/briar/messaging/duplex/DuplexConnection.java
@@ -20,19 +20,19 @@ import net.sf.briar.api.FormatException;
 import net.sf.briar.api.TransportId;
 import net.sf.briar.api.db.DatabaseComponent;
 import net.sf.briar.api.db.DbException;
-import net.sf.briar.api.db.event.ContactRemovedEvent;
-import net.sf.briar.api.db.event.DatabaseEvent;
-import net.sf.briar.api.db.event.DatabaseListener;
-import net.sf.briar.api.db.event.LocalSubscriptionsUpdatedEvent;
-import net.sf.briar.api.db.event.LocalTransportsUpdatedEvent;
-import net.sf.briar.api.db.event.MessageAddedEvent;
-import net.sf.briar.api.db.event.MessageExpiredEvent;
-import net.sf.briar.api.db.event.MessageRequestedEvent;
-import net.sf.briar.api.db.event.MessageToAckEvent;
-import net.sf.briar.api.db.event.MessageToRequestEvent;
-import net.sf.briar.api.db.event.RemoteRetentionTimeUpdatedEvent;
-import net.sf.briar.api.db.event.RemoteSubscriptionsUpdatedEvent;
-import net.sf.briar.api.db.event.RemoteTransportsUpdatedEvent;
+import net.sf.briar.api.event.ContactRemovedEvent;
+import net.sf.briar.api.event.Event;
+import net.sf.briar.api.event.EventListener;
+import net.sf.briar.api.event.LocalSubscriptionsUpdatedEvent;
+import net.sf.briar.api.event.LocalTransportsUpdatedEvent;
+import net.sf.briar.api.event.MessageAddedEvent;
+import net.sf.briar.api.event.MessageExpiredEvent;
+import net.sf.briar.api.event.MessageRequestedEvent;
+import net.sf.briar.api.event.MessageToAckEvent;
+import net.sf.briar.api.event.MessageToRequestEvent;
+import net.sf.briar.api.event.RemoteRetentionTimeUpdatedEvent;
+import net.sf.briar.api.event.RemoteSubscriptionsUpdatedEvent;
+import net.sf.briar.api.event.RemoteTransportsUpdatedEvent;
 import net.sf.briar.api.messaging.Ack;
 import net.sf.briar.api.messaging.Message;
 import net.sf.briar.api.messaging.MessageVerifier;
@@ -58,7 +58,7 @@ import net.sf.briar.api.transport.ConnectionWriter;
 import net.sf.briar.api.transport.ConnectionWriterFactory;
 import net.sf.briar.util.ByteUtils;
 
-abstract class DuplexConnection implements DatabaseListener {
+abstract class DuplexConnection implements EventListener {
 
 	private static final Logger LOG =
 			Logger.getLogger(DuplexConnection.class.getName());
@@ -122,7 +122,7 @@ abstract class DuplexConnection implements DatabaseListener {
 	protected abstract ConnectionWriter createConnectionWriter()
 			throws IOException;
 
-	public void eventOccurred(DatabaseEvent e) {
+	public void eventOccurred(Event e) {
 		if(e instanceof ContactRemovedEvent) {
 			ContactRemovedEvent c = (ContactRemovedEvent) e;
 			if(contactId.equals(c.getContactId())) writerTasks.add(CLOSE);
diff --git a/briar-core/src/net/sf/briar/plugins/PollerImpl.java b/briar-core/src/net/sf/briar/plugins/PollerImpl.java
index 8ae80eed4b..1a9bc63338 100644
--- a/briar-core/src/net/sf/briar/plugins/PollerImpl.java
+++ b/briar-core/src/net/sf/briar/plugins/PollerImpl.java
@@ -11,9 +11,9 @@ import java.util.logging.Logger;
 import javax.inject.Inject;
 
 import net.sf.briar.api.ContactId;
-import net.sf.briar.api.clock.Clock;
 import net.sf.briar.api.plugins.Plugin;
 import net.sf.briar.api.plugins.PluginExecutor;
+import net.sf.briar.api.system.Clock;
 import net.sf.briar.api.transport.ConnectionRegistry;
 
 class PollerImpl implements Poller, Runnable {
diff --git a/briar-core/src/net/sf/briar/plugins/file/FilePlugin.java b/briar-core/src/net/sf/briar/plugins/file/FilePlugin.java
index e2c7af5420..f770b78a14 100644
--- a/briar-core/src/net/sf/briar/plugins/file/FilePlugin.java
+++ b/briar-core/src/net/sf/briar/plugins/file/FilePlugin.java
@@ -13,11 +13,11 @@ import java.util.concurrent.Executor;
 import java.util.logging.Logger;
 
 import net.sf.briar.api.ContactId;
-import net.sf.briar.api.os.FileUtils;
 import net.sf.briar.api.plugins.simplex.SimplexPlugin;
 import net.sf.briar.api.plugins.simplex.SimplexPluginCallback;
 import net.sf.briar.api.plugins.simplex.SimplexTransportReader;
 import net.sf.briar.api.plugins.simplex.SimplexTransportWriter;
+import net.sf.briar.api.system.FileUtils;
 
 public abstract class FilePlugin implements SimplexPlugin {
 
diff --git a/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPlugin.java b/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPlugin.java
index a01a5f4344..90f91a122e 100644
--- a/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPlugin.java
+++ b/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPlugin.java
@@ -23,10 +23,10 @@ import java.util.logging.Logger;
 
 import net.sf.briar.api.TransportId;
 import net.sf.briar.api.TransportProperties;
-import net.sf.briar.api.clock.Clock;
 import net.sf.briar.api.crypto.PseudoRandom;
 import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
 import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
+import net.sf.briar.api.system.Clock;
 import net.sf.briar.util.ByteUtils;
 import net.sf.briar.util.LatchedReference;
 import net.sf.briar.util.StringUtils;
diff --git a/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPluginFactory.java b/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPluginFactory.java
index d3339b3b3f..475e4fbf83 100644
--- a/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPluginFactory.java
+++ b/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPluginFactory.java
@@ -3,11 +3,11 @@ package net.sf.briar.plugins.tcp;
 import java.util.concurrent.Executor;
 
 import net.sf.briar.api.TransportId;
-import net.sf.briar.api.clock.Clock;
-import net.sf.briar.api.clock.SystemClock;
 import net.sf.briar.api.plugins.duplex.DuplexPlugin;
 import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
 import net.sf.briar.api.plugins.duplex.DuplexPluginFactory;
+import net.sf.briar.api.system.Clock;
+import net.sf.briar.api.system.SystemClock;
 
 public class LanTcpPluginFactory implements DuplexPluginFactory {
 
diff --git a/briar-core/src/net/sf/briar/reliability/Receiver.java b/briar-core/src/net/sf/briar/reliability/Receiver.java
index 807a0a9f38..7874d49208 100644
--- a/briar-core/src/net/sf/briar/reliability/Receiver.java
+++ b/briar-core/src/net/sf/briar/reliability/Receiver.java
@@ -6,8 +6,8 @@ import java.util.Iterator;
 import java.util.SortedSet;
 import java.util.TreeSet;
 
-import net.sf.briar.api.clock.Clock;
 import net.sf.briar.api.reliability.ReadHandler;
+import net.sf.briar.api.system.Clock;
 
 class Receiver implements ReadHandler {
 
diff --git a/briar-core/src/net/sf/briar/reliability/ReliabilityLayerFactoryImpl.java b/briar-core/src/net/sf/briar/reliability/ReliabilityLayerFactoryImpl.java
index 406436dba8..6554536c51 100644
--- a/briar-core/src/net/sf/briar/reliability/ReliabilityLayerFactoryImpl.java
+++ b/briar-core/src/net/sf/briar/reliability/ReliabilityLayerFactoryImpl.java
@@ -4,12 +4,12 @@ import java.util.concurrent.Executor;
 
 import javax.inject.Inject;
 
-import net.sf.briar.api.clock.Clock;
-import net.sf.briar.api.clock.SystemClock;
 import net.sf.briar.api.reliability.ReliabilityExecutor;
 import net.sf.briar.api.reliability.ReliabilityLayer;
 import net.sf.briar.api.reliability.ReliabilityLayerFactory;
 import net.sf.briar.api.reliability.WriteHandler;
+import net.sf.briar.api.system.Clock;
+import net.sf.briar.api.system.SystemClock;
 
 class ReliabilityLayerFactoryImpl implements ReliabilityLayerFactory {
 
diff --git a/briar-core/src/net/sf/briar/reliability/ReliabilityLayerImpl.java b/briar-core/src/net/sf/briar/reliability/ReliabilityLayerImpl.java
index ed1df1a1a7..518a1c8538 100644
--- a/briar-core/src/net/sf/briar/reliability/ReliabilityLayerImpl.java
+++ b/briar-core/src/net/sf/briar/reliability/ReliabilityLayerImpl.java
@@ -11,9 +11,9 @@ import java.util.concurrent.Executor;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.logging.Logger;
 
-import net.sf.briar.api.clock.Clock;
 import net.sf.briar.api.reliability.ReliabilityLayer;
 import net.sf.briar.api.reliability.WriteHandler;
+import net.sf.briar.api.system.Clock;
 
 class ReliabilityLayerImpl implements ReliabilityLayer, WriteHandler {
 
diff --git a/briar-core/src/net/sf/briar/reliability/Sender.java b/briar-core/src/net/sf/briar/reliability/Sender.java
index 3208ea0fea..7d767f7b16 100644
--- a/briar-core/src/net/sf/briar/reliability/Sender.java
+++ b/briar-core/src/net/sf/briar/reliability/Sender.java
@@ -6,8 +6,8 @@ import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 
-import net.sf.briar.api.clock.Clock;
 import net.sf.briar.api.reliability.WriteHandler;
+import net.sf.briar.api.system.Clock;
 
 class Sender {
 
diff --git a/briar-core/src/net/sf/briar/clock/ClockModule.java b/briar-core/src/net/sf/briar/system/ClockModule.java
similarity index 52%
rename from briar-core/src/net/sf/briar/clock/ClockModule.java
rename to briar-core/src/net/sf/briar/system/ClockModule.java
index f3c1d921b6..663bfe815f 100644
--- a/briar-core/src/net/sf/briar/clock/ClockModule.java
+++ b/briar-core/src/net/sf/briar/system/ClockModule.java
@@ -1,9 +1,9 @@
-package net.sf.briar.clock;
+package net.sf.briar.system;
 
-import net.sf.briar.api.clock.Clock;
-import net.sf.briar.api.clock.SystemClock;
-import net.sf.briar.api.clock.SystemTimer;
-import net.sf.briar.api.clock.Timer;
+import net.sf.briar.api.system.Clock;
+import net.sf.briar.api.system.SystemClock;
+import net.sf.briar.api.system.SystemTimer;
+import net.sf.briar.api.system.Timer;
 
 import com.google.inject.AbstractModule;
 
diff --git a/briar-core/src/net/sf/briar/transport/KeyManagerImpl.java b/briar-core/src/net/sf/briar/transport/KeyManagerImpl.java
index 109df1e9bf..f14f7ca906 100644
--- a/briar-core/src/net/sf/briar/transport/KeyManagerImpl.java
+++ b/briar-core/src/net/sf/briar/transport/KeyManagerImpl.java
@@ -18,17 +18,17 @@ import javax.inject.Inject;
 
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.TransportId;
-import net.sf.briar.api.clock.Clock;
-import net.sf.briar.api.clock.Timer;
 import net.sf.briar.api.crypto.CryptoComponent;
 import net.sf.briar.api.crypto.KeyManager;
 import net.sf.briar.api.db.DatabaseComponent;
 import net.sf.briar.api.db.DbException;
-import net.sf.briar.api.db.event.ContactRemovedEvent;
-import net.sf.briar.api.db.event.DatabaseEvent;
-import net.sf.briar.api.db.event.DatabaseListener;
-import net.sf.briar.api.db.event.TransportAddedEvent;
-import net.sf.briar.api.db.event.TransportRemovedEvent;
+import net.sf.briar.api.event.ContactRemovedEvent;
+import net.sf.briar.api.event.Event;
+import net.sf.briar.api.event.EventListener;
+import net.sf.briar.api.event.TransportAddedEvent;
+import net.sf.briar.api.event.TransportRemovedEvent;
+import net.sf.briar.api.system.Clock;
+import net.sf.briar.api.system.Timer;
 import net.sf.briar.api.transport.ConnectionContext;
 import net.sf.briar.api.transport.ConnectionRecogniser;
 import net.sf.briar.api.transport.Endpoint;
@@ -36,7 +36,7 @@ import net.sf.briar.api.transport.TemporarySecret;
 import net.sf.briar.util.ByteUtils;
 
 // FIXME: Don't make alien calls with a lock held
-class KeyManagerImpl extends TimerTask implements KeyManager, DatabaseListener {
+class KeyManagerImpl extends TimerTask implements KeyManager, EventListener {
 
 	private static final int MS_BETWEEN_CHECKS = 60 * 1000;
 
@@ -324,7 +324,7 @@ class KeyManagerImpl extends TimerTask implements KeyManager, DatabaseListener {
 		}
 	}
 
-	public void eventOccurred(DatabaseEvent e) {
+	public void eventOccurred(Event e) {
 		if(e instanceof ContactRemovedEvent) {
 			ContactRemovedEvent c = (ContactRemovedEvent) e;
 			timer.schedule(new ContactRemovedTask(c), 0);
diff --git a/briar-desktop/src/net/sf/briar/plugins/DesktopPluginsModule.java b/briar-desktop/src/net/sf/briar/plugins/DesktopPluginsModule.java
index 76ad61ea59..cb733c89ad 100644
--- a/briar-desktop/src/net/sf/briar/plugins/DesktopPluginsModule.java
+++ b/briar-desktop/src/net/sf/briar/plugins/DesktopPluginsModule.java
@@ -6,13 +6,13 @@ import java.util.concurrent.Executor;
 
 import net.sf.briar.api.crypto.CryptoComponent;
 import net.sf.briar.api.lifecycle.ShutdownManager;
-import net.sf.briar.api.os.FileUtils;
 import net.sf.briar.api.plugins.PluginExecutor;
 import net.sf.briar.api.plugins.duplex.DuplexPluginConfig;
 import net.sf.briar.api.plugins.duplex.DuplexPluginFactory;
 import net.sf.briar.api.plugins.simplex.SimplexPluginConfig;
 import net.sf.briar.api.plugins.simplex.SimplexPluginFactory;
 import net.sf.briar.api.reliability.ReliabilityLayerFactory;
+import net.sf.briar.api.system.FileUtils;
 import net.sf.briar.plugins.bluetooth.BluetoothPluginFactory;
 import net.sf.briar.plugins.file.RemovableDrivePluginFactory;
 import net.sf.briar.plugins.modem.ModemPluginFactory;
diff --git a/briar-desktop/src/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java b/briar-desktop/src/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java
index f522fea0b2..1b61f1d5b6 100644
--- a/briar-desktop/src/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java
+++ b/briar-desktop/src/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java
@@ -24,11 +24,11 @@ import javax.microedition.io.StreamConnectionNotifier;
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.TransportId;
 import net.sf.briar.api.TransportProperties;
-import net.sf.briar.api.clock.Clock;
 import net.sf.briar.api.crypto.PseudoRandom;
 import net.sf.briar.api.plugins.duplex.DuplexPlugin;
 import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
 import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
+import net.sf.briar.api.system.Clock;
 import net.sf.briar.util.LatchedReference;
 import net.sf.briar.util.OsUtils;
 import net.sf.briar.util.StringUtils;
diff --git a/briar-desktop/src/net/sf/briar/plugins/bluetooth/BluetoothPluginFactory.java b/briar-desktop/src/net/sf/briar/plugins/bluetooth/BluetoothPluginFactory.java
index 88ede376ef..75dbcbdc37 100644
--- a/briar-desktop/src/net/sf/briar/plugins/bluetooth/BluetoothPluginFactory.java
+++ b/briar-desktop/src/net/sf/briar/plugins/bluetooth/BluetoothPluginFactory.java
@@ -4,11 +4,11 @@ import java.security.SecureRandom;
 import java.util.concurrent.Executor;
 
 import net.sf.briar.api.TransportId;
-import net.sf.briar.api.clock.Clock;
-import net.sf.briar.api.clock.SystemClock;
 import net.sf.briar.api.plugins.duplex.DuplexPlugin;
 import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
 import net.sf.briar.api.plugins.duplex.DuplexPluginFactory;
+import net.sf.briar.api.system.Clock;
+import net.sf.briar.api.system.SystemClock;
 
 public class BluetoothPluginFactory implements DuplexPluginFactory {
 
diff --git a/briar-desktop/src/net/sf/briar/plugins/file/RemovableDrivePlugin.java b/briar-desktop/src/net/sf/briar/plugins/file/RemovableDrivePlugin.java
index 05c981c6d8..cdb8862b15 100644
--- a/briar-desktop/src/net/sf/briar/plugins/file/RemovableDrivePlugin.java
+++ b/briar-desktop/src/net/sf/briar/plugins/file/RemovableDrivePlugin.java
@@ -13,8 +13,8 @@ import java.util.logging.Logger;
 
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.TransportId;
-import net.sf.briar.api.os.FileUtils;
 import net.sf.briar.api.plugins.simplex.SimplexPluginCallback;
+import net.sf.briar.api.system.FileUtils;
 import net.sf.briar.util.StringUtils;
 
 class RemovableDrivePlugin extends FilePlugin
diff --git a/briar-desktop/src/net/sf/briar/plugins/file/RemovableDrivePluginFactory.java b/briar-desktop/src/net/sf/briar/plugins/file/RemovableDrivePluginFactory.java
index 6af65eda85..fb1ae045ee 100644
--- a/briar-desktop/src/net/sf/briar/plugins/file/RemovableDrivePluginFactory.java
+++ b/briar-desktop/src/net/sf/briar/plugins/file/RemovableDrivePluginFactory.java
@@ -5,10 +5,10 @@ import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
 import java.util.concurrent.Executor;
 
 import net.sf.briar.api.TransportId;
-import net.sf.briar.api.os.FileUtils;
 import net.sf.briar.api.plugins.simplex.SimplexPlugin;
 import net.sf.briar.api.plugins.simplex.SimplexPluginCallback;
 import net.sf.briar.api.plugins.simplex.SimplexPluginFactory;
+import net.sf.briar.api.system.FileUtils;
 import net.sf.briar.util.OsUtils;
 
 public class RemovableDrivePluginFactory implements SimplexPluginFactory {
diff --git a/briar-desktop/src/net/sf/briar/plugins/modem/ModemFactoryImpl.java b/briar-desktop/src/net/sf/briar/plugins/modem/ModemFactoryImpl.java
index c6129d6a1f..858590a337 100644
--- a/briar-desktop/src/net/sf/briar/plugins/modem/ModemFactoryImpl.java
+++ b/briar-desktop/src/net/sf/briar/plugins/modem/ModemFactoryImpl.java
@@ -2,9 +2,9 @@ package net.sf.briar.plugins.modem;
 
 import java.util.concurrent.Executor;
 
-import net.sf.briar.api.clock.Clock;
-import net.sf.briar.api.clock.SystemClock;
 import net.sf.briar.api.reliability.ReliabilityLayerFactory;
+import net.sf.briar.api.system.Clock;
+import net.sf.briar.api.system.SystemClock;
 
 class ModemFactoryImpl implements ModemFactory {
 
diff --git a/briar-desktop/src/net/sf/briar/plugins/modem/ModemImpl.java b/briar-desktop/src/net/sf/briar/plugins/modem/ModemImpl.java
index 387051051c..d7922d1c09 100644
--- a/briar-desktop/src/net/sf/briar/plugins/modem/ModemImpl.java
+++ b/briar-desktop/src/net/sf/briar/plugins/modem/ModemImpl.java
@@ -14,10 +14,10 @@ import java.util.logging.Logger;
 
 import jssc.SerialPortEvent;
 import jssc.SerialPortEventListener;
-import net.sf.briar.api.clock.Clock;
 import net.sf.briar.api.reliability.ReliabilityLayer;
 import net.sf.briar.api.reliability.ReliabilityLayerFactory;
 import net.sf.briar.api.reliability.WriteHandler;
+import net.sf.briar.api.system.Clock;
 
 class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
 
diff --git a/briar-desktop/src/net/sf/briar/os/DesktopOsModule.java b/briar-desktop/src/net/sf/briar/system/DesktopOsModule.java
similarity index 73%
rename from briar-desktop/src/net/sf/briar/os/DesktopOsModule.java
rename to briar-desktop/src/net/sf/briar/system/DesktopOsModule.java
index b0a8a087b4..fb1e5cf3a2 100644
--- a/briar-desktop/src/net/sf/briar/os/DesktopOsModule.java
+++ b/briar-desktop/src/net/sf/briar/system/DesktopOsModule.java
@@ -1,6 +1,6 @@
-package net.sf.briar.os;
+package net.sf.briar.system;
 
-import net.sf.briar.api.os.FileUtils;
+import net.sf.briar.api.system.FileUtils;
 
 import com.google.inject.AbstractModule;
 
diff --git a/briar-desktop/src/net/sf/briar/os/FileUtilsImpl.java b/briar-desktop/src/net/sf/briar/system/FileUtilsImpl.java
similarity index 72%
rename from briar-desktop/src/net/sf/briar/os/FileUtilsImpl.java
rename to briar-desktop/src/net/sf/briar/system/FileUtilsImpl.java
index a86824272f..0773bdbbf1 100644
--- a/briar-desktop/src/net/sf/briar/os/FileUtilsImpl.java
+++ b/briar-desktop/src/net/sf/briar/system/FileUtilsImpl.java
@@ -1,9 +1,9 @@
-package net.sf.briar.os;
+package net.sf.briar.system;
 
 import java.io.File;
 import java.io.IOException;
 
-import net.sf.briar.api.os.FileUtils;
+import net.sf.briar.api.system.FileUtils;
 
 class FileUtilsImpl implements FileUtils {
 
diff --git a/briar-tests/src/net/sf/briar/ProtocolIntegrationTest.java b/briar-tests/src/net/sf/briar/ProtocolIntegrationTest.java
index 1a4b1c6590..d67802a3cc 100644
--- a/briar-tests/src/net/sf/briar/ProtocolIntegrationTest.java
+++ b/briar-tests/src/net/sf/briar/ProtocolIntegrationTest.java
@@ -41,7 +41,6 @@ import net.sf.briar.api.transport.ConnectionReader;
 import net.sf.briar.api.transport.ConnectionReaderFactory;
 import net.sf.briar.api.transport.ConnectionWriter;
 import net.sf.briar.api.transport.ConnectionWriterFactory;
-import net.sf.briar.clock.ClockModule;
 import net.sf.briar.crypto.CryptoModule;
 import net.sf.briar.db.DatabaseModule;
 import net.sf.briar.messaging.MessagingModule;
@@ -49,6 +48,7 @@ import net.sf.briar.messaging.duplex.DuplexMessagingModule;
 import net.sf.briar.messaging.simplex.SimplexMessagingModule;
 import net.sf.briar.reliability.ReliabilityModule;
 import net.sf.briar.serial.SerialModule;
+import net.sf.briar.system.ClockModule;
 import net.sf.briar.transport.TransportModule;
 
 import org.junit.Test;
diff --git a/briar-tests/src/net/sf/briar/TestDatabaseModule.java b/briar-tests/src/net/sf/briar/TestDatabaseModule.java
index 8ea2390ce7..26ccfb2dda 100644
--- a/briar-tests/src/net/sf/briar/TestDatabaseModule.java
+++ b/briar-tests/src/net/sf/briar/TestDatabaseModule.java
@@ -3,7 +3,7 @@ package net.sf.briar;
 import java.io.File;
 
 import net.sf.briar.api.db.DatabaseConfig;
-import net.sf.briar.api.os.FileUtils;
+import net.sf.briar.api.system.FileUtils;
 
 import com.google.inject.AbstractModule;
 
diff --git a/briar-tests/src/net/sf/briar/TestFileUtils.java b/briar-tests/src/net/sf/briar/TestFileUtils.java
index ca4828f914..470bd1c0ec 100644
--- a/briar-tests/src/net/sf/briar/TestFileUtils.java
+++ b/briar-tests/src/net/sf/briar/TestFileUtils.java
@@ -3,7 +3,7 @@ package net.sf.briar;
 import java.io.File;
 import java.io.IOException;
 
-import net.sf.briar.api.os.FileUtils;
+import net.sf.briar.api.system.FileUtils;
 
 public class TestFileUtils implements FileUtils {
 
diff --git a/briar-tests/src/net/sf/briar/db/DatabaseCleanerImplTest.java b/briar-tests/src/net/sf/briar/db/DatabaseCleanerImplTest.java
index a2c761e016..ea1797f464 100644
--- a/briar-tests/src/net/sf/briar/db/DatabaseCleanerImplTest.java
+++ b/briar-tests/src/net/sf/briar/db/DatabaseCleanerImplTest.java
@@ -5,9 +5,9 @@ import static java.util.concurrent.TimeUnit.SECONDS;
 import java.util.concurrent.CountDownLatch;
 
 import net.sf.briar.BriarTestCase;
-import net.sf.briar.api.clock.SystemTimer;
-import net.sf.briar.api.clock.Timer;
 import net.sf.briar.api.db.DbException;
+import net.sf.briar.api.system.SystemTimer;
+import net.sf.briar.api.system.Timer;
 import net.sf.briar.db.DatabaseCleaner.Callback;
 
 import org.junit.Test;
diff --git a/briar-tests/src/net/sf/briar/db/DatabaseComponentImplTest.java b/briar-tests/src/net/sf/briar/db/DatabaseComponentImplTest.java
index d07bb403ba..b8963654f1 100644
--- a/briar-tests/src/net/sf/briar/db/DatabaseComponentImplTest.java
+++ b/briar-tests/src/net/sf/briar/db/DatabaseComponentImplTest.java
@@ -5,10 +5,10 @@ import static net.sf.briar.db.DatabaseConstants.MIN_FREE_SPACE;
 
 import java.util.Collections;
 
-import net.sf.briar.api.clock.SystemClock;
 import net.sf.briar.api.db.DatabaseComponent;
 import net.sf.briar.api.db.DbException;
 import net.sf.briar.api.lifecycle.ShutdownManager;
+import net.sf.briar.api.system.SystemClock;
 import net.sf.briar.db.DatabaseCleaner.Callback;
 
 import org.jmock.Expectations;
diff --git a/briar-tests/src/net/sf/briar/db/DatabaseComponentTest.java b/briar-tests/src/net/sf/briar/db/DatabaseComponentTest.java
index d6311265f2..aaef125ab1 100644
--- a/briar-tests/src/net/sf/briar/db/DatabaseComponentTest.java
+++ b/briar-tests/src/net/sf/briar/db/DatabaseComponentTest.java
@@ -24,18 +24,18 @@ import net.sf.briar.api.db.NoSuchContactException;
 import net.sf.briar.api.db.NoSuchLocalAuthorException;
 import net.sf.briar.api.db.NoSuchSubscriptionException;
 import net.sf.briar.api.db.NoSuchTransportException;
-import net.sf.briar.api.db.event.ContactAddedEvent;
-import net.sf.briar.api.db.event.ContactRemovedEvent;
-import net.sf.briar.api.db.event.DatabaseListener;
-import net.sf.briar.api.db.event.LocalAuthorAddedEvent;
-import net.sf.briar.api.db.event.LocalAuthorRemovedEvent;
-import net.sf.briar.api.db.event.LocalSubscriptionsUpdatedEvent;
-import net.sf.briar.api.db.event.LocalTransportsUpdatedEvent;
-import net.sf.briar.api.db.event.MessageAddedEvent;
-import net.sf.briar.api.db.event.MessageToAckEvent;
-import net.sf.briar.api.db.event.MessageToRequestEvent;
-import net.sf.briar.api.db.event.SubscriptionAddedEvent;
-import net.sf.briar.api.db.event.SubscriptionRemovedEvent;
+import net.sf.briar.api.event.ContactAddedEvent;
+import net.sf.briar.api.event.ContactRemovedEvent;
+import net.sf.briar.api.event.EventListener;
+import net.sf.briar.api.event.LocalAuthorAddedEvent;
+import net.sf.briar.api.event.LocalAuthorRemovedEvent;
+import net.sf.briar.api.event.LocalSubscriptionsUpdatedEvent;
+import net.sf.briar.api.event.LocalTransportsUpdatedEvent;
+import net.sf.briar.api.event.MessageAddedEvent;
+import net.sf.briar.api.event.MessageToAckEvent;
+import net.sf.briar.api.event.MessageToRequestEvent;
+import net.sf.briar.api.event.SubscriptionAddedEvent;
+import net.sf.briar.api.event.SubscriptionRemovedEvent;
 import net.sf.briar.api.lifecycle.ShutdownManager;
 import net.sf.briar.api.messaging.Ack;
 import net.sf.briar.api.messaging.Group;
@@ -120,7 +120,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
 		final Database<Object> database = context.mock(Database.class);
 		final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
 		final ShutdownManager shutdown = context.mock(ShutdownManager.class);
-		final DatabaseListener listener = context.mock(DatabaseListener.class);
+		final EventListener listener = context.mock(EventListener.class);
 		context.checking(new Expectations() {{
 			exactly(11).of(database).startTransaction();
 			will(returnValue(txn));
@@ -278,7 +278,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
 		final Database<Object> database = context.mock(Database.class);
 		final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
 		final ShutdownManager shutdown = context.mock(ShutdownManager.class);
-		final DatabaseListener listener = context.mock(DatabaseListener.class);
+		final EventListener listener = context.mock(EventListener.class);
 		context.checking(new Expectations() {{
 			oneOf(database).startTransaction();
 			will(returnValue(txn));
@@ -990,7 +990,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
 		final Database<Object> database = context.mock(Database.class);
 		final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
 		final ShutdownManager shutdown = context.mock(ShutdownManager.class);
-		final DatabaseListener listener = context.mock(DatabaseListener.class);
+		final EventListener listener = context.mock(EventListener.class);
 		context.checking(new Expectations() {{
 			oneOf(database).startTransaction();
 			will(returnValue(txn));
@@ -1031,7 +1031,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
 		final Database<Object> database = context.mock(Database.class);
 		final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
 		final ShutdownManager shutdown = context.mock(ShutdownManager.class);
-		final DatabaseListener listener = context.mock(DatabaseListener.class);
+		final EventListener listener = context.mock(EventListener.class);
 		context.checking(new Expectations() {{
 			oneOf(database).startTransaction();
 			will(returnValue(txn));
@@ -1093,7 +1093,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
 		final Database<Object> database = context.mock(Database.class);
 		final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
 		final ShutdownManager shutdown = context.mock(ShutdownManager.class);
-		final DatabaseListener listener = context.mock(DatabaseListener.class);
+		final EventListener listener = context.mock(EventListener.class);
 		context.checking(new Expectations() {{
 			oneOf(database).startTransaction();
 			will(returnValue(txn));
@@ -1294,7 +1294,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
 		final Database<Object> database = context.mock(Database.class);
 		final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
 		final ShutdownManager shutdown = context.mock(ShutdownManager.class);
-		final DatabaseListener listener = context.mock(DatabaseListener.class);
+		final EventListener listener = context.mock(EventListener.class);
 		context.checking(new Expectations() {{
 			oneOf(database).startTransaction();
 			will(returnValue(txn));
@@ -1326,7 +1326,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
 		final Database<Object> database = context.mock(Database.class);
 		final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
 		final ShutdownManager shutdown = context.mock(ShutdownManager.class);
-		final DatabaseListener listener = context.mock(DatabaseListener.class);
+		final EventListener listener = context.mock(EventListener.class);
 		context.checking(new Expectations() {{
 			oneOf(database).startTransaction();
 			will(returnValue(txn));
@@ -1354,7 +1354,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
 		final Database<Object> database = context.mock(Database.class);
 		final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
 		final ShutdownManager shutdown = context.mock(ShutdownManager.class);
-		final DatabaseListener listener = context.mock(DatabaseListener.class);
+		final EventListener listener = context.mock(EventListener.class);
 		context.checking(new Expectations() {{
 			oneOf(database).startTransaction();
 			will(returnValue(txn));
@@ -1389,7 +1389,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
 		final Database<Object> database = context.mock(Database.class);
 		final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
 		final ShutdownManager shutdown = context.mock(ShutdownManager.class);
-		final DatabaseListener listener = context.mock(DatabaseListener.class);
+		final EventListener listener = context.mock(EventListener.class);
 		context.checking(new Expectations() {{
 			oneOf(database).startTransaction();
 			will(returnValue(txn));
@@ -1421,7 +1421,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
 		final Database<Object> database = context.mock(Database.class);
 		final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
 		final ShutdownManager shutdown = context.mock(ShutdownManager.class);
-		final DatabaseListener listener = context.mock(DatabaseListener.class);
+		final EventListener listener = context.mock(EventListener.class);
 		context.checking(new Expectations() {{
 			// setVisibility()
 			oneOf(database).startTransaction();
diff --git a/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java b/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java
index 29d3381e07..fd13917957 100644
--- a/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java
+++ b/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java
@@ -31,7 +31,6 @@ import net.sf.briar.api.LocalAuthor;
 import net.sf.briar.api.TransportConfig;
 import net.sf.briar.api.TransportId;
 import net.sf.briar.api.TransportProperties;
-import net.sf.briar.api.clock.SystemClock;
 import net.sf.briar.api.db.DbException;
 import net.sf.briar.api.db.MessageHeader;
 import net.sf.briar.api.messaging.Group;
@@ -39,6 +38,7 @@ import net.sf.briar.api.messaging.GroupId;
 import net.sf.briar.api.messaging.GroupStatus;
 import net.sf.briar.api.messaging.Message;
 import net.sf.briar.api.messaging.MessageId;
+import net.sf.briar.api.system.SystemClock;
 import net.sf.briar.api.transport.Endpoint;
 import net.sf.briar.api.transport.TemporarySecret;
 
diff --git a/briar-tests/src/net/sf/briar/messaging/ConstantsTest.java b/briar-tests/src/net/sf/briar/messaging/ConstantsTest.java
index 9968be2855..9834c6f4b7 100644
--- a/briar-tests/src/net/sf/briar/messaging/ConstantsTest.java
+++ b/briar-tests/src/net/sf/briar/messaging/ConstantsTest.java
@@ -40,12 +40,12 @@ import net.sf.briar.api.messaging.PacketWriter;
 import net.sf.briar.api.messaging.PacketWriterFactory;
 import net.sf.briar.api.messaging.SubscriptionUpdate;
 import net.sf.briar.api.messaging.TransportUpdate;
-import net.sf.briar.clock.ClockModule;
 import net.sf.briar.crypto.CryptoModule;
 import net.sf.briar.db.DatabaseModule;
 import net.sf.briar.messaging.duplex.DuplexMessagingModule;
 import net.sf.briar.messaging.simplex.SimplexMessagingModule;
 import net.sf.briar.serial.SerialModule;
+import net.sf.briar.system.ClockModule;
 import net.sf.briar.transport.TransportModule;
 
 import org.junit.Test;
diff --git a/briar-tests/src/net/sf/briar/messaging/simplex/OutgoingSimplexConnectionTest.java b/briar-tests/src/net/sf/briar/messaging/simplex/OutgoingSimplexConnectionTest.java
index 3021e53923..3138549bd4 100644
--- a/briar-tests/src/net/sf/briar/messaging/simplex/OutgoingSimplexConnectionTest.java
+++ b/briar-tests/src/net/sf/briar/messaging/simplex/OutgoingSimplexConnectionTest.java
@@ -26,11 +26,11 @@ import net.sf.briar.api.messaging.PacketWriterFactory;
 import net.sf.briar.api.transport.ConnectionContext;
 import net.sf.briar.api.transport.ConnectionRegistry;
 import net.sf.briar.api.transport.ConnectionWriterFactory;
-import net.sf.briar.clock.ClockModule;
 import net.sf.briar.crypto.CryptoModule;
 import net.sf.briar.messaging.MessagingModule;
 import net.sf.briar.messaging.duplex.DuplexMessagingModule;
 import net.sf.briar.serial.SerialModule;
+import net.sf.briar.system.ClockModule;
 import net.sf.briar.transport.TransportModule;
 
 import org.jmock.Expectations;
diff --git a/briar-tests/src/net/sf/briar/messaging/simplex/SimplexMessagingIntegrationTest.java b/briar-tests/src/net/sf/briar/messaging/simplex/SimplexMessagingIntegrationTest.java
index 3ddb98eaf1..197676df36 100644
--- a/briar-tests/src/net/sf/briar/messaging/simplex/SimplexMessagingIntegrationTest.java
+++ b/briar-tests/src/net/sf/briar/messaging/simplex/SimplexMessagingIntegrationTest.java
@@ -20,9 +20,9 @@ import net.sf.briar.api.LocalAuthor;
 import net.sf.briar.api.TransportId;
 import net.sf.briar.api.crypto.KeyManager;
 import net.sf.briar.api.db.DatabaseComponent;
-import net.sf.briar.api.db.event.DatabaseEvent;
-import net.sf.briar.api.db.event.DatabaseListener;
-import net.sf.briar.api.db.event.MessageAddedEvent;
+import net.sf.briar.api.event.Event;
+import net.sf.briar.api.event.EventListener;
+import net.sf.briar.api.event.MessageAddedEvent;
 import net.sf.briar.api.messaging.Group;
 import net.sf.briar.api.messaging.GroupId;
 import net.sf.briar.api.messaging.Message;
@@ -36,13 +36,13 @@ import net.sf.briar.api.transport.ConnectionRecogniser;
 import net.sf.briar.api.transport.ConnectionRegistry;
 import net.sf.briar.api.transport.ConnectionWriterFactory;
 import net.sf.briar.api.transport.Endpoint;
-import net.sf.briar.clock.ClockModule;
 import net.sf.briar.crypto.CryptoModule;
 import net.sf.briar.db.DatabaseModule;
 import net.sf.briar.messaging.MessagingModule;
 import net.sf.briar.messaging.duplex.DuplexMessagingModule;
 import net.sf.briar.plugins.ImmediateExecutor;
 import net.sf.briar.serial.SerialModule;
+import net.sf.briar.system.ClockModule;
 import net.sf.briar.transport.TransportModule;
 
 import org.junit.After;
@@ -234,11 +234,11 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
 		TestUtils.deleteTestDirectory(testDir);
 	}
 
-	private static class MessageListener implements DatabaseListener {
+	private static class MessageListener implements EventListener {
 
 		private boolean messageAdded = false;
 
-		public void eventOccurred(DatabaseEvent e) {
+		public void eventOccurred(Event e) {
 			if(e instanceof MessageAddedEvent) messageAdded = true;
 		}
 	}
diff --git a/briar-tests/src/net/sf/briar/plugins/bluetooth/BluetoothClientTest.java b/briar-tests/src/net/sf/briar/plugins/bluetooth/BluetoothClientTest.java
index 18be16bfd1..a3b8ca6246 100644
--- a/briar-tests/src/net/sf/briar/plugins/bluetooth/BluetoothClientTest.java
+++ b/briar-tests/src/net/sf/briar/plugins/bluetooth/BluetoothClientTest.java
@@ -10,7 +10,7 @@ import java.util.concurrent.Executors;
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.TransportConfig;
 import net.sf.briar.api.TransportProperties;
-import net.sf.briar.api.clock.SystemClock;
+import net.sf.briar.api.system.SystemClock;
 import net.sf.briar.plugins.DuplexClientTest;
 
 // This is not a JUnit test - it has to be run manually while the server test
diff --git a/briar-tests/src/net/sf/briar/plugins/bluetooth/BluetoothServerTest.java b/briar-tests/src/net/sf/briar/plugins/bluetooth/BluetoothServerTest.java
index 08ade2b39e..456c81b44b 100644
--- a/briar-tests/src/net/sf/briar/plugins/bluetooth/BluetoothServerTest.java
+++ b/briar-tests/src/net/sf/briar/plugins/bluetooth/BluetoothServerTest.java
@@ -8,7 +8,7 @@ import java.util.concurrent.Executors;
 
 import net.sf.briar.api.TransportConfig;
 import net.sf.briar.api.TransportProperties;
-import net.sf.briar.api.clock.SystemClock;
+import net.sf.briar.api.system.SystemClock;
 import net.sf.briar.plugins.DuplexServerTest;
 
 // This is not a JUnit test - it has to be run manually while the client test
diff --git a/briar-tests/src/net/sf/briar/plugins/file/RemovableDrivePluginTest.java b/briar-tests/src/net/sf/briar/plugins/file/RemovableDrivePluginTest.java
index 527d1d6d51..fd287dc143 100644
--- a/briar-tests/src/net/sf/briar/plugins/file/RemovableDrivePluginTest.java
+++ b/briar-tests/src/net/sf/briar/plugins/file/RemovableDrivePluginTest.java
@@ -15,9 +15,9 @@ import net.sf.briar.BriarTestCase;
 import net.sf.briar.TestFileUtils;
 import net.sf.briar.TestUtils;
 import net.sf.briar.api.ContactId;
-import net.sf.briar.api.os.FileUtils;
 import net.sf.briar.api.plugins.simplex.SimplexPluginCallback;
 import net.sf.briar.api.plugins.simplex.SimplexTransportWriter;
+import net.sf.briar.api.system.FileUtils;
 import net.sf.briar.plugins.ImmediateExecutor;
 import net.sf.briar.plugins.file.RemovableDriveMonitor.Callback;
 
diff --git a/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpClientTest.java b/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpClientTest.java
index 9472213b13..a74ea9d6d8 100644
--- a/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpClientTest.java
+++ b/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpClientTest.java
@@ -9,8 +9,8 @@ import java.util.concurrent.Executors;
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.TransportConfig;
 import net.sf.briar.api.TransportProperties;
-import net.sf.briar.api.clock.Clock;
-import net.sf.briar.api.clock.SystemClock;
+import net.sf.briar.api.system.Clock;
+import net.sf.briar.api.system.SystemClock;
 import net.sf.briar.plugins.DuplexClientTest;
 
 // This is not a JUnit test - it has to be run manually while the server test
diff --git a/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpPluginTest.java b/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpPluginTest.java
index a335a908d6..da8ffbc3d6 100644
--- a/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpPluginTest.java
+++ b/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpPluginTest.java
@@ -17,11 +17,11 @@ import net.sf.briar.BriarTestCase;
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.TransportConfig;
 import net.sf.briar.api.TransportProperties;
-import net.sf.briar.api.clock.Clock;
-import net.sf.briar.api.clock.SystemClock;
 import net.sf.briar.api.plugins.duplex.DuplexPlugin;
 import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
 import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
+import net.sf.briar.api.system.Clock;
+import net.sf.briar.api.system.SystemClock;
 
 import org.junit.Test;
 
diff --git a/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpServerTest.java b/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpServerTest.java
index 16d7d73f65..5fb926cf8b 100644
--- a/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpServerTest.java
+++ b/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpServerTest.java
@@ -7,8 +7,8 @@ import java.util.concurrent.Executors;
 
 import net.sf.briar.api.TransportConfig;
 import net.sf.briar.api.TransportProperties;
-import net.sf.briar.api.clock.Clock;
-import net.sf.briar.api.clock.SystemClock;
+import net.sf.briar.api.system.Clock;
+import net.sf.briar.api.system.SystemClock;
 import net.sf.briar.plugins.DuplexServerTest;
 
 // This is not a JUnit test - it has to be run manually while the client test
diff --git a/briar-tests/src/net/sf/briar/transport/KeyManagerImplTest.java b/briar-tests/src/net/sf/briar/transport/KeyManagerImplTest.java
index 32b418f796..6337df582c 100644
--- a/briar-tests/src/net/sf/briar/transport/KeyManagerImplTest.java
+++ b/briar-tests/src/net/sf/briar/transport/KeyManagerImplTest.java
@@ -10,11 +10,11 @@ import net.sf.briar.BriarTestCase;
 import net.sf.briar.TestUtils;
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.TransportId;
-import net.sf.briar.api.clock.Clock;
-import net.sf.briar.api.clock.Timer;
 import net.sf.briar.api.crypto.CryptoComponent;
 import net.sf.briar.api.db.DatabaseComponent;
-import net.sf.briar.api.db.event.DatabaseListener;
+import net.sf.briar.api.event.EventListener;
+import net.sf.briar.api.system.Clock;
+import net.sf.briar.api.system.Timer;
 import net.sf.briar.api.transport.ConnectionContext;
 import net.sf.briar.api.transport.ConnectionRecogniser;
 import net.sf.briar.api.transport.Endpoint;
@@ -68,7 +68,7 @@ public class KeyManagerImplTest extends BriarTestCase {
 
 		context.checking(new Expectations() {{
 			// start()
-			oneOf(db).addListener(with(any(DatabaseListener.class)));
+			oneOf(db).addListener(with(any(EventListener.class)));
 			oneOf(db).getSecrets();
 			will(returnValue(Collections.emptyList()));
 			oneOf(db).getTransportLatencies();
@@ -78,7 +78,7 @@ public class KeyManagerImplTest extends BriarTestCase {
 			oneOf(timer).scheduleAtFixedRate(with(keyManager),
 					with(any(long.class)), with(any(long.class)));
 			// stop()
-			oneOf(db).removeListener(with(any(DatabaseListener.class)));
+			oneOf(db).removeListener(with(any(EventListener.class)));
 			oneOf(timer).cancel();
 			oneOf(connectionRecogniser).removeSecrets();
 		}});
@@ -110,7 +110,7 @@ public class KeyManagerImplTest extends BriarTestCase {
 
 		context.checking(new Expectations() {{
 			// start()
-			oneOf(db).addListener(with(any(DatabaseListener.class)));
+			oneOf(db).addListener(with(any(EventListener.class)));
 			oneOf(db).getSecrets();
 			will(returnValue(Collections.emptyList()));
 			oneOf(db).getTransportLatencies();
@@ -135,7 +135,7 @@ public class KeyManagerImplTest extends BriarTestCase {
 			oneOf(connectionRecogniser).addSecret(s1);
 			oneOf(connectionRecogniser).addSecret(s2);
 			// stop()
-			oneOf(db).removeListener(with(any(DatabaseListener.class)));
+			oneOf(db).removeListener(with(any(EventListener.class)));
 			oneOf(timer).cancel();
 			oneOf(connectionRecogniser).removeSecrets();
 		}});
@@ -168,7 +168,7 @@ public class KeyManagerImplTest extends BriarTestCase {
 
 		context.checking(new Expectations() {{
 			// start()
-			oneOf(db).addListener(with(any(DatabaseListener.class)));
+			oneOf(db).addListener(with(any(EventListener.class)));
 			oneOf(db).getSecrets();
 			will(returnValue(Collections.emptyList()));
 			oneOf(db).getTransportLatencies();
@@ -196,7 +196,7 @@ public class KeyManagerImplTest extends BriarTestCase {
 			oneOf(db).incrementConnectionCounter(contactId, transportId, 1);
 			will(returnValue(0L));
 			// stop()
-			oneOf(db).removeListener(with(any(DatabaseListener.class)));
+			oneOf(db).removeListener(with(any(EventListener.class)));
 			oneOf(timer).cancel();
 			oneOf(connectionRecogniser).removeSecrets();
 		}});
@@ -237,7 +237,7 @@ public class KeyManagerImplTest extends BriarTestCase {
 
 		context.checking(new Expectations() {{
 			// start()
-			oneOf(db).addListener(with(any(DatabaseListener.class)));
+			oneOf(db).addListener(with(any(EventListener.class)));
 			oneOf(db).getSecrets();
 			will(returnValue(Arrays.asList(s0, s1, s2)));
 			oneOf(db).getTransportLatencies();
@@ -253,7 +253,7 @@ public class KeyManagerImplTest extends BriarTestCase {
 			oneOf(timer).scheduleAtFixedRate(with(keyManager),
 					with(any(long.class)), with(any(long.class)));
 			// stop()
-			oneOf(db).removeListener(with(any(DatabaseListener.class)));
+			oneOf(db).removeListener(with(any(EventListener.class)));
 			oneOf(timer).cancel();
 			oneOf(connectionRecogniser).removeSecrets();
 		}});
@@ -287,7 +287,7 @@ public class KeyManagerImplTest extends BriarTestCase {
 
 		context.checking(new Expectations() {{
 			// start()
-			oneOf(db).addListener(with(any(DatabaseListener.class)));
+			oneOf(db).addListener(with(any(EventListener.class)));
 			oneOf(db).getSecrets();
 			will(returnValue(Arrays.asList(s0, s1, s2)));
 			oneOf(db).getTransportLatencies();
@@ -311,7 +311,7 @@ public class KeyManagerImplTest extends BriarTestCase {
 			oneOf(timer).scheduleAtFixedRate(with(keyManager),
 					with(any(long.class)), with(any(long.class)));
 			// stop()
-			oneOf(db).removeListener(with(any(DatabaseListener.class)));
+			oneOf(db).removeListener(with(any(EventListener.class)));
 			oneOf(timer).cancel();
 			oneOf(connectionRecogniser).removeSecrets();
 		}});
@@ -346,7 +346,7 @@ public class KeyManagerImplTest extends BriarTestCase {
 
 		context.checking(new Expectations() {{
 			// start()
-			oneOf(db).addListener(with(any(DatabaseListener.class)));
+			oneOf(db).addListener(with(any(EventListener.class)));
 			oneOf(db).getSecrets();
 			will(returnValue(Arrays.asList(s0, s1, s2)));
 			oneOf(db).getTransportLatencies();
@@ -371,7 +371,7 @@ public class KeyManagerImplTest extends BriarTestCase {
 			oneOf(timer).scheduleAtFixedRate(with(keyManager),
 					with(any(long.class)), with(any(long.class)));
 			// stop()
-			oneOf(db).removeListener(with(any(DatabaseListener.class)));
+			oneOf(db).removeListener(with(any(EventListener.class)));
 			oneOf(timer).cancel();
 			oneOf(connectionRecogniser).removeSecrets();
 		}});
@@ -403,7 +403,7 @@ public class KeyManagerImplTest extends BriarTestCase {
 
 		context.checking(new Expectations() {{
 			// start()
-			oneOf(db).addListener(with(any(DatabaseListener.class)));
+			oneOf(db).addListener(with(any(EventListener.class)));
 			oneOf(db).getSecrets();
 			will(returnValue(Arrays.asList(s0, s1, s2)));
 			oneOf(db).getTransportLatencies();
@@ -425,7 +425,7 @@ public class KeyManagerImplTest extends BriarTestCase {
 			oneOf(db).incrementConnectionCounter(contactId, transportId, 1);
 			will(returnValue(0L));
 			// stop()
-			oneOf(db).removeListener(with(any(DatabaseListener.class)));
+			oneOf(db).removeListener(with(any(EventListener.class)));
 			oneOf(timer).cancel();
 			oneOf(connectionRecogniser).removeSecrets();
 		}});
@@ -468,7 +468,7 @@ public class KeyManagerImplTest extends BriarTestCase {
 
 		context.checking(new Expectations() {{
 			// start()
-			oneOf(db).addListener(with(any(DatabaseListener.class)));
+			oneOf(db).addListener(with(any(EventListener.class)));
 			oneOf(db).getSecrets();
 			will(returnValue(Arrays.asList(s0, s1, s2)));
 			oneOf(db).getTransportLatencies();
@@ -499,7 +499,7 @@ public class KeyManagerImplTest extends BriarTestCase {
 			oneOf(db).incrementConnectionCounter(contactId, transportId, 2);
 			will(returnValue(0L));
 			// stop()
-			oneOf(db).removeListener(with(any(DatabaseListener.class)));
+			oneOf(db).removeListener(with(any(EventListener.class)));
 			oneOf(timer).cancel();
 			oneOf(connectionRecogniser).removeSecrets();
 		}});
@@ -543,7 +543,7 @@ public class KeyManagerImplTest extends BriarTestCase {
 
 		context.checking(new Expectations() {{
 			// start()
-			oneOf(db).addListener(with(any(DatabaseListener.class)));
+			oneOf(db).addListener(with(any(EventListener.class)));
 			oneOf(db).getSecrets();
 			will(returnValue(Arrays.asList(s0, s1, s2)));
 			oneOf(db).getTransportLatencies();
@@ -576,7 +576,7 @@ public class KeyManagerImplTest extends BriarTestCase {
 			oneOf(db).incrementConnectionCounter(contactId, transportId, 3);
 			will(returnValue(0L));
 			// stop()
-			oneOf(db).removeListener(with(any(DatabaseListener.class)));
+			oneOf(db).removeListener(with(any(EventListener.class)));
 			oneOf(timer).cancel();
 			oneOf(connectionRecogniser).removeSecrets();
 		}});
diff --git a/briar-tests/src/net/sf/briar/transport/KeyRotationIntegrationTest.java b/briar-tests/src/net/sf/briar/transport/KeyRotationIntegrationTest.java
index 70d664955f..ce665878b7 100644
--- a/briar-tests/src/net/sf/briar/transport/KeyRotationIntegrationTest.java
+++ b/briar-tests/src/net/sf/briar/transport/KeyRotationIntegrationTest.java
@@ -11,12 +11,12 @@ import net.sf.briar.BriarTestCase;
 import net.sf.briar.TestUtils;
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.TransportId;
-import net.sf.briar.api.clock.Clock;
-import net.sf.briar.api.clock.Timer;
 import net.sf.briar.api.crypto.CryptoComponent;
 import net.sf.briar.api.crypto.SecretKey;
 import net.sf.briar.api.db.DatabaseComponent;
-import net.sf.briar.api.db.event.DatabaseListener;
+import net.sf.briar.api.event.EventListener;
+import net.sf.briar.api.system.Clock;
+import net.sf.briar.api.system.Timer;
 import net.sf.briar.api.transport.ConnectionContext;
 import net.sf.briar.api.transport.ConnectionRecogniser;
 import net.sf.briar.api.transport.Endpoint;
@@ -85,7 +85,7 @@ public class KeyRotationIntegrationTest extends BriarTestCase {
 
 		context.checking(new Expectations() {{
 			// start()
-			oneOf(db).addListener(with(any(DatabaseListener.class)));
+			oneOf(db).addListener(with(any(EventListener.class)));
 			oneOf(db).getSecrets();
 			will(returnValue(Collections.emptyList()));
 			oneOf(db).getTransportLatencies();
@@ -95,7 +95,7 @@ public class KeyRotationIntegrationTest extends BriarTestCase {
 			oneOf(timer).scheduleAtFixedRate(with(keyManager),
 					with(any(long.class)), with(any(long.class)));
 			// stop()
-			oneOf(db).removeListener(with(any(DatabaseListener.class)));
+			oneOf(db).removeListener(with(any(EventListener.class)));
 			oneOf(timer).cancel();
 		}});
 
@@ -129,7 +129,7 @@ public class KeyRotationIntegrationTest extends BriarTestCase {
 
 		context.checking(new Expectations() {{
 			// start()
-			oneOf(db).addListener(with(any(DatabaseListener.class)));
+			oneOf(db).addListener(with(any(EventListener.class)));
 			oneOf(db).getSecrets();
 			will(returnValue(Collections.emptyList()));
 			oneOf(db).getTransportLatencies();
@@ -217,7 +217,7 @@ public class KeyRotationIntegrationTest extends BriarTestCase {
 			}
 			oneOf(k2).erase();
 			// Remove the listener and stop the timer
-			oneOf(db).removeListener(with(any(DatabaseListener.class)));
+			oneOf(db).removeListener(with(any(EventListener.class)));
 			oneOf(timer).cancel();
 		}});
 
@@ -252,7 +252,7 @@ public class KeyRotationIntegrationTest extends BriarTestCase {
 
 		context.checking(new Expectations() {{
 			// start()
-			oneOf(db).addListener(with(any(DatabaseListener.class)));
+			oneOf(db).addListener(with(any(EventListener.class)));
 			oneOf(db).getSecrets();
 			will(returnValue(Collections.emptyList()));
 			oneOf(db).getTransportLatencies();
@@ -343,7 +343,7 @@ public class KeyRotationIntegrationTest extends BriarTestCase {
 			}
 			oneOf(k2).erase();
 			// Remove the listener and stop the timer
-			oneOf(db).removeListener(with(any(DatabaseListener.class)));
+			oneOf(db).removeListener(with(any(EventListener.class)));
 			oneOf(timer).cancel();
 		}});
 
@@ -386,7 +386,7 @@ public class KeyRotationIntegrationTest extends BriarTestCase {
 
 		context.checking(new Expectations() {{
 			// start()
-			oneOf(db).addListener(with(any(DatabaseListener.class)));
+			oneOf(db).addListener(with(any(EventListener.class)));
 			oneOf(db).getSecrets();
 			will(returnValue(Collections.emptyList()));
 			oneOf(db).getTransportLatencies();
@@ -485,7 +485,7 @@ public class KeyRotationIntegrationTest extends BriarTestCase {
 			}
 			oneOf(k2).erase();
 			// Remove the listener and stop the timer
-			oneOf(db).removeListener(with(any(DatabaseListener.class)));
+			oneOf(db).removeListener(with(any(EventListener.class)));
 			oneOf(timer).cancel();
 		}});
 
@@ -531,7 +531,7 @@ public class KeyRotationIntegrationTest extends BriarTestCase {
 
 		context.checking(new Expectations() {{
 			// start()
-			oneOf(db).addListener(with(any(DatabaseListener.class)));
+			oneOf(db).addListener(with(any(EventListener.class)));
 			oneOf(db).getSecrets();
 			will(returnValue(Arrays.asList(s0, s1, s2)));
 			oneOf(db).getTransportLatencies();
@@ -611,7 +611,7 @@ public class KeyRotationIntegrationTest extends BriarTestCase {
 			}
 			oneOf(k2).erase();
 			// Remove the listener and stop the timer
-			oneOf(db).removeListener(with(any(DatabaseListener.class)));
+			oneOf(db).removeListener(with(any(EventListener.class)));
 			oneOf(timer).cancel();
 		}});
 
@@ -647,7 +647,7 @@ public class KeyRotationIntegrationTest extends BriarTestCase {
 
 		context.checking(new Expectations() {{
 			// start()
-			oneOf(db).addListener(with(any(DatabaseListener.class)));
+			oneOf(db).addListener(with(any(EventListener.class)));
 			oneOf(db).getSecrets();
 			will(returnValue(Arrays.asList(s0, s1, s2)));
 			oneOf(db).getTransportLatencies();
@@ -735,7 +735,7 @@ public class KeyRotationIntegrationTest extends BriarTestCase {
 			}
 			oneOf(k3).erase();
 			// Remove the listener and stop the timer
-			oneOf(db).removeListener(with(any(DatabaseListener.class)));
+			oneOf(db).removeListener(with(any(EventListener.class)));
 			oneOf(timer).cancel();
 		}});
 
@@ -772,7 +772,7 @@ public class KeyRotationIntegrationTest extends BriarTestCase {
 
 		context.checking(new Expectations() {{
 			// start()
-			oneOf(db).addListener(with(any(DatabaseListener.class)));
+			oneOf(db).addListener(with(any(EventListener.class)));
 			oneOf(db).getSecrets();
 			will(returnValue(Arrays.asList(s0, s1, s2)));
 			oneOf(db).getTransportLatencies();
@@ -861,7 +861,7 @@ public class KeyRotationIntegrationTest extends BriarTestCase {
 			}
 			oneOf(k4).erase();
 			// Remove the listener and stop the timer
-			oneOf(db).removeListener(with(any(DatabaseListener.class)));
+			oneOf(db).removeListener(with(any(EventListener.class)));
 			oneOf(timer).cancel();
 		}});
 
-- 
GitLab