diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java
index 4193fbd2a0804f9a08c83f5b08231bd0f081f797..3458c97e38362c67490acc0116ff5358b3a67dbb 100644
--- a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java
@@ -36,7 +36,7 @@ import org.briarproject.bramble.api.settings.Settings;
 import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
 import org.briarproject.bramble.api.system.LocationUtils;
 import org.briarproject.bramble.util.IoUtils;
-import org.briarproject.bramble.util.ScheduledExecutorServiceWakeLock;
+import org.briarproject.bramble.util.RenewableWakeLock;
 import org.briarproject.bramble.util.StringUtils;
 
 import java.io.Closeable;
@@ -120,12 +120,10 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
 	private final ConnectionStatus connectionStatus;
 	private final File torDirectory, torFile, geoIpFile, configFile;
 	private final File doneFile, cookieFile;
+	private final RenewableWakeLock wakeLock;
 	private final AtomicReference<Future<?>> connectivityCheck =
 			new AtomicReference<>();
 	private final AtomicBoolean used = new AtomicBoolean(false);
-	private final ScheduledExecutorServiceWakeLock scheduledExecutorServiceWakeLock;
-
-	private PowerManager.WakeLock wakeLock;
 
 	private volatile boolean running = false;
 	private volatile ServerSocket socket = null;
@@ -161,24 +159,11 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
 		// Don't execute more than one connection status check at a time
 		connectionStatusExecutor = new PoliteExecutor("TorPlugin",
 				ioExecutor, 1);
-		scheduledExecutorServiceWakeLock =
-				new ScheduledExecutorServiceWakeLock(appContext);
-		scheduledExecutorServiceWakeLock.setRunnable((Runnable) () -> {
-			LOG.info("Renewing wake lock");
-			wakeLock.release();
-			aquireWakeLock();
-		});
-		aquireWakeLock();
-	}
-
-	private void aquireWakeLock(){
-		LOG.info("Aquiring wake lock");
 		PowerManager pm = (PowerManager)
 				appContext.getSystemService(POWER_SERVICE);
-		// This tag will prevent Huawei's powermanager from killing us.
-		wakeLock = pm.newWakeLock(PARTIAL_WAKE_LOCK, "LocationManagerService");
-		wakeLock.setReferenceCounted(false);
-		scheduledExecutorServiceWakeLock.setAlarm(1800000, MILLISECONDS);
+		// This tag will prevent Huawei's power manager from killing us
+		wakeLock = new RenewableWakeLock(pm, scheduler, PARTIAL_WAKE_LOCK,
+				"LocationManagerService", 30, MINUTES);
 	}
 
 	@Override
@@ -530,7 +515,6 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
 			}
 		}
 		wakeLock.release();
-		scheduledExecutorServiceWakeLock.cancelAlarm();
 	}
 
 	@Override
