From c089a099f0e124272dd88ce47308f08d30b3ce62 Mon Sep 17 00:00:00 2001 From: akwizgran <michael@briarproject.org> Date: Wed, 11 Oct 2017 15:39:22 +0100 Subject: [PATCH] Refactor wake lock to use existing ScheduledExecutorService. --- .../bramble/plugin/tor/TorPlugin.java | 26 ++---- .../bramble/util/RenewableWakeLock.java | 90 +++++++++++++++++++ .../ScheduledExecutorServiceWakeLock.java | 47 ---------- 3 files changed, 95 insertions(+), 68 deletions(-) create mode 100644 bramble-android/src/main/java/org/briarproject/bramble/util/RenewableWakeLock.java delete mode 100644 bramble-android/src/main/java/org/briarproject/bramble/util/ScheduledExecutorServiceWakeLock.java 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 4193fbd2a0..3458c97e38 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 0000000000..4b2dfb1ffa --- /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 4dff3946d0..0000000000 --- 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; - } -} -- GitLab