diff --git a/bramble-android/src/main/java/org/briarproject/bramble/api/system/AndroidWakeLockManager.java b/bramble-android/src/main/java/org/briarproject/bramble/api/system/AndroidWakeLockManager.java
index 0ebf256a2..b1cad4377 100644
--- a/bramble-android/src/main/java/org/briarproject/bramble/api/system/AndroidWakeLockManager.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/api/system/AndroidWakeLockManager.java
@@ -24,4 +24,12 @@ public interface AndroidWakeLockManager {
* thrown while submitting or running the task.
*/
void executeWakefully(Runnable r, Executor executor, String tag);
+
+ /**
+ * Starts a dedicated thread to run the given task asynchronously. A wake
+ * lock is acquired before starting the thread and released when the task
+ * completes, or if an exception is thrown while starting the thread or
+ * running the task.
+ */
+ void executeWakefully(Runnable r, String tag);
}
diff --git a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidWakeLockManagerImpl.java b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidWakeLockManagerImpl.java
index bf80c5fc0..f976e518d 100644
--- a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidWakeLockManagerImpl.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidWakeLockManagerImpl.java
@@ -86,6 +86,24 @@ class AndroidWakeLockManagerImpl implements AndroidWakeLockManager {
}
}
+ @Override
+ public void executeWakefully(Runnable r, String tag) {
+ AndroidWakeLock wakeLock = createWakeLock(tag);
+ wakeLock.acquire();
+ try {
+ new Thread(() -> {
+ try {
+ r.run();
+ } finally {
+ wakeLock.release();
+ }
+ }).start();
+ } catch (Exception e) {
+ wakeLock.release();
+ throw e;
+ }
+ }
+
private String getWakeLockTag(Context ctx) {
PackageManager pm = ctx.getPackageManager();
for (PackageInfo info : pm.getInstalledPackages(0)) {
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java b/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java
index 0c4de76ee..fedf33ba3 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java
@@ -24,6 +24,7 @@ import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.plugin.PluginManager;
import org.briarproject.bramble.api.settings.SettingsManager;
import org.briarproject.bramble.api.system.AndroidExecutor;
+import org.briarproject.bramble.api.system.AndroidWakeLockManager;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.plugin.tor.CircumventionProvider;
@@ -166,6 +167,8 @@ public interface AndroidComponent
FeatureFlags featureFlags();
+ AndroidWakeLockManager wakeLockManager();
+
void inject(SignInReminderReceiver briarService);
void inject(BriarService briarService);
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/BriarService.java b/briar-android/src/main/java/org/briarproject/briar/android/BriarService.java
index 952664002..a949161e9 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/BriarService.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/BriarService.java
@@ -20,14 +20,12 @@ import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.AndroidWakeLockManager;
-import org.briarproject.bramble.api.system.WakefulIoExecutor;
import org.briarproject.briar.R;
import org.briarproject.briar.android.logout.HideUiActivity;
import org.briarproject.briar.api.android.AndroidNotificationManager;
import org.briarproject.briar.api.android.LockManager;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
@@ -86,9 +84,6 @@ public class BriarService extends Service {
LockManager lockManager;
@Inject
AndroidWakeLockManager wakeLockManager;
- @Inject
- @WakefulIoExecutor
- Executor wakefulIoExecutor;
// Fields that are accessed from background threads must be volatile
@Inject
@@ -140,7 +135,7 @@ public class BriarService extends Service {
notificationManager.getForegroundNotification();
startForeground(ONGOING_NOTIFICATION_ID, foregroundNotification);
// Start the services in a background thread
- wakefulIoExecutor.execute(() -> {
+ wakeLockManager.executeWakefully(() -> {
StartResult result = lifecycleManager.startServices(dbKey);
if (result == SUCCESS) {
started = true;
@@ -153,7 +148,7 @@ public class BriarService extends Service {
showStartupFailureNotification(result);
stopSelf();
}
- });
+ }, "LifecycleStartup");
// Register for device shutdown broadcasts
receiver = new BroadcastReceiver() {
@Override
@@ -224,9 +219,9 @@ public class BriarService extends Service {
stopForeground(true);
if (receiver != null) unregisterReceiver(receiver);
// Stop the services in a background thread
- wakefulIoExecutor.execute(() -> {
+ wakeLockManager.executeWakefully(() -> {
if (started) lifecycleManager.stopServices();
- });
+ }, "LifecycleShutdown");
}, "LifecycleShutdown");
}
@@ -279,7 +274,7 @@ public class BriarService extends Service {
// Hide the UI
hideUi();
// Wait for shutdown to complete, then exit
- wakefulIoExecutor.execute(() -> {
+ wakeLockManager.executeWakefully(() -> {
try {
if (started) lifecycleManager.waitForShutdown();
} catch (InterruptedException e) {
@@ -287,7 +282,7 @@ public class BriarService extends Service {
}
LOG.info("Exiting");
System.exit(0);
- });
+ }, "BackgroundShutdown");
}, "BackgroundShutdown");
}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java b/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java
index 60edec57d..02c18b341 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java
@@ -82,13 +82,19 @@ import org.briarproject.briar.android.test.TestDataActivity;
import dagger.Component;
@ActivityScope
-@Component(
- modules = {ActivityModule.class, ForumModule.class, SharingModule.class,
- BlogModule.class, ContactModule.class, GroupListModule.class,
- CreateGroupModule.class, GroupInvitationModule.class,
- GroupConversationModule.class, GroupMemberModule.class,
- GroupRevealModule.class},
- dependencies = AndroidComponent.class)
+@Component(modules = {
+ ActivityModule.class,
+ BlogModule.class,
+ ContactModule.class,
+ CreateGroupModule.class,
+ ForumModule.class,
+ GroupInvitationModule.class,
+ GroupConversationModule.class,
+ GroupListModule.class,
+ GroupMemberModule.class,
+ GroupRevealModule.class,
+ SharingModule.class
+}, dependencies = AndroidComponent.class)
public interface ActivityComponent {
Activity activity();
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/activity/BriarActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/activity/BriarActivity.java
index 15de79805..e8ce42f32 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/activity/BriarActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/activity/BriarActivity.java
@@ -7,6 +7,8 @@ import android.widget.CheckBox;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.bramble.api.system.AndroidWakeLockManager;
+import org.briarproject.bramble.api.system.Wakeful;
import org.briarproject.briar.R;
import org.briarproject.briar.android.account.UnlockActivity;
import org.briarproject.briar.android.controller.BriarController;
@@ -32,6 +34,7 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
import static android.os.Build.VERSION.SDK_INT;
import static java.util.logging.Level.INFO;
+import static java.util.logging.Logger.getLogger;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_DOZE_WHITELISTING;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PASSWORD;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_UNLOCK;
@@ -47,7 +50,7 @@ public abstract class BriarActivity extends BaseActivity {
public static final String GROUP_NAME = "briar.GROUP_NAME";
private static final Logger LOG =
- Logger.getLogger(BriarActivity.class.getName());
+ getLogger(BriarActivity.class.getName());
@Inject
BriarController briarController;
@@ -56,6 +59,8 @@ public abstract class BriarActivity extends BaseActivity {
DbController dbController;
@Inject
protected LockManager lockManager;
+ @Inject
+ AndroidWakeLockManager wakeLockManager;
@Override
public void onStart() {
@@ -130,6 +135,7 @@ public abstract class BriarActivity extends BaseActivity {
/**
* Sets the transition animations.
+ *
* @param enterTransition used to move views into initial positions
* @param exitTransition used to move views out when starting a new activity.
* @param returnTransition used when window is closing, because the activity is finishing.
@@ -197,22 +203,29 @@ public abstract class BriarActivity extends BaseActivity {
protected void signOut(boolean removeFromRecentApps,
boolean deleteAccount) {
- if (briarController.accountSignedIn()) {
- // Don't use UiResultHandler because we want the result even if
- // this activity has been destroyed
- briarController.signOut(result -> runOnUiThread(
- () -> exit(removeFromRecentApps)), deleteAccount);
- } else {
- if (deleteAccount) briarController.deleteAccount();
- exit(removeFromRecentApps);
- }
+ // Hold a wake lock to ensure we exit before the device goes to sleep
+ wakeLockManager.runWakefully(() -> {
+ if (briarController.accountSignedIn()) {
+ // Don't use UiResultHandler because we want the result even if
+ // this activity has been destroyed
+ briarController.signOut(result ->
+ wakeLockManager.executeWakefully(() ->
+ exit(removeFromRecentApps),
+ this::runOnUiThread, "SignOut"), deleteAccount);
+ } else {
+ if (deleteAccount) briarController.deleteAccount();
+ exit(removeFromRecentApps);
+ }
+ }, "SignOut");
}
+ @Wakeful
private void exit(boolean removeFromRecentApps) {
if (removeFromRecentApps) startExitActivity();
else finishAndExit();
}
+ @Wakeful
private void startExitActivity() {
Intent i = new Intent(this, ExitActivity.class);
i.addFlags(FLAG_ACTIVITY_NEW_TASK
@@ -222,6 +235,7 @@ public abstract class BriarActivity extends BaseActivity {
startActivity(i);
}
+ @Wakeful
private void finishAndExit() {
if (SDK_INT >= 21) finishAndRemoveTask();
else supportFinishAfterTransition();
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/controller/BriarController.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/BriarController.java
index c86e6f905..33cbb9e64 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/controller/BriarController.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/BriarController.java
@@ -1,7 +1,10 @@
package org.briarproject.briar.android.controller;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.system.Wakeful;
import org.briarproject.briar.android.controller.handler.ResultHandler;
+@NotNullByDefault
public interface BriarController extends ActivityLifecycleController {
void startAndBindService();
@@ -16,7 +19,8 @@ public interface BriarController extends ActivityLifecycleController {
void doNotAskAgainForDozeWhiteListing();
- void signOut(ResultHandler eventHandler, boolean deleteAccount);
+ @Wakeful
+ void signOut(ResultHandler handler, boolean deleteAccount);
void deleteAccount();
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/controller/BriarControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/BriarControllerImpl.java
index 2e4479716..65c3efec4 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/controller/BriarControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/BriarControllerImpl.java
@@ -8,8 +8,10 @@ import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.settings.SettingsManager;
+import org.briarproject.bramble.api.system.AndroidWakeLockManager;
import org.briarproject.briar.android.BriarService;
import org.briarproject.briar.android.BriarService.BriarServiceConnection;
import org.briarproject.briar.android.controller.handler.ResultHandler;
@@ -23,15 +25,17 @@ import javax.inject.Inject;
import androidx.annotation.CallSuper;
import static java.util.logging.Level.WARNING;
+import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STARTING_SERVICES;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
+@NotNullByDefault
public class BriarControllerImpl implements BriarController {
private static final Logger LOG =
- Logger.getLogger(BriarControllerImpl.class.getName());
+ getLogger(BriarControllerImpl.class.getName());
public static final String DOZE_ASK_AGAIN = "dozeAskAgain";
@@ -41,6 +45,7 @@ public class BriarControllerImpl implements BriarController {
private final Executor databaseExecutor;
private final SettingsManager settingsManager;
private final DozeWatchdog dozeWatchdog;
+ private final AndroidWakeLockManager wakeLockManager;
private final Activity activity;
private boolean bound = false;
@@ -50,7 +55,9 @@ public class BriarControllerImpl implements BriarController {
AccountManager accountManager,
LifecycleManager lifecycleManager,
@DatabaseExecutor Executor databaseExecutor,
- SettingsManager settingsManager, DozeWatchdog dozeWatchdog,
+ SettingsManager settingsManager,
+ DozeWatchdog dozeWatchdog,
+ AndroidWakeLockManager wakeLockManager,
Activity activity) {
this.serviceConnection = serviceConnection;
this.accountManager = accountManager;
@@ -58,6 +65,7 @@ public class BriarControllerImpl implements BriarController {
this.databaseExecutor = databaseExecutor;
this.settingsManager = settingsManager;
this.dozeWatchdog = dozeWatchdog;
+ this.wakeLockManager = wakeLockManager;
this.activity = activity;
}
@@ -127,9 +135,8 @@ public class BriarControllerImpl implements BriarController {
}
@Override
- public void signOut(ResultHandler eventHandler,
- boolean deleteAccount) {
- new Thread(() -> {
+ public void signOut(ResultHandler handler, boolean deleteAccount) {
+ wakeLockManager.executeWakefully(() -> {
try {
// Wait for the service to finish starting up
IBinder binder = serviceConnection.waitForBinder();
@@ -145,8 +152,8 @@ public class BriarControllerImpl implements BriarController {
} finally {
if (deleteAccount) accountManager.deleteAccount();
}
- eventHandler.onResult(null);
- }).start();
+ handler.onResult(null);
+ }, "SignOut");
}
@Override
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/panic/PanicResponderActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/panic/PanicResponderActivity.java
index b1ca57ee6..1491e3659 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/panic/PanicResponderActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/panic/PanicResponderActivity.java
@@ -4,17 +4,14 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
-import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
-import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import java.util.logging.Logger;
import javax.annotation.Nullable;
-import javax.inject.Inject;
import androidx.preference.PreferenceManager;
import info.guardianproject.GuardianProjectRSA4096;
@@ -23,6 +20,7 @@ import info.guardianproject.panic.PanicResponder;
import info.guardianproject.trustedintents.TrustedIntents;
import static android.os.Build.VERSION.SDK_INT;
+import static java.util.logging.Logger.getLogger;
import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_LOCK;
import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_PURGE;
@@ -31,12 +29,7 @@ import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_
public class PanicResponderActivity extends BriarActivity {
private static final Logger LOG =
- Logger.getLogger(PanicResponderActivity.class.getName());
-
- @Inject
- protected LifecycleManager lifecycleManager;
- @Inject
- protected AndroidExecutor androidExecutor;
+ getLogger(PanicResponderActivity.class.getName());
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -63,11 +56,14 @@ public class PanicResponderActivity extends BriarActivity {
// Performing panic responses
if (sharedPref.getBoolean(KEY_PURGE, false)) {
LOG.info("Purging all data...");
- deleteAllData();
+ signOut(true, true);
+ } else {
+ LOG.info("Signing out...");
+ signOut(true, false);
}
- }
- // non-destructive actions are allowed by non-connected trusted apps
- if (sharedPref.getBoolean(KEY_LOCK, true)) {
+ } else if (sharedPref.getBoolean(KEY_LOCK, true)) {
+ // non-destructive actions are allowed by non-connected
+ // trusted apps
LOG.info("Signing out...");
signOut(true, false);
}
@@ -85,11 +81,4 @@ public class PanicResponderActivity extends BriarActivity {
public void injectActivity(ActivityComponent component) {
component.inject(this);
}
-
- private void deleteAllData() {
- androidExecutor.runOnBackgroundThread(() -> {
- LOG.info("Signing out...");
- signOut(true, true);
- });
- }
}