Hold a wake lock during app startup and shutdown.

This commit is contained in:
akwizgran
2020-08-10 16:50:40 +01:00
parent 452c3afbb3
commit 1e2dc862ef

View File

@@ -19,12 +19,15 @@ import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult; import org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult;
import org.briarproject.bramble.api.system.AndroidExecutor; 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.R;
import org.briarproject.briar.android.logout.HideUiActivity; import org.briarproject.briar.android.logout.HideUiActivity;
import org.briarproject.briar.api.android.AndroidNotificationManager; import org.briarproject.briar.api.android.AndroidNotificationManager;
import org.briarproject.briar.api.android.LockManager; import org.briarproject.briar.api.android.LockManager;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger; import java.util.logging.Logger;
@@ -48,6 +51,7 @@ import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.ALREADY_RUNNING; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.ALREADY_RUNNING;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SUCCESS; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SUCCESS;
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
import static org.briarproject.briar.android.BriarApplication.ENTRY_ACTIVITY; import static org.briarproject.briar.android.BriarApplication.ENTRY_ACTIVITY;
import static org.briarproject.briar.api.android.AndroidNotificationManager.FAILURE_CHANNEL_ID; import static org.briarproject.briar.api.android.AndroidNotificationManager.FAILURE_CHANNEL_ID;
import static org.briarproject.briar.api.android.AndroidNotificationManager.FAILURE_NOTIFICATION_ID; import static org.briarproject.briar.api.android.AndroidNotificationManager.FAILURE_NOTIFICATION_ID;
@@ -80,6 +84,11 @@ public class BriarService extends Service {
AccountManager accountManager; AccountManager accountManager;
@Inject @Inject
LockManager lockManager; LockManager lockManager;
@Inject
AndroidWakeLockManager wakeLockManager;
@Inject
@WakefulIoExecutor
Executor wakefulIoExecutor;
// Fields that are accessed from background threads must be volatile // Fields that are accessed from background threads must be volatile
@Inject @Inject
@@ -108,54 +117,57 @@ public class BriarService extends Service {
return; return;
} }
// Create notification channels // Hold a wake lock during startup
if (SDK_INT >= 26) { wakeLockManager.runWakefully(() -> {
NotificationManager nm = (NotificationManager) // Create notification channels
getSystemService(NOTIFICATION_SERVICE); if (SDK_INT >= 26) {
NotificationChannel ongoingChannel = new NotificationChannel( NotificationManager nm = (NotificationManager)
ONGOING_CHANNEL_ID, requireNonNull(getSystemService(NOTIFICATION_SERVICE));
getString(R.string.ongoing_notification_title), NotificationChannel ongoingChannel = new NotificationChannel(
IMPORTANCE_NONE); ONGOING_CHANNEL_ID,
ongoingChannel.setLockscreenVisibility(VISIBILITY_SECRET); getString(R.string.ongoing_notification_title),
nm.createNotificationChannel(ongoingChannel); IMPORTANCE_NONE);
NotificationChannel failureChannel = new NotificationChannel( ongoingChannel.setLockscreenVisibility(VISIBILITY_SECRET);
FAILURE_CHANNEL_ID, nm.createNotificationChannel(ongoingChannel);
getString(R.string.startup_failed_notification_title), NotificationChannel failureChannel = new NotificationChannel(
IMPORTANCE_DEFAULT); FAILURE_CHANNEL_ID,
failureChannel.setLockscreenVisibility(VISIBILITY_SECRET); getString(R.string.startup_failed_notification_title),
nm.createNotificationChannel(failureChannel); IMPORTANCE_DEFAULT);
} failureChannel.setLockscreenVisibility(VISIBILITY_SECRET);
Notification foregroundNotification = nm.createNotificationChannel(failureChannel);
notificationManager.getForegroundNotification();
startForeground(ONGOING_NOTIFICATION_ID, foregroundNotification);
// Start the services in a background thread
new Thread(() -> {
StartResult result = lifecycleManager.startServices(dbKey);
if (result == SUCCESS) {
started = true;
} else if (result == ALREADY_RUNNING) {
LOG.info("Already running");
stopSelf();
} else {
if (LOG.isLoggable(WARNING))
LOG.warning("Startup failed: " + result);
showStartupFailureNotification(result);
stopSelf();
} }
}).start(); Notification foregroundNotification =
// Register for device shutdown broadcasts notificationManager.getForegroundNotification();
receiver = new BroadcastReceiver() { startForeground(ONGOING_NOTIFICATION_ID, foregroundNotification);
@Override // Start the services in a background thread
public void onReceive(Context context, Intent intent) { wakefulIoExecutor.execute(() -> {
LOG.info("Device is shutting down"); StartResult result = lifecycleManager.startServices(dbKey);
shutdownFromBackground(); if (result == SUCCESS) {
} started = true;
}; } else if (result == ALREADY_RUNNING) {
IntentFilter filter = new IntentFilter(); LOG.info("Already running");
filter.addAction(ACTION_SHUTDOWN); stopSelf();
filter.addAction("android.intent.action.QUICKBOOT_POWEROFF"); } else {
filter.addAction("com.htc.intent.action.QUICKBOOT_POWEROFF"); if (LOG.isLoggable(WARNING))
registerReceiver(receiver, filter); LOG.warning("Startup failed: " + result);
showStartupFailureNotification(result);
stopSelf();
}
});
// Register for device shutdown broadcasts
receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
LOG.info("Device is shutting down");
shutdownFromBackground();
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_SHUTDOWN);
filter.addAction("android.intent.action.QUICKBOOT_POWEROFF");
filter.addAction("com.htc.intent.action.QUICKBOOT_POWEROFF");
registerReceiver(receiver, filter);
}, "LifecycleStartup");
} }
@Override @Override
@@ -179,8 +191,8 @@ public class BriarService extends Service {
i.putExtra(EXTRA_NOTIFICATION_ID, FAILURE_NOTIFICATION_ID); i.putExtra(EXTRA_NOTIFICATION_ID, FAILURE_NOTIFICATION_ID);
b.setContentIntent(PendingIntent.getActivity(BriarService.this, b.setContentIntent(PendingIntent.getActivity(BriarService.this,
0, i, FLAG_UPDATE_CURRENT)); 0, i, FLAG_UPDATE_CURRENT));
Object o = getSystemService(NOTIFICATION_SERVICE); NotificationManager nm = (NotificationManager)
NotificationManager nm = (NotificationManager) o; requireNonNull(getSystemService(NOTIFICATION_SERVICE));
nm.notify(FAILURE_NOTIFICATION_ID, b.build()); nm.notify(FAILURE_NOTIFICATION_ID, b.build());
// Bring the dashboard to the front to clear the back stack // Bring the dashboard to the front to clear the back stack
i = new Intent(BriarService.this, ENTRY_ACTIVITY); i = new Intent(BriarService.this, ENTRY_ACTIVITY);
@@ -205,14 +217,17 @@ public class BriarService extends Service {
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); // Hold a wake lock during shutdown
LOG.info("Destroyed"); wakeLockManager.runWakefully(() -> {
stopForeground(true); super.onDestroy();
if (receiver != null) unregisterReceiver(receiver); LOG.info("Destroyed");
// Stop the services in a background thread stopForeground(true);
new Thread(() -> { if (receiver != null) unregisterReceiver(receiver);
if (started) lifecycleManager.stopServices(); // Stop the services in a background thread
}).start(); wakefulIoExecutor.execute(() -> {
if (started) lifecycleManager.stopServices();
});
}, "LifecycleShutdown");
} }
@Override @Override
@@ -257,20 +272,23 @@ public class BriarService extends Service {
} }
private void shutdownFromBackground() { private void shutdownFromBackground() {
// Stop the service // Hold a wake lock during shutdown
stopSelf(); wakeLockManager.runWakefully(() -> {
// Hide the UI // Stop the service
hideUi(); stopSelf();
// Wait for shutdown to complete, then exit // Hide the UI
new Thread(() -> { hideUi();
try { // Wait for shutdown to complete, then exit
if (started) lifecycleManager.waitForShutdown(); wakefulIoExecutor.execute(() -> {
} catch (InterruptedException e) { try {
LOG.info("Interrupted while waiting for shutdown"); if (started) lifecycleManager.waitForShutdown();
} } catch (InterruptedException e) {
LOG.info("Exiting"); LOG.info("Interrupted while waiting for shutdown");
System.exit(0); }
}).start(); LOG.info("Exiting");
System.exit(0);
});
}, "BackgroundShutdown");
} }
/** /**