diff --git a/bramble-android/src/main/java/org/briarproject/bramble/util/RenewableWakeLock.java b/bramble-android/src/main/java/org/briarproject/bramble/util/RenewableWakeLock.java
new file mode 100644
index 0000000000000000000000000000000000000000..4b2dfb1ffaf4375bcd5b8ea630f3b1df1c097c01
--- /dev/null
+++ b/bramble-android/src/main/java/org/briarproject/bramble/util/RenewableWakeLock.java
@@ -0,0 +1,90 @@
+package org.briarproject.bramble.util;
+
+import android.os.PowerManager;
+
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+
+import static java.util.logging.Level.INFO;
+
+public class RenewableWakeLock {
+
+	private static final Logger LOG =
+			Logger.getLogger(RenewableWakeLock.class.getName());
+
+	private final PowerManager powerManager;
+	private final ScheduledExecutorService scheduler;
+	private final int levelAndFlags;
+	private final String tag;
+	private final long duration;
+	private final TimeUnit timeUnit;
+	private final Runnable renewTask;
+
+	private final Object lock = new Object();
+	private PowerManager.WakeLock wakeLock; // Locking: lock
+	private ScheduledFuture future; // Locking: lock
+
+	public RenewableWakeLock(PowerManager powerManager,
+			ScheduledExecutorService scheduler, int levelAndFlags, String tag,
+			long duration, TimeUnit timeUnit) {
+		this.powerManager = powerManager;
+		this.scheduler = scheduler;
+		this.levelAndFlags = levelAndFlags;
+		this.tag = tag;
+		this.duration = duration;
+		this.timeUnit = timeUnit;
+		renewTask = new Runnable() {
+			@Override
+			public void run() {
+				renew();
+			}
+		};
+	}
+
+	public void acquire() {
+		if (LOG.isLoggable(INFO)) LOG.info("Acquiring wake lock " + tag );
+		synchronized (lock) {
+			if (wakeLock != null) {
+				LOG.info("Already acquired");
+				return;
+			}
+			wakeLock = powerManager.newWakeLock(levelAndFlags, tag);
+			wakeLock.setReferenceCounted(false);
+			wakeLock.acquire();
+			future = scheduler.schedule(renewTask, duration, timeUnit);
+		}
+	}
+
+	private void renew() {
+		if (LOG.isLoggable(INFO)) LOG.info("Renewing wake lock " + tag );
+		synchronized (lock) {
+			if (wakeLock == null) {
+				LOG.info("Already released");
+				return;
+			}
+			PowerManager.WakeLock oldWakeLock = wakeLock;
+			wakeLock = powerManager.newWakeLock(levelAndFlags, tag);
+			wakeLock.setReferenceCounted(false);
+			wakeLock.acquire();
+			oldWakeLock.release();
+			future = scheduler.schedule(renewTask, duration, timeUnit);
+		}
+	}
+
+	public void release() {
+		if (LOG.isLoggable(INFO)) LOG.info("Releasing wake lock " + tag );
+		synchronized (lock) {
+			if (wakeLock == null) {
+				LOG.info("Already released");
+				return;
+			}
+			future.cancel(false);
+			future = null;
+			wakeLock.release();
+			wakeLock = null;
+		}
+	}
+}
+
diff --git a/bramble-android/src/main/java/org/briarproject/bramble/util/ScheduledExecutorServiceWakeLock.java b/bramble-android/src/main/java/org/briarproject/bramble/util/ScheduledExecutorServiceWakeLock.java
deleted file mode 100644
index 4dff3946d0938b6a044ea26f4104f0751f7e0e0e..0000000000000000000000000000000000000000
--- a/bramble-android/src/main/java/org/briarproject/bramble/util/ScheduledExecutorServiceWakeLock.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.briarproject.bramble.util;
-
-import android.content.Context;
-
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.TimeUnit;
-
-public class ScheduledExecutorServiceWakeLock {
-
-	final Context appContext;
-
-	private static final ThreadFactory THREAD_FACTORY = new ThreadFactory() {
-		@Override
-		public Thread newThread(Runnable r) {
-			Thread t = new Thread(r);
-			t.setDaemon(true);
-			return t;
-		}
-	};
-
-	private ScheduledExecutorService scheduledExecutorService = null; // Locking: this
-	private Runnable runnable;
-
-	public ScheduledExecutorServiceWakeLock(Context appContext) {
-		this.appContext = appContext;
-	}
-
-	public void setRunnable(Runnable r){
-		runnable = r;
-	}
-
-	public synchronized void setAlarm(long delay, TimeUnit unit) {
-		if(runnable == null)
-			return;
-		if (scheduledExecutorService == null)
-			scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(THREAD_FACTORY);
-		scheduledExecutorService.schedule(runnable, delay, unit);
-	}
-
-	public synchronized void cancelAlarm() {
-		if (scheduledExecutorService == null) throw new IllegalStateException();
-		scheduledExecutorService.shutdownNow();
-		scheduledExecutorService = null;
-	}
-}