diff --git a/api/net/sf/briar/api/plugins/duplex/DuplexPluginFactory.java b/api/net/sf/briar/api/plugins/duplex/DuplexPluginFactory.java
index 5d9609ff902d44b0401d635f546b0a57f3dfa8f4..c790dc9b6e78518a33b2429e4752c247bbee0b67 100644
--- a/api/net/sf/briar/api/plugins/duplex/DuplexPluginFactory.java
+++ b/api/net/sf/briar/api/plugins/duplex/DuplexPluginFactory.java
@@ -2,8 +2,10 @@ package net.sf.briar.api.plugins.duplex;
 
 import java.util.concurrent.Executor;
 
+import net.sf.briar.clock.Clock;
+
 public interface DuplexPluginFactory {
 
-	DuplexPlugin createPlugin(Executor pluginExecutor,
+	DuplexPlugin createPlugin(Executor pluginExecutor, Clock clock,
 			DuplexPluginCallback callback);
 }
diff --git a/api/net/sf/briar/api/plugins/simplex/SimplexPluginFactory.java b/api/net/sf/briar/api/plugins/simplex/SimplexPluginFactory.java
index d114ec376b08928d9fed433e896899a052d8b149..1da8775230790b39ef7950f2fce1c0d2b99514b4 100644
--- a/api/net/sf/briar/api/plugins/simplex/SimplexPluginFactory.java
+++ b/api/net/sf/briar/api/plugins/simplex/SimplexPluginFactory.java
@@ -2,8 +2,10 @@ package net.sf.briar.api.plugins.simplex;
 
 import java.util.concurrent.Executor;
 
+import net.sf.briar.clock.Clock;
+
 public interface SimplexPluginFactory {
 
-	SimplexPlugin createPlugin(Executor pluginExecutor,
+	SimplexPlugin createPlugin(Executor pluginExecutor, Clock clock,
 			SimplexPluginCallback callback);
 }
diff --git a/api/net/sf/briar/clock/Clock.java b/api/net/sf/briar/clock/Clock.java
new file mode 100644
index 0000000000000000000000000000000000000000..701d11412bd330151f4d930adf61f4c0a262fe08
--- /dev/null
+++ b/api/net/sf/briar/clock/Clock.java
@@ -0,0 +1,11 @@
+package net.sf.briar.clock;
+
+/**
+ * An interface for time-related system functions that allows them to be
+ * replaced for testing.
+ */
+public interface Clock {
+
+	/** @see {@link java.lang.System#currentTimeMillis()} */
+	long currentTimeMillis();
+}
diff --git a/api/net/sf/briar/clock/SystemClock.java b/api/net/sf/briar/clock/SystemClock.java
new file mode 100644
index 0000000000000000000000000000000000000000..460b147e892febd68452ffa39cafd60862d79619
--- /dev/null
+++ b/api/net/sf/briar/clock/SystemClock.java
@@ -0,0 +1,9 @@
+package net.sf.briar.clock;
+
+/** Default clock implementation. */
+public class SystemClock implements Clock {
+
+	public long currentTimeMillis() {
+		return System.currentTimeMillis();
+	}
+}
diff --git a/components/net/sf/briar/clock/ClockModule.java b/components/net/sf/briar/clock/ClockModule.java
new file mode 100644
index 0000000000000000000000000000000000000000..42ad9217f919073ed2fade1c081d35717ddf1d39
--- /dev/null
+++ b/components/net/sf/briar/clock/ClockModule.java
@@ -0,0 +1,11 @@
+package net.sf.briar.clock;
+
+import com.google.inject.AbstractModule;
+
+public class ClockModule extends AbstractModule {
+
+	@Override
+	protected void configure() {
+		bind(Clock.class).to(SystemClock.class);
+	}
+}
diff --git a/components/net/sf/briar/db/DatabaseComponentImpl.java b/components/net/sf/briar/db/DatabaseComponentImpl.java
index c9603296100e7f57e65aeaaf945c0c533580bd64..ad21a135f02f503f41ca9e74625b1e662032bf68 100644
--- a/components/net/sf/briar/db/DatabaseComponentImpl.java
+++ b/components/net/sf/briar/db/DatabaseComponentImpl.java
@@ -61,6 +61,7 @@ import net.sf.briar.api.protocol.TransportIndex;
 import net.sf.briar.api.protocol.TransportUpdate;
 import net.sf.briar.api.transport.ConnectionContext;
 import net.sf.briar.api.transport.ConnectionWindow;
+import net.sf.briar.clock.Clock;
 import net.sf.briar.util.ByteUtils;
 
 import com.google.inject.Inject;
@@ -103,6 +104,7 @@ DatabaseCleaner.Callback {
 	private final DatabaseCleaner cleaner;
 	private final ShutdownManager shutdown;
 	private final PacketFactory packetFactory;
+	private final Clock clock;
 
 	private final Collection<DatabaseListener> listeners =
 		new CopyOnWriteArrayList<DatabaseListener>();
@@ -117,11 +119,13 @@ DatabaseCleaner.Callback {
 
 	@Inject
 	DatabaseComponentImpl(Database<T> db, DatabaseCleaner cleaner,
-			ShutdownManager shutdown, PacketFactory packetFactory) {
+			ShutdownManager shutdown, PacketFactory packetFactory,
+			Clock clock) {
 		this.db = db;
 		this.cleaner = cleaner;
 		this.shutdown = shutdown;
 		this.packetFactory = packetFactory;
+		this.clock = clock;
 	}
 
 	public void open(boolean resume) throws DbException, IOException {
@@ -632,7 +636,7 @@ DatabaseCleaner.Callback {
 			try {
 				T txn = db.startTransaction();
 				try {
-					timestamp = System.currentTimeMillis() - 1;
+					timestamp = clock.currentTimeMillis() - 1;
 					holes = db.getVisibleHoles(txn, c, timestamp);
 					subs = db.getVisibleSubscriptions(txn, c, timestamp);
 					expiry = db.getExpiryTime(txn);
@@ -652,7 +656,7 @@ DatabaseCleaner.Callback {
 	}
 
 	private boolean updateIsDue(long sent) {
-		long now = System.currentTimeMillis();
+		long now = clock.currentTimeMillis();
 		return now - sent >= DatabaseConstants.MAX_UPDATE_INTERVAL;
 	}
 
@@ -686,7 +690,7 @@ DatabaseCleaner.Callback {
 				T txn = db.startTransaction();
 				try {
 					transports = db.getLocalTransports(txn);
-					timestamp = System.currentTimeMillis();
+					timestamp = clock.currentTimeMillis();
 					db.setTransportsSent(txn, c, timestamp);
 					db.commitTransaction(txn);
 				} catch(DbException e) {
@@ -1328,7 +1332,7 @@ DatabaseCleaner.Callback {
 			try {
 				if(!p.equals(db.getLocalProperties(txn, t))) {
 					db.setLocalProperties(txn, t, p);
-					db.setTransportsModified(txn, System.currentTimeMillis());
+					db.setTransportsModified(txn, clock.currentTimeMillis());
 					changed = true;
 				}
 				db.commitTransaction(txn);
@@ -1606,7 +1610,7 @@ DatabaseCleaner.Callback {
 
 	public boolean shouldCheckFreeSpace() {
 		synchronized(spaceLock) {
-			long now = System.currentTimeMillis();
+			long now = clock.currentTimeMillis();
 			if(bytesStoredSinceLastCheck > MAX_BYTES_BETWEEN_SPACE_CHECKS
 					|| now - timeOfLastCheck > MAX_MS_BETWEEN_SPACE_CHECKS) {
 				bytesStoredSinceLastCheck = 0L;
diff --git a/components/net/sf/briar/db/DatabaseModule.java b/components/net/sf/briar/db/DatabaseModule.java
index 9fa851d6d1ea897ac97760fa0b42f1e0bd35f64f..9c2b4b0210cccd5e6a79961db52b35b9b85914d3 100644
--- a/components/net/sf/briar/db/DatabaseModule.java
+++ b/components/net/sf/briar/db/DatabaseModule.java
@@ -15,6 +15,7 @@ import net.sf.briar.api.protocol.GroupFactory;
 import net.sf.briar.api.protocol.PacketFactory;
 import net.sf.briar.api.transport.ConnectionContextFactory;
 import net.sf.briar.api.transport.ConnectionWindowFactory;
+import net.sf.briar.clock.Clock;
 import net.sf.briar.util.BoundedExecutor;
 
 import com.google.inject.AbstractModule;
@@ -51,16 +52,16 @@ public class DatabaseModule extends AbstractModule {
 			@DatabasePassword Password password, @DatabaseMaxSize long maxSize,
 			ConnectionContextFactory connectionContextFactory,
 			ConnectionWindowFactory connectionWindowFactory,
-			GroupFactory groupFactory) {
+			GroupFactory groupFactory, Clock clock) {
 		return new H2Database(dir, password, maxSize, connectionContextFactory,
-				connectionWindowFactory, groupFactory);
+				connectionWindowFactory, groupFactory, clock);
 	}
 
 	@Provides @Singleton
 	DatabaseComponent getDatabaseComponent(Database<Connection> db,
 			DatabaseCleaner cleaner, ShutdownManager shutdown,
-			PacketFactory packetFactory) {
+			PacketFactory packetFactory, Clock clock) {
 		return new DatabaseComponentImpl<Connection>(db, cleaner, shutdown,
-				packetFactory);
+				packetFactory, clock);
 	}
 }
diff --git a/components/net/sf/briar/db/H2Database.java b/components/net/sf/briar/db/H2Database.java
index 4b975e2e2924c0e078f7221c53d3c21f7597f66b..42bc5622d0fe8bd73c2439e644f300502c6e35a5 100644
--- a/components/net/sf/briar/db/H2Database.java
+++ b/components/net/sf/briar/db/H2Database.java
@@ -16,6 +16,7 @@ import net.sf.briar.api.db.DbException;
 import net.sf.briar.api.protocol.GroupFactory;
 import net.sf.briar.api.transport.ConnectionContextFactory;
 import net.sf.briar.api.transport.ConnectionWindowFactory;
+import net.sf.briar.clock.Clock;
 
 import org.apache.commons.io.FileSystemUtils;
 
@@ -40,9 +41,9 @@ class H2Database extends JdbcDatabase {
 			@DatabaseMaxSize long maxSize,
 			ConnectionContextFactory connectionContextFactory,
 			ConnectionWindowFactory connectionWindowFactory,
-			GroupFactory groupFactory) {
+			GroupFactory groupFactory, Clock clock) {
 		super(connectionContextFactory, connectionWindowFactory, groupFactory,
-				HASH_TYPE, BINARY_TYPE, COUNTER_TYPE, SECRET_TYPE);
+				clock, HASH_TYPE, BINARY_TYPE, COUNTER_TYPE, SECRET_TYPE);
 		home = new File(dir, "db");
 		this.password = password;
 		url = "jdbc:h2:split:" + home.getPath()
diff --git a/components/net/sf/briar/db/JdbcDatabase.java b/components/net/sf/briar/db/JdbcDatabase.java
index 7e4daaec8f6e9e88db7eab57a5fdbf553d331997..8d5d87eaebcebd244e9d855311282073433d99d0 100644
--- a/components/net/sf/briar/db/JdbcDatabase.java
+++ b/components/net/sf/briar/db/JdbcDatabase.java
@@ -42,6 +42,7 @@ import net.sf.briar.api.transport.ConnectionContext;
 import net.sf.briar.api.transport.ConnectionContextFactory;
 import net.sf.briar.api.transport.ConnectionWindow;
 import net.sf.briar.api.transport.ConnectionWindowFactory;
+import net.sf.briar.clock.Clock;
 import net.sf.briar.util.FileUtils;
 
 /**
@@ -275,6 +276,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 	private final ConnectionContextFactory connectionContextFactory;
 	private final ConnectionWindowFactory connectionWindowFactory;
 	private final GroupFactory groupFactory;
+	private final Clock clock;
 	// Different database libraries use different names for certain types
 	private final String hashType, binaryType, counterType, secretType;
 
@@ -288,11 +290,12 @@ abstract class JdbcDatabase implements Database<Connection> {
 
 	JdbcDatabase(ConnectionContextFactory connectionContextFactory,
 			ConnectionWindowFactory connectionWindowFactory,
-			GroupFactory groupFactory, String hashType, String binaryType,
-			String counterType, String secretType) {
+			GroupFactory groupFactory, Clock clock, String hashType,
+			String binaryType, String counterType, String secretType) {
 		this.connectionContextFactory = connectionContextFactory;
 		this.connectionWindowFactory = connectionWindowFactory;
 		this.groupFactory = groupFactory;
+		this.clock = clock;
 		this.hashType = hashType;
 		this.binaryType = binaryType;
 		this.counterType = counterType;
@@ -654,7 +657,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 			ps = txn.prepareStatement(sql);
 			ps.setBytes(1, b.getBytes());
 			ps.setInt(2, c.getInt());
-			ps.setLong(3, System.currentTimeMillis());
+			ps.setLong(3, clock.currentTimeMillis());
 			int affected = ps.executeUpdate();
 			if(affected != 1) throw new DbStateException();
 			ps.close();
@@ -741,7 +744,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 			ps.setBytes(1, g.getId().getBytes());
 			ps.setString(2, g.getName());
 			ps.setBytes(3, g.getPublicKey());
-			long now = System.currentTimeMillis();
+			long now = clock.currentTimeMillis();
 			ps.setLong(4, now);
 			int affected = ps.executeUpdate();
 			if(affected != 1) throw new DbStateException();
@@ -2230,7 +2233,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 		ResultSet rs = null;
 		try {
 			// Remove the group ID from the visibility lists
-			long now = System.currentTimeMillis();
+			long now = clock.currentTimeMillis();
 			String sql = "SELECT contactId, nextId FROM visibilities"
 				+ " WHERE groupId = ?";
 			ps = txn.prepareStatement(sql);
@@ -2342,7 +2345,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 			ps = txn.prepareStatement(sql);
 			if(nextId == null) ps.setNull(1, Types.BINARY); // At the tail
 			else ps.setBytes(1, nextId); // At the head or in the middle
-			ps.setLong(2, System.currentTimeMillis());
+			ps.setLong(2, clock.currentTimeMillis());
 			ps.setInt(3, c.getInt());
 			ps.setBytes(4, g.getBytes());
 			affected = ps.executeUpdate();
diff --git a/components/net/sf/briar/plugins/InvitationStarterImpl.java b/components/net/sf/briar/plugins/InvitationStarterImpl.java
index 0df6981e2f4e735945a9886369533b744583b902..f67be85716375930e82b7ecff9c4624a2779a917 100644
--- a/components/net/sf/briar/plugins/InvitationStarterImpl.java
+++ b/components/net/sf/briar/plugins/InvitationStarterImpl.java
@@ -12,8 +12,6 @@ import java.security.KeyPair;
 import java.util.Arrays;
 import java.util.concurrent.Executor;
 
-import javax.inject.Inject;
-
 import net.sf.briar.api.crypto.CryptoComponent;
 import net.sf.briar.api.crypto.MessageDigest;
 import net.sf.briar.api.crypto.PseudoRandom;
@@ -32,6 +30,8 @@ import net.sf.briar.api.serial.Writer;
 import net.sf.briar.api.serial.WriterFactory;
 import net.sf.briar.util.ByteUtils;
 
+import com.google.inject.Inject;
+
 class InvitationStarterImpl implements InvitationStarter {
 
 	private static final String TIMED_OUT = "INVITATION_TIMED_OUT";
diff --git a/components/net/sf/briar/plugins/PluginManagerImpl.java b/components/net/sf/briar/plugins/PluginManagerImpl.java
index ab05b6de48f47c5fe0bec1a36ec412a67c3f0c4e..0da6aef13ff39374c80a71902454d678820465ee 100644
--- a/components/net/sf/briar/plugins/PluginManagerImpl.java
+++ b/components/net/sf/briar/plugins/PluginManagerImpl.java
@@ -35,6 +35,7 @@ import net.sf.briar.api.protocol.TransportId;
 import net.sf.briar.api.protocol.TransportIndex;
 import net.sf.briar.api.transport.ConnectionDispatcher;
 import net.sf.briar.api.ui.UiCallback;
+import net.sf.briar.clock.Clock;
 
 import com.google.inject.Inject;
 
@@ -54,6 +55,7 @@ class PluginManagerImpl implements PluginManager {
 	};
 
 	private final ExecutorService pluginExecutor;
+	private final Clock clock;
 	private final DatabaseComponent db;
 	private final Poller poller;
 	private final ConnectionDispatcher dispatcher;
@@ -63,9 +65,10 @@ class PluginManagerImpl implements PluginManager {
 
 	@Inject
 	PluginManagerImpl(@PluginExecutor ExecutorService pluginExecutor,
-			DatabaseComponent db, Poller poller,
+			Clock clock, DatabaseComponent db, Poller poller,
 			ConnectionDispatcher dispatcher, UiCallback uiCallback) {
 		this.pluginExecutor = pluginExecutor;
+		this.clock = clock;
 		this.db = db;
 		this.poller = poller;
 		this.dispatcher = dispatcher;
@@ -88,7 +91,7 @@ class PluginManagerImpl implements PluginManager {
 						(SimplexPluginFactory) c.newInstance();
 				SimplexCallback callback = new SimplexCallback();
 				SimplexPlugin plugin = factory.createPlugin(pluginExecutor,
-						callback);
+						clock, callback);
 				if(plugin == null) {
 					if(LOG.isLoggable(Level.INFO)) {
 						LOG.info(factory.getClass().getSimpleName()
@@ -128,7 +131,7 @@ class PluginManagerImpl implements PluginManager {
 						(DuplexPluginFactory) c.newInstance();
 				DuplexCallback callback = new DuplexCallback();
 				DuplexPlugin plugin = factory.createPlugin(pluginExecutor,
-						callback);
+						clock, callback);
 				if(plugin == null) {
 					if(LOG.isLoggable(Level.INFO)) {
 						LOG.info(factory.getClass().getSimpleName()
diff --git a/components/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java b/components/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java
index 9e8e58b6a7b7f42d336ae329432cb6d778f0f76c..2d295bc939b3fb09e81023214cddf2d45d43b6f1 100644
--- a/components/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java
+++ b/components/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java
@@ -32,6 +32,7 @@ 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.protocol.TransportId;
+import net.sf.briar.clock.Clock;
 import net.sf.briar.util.OsUtils;
 import net.sf.briar.util.StringUtils;
 
@@ -47,6 +48,7 @@ class BluetoothPlugin implements DuplexPlugin {
 		Logger.getLogger(BluetoothPlugin.class.getName());
 
 	private final Executor pluginExecutor;
+	private final Clock clock;
 	private final DuplexPluginCallback callback;
 	private final long pollingInterval;
 	private final Object discoveryLock = new Object();
@@ -58,9 +60,10 @@ class BluetoothPlugin implements DuplexPlugin {
 	private LocalDevice localDevice = null; // Locking: this
 	private StreamConnectionNotifier socket = null; // Locking: this
 
-	BluetoothPlugin(@PluginExecutor Executor pluginExecutor,
+	BluetoothPlugin(@PluginExecutor Executor pluginExecutor, Clock clock,
 			DuplexPluginCallback callback, long pollingInterval) {
 		this.pluginExecutor = pluginExecutor;
+		this.clock = clock;
 		this.callback = callback;
 		this.pollingInterval = pollingInterval;
 		scheduler = Executors.newScheduledThreadPool(0);
@@ -360,9 +363,9 @@ class BluetoothPlugin implements DuplexPlugin {
 		}
 		DiscoveryAgent discoveryAgent = localDevice.getDiscoveryAgent();
 		// Try to discover the other party until the invitation times out
-		long end = System.currentTimeMillis() + c.getTimeout();
+		long end = clock.currentTimeMillis() + c.getTimeout();
 		String url = null;
-		while(url == null && System.currentTimeMillis() < end) {
+		while(url == null && clock.currentTimeMillis() < end) {
 			InvitationListener listener = new InvitationListener(discoveryAgent,
 					c.getUuid());
 			// FIXME: Avoid making alien calls with a lock held
diff --git a/components/net/sf/briar/plugins/bluetooth/BluetoothPluginFactory.java b/components/net/sf/briar/plugins/bluetooth/BluetoothPluginFactory.java
index 615c3c66d94adfe1065625dbeeb9d175783bb9e8..1b138c0041c38eaf9e390ae1f7ec5047d8b31758 100644
--- a/components/net/sf/briar/plugins/bluetooth/BluetoothPluginFactory.java
+++ b/components/net/sf/briar/plugins/bluetooth/BluetoothPluginFactory.java
@@ -6,13 +6,15 @@ import net.sf.briar.api.plugins.PluginExecutor;
 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.clock.Clock;
 
 public class BluetoothPluginFactory implements DuplexPluginFactory {
 
 	private static final long POLLING_INTERVAL = 3L * 60L * 1000L; // 3 mins
 
 	public DuplexPlugin createPlugin(@PluginExecutor Executor pluginExecutor,
-			DuplexPluginCallback callback) {
-		return new BluetoothPlugin(pluginExecutor, callback, POLLING_INTERVAL);
+			Clock clock, DuplexPluginCallback callback) {
+		return new BluetoothPlugin(pluginExecutor, clock, callback,
+				POLLING_INTERVAL);
 	}
 }
diff --git a/components/net/sf/briar/plugins/email/GmailPluginFactory.java b/components/net/sf/briar/plugins/email/GmailPluginFactory.java
index 244a89373d3b91c62e38f2cae87c279fa5a12590..4b912e28d05be5f98f4a62d9e7598927959201b1 100644
--- a/components/net/sf/briar/plugins/email/GmailPluginFactory.java
+++ b/components/net/sf/briar/plugins/email/GmailPluginFactory.java
@@ -5,10 +5,11 @@ import java.util.concurrent.Executor;
 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.clock.Clock;
 
 public class GmailPluginFactory implements SimplexPluginFactory {
 
-	public SimplexPlugin createPlugin(Executor pluginExecutor,
+	public SimplexPlugin createPlugin(Executor pluginExecutor, Clock clock,
 			SimplexPluginCallback callback) {
 		
 		return new GmailPlugin(pluginExecutor, callback);
diff --git a/components/net/sf/briar/plugins/file/RemovableDrivePluginFactory.java b/components/net/sf/briar/plugins/file/RemovableDrivePluginFactory.java
index 689efc8502309661b750717957f3d724e71e07de..6a453f559b485f26903b1eff9e56ad4f3bbf05bf 100644
--- a/components/net/sf/briar/plugins/file/RemovableDrivePluginFactory.java
+++ b/components/net/sf/briar/plugins/file/RemovableDrivePluginFactory.java
@@ -6,6 +6,7 @@ import net.sf.briar.api.plugins.PluginExecutor;
 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.clock.Clock;
 import net.sf.briar.util.OsUtils;
 
 public class RemovableDrivePluginFactory implements SimplexPluginFactory {
@@ -13,7 +14,7 @@ public class RemovableDrivePluginFactory implements SimplexPluginFactory {
 	private static final long POLLING_INTERVAL = 10L * 1000L; // 10 seconds
 
 	public SimplexPlugin createPlugin(@PluginExecutor Executor pluginExecutor,
-			SimplexPluginCallback callback) {
+			Clock clock, SimplexPluginCallback callback) {
 		RemovableDriveFinder finder;
 		RemovableDriveMonitor monitor;
 		if(OsUtils.isLinux()) {
diff --git a/components/net/sf/briar/plugins/socket/SimpleSocketPluginFactory.java b/components/net/sf/briar/plugins/socket/SimpleSocketPluginFactory.java
index d8499fb32e8c16173ef8ee10f37414b3d46a1ce1..9ee36419eb123836b81aacaef39b882c9012bb49 100644
--- a/components/net/sf/briar/plugins/socket/SimpleSocketPluginFactory.java
+++ b/components/net/sf/briar/plugins/socket/SimpleSocketPluginFactory.java
@@ -6,13 +6,14 @@ import net.sf.briar.api.plugins.PluginExecutor;
 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.clock.Clock;
 
 public class SimpleSocketPluginFactory implements DuplexPluginFactory {
 
 	private static final long POLLING_INTERVAL = 5L * 60L * 1000L; // 5 mins
 
 	public DuplexPlugin createPlugin(@PluginExecutor Executor pluginExecutor,
-			DuplexPluginCallback callback) {
+			Clock clock, DuplexPluginCallback callback) {
 		return new SimpleSocketPlugin(pluginExecutor, callback,
 				POLLING_INTERVAL);
 	}
diff --git a/components/net/sf/briar/plugins/tor/TorPluginFactory.java b/components/net/sf/briar/plugins/tor/TorPluginFactory.java
index e7caf6aa195a70df7ec528e3da811c7d19957a2a..78cd3d5e923f4ed5fbe37ebf1636549c6416c78d 100644
--- a/components/net/sf/briar/plugins/tor/TorPluginFactory.java
+++ b/components/net/sf/briar/plugins/tor/TorPluginFactory.java
@@ -6,13 +6,14 @@ import net.sf.briar.api.plugins.PluginExecutor;
 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.clock.Clock;
 
 public class TorPluginFactory implements DuplexPluginFactory {
 
 	private static final long POLLING_INTERVAL = 15L * 60L * 1000L; // 15 mins
 
 	public DuplexPlugin createPlugin(@PluginExecutor Executor pluginExecutor,
-			DuplexPluginCallback callback) {
+			Clock clock, DuplexPluginCallback callback) {
 		return new TorPlugin(pluginExecutor, callback, POLLING_INTERVAL);
 	}
 }
diff --git a/test/net/sf/briar/ProtocolIntegrationTest.java b/test/net/sf/briar/ProtocolIntegrationTest.java
index 35942d2dfc8a5002680b853dc988126b083cda43..5f742831710fefde2f4b36d7a840c1ddc1adf490 100644
--- a/test/net/sf/briar/ProtocolIntegrationTest.java
+++ b/test/net/sf/briar/ProtocolIntegrationTest.java
@@ -46,6 +46,7 @@ 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.lifecycle.LifecycleModule;
@@ -83,7 +84,7 @@ public class ProtocolIntegrationTest extends BriarTestCase {
 
 	public ProtocolIntegrationTest() throws Exception {
 		super();
-		Injector i = Guice.createInjector(new CryptoModule(),
+		Injector i = Guice.createInjector(new ClockModule(), new CryptoModule(),
 				new DatabaseModule(), new LifecycleModule(),
 				new ProtocolModule(), new SerialModule(),
 				new TestDatabaseModule(), new SimplexProtocolModule(),
diff --git a/test/net/sf/briar/db/DatabaseComponentImplTest.java b/test/net/sf/briar/db/DatabaseComponentImplTest.java
index ccab25ee694414696e26316fb89a8ad75bcde4e9..474be1e37a2b8e3102c0b293756233f546089079 100644
--- a/test/net/sf/briar/db/DatabaseComponentImplTest.java
+++ b/test/net/sf/briar/db/DatabaseComponentImplTest.java
@@ -9,6 +9,7 @@ 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.protocol.PacketFactory;
+import net.sf.briar.clock.SystemClock;
 import net.sf.briar.db.DatabaseCleaner.Callback;
 
 import org.jmock.Expectations;
@@ -145,6 +146,6 @@ public class DatabaseComponentImplTest extends DatabaseComponentTest {
 			Database<T> database, DatabaseCleaner cleaner,
 			ShutdownManager shutdown, PacketFactory packetFactory) {
 		return new DatabaseComponentImpl<T>(database, cleaner, shutdown,
-				packetFactory);
+				packetFactory, new SystemClock());
 	}
 }
diff --git a/test/net/sf/briar/db/H2DatabaseTest.java b/test/net/sf/briar/db/H2DatabaseTest.java
index 671cc5905bdfb905fd4b10d458b1a915765ce71c..2c743f7b722633b08da7cc615d2c2bb3cfec211e 100644
--- a/test/net/sf/briar/db/H2DatabaseTest.java
+++ b/test/net/sf/briar/db/H2DatabaseTest.java
@@ -42,6 +42,7 @@ import net.sf.briar.api.transport.ConnectionContextFactory;
 import net.sf.briar.api.transport.ConnectionWindow;
 import net.sf.briar.api.transport.ConnectionWindowFactory;
 import net.sf.briar.api.transport.TransportConstants;
+import net.sf.briar.clock.SystemClock;
 import net.sf.briar.crypto.CryptoModule;
 import net.sf.briar.lifecycle.LifecycleModule;
 import net.sf.briar.protocol.ProtocolModule;
@@ -1847,7 +1848,7 @@ public class H2DatabaseTest extends BriarTestCase {
 	private Database<Connection> open(boolean resume) throws Exception {
 		Database<Connection> db = new H2Database(testDir, password, MAX_SIZE,
 				connectionContextFactory, connectionWindowFactory,
-				groupFactory);
+				groupFactory, new SystemClock());
 		db.open(resume);
 		return db;
 	}
diff --git a/test/net/sf/briar/plugins/PluginManagerImplTest.java b/test/net/sf/briar/plugins/PluginManagerImplTest.java
index feda37c3db7f85a682ca75babf7c4adb15997902..c1c1a30f904a950e065abe854e3001dbae22a4f7 100644
--- a/test/net/sf/briar/plugins/PluginManagerImplTest.java
+++ b/test/net/sf/briar/plugins/PluginManagerImplTest.java
@@ -13,6 +13,7 @@ import net.sf.briar.api.protocol.TransportId;
 import net.sf.briar.api.protocol.TransportIndex;
 import net.sf.briar.api.transport.ConnectionDispatcher;
 import net.sf.briar.api.ui.UiCallback;
+import net.sf.briar.clock.SystemClock;
 
 import org.jmock.Expectations;
 import org.jmock.Mockery;
@@ -27,7 +28,7 @@ public class PluginManagerImplTest extends BriarTestCase {
 		final DatabaseComponent db = context.mock(DatabaseComponent.class);
 		final Poller poller = context.mock(Poller.class);
 		final ConnectionDispatcher dispatcher =
-			context.mock(ConnectionDispatcher.class);
+				context.mock(ConnectionDispatcher.class);
 		final UiCallback uiCallback = context.mock(UiCallback.class);
 		final AtomicInteger index = new AtomicInteger(0);
 		context.checking(new Expectations() {{
@@ -47,8 +48,8 @@ public class PluginManagerImplTest extends BriarTestCase {
 			oneOf(poller).stop();
 		}});
 		ExecutorService executor = Executors.newCachedThreadPool();
-		PluginManagerImpl p = new PluginManagerImpl(executor, db, poller,
-				dispatcher, uiCallback);
+		PluginManagerImpl p = new PluginManagerImpl(executor, new SystemClock(),
+				db, poller, dispatcher, uiCallback);
 		// We expect either 3 or 4 plugins to be started, depending on whether
 		// the test machine has a Bluetooth device
 		int started = p.start();
diff --git a/test/net/sf/briar/plugins/bluetooth/BluetoothClientTest.java b/test/net/sf/briar/plugins/bluetooth/BluetoothClientTest.java
index 96ee30ca24649b05675f72369cfe69f4b0555620..39c9d4331d4abaf7222ca0ac2ff495823c258d23 100644
--- a/test/net/sf/briar/plugins/bluetooth/BluetoothClientTest.java
+++ b/test/net/sf/briar/plugins/bluetooth/BluetoothClientTest.java
@@ -9,6 +9,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.clock.SystemClock;
 import net.sf.briar.plugins.DuplexClientTest;
 
 // This is not a JUnit test - it has to be run manually while the server test
@@ -25,7 +26,7 @@ public class BluetoothClientTest extends DuplexClientTest {
 		// Create the plugin
 		callback = new ClientCallback(new TransportConfig(),
 				new TransportProperties(), remote);
-		plugin = new BluetoothPlugin(executor, callback, 0L);
+		plugin = new BluetoothPlugin(executor, new SystemClock(), callback, 0L);
 	}
 
 	public static void main(String[] args) throws Exception {
diff --git a/test/net/sf/briar/plugins/bluetooth/BluetoothServerTest.java b/test/net/sf/briar/plugins/bluetooth/BluetoothServerTest.java
index b818d05e7355f452848c59e40c5b7543dfe2dd6a..8bd8eef571aa25c74295224f1694bb39f0ea9e6d 100644
--- a/test/net/sf/briar/plugins/bluetooth/BluetoothServerTest.java
+++ b/test/net/sf/briar/plugins/bluetooth/BluetoothServerTest.java
@@ -7,6 +7,7 @@ import java.util.concurrent.Executors;
 
 import net.sf.briar.api.TransportConfig;
 import net.sf.briar.api.TransportProperties;
+import net.sf.briar.clock.SystemClock;
 import net.sf.briar.plugins.DuplexServerTest;
 
 // This is not a JUnit test - it has to be run manually while the client test
@@ -20,7 +21,7 @@ public class BluetoothServerTest extends DuplexServerTest {
 		// Create the plugin
 		callback = new ServerCallback(new TransportConfig(), local,
 				Collections.singletonMap(contactId, new TransportProperties()));
-		plugin = new BluetoothPlugin(executor, callback, 0L);
+		plugin = new BluetoothPlugin(executor, new SystemClock(), callback, 0L);
 	}
 
 	public static void main(String[] args) throws Exception {
diff --git a/test/net/sf/briar/plugins/email/GmailPluginTester.java b/test/net/sf/briar/plugins/email/GmailPluginTester.java
index 6d54456fbd5fd81f6c9dabec03d539a92550ac24..17145c0e26a8dc2ee60d00f6f3f988a4633a508d 100644
--- a/test/net/sf/briar/plugins/email/GmailPluginTester.java
+++ b/test/net/sf/briar/plugins/email/GmailPluginTester.java
@@ -1,25 +1,21 @@
 package net.sf.briar.plugins.email;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
 
 import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Set;
-import java.util.Map.Entry;
 import java.util.concurrent.Executors;
 
-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.plugins.simplex.SimplexPluginCallback;
 import net.sf.briar.api.plugins.simplex.SimplexTransportReader;
 import net.sf.briar.api.plugins.simplex.SimplexTransportWriter;
+import net.sf.briar.clock.SystemClock;
 
-import org.jmock.Mockery;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -106,7 +102,8 @@ Map<ContactId,TransportProperties> map = new HashMap<ContactId, TransportPropert
 	public void testPluginFactoryCreation()
 	{
 		GmailPluginFactory plugin = new GmailPluginFactory();
-		plugin.createPlugin(Executors.newSingleThreadExecutor(), callback);
+		plugin.createPlugin(Executors.newSingleThreadExecutor(),
+				new SystemClock(), callback);
 	}
 	
 	@Test
diff --git a/test/net/sf/briar/protocol/simplex/SimplexConnectionReadWriteTest.java b/test/net/sf/briar/protocol/simplex/SimplexConnectionReadWriteTest.java
index 0649fd31038b5dd4739aef90ba7b3386c6562be5..036392a974491c7e1d48735a15f05e94948d38b4 100644
--- a/test/net/sf/briar/protocol/simplex/SimplexConnectionReadWriteTest.java
+++ b/test/net/sf/briar/protocol/simplex/SimplexConnectionReadWriteTest.java
@@ -30,6 +30,7 @@ import net.sf.briar.api.transport.ConnectionReaderFactory;
 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.clock.ClockModule;
 import net.sf.briar.crypto.CryptoModule;
 import net.sf.briar.db.DatabaseModule;
 import net.sf.briar.lifecycle.LifecycleModule;
@@ -77,8 +78,9 @@ public class SimplexConnectionReadWriteTest extends BriarTestCase {
 	}
 
 	private Injector createInjector(File dir) {
-		return Guice.createInjector(new CryptoModule(), new DatabaseModule(),
-				new LifecycleModule(), new ProtocolModule(), new SerialModule(),
+		return Guice.createInjector(new ClockModule(), new CryptoModule(),
+				new DatabaseModule(), new LifecycleModule(),
+				new ProtocolModule(), new SerialModule(),
 				new TestDatabaseModule(dir), new SimplexProtocolModule(),
 				new TransportModule(), new DuplexProtocolModule());
 	}
diff --git a/test/net/sf/briar/transport/ConnectionWriterTest.java b/test/net/sf/briar/transport/ConnectionWriterTest.java
index 6c416658ece44c33c6f26a165c0298381600d20a..615944366c870e6a8975975bd0a5051e34785eb6 100644
--- a/test/net/sf/briar/transport/ConnectionWriterTest.java
+++ b/test/net/sf/briar/transport/ConnectionWriterTest.java
@@ -10,6 +10,7 @@ import net.sf.briar.BriarTestCase;
 import net.sf.briar.TestDatabaseModule;
 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.lifecycle.LifecycleModule;
@@ -30,7 +31,7 @@ public class ConnectionWriterTest extends BriarTestCase {
 
 	public ConnectionWriterTest() throws Exception {
 		super();
-		Injector i = Guice.createInjector(new CryptoModule(),
+		Injector i = Guice.createInjector(new ClockModule(), new CryptoModule(),
 				new DatabaseModule(), new LifecycleModule(),
 				new ProtocolModule(), new SerialModule(),
 				new TestDatabaseModule(), new SimplexProtocolModule(),