From bb8cb9bcbbc6704c068427859fb3453fd017b758 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Mon, 20 Nov 2017 16:27:39 -0200 Subject: [PATCH 1/6] Show Doze Dialog only after startup and provide "don't ask again" option --- .../android/navdrawer/NavDrawerActivity.java | 47 ++++++++++++++----- .../navdrawer/NavDrawerController.java | 7 +++ .../navdrawer/NavDrawerControllerImpl.java | 44 +++++++++++++++++ .../src/main/res/layout/checkbox.xml | 16 +++++++ briar-android/src/main/res/values/strings.xml | 1 + 5 files changed, 103 insertions(+), 12 deletions(-) create mode 100644 briar-android/src/main/res/layout/checkbox.xml diff --git a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java index e0ad7d8c9..4ce1d18b2 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java @@ -19,6 +19,7 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; +import android.widget.CheckBox; import android.widget.GridView; import android.widget.ImageView; import android.widget.TextView; @@ -54,11 +55,11 @@ import static android.support.v4.widget.DrawerLayout.LOCK_MODE_LOCKED_CLOSED; import static android.view.View.GONE; import static android.view.View.VISIBLE; 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.navdrawer.NavDrawerController.ExpiryWarning.NO; import static org.briarproject.briar.android.navdrawer.NavDrawerController.ExpiryWarning.UPDATE; import static org.briarproject.briar.android.util.UiUtils.getDaysUntilExpiry; import static org.briarproject.briar.android.util.UiUtils.getDozeWhitelistingIntent; -import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting; public class NavDrawerActivity extends BriarActivity implements BaseFragmentListener, TransportStateListener, @@ -151,7 +152,21 @@ public class NavDrawerActivity extends BriarActivity implements if (expiry != NO) showExpiryWarning(expiry); } }); - if (needsDozeWhitelisting(this)) requestDozeWhitelisting(); + } + + @Override + protected void onActivityResult(int request, int result, Intent data) { + super.onActivityResult(request, result, data); + if (request == REQUEST_PASSWORD && result == RESULT_OK) { + controller.askDozeWhitelisting(this, + new UiResultHandler(this) { + @Override + public void onResultUi(Boolean ask) { + if (!ask) return; + requestDozeWhitelisting(); + } + }); + } } private void exitIfStartupFailed(Intent intent) { @@ -315,16 +330,24 @@ public class NavDrawerActivity extends BriarActivity implements @TargetApi(23) private void requestDozeWhitelisting() { - new AlertDialog.Builder(this, R.style.BriarDialogTheme) - .setMessage(R.string.setup_doze_intro) - .setPositiveButton(R.string.ok, - (dialog, which) -> { - Intent i = getDozeWhitelistingIntent( - NavDrawerActivity.this); - startActivityForResult(i, - REQUEST_DOZE_WHITELISTING); - }) - .show(); + AlertDialog.Builder b = + new AlertDialog.Builder(this, R.style.BriarDialogTheme); + b.setMessage(R.string.setup_doze_intro); + b.setView(R.layout.checkbox); + b.setPositiveButton(R.string.ok, + (dialog, which) -> { + Intent i = getDozeWhitelistingIntent( + NavDrawerActivity.this); + startActivityForResult(i, REQUEST_DOZE_WHITELISTING); + }); + b.setNegativeButton(R.string.cancel, + (dialog, which) -> { + CheckBox checkBox = (CheckBox) ((AlertDialog) dialog) + .findViewById(R.id.checkbox); + if (checkBox.isChecked()) + controller.doNotAskAgainForDozeWhiteListing(); + }); + b.show(); } private void initializeTransports(LayoutInflater inflater) { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerController.java b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerController.java index 4b7c5a52a..21c220d6a 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerController.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerController.java @@ -1,5 +1,7 @@ package org.briarproject.briar.android.navdrawer; +import android.content.Context; + import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.briar.android.controller.ActivityLifecycleController; @@ -16,4 +18,9 @@ public interface NavDrawerController extends ActivityLifecycleController { void expiryWarningDismissed(); + void askDozeWhitelisting(final Context ctx, + final ResultHandler handler); + + void doNotAskAgainForDozeWhiteListing(); + } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerControllerImpl.java index 00a62705c..0e25288d0 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerControllerImpl.java @@ -1,6 +1,7 @@ package org.briarproject.briar.android.navdrawer; import android.app.Activity; +import android.content.Context; import org.briarproject.bramble.api.db.DatabaseExecutor; import org.briarproject.bramble.api.db.DbException; @@ -32,6 +33,7 @@ import static org.briarproject.briar.android.navdrawer.NavDrawerController.Expir import static org.briarproject.briar.android.navdrawer.NavDrawerController.ExpiryWarning.SHOW; import static org.briarproject.briar.android.navdrawer.NavDrawerController.ExpiryWarning.UPDATE; import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE; +import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting; @MethodsNotNullByDefault @ParametersNotNullByDefault @@ -42,6 +44,7 @@ public class NavDrawerControllerImpl extends DbControllerImpl Logger.getLogger(NavDrawerControllerImpl.class.getName()); private static final String EXPIRY_DATE_WARNING = "expiryDateWarning"; private static final String EXPIRY_SHOW_UPDATE = "expiryShowUpdate"; + private static final String DOZE_ASK_AGAIN = "dozeAskAgain"; private final PluginManager pluginManager; private final SettingsManager settingsManager; @@ -154,6 +157,47 @@ public class NavDrawerControllerImpl extends DbControllerImpl }); } + @Override + public void askDozeWhitelisting(final Context ctx, + final ResultHandler handler) { + if (!needsDozeWhitelisting(ctx)) { + handler.onResult(false); + return; + } + runOnDbThread(new Runnable() { + @Override + public void run() { + try { + Settings settings = + settingsManager.getSettings(SETTINGS_NAMESPACE); + boolean ask = settings.getBoolean(DOZE_ASK_AGAIN, true); + handler.onResult(ask); + } catch (DbException e) { + if (LOG.isLoggable(WARNING)) + LOG.log(WARNING, e.toString(), e); + handler.onResult(true); + } + } + }); + } + + @Override + public void doNotAskAgainForDozeWhiteListing() { + runOnDbThread(new Runnable() { + @Override + public void run() { + try { + Settings settings = new Settings(); + settings.putBoolean(DOZE_ASK_AGAIN, false); + settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE); + } catch (DbException e) { + if (LOG.isLoggable(WARNING)) + LOG.log(WARNING, e.toString(), e); + } + } + }); + } + @Override public boolean isTransportRunning(TransportId transportId) { Plugin plugin = pluginManager.getPlugin(transportId); diff --git a/briar-android/src/main/res/layout/checkbox.xml b/briar-android/src/main/res/layout/checkbox.xml new file mode 100644 index 000000000..eb3dfe6a4 --- /dev/null +++ b/briar-android/src/main/res/layout/checkbox.xml @@ -0,0 +1,16 @@ + + + + + + diff --git a/briar-android/src/main/res/values/strings.xml b/briar-android/src/main/res/values/strings.xml index 98c44d56c..e9d5d2ef1 100644 --- a/briar-android/src/main/res/values/strings.xml +++ b/briar-android/src/main/res/values/strings.xml @@ -19,6 +19,7 @@ Passwords do not match Create Account More Information + Don\'t ask again Enter your password: From 4267800db2848406eab3d1d9df8431e1281e70c5 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Mon, 20 Nov 2017 16:38:12 -0200 Subject: [PATCH 2/6] Allow Account Creation without Doze White-listing --- .../org/briarproject/briar/android/login/DozeFragment.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/DozeFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/login/DozeFragment.java index 68dc24345..005c600d8 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/login/DozeFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/login/DozeFragment.java @@ -26,6 +26,7 @@ public class DozeFragment extends SetupFragment { private Button dozeButton; private ProgressBar progressBar; + private boolean secondAttempt = false; public static DozeFragment newInstance() { return new DozeFragment(); @@ -64,10 +65,11 @@ public class DozeFragment extends SetupFragment { public void onActivityResult(int request, int result, Intent data) { super.onActivityResult(request, result, data); if (request == REQUEST_DOZE_WHITELISTING) { - if (!setupController.needsDozeWhitelisting()) { + if (!setupController.needsDozeWhitelisting() || secondAttempt) { dozeButton.setEnabled(false); onClick(dozeButton); } else { + secondAttempt = true; showOnboardingDialog(getContext(), getHelpText()); } } From ec2f372933a5e0fe8181c8df3e4e9edaab65c89c Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Mon, 20 Nov 2017 17:44:46 -0200 Subject: [PATCH 3/6] Remember that app entered doze mode and inform user when returning --- .../briar/android/BriarService.java | 42 +++++++++++- .../briar/android/activity/BriarActivity.java | 35 ++++++++++ .../android/controller/BriarController.java | 8 +++ .../controller/BriarControllerImpl.java | 64 ++++++++++++++++++- .../navdrawer/NavDrawerControllerImpl.java | 47 ++++++-------- briar-android/src/main/res/values/strings.xml | 4 +- 6 files changed, 170 insertions(+), 30 deletions(-) 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 0e6bb7c39..ea4e273e2 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 @@ -3,12 +3,16 @@ package org.briarproject.briar.android; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; +import android.content.BroadcastReceiver; import android.content.ComponentName; +import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.ServiceConnection; import android.os.Binder; -import android.os.Build; import android.os.IBinder; +import android.os.PowerManager; +import android.support.annotation.Nullable; import android.support.v4.app.NotificationCompat; import android.support.v4.content.ContextCompat; @@ -28,12 +32,15 @@ import javax.inject.Inject; import static android.app.PendingIntent.FLAG_UPDATE_CURRENT; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; +import static android.os.Build.VERSION.SDK_INT; +import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED; import static android.support.v4.app.NotificationCompat.CATEGORY_SERVICE; import static android.support.v4.app.NotificationCompat.PRIORITY_MIN; import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET; 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.SUCCESS; +import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting; public class BriarService extends Service { @@ -45,6 +52,9 @@ public class BriarService extends Service { private final AtomicBoolean created = new AtomicBoolean(false); private final Binder binder = new BriarBinder(); + @Nullable + private BriarBroadcastReceiver receiver = null; + private boolean hasDozed = false; @Inject protected DatabaseConfig databaseConfig; @@ -84,7 +94,7 @@ public class BriarService extends Service { Intent i = new Intent(this, NavDrawerActivity.class); i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP); b.setContentIntent(PendingIntent.getActivity(this, 0, i, 0)); - if (Build.VERSION.SDK_INT >= 21) { + if (SDK_INT >= 21) { b.setCategory(CATEGORY_SERVICE); b.setVisibility(VISIBILITY_SECRET); } @@ -109,6 +119,7 @@ public class BriarService extends Service { } } }.start(); + registerBroadcastReceiver(); } private void showStartupFailureNotification(StartResult result) { @@ -153,6 +164,7 @@ public class BriarService extends Service { public void onDestroy() { super.onDestroy(); LOG.info("Destroyed"); + if (receiver != null) unregisterReceiver(receiver); stopForeground(true); // Stop the services in a background thread new Thread() { @@ -170,6 +182,21 @@ public class BriarService extends Service { // FIXME: Work out what to do about it } + private void registerBroadcastReceiver() { + if (SDK_INT < 23) return; + IntentFilter filter = new IntentFilter(ACTION_DEVICE_IDLE_MODE_CHANGED); + if (receiver == null) receiver = new BriarBroadcastReceiver(); + registerReceiver(receiver, filter); + } + + public boolean hasDozed() { + return hasDozed; + } + + public void resetDozeFlag() { + hasDozed = false; + } + /** * Waits for all services to start before returning. */ @@ -225,4 +252,15 @@ public class BriarService extends Service { return binder; } } + + public class BriarBroadcastReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + if (SDK_INT < 23 || !needsDozeWhitelisting(getApplicationContext())) + return; + PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); + if (pm.isDeviceIdleMode()) hasDozed = true; + } + } + } 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 e98a63cfa..9d9f5b0de 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 @@ -4,15 +4,18 @@ import android.annotation.SuppressLint; import android.content.Intent; import android.os.Build; import android.support.v7.app.ActionBar; +import android.support.v7.app.AlertDialog; import android.support.v7.widget.Toolbar; import android.transition.Slide; import android.transition.Transition; import android.view.Gravity; import android.view.Window; +import android.widget.CheckBox; import org.briarproject.briar.R; import org.briarproject.briar.android.controller.BriarController; import org.briarproject.briar.android.controller.DbController; +import org.briarproject.briar.android.controller.handler.UiResultHandler; import org.briarproject.briar.android.login.PasswordActivity; import org.briarproject.briar.android.panic.ExitActivity; @@ -25,7 +28,9 @@ import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK; import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION; +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.util.UiUtils.getDozeWhitelistingIntent; @SuppressLint("Registered") public abstract class BriarActivity extends BaseActivity { @@ -59,6 +64,13 @@ public abstract class BriarActivity extends BaseActivity { if (!briarController.hasEncryptionKey() && !isFinishing()) { Intent i = new Intent(this, PasswordActivity.class); startActivityForResult(i, REQUEST_PASSWORD); + } else { + briarController.hasDozed(new UiResultHandler(this) { + @Override + public void onResultUi(Boolean result) { + if (result) showDozeDialog(); + } + }); } } @@ -97,6 +109,29 @@ public abstract class BriarActivity extends BaseActivity { return toolbar; } + private void showDozeDialog() { + AlertDialog.Builder b = + new AlertDialog.Builder(this, R.style.BriarDialogTheme); + b.setMessage(getString(R.string.warning_dozed, + getString(R.string.app_name))); + b.setView(R.layout.checkbox); + b.setPositiveButton(R.string.fix, + (dialog, which) -> { + Intent i = getDozeWhitelistingIntent(BriarActivity.this); + startActivityForResult(i, REQUEST_DOZE_WHITELISTING); + dialog.dismiss(); + }); + b.setNegativeButton(R.string.cancel, + (dialog, which) -> dialog.dismiss()); + b.setOnDismissListener(dialog -> { + CheckBox checkBox = (CheckBox) ((AlertDialog) dialog) + .findViewById(R.id.checkbox); + if (checkBox.isChecked()) + briarController.doNotNotifyWhenDozed(); + }); + b.show(); + } + protected void signOut(boolean removeFromRecentApps) { if (briarController.hasEncryptionKey()) { // Don't use UiResultHandler because we want the result even if 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 38c1ca93b..8d7aaacd5 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 @@ -8,5 +8,13 @@ public interface BriarController extends ActivityLifecycleController { boolean hasEncryptionKey(); + /** + * Returns true via the handler when the app has dozed + * without being white-listed. + */ + void hasDozed(ResultHandler handler); + + void doNotNotifyWhenDozed(); + void signOut(ResultHandler eventHandler); } 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 ff010ecac..7faaaa1de 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 @@ -6,30 +6,48 @@ import android.os.IBinder; import android.support.annotation.CallSuper; import org.briarproject.bramble.api.db.DatabaseConfig; +import org.briarproject.bramble.api.db.DatabaseExecutor; +import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.settings.Settings; +import org.briarproject.bramble.api.settings.SettingsManager; import org.briarproject.briar.android.BriarService; import org.briarproject.briar.android.BriarService.BriarServiceConnection; import org.briarproject.briar.android.controller.handler.ResultHandler; +import java.util.concurrent.Executor; import java.util.logging.Logger; import javax.inject.Inject; +import static java.util.logging.Level.WARNING; +import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE; +import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting; + public class BriarControllerImpl implements BriarController { private static final Logger LOG = Logger.getLogger(BriarControllerImpl.class.getName()); + private static final String HAS_DOZED_ASK_AGAIN = "hasDozedAskAgain"; + private final BriarServiceConnection serviceConnection; private final DatabaseConfig databaseConfig; + @DatabaseExecutor + private final Executor databaseExecutor; + private final SettingsManager settingsManager; private final Activity activity; private boolean bound = false; @Inject BriarControllerImpl(BriarServiceConnection serviceConnection, - DatabaseConfig databaseConfig, Activity activity) { + DatabaseConfig databaseConfig, + @DatabaseExecutor Executor databaseExecutor, + SettingsManager settingsManager, Activity activity) { this.serviceConnection = serviceConnection; this.databaseConfig = databaseConfig; + this.databaseExecutor = databaseExecutor; + this.settingsManager = settingsManager; this.activity = activity; } @@ -65,6 +83,50 @@ public class BriarControllerImpl implements BriarController { return databaseConfig.getEncryptionKey() != null; } + @Override + public void hasDozed(ResultHandler handler) { + // check this first, to hit the DbThread only when really necessary + if (!needsDozeWhitelisting(activity)) { + handler.onResult(false); + return; + } + databaseExecutor.execute(() -> { + try { + Settings settings = + settingsManager.getSettings(SETTINGS_NAMESPACE); + boolean ask = settings.getBoolean(HAS_DOZED_ASK_AGAIN, true); + if (!ask) { + handler.onResult(false); + return; + } + IBinder binder = serviceConnection.waitForBinder(); + BriarService service = + ((BriarService.BriarBinder) binder).getService(); + handler.onResult(service.hasDozed()); + service.resetDozeFlag(); + } catch (InterruptedException e) { + LOG.warning("Interrupted while waiting for service"); + } catch (DbException e) { + if (LOG.isLoggable(WARNING)) + LOG.log(WARNING, e.toString(), e); + } + }); + } + + @Override + public void doNotNotifyWhenDozed() { + databaseExecutor.execute(() -> { + try { + Settings settings = new Settings(); + settings.putBoolean(HAS_DOZED_ASK_AGAIN, false); + settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE); + } catch (DbException e) { + if (LOG.isLoggable(WARNING)) + LOG.log(WARNING, e.toString(), e); + } + }); + } + @Override public void signOut(ResultHandler eventHandler) { new Thread() { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerControllerImpl.java index 0e25288d0..aa89c0dfa 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerControllerImpl.java @@ -158,42 +158,37 @@ public class NavDrawerControllerImpl extends DbControllerImpl } @Override - public void askDozeWhitelisting(final Context ctx, - final ResultHandler handler) { + public void askDozeWhitelisting(Context ctx, + ResultHandler handler) { + // check this first, to hit the DbThread only when really necessary if (!needsDozeWhitelisting(ctx)) { handler.onResult(false); return; } - runOnDbThread(new Runnable() { - @Override - public void run() { - try { - Settings settings = - settingsManager.getSettings(SETTINGS_NAMESPACE); - boolean ask = settings.getBoolean(DOZE_ASK_AGAIN, true); - handler.onResult(ask); - } catch (DbException e) { - if (LOG.isLoggable(WARNING)) - LOG.log(WARNING, e.toString(), e); - handler.onResult(true); - } + runOnDbThread(() -> { + try { + Settings settings = + settingsManager.getSettings(SETTINGS_NAMESPACE); + boolean ask = settings.getBoolean(DOZE_ASK_AGAIN, true); + handler.onResult(ask); + } catch (DbException e) { + if (LOG.isLoggable(WARNING)) + LOG.log(WARNING, e.toString(), e); + handler.onResult(true); } }); } @Override public void doNotAskAgainForDozeWhiteListing() { - runOnDbThread(new Runnable() { - @Override - public void run() { - try { - Settings settings = new Settings(); - settings.putBoolean(DOZE_ASK_AGAIN, false); - settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE); - } catch (DbException e) { - if (LOG.isLoggable(WARNING)) - LOG.log(WARNING, e.toString(), e); - } + runOnDbThread(() -> { + try { + Settings settings = new Settings(); + settings.putBoolean(DOZE_ASK_AGAIN, false); + settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE); + } catch (DbException e) { + if (LOG.isLoggable(WARNING)) + LOG.log(WARNING, e.toString(), e); } }); } diff --git a/briar-android/src/main/res/values/strings.xml b/briar-android/src/main/res/values/strings.xml index e9d5d2ef1..fa95e33a8 100644 --- a/briar-android/src/main/res/values/strings.xml +++ b/briar-android/src/main/res/values/strings.xml @@ -95,6 +95,8 @@ The entered text is too long Show Help Dialog + %s was unable to run in the background + Fix It seems that you are new here and have no contacts yet.\n\nTap the + icon at the top and follow the instructions to add some friends to your list.\n\nPlease remember: You can only add new contacts face-to-face to prevent anyone from impersonating you or reading your messages in the future. @@ -391,7 +393,7 @@ Screen overlay detected Another app is drawing on top of Briar. To protect your security, Briar will not respond to touches when another app is drawing on top.\n\nTry turning off the following apps when using Briar:\n\n%1$s - + Camera permission To scan the QR code, Briar needs access to the camera. You have denied access to the camera, but adding contacts requires using the camera.\n\nPlease consider granting access. From 4ca86ee4eb9103fd2f3c813a751eb90837a93b83 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Tue, 21 Nov 2017 15:54:48 -0200 Subject: [PATCH 4/6] Address review comments --- .../briar/android/BriarService.java | 5 +- .../briar/android/activity/BriarActivity.java | 12 +++-- .../android/controller/BriarController.java | 2 +- .../controller/BriarControllerImpl.java | 51 +++++++++++-------- .../android/navdrawer/NavDrawerActivity.java | 35 ++----------- .../navdrawer/NavDrawerController.java | 6 +-- .../navdrawer/NavDrawerControllerImpl.java | 18 +------ 7 files changed, 50 insertions(+), 79 deletions(-) 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 ea4e273e2..2ac0c3e3e 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 @@ -54,7 +54,6 @@ public class BriarService extends Service { private final Binder binder = new BriarBinder(); @Nullable private BriarBroadcastReceiver receiver = null; - private boolean hasDozed = false; @Inject protected DatabaseConfig databaseConfig; @@ -63,7 +62,7 @@ public class BriarService extends Service { protected volatile LifecycleManager lifecycleManager; @Inject protected volatile AndroidExecutor androidExecutor; - private volatile boolean started = false; + private volatile boolean started = false, hasDozed = false; @Override public void onCreate() { @@ -185,7 +184,7 @@ public class BriarService extends Service { private void registerBroadcastReceiver() { if (SDK_INT < 23) return; IntentFilter filter = new IntentFilter(ACTION_DEVICE_IDLE_MODE_CHANGED); - if (receiver == null) receiver = new BriarBroadcastReceiver(); + receiver = new BriarBroadcastReceiver(); registerReceiver(receiver, filter); } 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 9d9f5b0de..64cc194f3 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 @@ -68,7 +68,10 @@ public abstract class BriarActivity extends BaseActivity { briarController.hasDozed(new UiResultHandler(this) { @Override public void onResultUi(Boolean result) { - if (result) showDozeDialog(); + if (result) { + showDozeDialog(getString(R.string.warning_dozed, + getString(R.string.app_name))); + } } }); } @@ -109,11 +112,10 @@ public abstract class BriarActivity extends BaseActivity { return toolbar; } - private void showDozeDialog() { + protected void showDozeDialog(String message) { AlertDialog.Builder b = new AlertDialog.Builder(this, R.style.BriarDialogTheme); - b.setMessage(getString(R.string.warning_dozed, - getString(R.string.app_name))); + b.setMessage(message); b.setView(R.layout.checkbox); b.setPositiveButton(R.string.fix, (dialog, which) -> { @@ -127,7 +129,7 @@ public abstract class BriarActivity extends BaseActivity { CheckBox checkBox = (CheckBox) ((AlertDialog) dialog) .findViewById(R.id.checkbox); if (checkBox.isChecked()) - briarController.doNotNotifyWhenDozed(); + briarController.doNotAskAgainForDozeWhiteListing(); }); b.show(); } 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 8d7aaacd5..350faeaba 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 @@ -14,7 +14,7 @@ public interface BriarController extends ActivityLifecycleController { */ void hasDozed(ResultHandler handler); - void doNotNotifyWhenDozed(); + void doNotAskAgainForDozeWhiteListing(); void signOut(ResultHandler eventHandler); } 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 7faaaa1de..9ecd35e91 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 @@ -4,6 +4,8 @@ import android.app.Activity; import android.content.Intent; import android.os.IBinder; import android.support.annotation.CallSuper; +import android.support.annotation.Nullable; +import android.support.annotation.WorkerThread; import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.db.DatabaseExecutor; @@ -28,7 +30,7 @@ public class BriarControllerImpl implements BriarController { private static final Logger LOG = Logger.getLogger(BriarControllerImpl.class.getName()); - private static final String HAS_DOZED_ASK_AGAIN = "hasDozedAskAgain"; + public static final String DOZE_ASK_AGAIN = "dozeAskAgain"; private final BriarServiceConnection serviceConnection; private final DatabaseConfig databaseConfig; @@ -39,6 +41,9 @@ public class BriarControllerImpl implements BriarController { private boolean bound = false; + @Nullable + private volatile BriarService service; + @Inject BriarControllerImpl(BriarServiceConnection serviceConnection, DatabaseConfig databaseConfig, @@ -76,6 +81,15 @@ public class BriarControllerImpl implements BriarController { activity.startService(new Intent(activity, BriarService.class)); bound = activity.bindService(new Intent(activity, BriarService.class), serviceConnection, 0); + if (!bound) throw new IllegalStateException(); + + new Thread(() -> { + try { + service = getBriarService(); + } catch (InterruptedException e) { + LOG.warning("Interrupted while waiting for service"); + } + }).start(); } @Override @@ -85,27 +99,19 @@ public class BriarControllerImpl implements BriarController { @Override public void hasDozed(ResultHandler handler) { - // check this first, to hit the DbThread only when really necessary - if (!needsDozeWhitelisting(activity)) { + BriarService briarService = service; + if (briarService == null || !briarService.hasDozed() || + !needsDozeWhitelisting(activity)) { handler.onResult(false); return; } + if (briarService.hasDozed()) briarService.resetDozeFlag(); databaseExecutor.execute(() -> { try { Settings settings = settingsManager.getSettings(SETTINGS_NAMESPACE); - boolean ask = settings.getBoolean(HAS_DOZED_ASK_AGAIN, true); - if (!ask) { - handler.onResult(false); - return; - } - IBinder binder = serviceConnection.waitForBinder(); - BriarService service = - ((BriarService.BriarBinder) binder).getService(); - handler.onResult(service.hasDozed()); - service.resetDozeFlag(); - } catch (InterruptedException e) { - LOG.warning("Interrupted while waiting for service"); + boolean ask = settings.getBoolean(DOZE_ASK_AGAIN, true); + handler.onResult(ask); } catch (DbException e) { if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); @@ -114,11 +120,11 @@ public class BriarControllerImpl implements BriarController { } @Override - public void doNotNotifyWhenDozed() { + public void doNotAskAgainForDozeWhiteListing() { databaseExecutor.execute(() -> { try { Settings settings = new Settings(); - settings.putBoolean(HAS_DOZED_ASK_AGAIN, false); + settings.putBoolean(DOZE_ASK_AGAIN, false); settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE); } catch (DbException e) { if (LOG.isLoggable(WARNING)) @@ -131,12 +137,11 @@ public class BriarControllerImpl implements BriarController { public void signOut(ResultHandler eventHandler) { new Thread() { @Override + @SuppressWarnings("ConstantConditions") public void run() { try { + if (service == null) service = getBriarService(); // Wait for the service to finish starting up - IBinder binder = serviceConnection.waitForBinder(); - BriarService service = - ((BriarService.BriarBinder) binder).getService(); service.waitForStartup(); // Shut down the service and wait for it to shut down LOG.info("Shutting down service"); @@ -150,6 +155,12 @@ public class BriarControllerImpl implements BriarController { }.start(); } + @WorkerThread + private BriarService getBriarService() throws InterruptedException { + IBinder binder = serviceConnection.waitForBinder(); + return ((BriarService.BriarBinder) binder).getService(); + } + private void unbindService() { if (bound) activity.unbindService(serviceConnection); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java index 4ce1d18b2..c5e4a5b12 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java @@ -1,7 +1,6 @@ package org.briarproject.briar.android.navdrawer; import android.annotation.SuppressLint; -import android.annotation.TargetApi; import android.content.Intent; import android.content.res.Configuration; import android.os.Bundle; @@ -12,14 +11,12 @@ import android.support.v4.app.FragmentTransaction; import android.support.v4.content.ContextCompat; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBarDrawerToggle; -import android.support.v7.app.AlertDialog; import android.support.v7.widget.Toolbar; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; -import android.widget.CheckBox; import android.widget.GridView; import android.widget.ImageView; import android.widget.TextView; @@ -54,12 +51,10 @@ import static android.support.v4.view.GravityCompat.START; import static android.support.v4.widget.DrawerLayout.LOCK_MODE_LOCKED_CLOSED; import static android.view.View.GONE; import static android.view.View.VISIBLE; -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.navdrawer.NavDrawerController.ExpiryWarning.NO; import static org.briarproject.briar.android.navdrawer.NavDrawerController.ExpiryWarning.UPDATE; import static org.briarproject.briar.android.util.UiUtils.getDaysUntilExpiry; -import static org.briarproject.briar.android.util.UiUtils.getDozeWhitelistingIntent; public class NavDrawerActivity extends BriarActivity implements BaseFragmentListener, TransportStateListener, @@ -158,12 +153,14 @@ public class NavDrawerActivity extends BriarActivity implements protected void onActivityResult(int request, int result, Intent data) { super.onActivityResult(request, result, data); if (request == REQUEST_PASSWORD && result == RESULT_OK) { - controller.askDozeWhitelisting(this, + controller.shouldAskForDozeWhitelisting(this, new UiResultHandler(this) { @Override public void onResultUi(Boolean ask) { - if (!ask) return; - requestDozeWhitelisting(); + if (ask) { + showDozeDialog( + getString(R.string.setup_doze_intro)); + } } }); } @@ -328,28 +325,6 @@ public class NavDrawerActivity extends BriarActivity implements expiryWarning.setVisibility(VISIBLE); } - @TargetApi(23) - private void requestDozeWhitelisting() { - AlertDialog.Builder b = - new AlertDialog.Builder(this, R.style.BriarDialogTheme); - b.setMessage(R.string.setup_doze_intro); - b.setView(R.layout.checkbox); - b.setPositiveButton(R.string.ok, - (dialog, which) -> { - Intent i = getDozeWhitelistingIntent( - NavDrawerActivity.this); - startActivityForResult(i, REQUEST_DOZE_WHITELISTING); - }); - b.setNegativeButton(R.string.cancel, - (dialog, which) -> { - CheckBox checkBox = (CheckBox) ((AlertDialog) dialog) - .findViewById(R.id.checkbox); - if (checkBox.isChecked()) - controller.doNotAskAgainForDozeWhiteListing(); - }); - b.show(); - } - private void initializeTransports(LayoutInflater inflater) { transports = new ArrayList<>(3); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerController.java b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerController.java index 21c220d6a..d2d883e90 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerController.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerController.java @@ -18,9 +18,7 @@ public interface NavDrawerController extends ActivityLifecycleController { void expiryWarningDismissed(); - void askDozeWhitelisting(final Context ctx, - final ResultHandler handler); - - void doNotAskAgainForDozeWhiteListing(); + void shouldAskForDozeWhitelisting(Context ctx, + ResultHandler handler); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerControllerImpl.java index aa89c0dfa..ba5a22f2c 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerControllerImpl.java @@ -29,6 +29,7 @@ import javax.inject.Inject; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import static org.briarproject.briar.android.BriarApplication.EXPIRY_DATE; +import static org.briarproject.briar.android.controller.BriarControllerImpl.DOZE_ASK_AGAIN; import static org.briarproject.briar.android.navdrawer.NavDrawerController.ExpiryWarning.NO; import static org.briarproject.briar.android.navdrawer.NavDrawerController.ExpiryWarning.SHOW; import static org.briarproject.briar.android.navdrawer.NavDrawerController.ExpiryWarning.UPDATE; @@ -44,7 +45,6 @@ public class NavDrawerControllerImpl extends DbControllerImpl Logger.getLogger(NavDrawerControllerImpl.class.getName()); private static final String EXPIRY_DATE_WARNING = "expiryDateWarning"; private static final String EXPIRY_SHOW_UPDATE = "expiryShowUpdate"; - private static final String DOZE_ASK_AGAIN = "dozeAskAgain"; private final PluginManager pluginManager; private final SettingsManager settingsManager; @@ -158,7 +158,7 @@ public class NavDrawerControllerImpl extends DbControllerImpl } @Override - public void askDozeWhitelisting(Context ctx, + public void shouldAskForDozeWhitelisting(Context ctx, ResultHandler handler) { // check this first, to hit the DbThread only when really necessary if (!needsDozeWhitelisting(ctx)) { @@ -179,20 +179,6 @@ public class NavDrawerControllerImpl extends DbControllerImpl }); } - @Override - public void doNotAskAgainForDozeWhiteListing() { - runOnDbThread(() -> { - try { - Settings settings = new Settings(); - settings.putBoolean(DOZE_ASK_AGAIN, false); - settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE); - } catch (DbException e) { - if (LOG.isLoggable(WARNING)) - LOG.log(WARNING, e.toString(), e); - } - }); - } - @Override public boolean isTransportRunning(TransportId transportId) { Plugin plugin = pluginManager.getPlugin(transportId); From 748fa77d9464b90768bd122959f025fb037583aa Mon Sep 17 00:00:00 2001 From: akwizgran Date: Wed, 22 Nov 2017 11:07:28 +0000 Subject: [PATCH 5/6] Move doze receiver out of BriarService. --- .../briar/android/AndroidComponent.java | 3 + .../briarproject/briar/android/AppModule.java | 11 ++++ .../briar/android/BriarService.java | 43 +------------- .../briar/android/DozeWatchdogImpl.java | 56 +++++++++++++++++++ .../briar/android/activity/BriarActivity.java | 8 +-- .../controller/BriarControllerImpl.java | 37 ++++-------- .../briar/api/android/DozeWatchdog.java | 6 ++ 7 files changed, 93 insertions(+), 71 deletions(-) create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/DozeWatchdogImpl.java create mode 100644 briar-android/src/main/java/org/briarproject/briar/api/android/DozeWatchdog.java 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 652ef527d..763c50332 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 @@ -26,6 +26,7 @@ import org.briarproject.briar.BriarCoreEagerSingletons; import org.briarproject.briar.BriarCoreModule; import org.briarproject.briar.android.reporting.BriarReportSender; import org.briarproject.briar.api.android.AndroidNotificationManager; +import org.briarproject.briar.api.android.DozeWatchdog; import org.briarproject.briar.api.android.ScreenFilterMonitor; import org.briarproject.briar.api.blog.BlogManager; import org.briarproject.briar.api.blog.BlogPostFactory; @@ -140,6 +141,8 @@ public interface AndroidComponent TestDataCreator testDataCreator(); + DozeWatchdog dozeWatchdog(); + @IoExecutor Executor ioExecutor(); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java index 725a69047..c0e068976 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java @@ -15,6 +15,7 @@ import org.briarproject.bramble.api.reporting.DevConfig; import org.briarproject.bramble.api.ui.UiCallback; import org.briarproject.bramble.util.StringUtils; import org.briarproject.briar.api.android.AndroidNotificationManager; +import org.briarproject.briar.api.android.DozeWatchdog; import org.briarproject.briar.api.android.ReferenceManager; import org.briarproject.briar.api.android.ScreenFilterMonitor; @@ -40,6 +41,8 @@ public class AppModule { AndroidNotificationManager androidNotificationManager; @Inject NetworkUsageLogger networkUsageLogger; + @Inject + DozeWatchdog dozeWatchdog; } private final Application application; @@ -183,4 +186,12 @@ public class AppModule { lifecycleManager.registerService(networkUsageLogger); return networkUsageLogger; } + + @Provides + @Singleton + DozeWatchdog provideDozeWatchdog(LifecycleManager lifecycleManager) { + DozeWatchdogImpl dozeWatchdog = new DozeWatchdogImpl(application); + lifecycleManager.registerService(dozeWatchdog); + return dozeWatchdog; + } } 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 2ac0c3e3e..0e6bb7c39 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 @@ -3,16 +3,12 @@ package org.briarproject.briar.android; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; -import android.content.BroadcastReceiver; import android.content.ComponentName; -import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.content.ServiceConnection; import android.os.Binder; +import android.os.Build; import android.os.IBinder; -import android.os.PowerManager; -import android.support.annotation.Nullable; import android.support.v4.app.NotificationCompat; import android.support.v4.content.ContextCompat; @@ -32,15 +28,12 @@ import javax.inject.Inject; import static android.app.PendingIntent.FLAG_UPDATE_CURRENT; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; -import static android.os.Build.VERSION.SDK_INT; -import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED; import static android.support.v4.app.NotificationCompat.CATEGORY_SERVICE; import static android.support.v4.app.NotificationCompat.PRIORITY_MIN; import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET; 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.SUCCESS; -import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting; public class BriarService extends Service { @@ -52,8 +45,6 @@ public class BriarService extends Service { private final AtomicBoolean created = new AtomicBoolean(false); private final Binder binder = new BriarBinder(); - @Nullable - private BriarBroadcastReceiver receiver = null; @Inject protected DatabaseConfig databaseConfig; @@ -62,7 +53,7 @@ public class BriarService extends Service { protected volatile LifecycleManager lifecycleManager; @Inject protected volatile AndroidExecutor androidExecutor; - private volatile boolean started = false, hasDozed = false; + private volatile boolean started = false; @Override public void onCreate() { @@ -93,7 +84,7 @@ public class BriarService extends Service { Intent i = new Intent(this, NavDrawerActivity.class); i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP); b.setContentIntent(PendingIntent.getActivity(this, 0, i, 0)); - if (SDK_INT >= 21) { + if (Build.VERSION.SDK_INT >= 21) { b.setCategory(CATEGORY_SERVICE); b.setVisibility(VISIBILITY_SECRET); } @@ -118,7 +109,6 @@ public class BriarService extends Service { } } }.start(); - registerBroadcastReceiver(); } private void showStartupFailureNotification(StartResult result) { @@ -163,7 +153,6 @@ public class BriarService extends Service { public void onDestroy() { super.onDestroy(); LOG.info("Destroyed"); - if (receiver != null) unregisterReceiver(receiver); stopForeground(true); // Stop the services in a background thread new Thread() { @@ -181,21 +170,6 @@ public class BriarService extends Service { // FIXME: Work out what to do about it } - private void registerBroadcastReceiver() { - if (SDK_INT < 23) return; - IntentFilter filter = new IntentFilter(ACTION_DEVICE_IDLE_MODE_CHANGED); - receiver = new BriarBroadcastReceiver(); - registerReceiver(receiver, filter); - } - - public boolean hasDozed() { - return hasDozed; - } - - public void resetDozeFlag() { - hasDozed = false; - } - /** * Waits for all services to start before returning. */ @@ -251,15 +225,4 @@ public class BriarService extends Service { return binder; } } - - public class BriarBroadcastReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - if (SDK_INT < 23 || !needsDozeWhitelisting(getApplicationContext())) - return; - PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); - if (pm.isDeviceIdleMode()) hasDozed = true; - } - } - } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/DozeWatchdogImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/DozeWatchdogImpl.java new file mode 100644 index 000000000..9b104ca0f --- /dev/null +++ b/briar-android/src/main/java/org/briarproject/briar/android/DozeWatchdogImpl.java @@ -0,0 +1,56 @@ +package org.briarproject.briar.android; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.PowerManager; + +import org.briarproject.bramble.api.lifecycle.Service; +import org.briarproject.bramble.api.lifecycle.ServiceException; +import org.briarproject.briar.api.android.DozeWatchdog; + +import java.util.concurrent.atomic.AtomicBoolean; + +import static android.content.Context.POWER_SERVICE; +import static android.os.Build.VERSION.SDK_INT; +import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED; + +class DozeWatchdogImpl implements DozeWatchdog, Service { + + private final Context appContext; + private final AtomicBoolean dozed = new AtomicBoolean(false); + private final BroadcastReceiver receiver = new DozeBroadcastReceiver(); + + DozeWatchdogImpl(Context appContext) { + this.appContext = appContext; + } + + @Override + public boolean getAndResetDozeFlag() { + return dozed.getAndSet(false); + } + + @Override + public void startService() throws ServiceException { + if (SDK_INT < 23) return; + IntentFilter filter = new IntentFilter(ACTION_DEVICE_IDLE_MODE_CHANGED); + appContext.registerReceiver(receiver, filter); + } + + @Override + public void stopService() throws ServiceException { + appContext.unregisterReceiver(receiver); + } + + private class DozeBroadcastReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + if (SDK_INT < 23) return; + PowerManager pm = + (PowerManager) appContext.getSystemService(POWER_SERVICE); + if (pm.isDeviceIdleMode()) dozed.set(true); + } + } +} 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 64cc194f3..d00730f24 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 @@ -2,7 +2,6 @@ package org.briarproject.briar.android.activity; import android.annotation.SuppressLint; import android.content.Intent; -import android.os.Build; import android.support.v7.app.ActionBar; import android.support.v7.app.AlertDialog; import android.support.v7.widget.Toolbar; @@ -28,6 +27,7 @@ import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK; import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; 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 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.util.UiUtils.getDozeWhitelistingIntent; @@ -64,7 +64,7 @@ public abstract class BriarActivity extends BaseActivity { if (!briarController.hasEncryptionKey() && !isFinishing()) { Intent i = new Intent(this, PasswordActivity.class); startActivityForResult(i, REQUEST_PASSWORD); - } else { + } else if (SDK_INT >= 23) { briarController.hasDozed(new UiResultHandler(this) { @Override public void onResultUi(Boolean result) { @@ -78,7 +78,7 @@ public abstract class BriarActivity extends BaseActivity { } public void setSceneTransitionAnimation() { - if (Build.VERSION.SDK_INT < 21) return; + if (SDK_INT < 21) return; Transition slide = new Slide(Gravity.RIGHT); slide.excludeTarget(android.R.id.statusBarBackground, true); slide.excludeTarget(android.R.id.navigationBarBackground, true); @@ -160,7 +160,7 @@ public abstract class BriarActivity extends BaseActivity { } private void finishAndExit() { - if (Build.VERSION.SDK_INT >= 21) finishAndRemoveTask(); + if (SDK_INT >= 21) finishAndRemoveTask(); else supportFinishAfterTransition(); LOG.info("Exiting"); System.exit(0); 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 9ecd35e91..a8d90dd0c 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 @@ -4,8 +4,6 @@ import android.app.Activity; import android.content.Intent; import android.os.IBinder; import android.support.annotation.CallSuper; -import android.support.annotation.Nullable; -import android.support.annotation.WorkerThread; import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.db.DatabaseExecutor; @@ -15,6 +13,7 @@ import org.briarproject.bramble.api.settings.SettingsManager; import org.briarproject.briar.android.BriarService; import org.briarproject.briar.android.BriarService.BriarServiceConnection; import org.briarproject.briar.android.controller.handler.ResultHandler; +import org.briarproject.briar.api.android.DozeWatchdog; import java.util.concurrent.Executor; import java.util.logging.Logger; @@ -37,22 +36,22 @@ public class BriarControllerImpl implements BriarController { @DatabaseExecutor private final Executor databaseExecutor; private final SettingsManager settingsManager; + private final DozeWatchdog dozeWatchdog; private final Activity activity; private boolean bound = false; - @Nullable - private volatile BriarService service; - @Inject BriarControllerImpl(BriarServiceConnection serviceConnection, DatabaseConfig databaseConfig, @DatabaseExecutor Executor databaseExecutor, - SettingsManager settingsManager, Activity activity) { + SettingsManager settingsManager, DozeWatchdog dozeWatchdog, + Activity activity) { this.serviceConnection = serviceConnection; this.databaseConfig = databaseConfig; this.databaseExecutor = databaseExecutor; this.settingsManager = settingsManager; + this.dozeWatchdog = dozeWatchdog; this.activity = activity; } @@ -81,15 +80,6 @@ public class BriarControllerImpl implements BriarController { activity.startService(new Intent(activity, BriarService.class)); bound = activity.bindService(new Intent(activity, BriarService.class), serviceConnection, 0); - if (!bound) throw new IllegalStateException(); - - new Thread(() -> { - try { - service = getBriarService(); - } catch (InterruptedException e) { - LOG.warning("Interrupted while waiting for service"); - } - }).start(); } @Override @@ -99,13 +89,11 @@ public class BriarControllerImpl implements BriarController { @Override public void hasDozed(ResultHandler handler) { - BriarService briarService = service; - if (briarService == null || !briarService.hasDozed() || - !needsDozeWhitelisting(activity)) { + if (!dozeWatchdog.getAndResetDozeFlag() + || !needsDozeWhitelisting(activity)) { handler.onResult(false); return; } - if (briarService.hasDozed()) briarService.resetDozeFlag(); databaseExecutor.execute(() -> { try { Settings settings = @@ -137,11 +125,12 @@ public class BriarControllerImpl implements BriarController { public void signOut(ResultHandler eventHandler) { new Thread() { @Override - @SuppressWarnings("ConstantConditions") public void run() { try { - if (service == null) service = getBriarService(); // Wait for the service to finish starting up + IBinder binder = serviceConnection.waitForBinder(); + BriarService service = + ((BriarService.BriarBinder) binder).getService(); service.waitForStartup(); // Shut down the service and wait for it to shut down LOG.info("Shutting down service"); @@ -155,12 +144,6 @@ public class BriarControllerImpl implements BriarController { }.start(); } - @WorkerThread - private BriarService getBriarService() throws InterruptedException { - IBinder binder = serviceConnection.waitForBinder(); - return ((BriarService.BriarBinder) binder).getService(); - } - private void unbindService() { if (bound) activity.unbindService(serviceConnection); } diff --git a/briar-android/src/main/java/org/briarproject/briar/api/android/DozeWatchdog.java b/briar-android/src/main/java/org/briarproject/briar/api/android/DozeWatchdog.java new file mode 100644 index 000000000..9b37aebff --- /dev/null +++ b/briar-android/src/main/java/org/briarproject/briar/api/android/DozeWatchdog.java @@ -0,0 +1,6 @@ +package org.briarproject.briar.api.android; + +public interface DozeWatchdog { + + boolean getAndResetDozeFlag(); +} From 9f3a63d8c4dd0cceea1cf03c928b2c5172ca37e6 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Wed, 22 Nov 2017 11:37:58 +0000 Subject: [PATCH 6/6] Don't unregister receiver unless it was registered. --- .../java/org/briarproject/briar/android/DozeWatchdogImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/briar-android/src/main/java/org/briarproject/briar/android/DozeWatchdogImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/DozeWatchdogImpl.java index 9b104ca0f..e6cf8e227 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/DozeWatchdogImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/DozeWatchdogImpl.java @@ -40,6 +40,7 @@ class DozeWatchdogImpl implements DozeWatchdog, Service { @Override public void stopService() throws ServiceException { + if (SDK_INT < 23) return; appContext.unregisterReceiver(receiver); }