diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/account/AccountManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/account/AccountManager.java
index 2e1b5a951..45fd48c14 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/account/AccountManager.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/account/AccountManager.java
@@ -67,4 +67,8 @@ public interface AccountManager {
* and stored.
*/
boolean changePassword(String oldPassword, String newPassword);
+
+ boolean isLocked();
+
+ void setLocked(boolean locked);
}
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/account/AccountManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/account/AccountManagerImpl.java
index 7eda4688b..2ebc34e19 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/account/AccountManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/account/AccountManagerImpl.java
@@ -45,6 +45,7 @@ class AccountManagerImpl implements AccountManager {
@Nullable
private volatile SecretKey databaseKey = null;
+ private volatile boolean locked = false;
@Inject
AccountManagerImpl(DatabaseConfig databaseConfig, CryptoComponent crypto,
@@ -218,4 +219,16 @@ class AccountManagerImpl implements AccountManager {
return key != null && encryptAndStoreDatabaseKey(key, newPassword);
}
}
+
+ @Override
+ public boolean isLocked() {
+ return locked;
+ }
+
+ @Override
+ public void setLocked(boolean locked) {
+ synchronized (stateChangeLock) {
+ this.locked = locked;
+ }
+ }
}
diff --git a/briar-android/src/main/AndroidManifest.xml b/briar-android/src/main/AndroidManifest.xml
index cbad8472d..44412ad28 100644
--- a/briar-android/src/main/AndroidManifest.xml
+++ b/briar-android/src/main/AndroidManifest.xml
@@ -402,5 +402,11 @@
android:theme="@android:style/Theme.NoDisplay">
+
+
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/TestingConstants.java b/briar-android/src/main/java/org/briarproject/briar/android/TestingConstants.java
index ea67d50ec..bbcab474b 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/TestingConstants.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/TestingConstants.java
@@ -40,4 +40,9 @@ public interface TestingConstants {
* Feature flag for enabling the sign-in reminder in release builds.
*/
boolean FEATURE_FLAG_SIGN_IN_REMINDER = IS_DEBUG_BUILD;
+
+ /**
+ * Feature flag for enabling the PIN lock in release builds.
+ */
+ boolean FEATURE_FLAG_PIN_LOCK = IS_DEBUG_BUILD;
}
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 1d92a31f3..8a8abb9f8 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
@@ -37,6 +37,7 @@ import org.briarproject.briar.android.login.OpenDatabaseActivity;
import org.briarproject.briar.android.login.PasswordActivity;
import org.briarproject.briar.android.login.PasswordFragment;
import org.briarproject.briar.android.login.SetupActivity;
+import org.briarproject.briar.android.login.UnlockActivity;
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
import org.briarproject.briar.android.panic.PanicPreferencesActivity;
import org.briarproject.briar.android.panic.PanicResponderActivity;
@@ -163,6 +164,8 @@ public interface ActivityComponent {
void inject(StartupFailureActivity activity);
+ void inject(UnlockActivity activity);
+
// Fragments
void inject(AuthorNameFragment fragment);
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 cf71839f9..018803d0b 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
@@ -16,6 +16,7 @@ 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.login.UnlockActivity;
import org.briarproject.briar.android.logout.ExitActivity;
import java.util.logging.Logger;
@@ -30,6 +31,7 @@ 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.activity.RequestCodes.REQUEST_UNLOCK;
import static org.briarproject.briar.android.util.UiUtils.getDozeWhitelistingIntent;
import static org.briarproject.briar.android.util.UiUtils.isSamsung7;
@@ -55,6 +57,8 @@ public abstract class BriarActivity extends BaseActivity {
if (request == REQUEST_PASSWORD) {
if (result == RESULT_OK) briarController.startAndBindService();
else supportFinishAfterTransition();
+ } else if (request == REQUEST_UNLOCK) {
+ if (result != RESULT_OK) supportFinishAfterTransition();
}
}
@@ -64,6 +68,9 @@ public abstract class BriarActivity extends BaseActivity {
if (!briarController.accountSignedIn() && !isFinishing()) {
Intent i = new Intent(this, PasswordActivity.class);
startActivityForResult(i, REQUEST_PASSWORD);
+ } else if(briarController.isLocked()) {
+ Intent i = new Intent(this, UnlockActivity.class);
+ startActivityForResult(i, REQUEST_UNLOCK);
} else if (SDK_INT >= 23) {
briarController.hasDozed(new UiResultHandler(this) {
@Override
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/activity/RequestCodes.java b/briar-android/src/main/java/org/briarproject/briar/android/activity/RequestCodes.java
index 4b8caa3d2..27cc57e09 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/activity/RequestCodes.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/activity/RequestCodes.java
@@ -12,5 +12,6 @@ public interface RequestCodes {
int REQUEST_PERMISSION_CAMERA = 8;
int REQUEST_DOZE_WHITELISTING = 9;
int REQUEST_ENABLE_BLUETOOTH = 10;
+ int REQUEST_UNLOCK = 11;
}
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 e4e60c692..78c824b43 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,6 +8,8 @@ public interface BriarController extends ActivityLifecycleController {
boolean accountSignedIn();
+ boolean isLocked();
+
/**
* Returns true via the handler when the app has dozed
* without being white-listed.
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 1271f4d21..f858bf05a 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
@@ -87,6 +87,11 @@ public class BriarControllerImpl implements BriarController {
return accountManager.hasDatabaseKey();
}
+ @Override
+ public boolean isLocked() {
+ return accountManager.isLocked();
+ }
+
@Override
public void hasDozed(ResultHandler handler) {
if (!dozeWatchdog.getAndResetDozeFlag()
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/UnlockActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/login/UnlockActivity.java
new file mode 100644
index 000000000..bc2129ab3
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/UnlockActivity.java
@@ -0,0 +1,81 @@
+package org.briarproject.briar.android.login;
+
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.annotation.RequiresApi;
+import android.support.v4.app.ActivityCompat;
+import android.widget.Button;
+
+import org.briarproject.bramble.api.account.AccountManager;
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BaseActivity;
+
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+
+import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_UNLOCK;
+
+@RequiresApi(21)
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
+public class UnlockActivity extends BaseActivity {
+
+ private static final Logger LOG =
+ Logger.getLogger(UnlockActivity.class.getSimpleName());
+
+ @Inject
+ AccountManager accountManager;
+
+ @Override
+ public void injectActivity(ActivityComponent component) {
+ component.inject(this);
+ }
+
+ public void onCreate(@Nullable Bundle state) {
+ super.onCreate(state);
+ setContentView(R.layout.activity_unlock);
+
+ Button button = findViewById(R.id.unlock);
+ button.setOnClickListener(view -> requestKeyguardUnlock());
+ requestKeyguardUnlock();
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode,
+ Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == REQUEST_UNLOCK && resultCode == RESULT_OK) {
+ unlock();
+ }
+ }
+
+ private void requestKeyguardUnlock() {
+ KeyguardManager keyguardManager = (KeyguardManager) getSystemService(
+ Context.KEYGUARD_SERVICE);
+ assert keyguardManager != null;
+ Intent intent = keyguardManager
+ .createConfirmDeviceCredentialIntent(getString(R.string.lock_unlock),
+ null);
+ if (intent == null) {
+ // the user must have removed the screen lock since locked
+ LOG.warning("Unlocking without keyguard");
+ unlock();
+ } else {
+ startActivityForResult(intent, REQUEST_UNLOCK);
+ }
+ }
+
+ private void unlock() {
+ accountManager.setLocked(false);
+ setResult(RESULT_OK);
+ ActivityCompat.finishAfterTransition(this);
+ }
+
+}
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 e7800f1db..d75ee60ee 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
@@ -7,6 +7,7 @@ import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.design.widget.NavigationView.OnNavigationItemSelectedListener;
+import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.ContextCompat;
@@ -59,6 +60,7 @@ import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PASSW
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.hasScreenLock;
public class NavDrawerActivity extends BriarActivity implements
BaseFragmentListener, TransportStateListener,
@@ -152,6 +154,14 @@ public class NavDrawerActivity extends BriarActivity implements
public void onStart() {
super.onStart();
updateTransports();
+ if (hasScreenLock(this)) {
+ controller.isLockable(new UiResultHandler(this) {
+ @Override
+ public void onResultUi(@NonNull Boolean lockable) {
+ setLockVisible(lockable);
+ }
+ });
+ } else setLockVisible(false);
controller.showExpiryWarning(new UiResultHandler(this) {
@Override
public void onResultUi(ExpiryWarning expiry) {
@@ -213,9 +223,15 @@ public class NavDrawerActivity extends BriarActivity implements
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
drawerLayout.closeDrawer(START);
clearBackStack();
- loadFragment(item.getItemId());
- // Don't display the Settings item as checked
- return item.getItemId() != R.id.nav_btn_settings;
+ if (item.getItemId() == R.id.nav_btn_lock) {
+ controller.lock();
+ ActivityCompat.finishAfterTransition(this);
+ return false;
+ } else {
+ loadFragment(item.getItemId());
+ // Don't display the Settings item as checked
+ return item.getItemId() != R.id.nav_btn_settings;
+ }
}
@Override
@@ -301,6 +317,11 @@ public class NavDrawerActivity extends BriarActivity implements
// Do nothing for now
}
+ private void setLockVisible(boolean visible) {
+ MenuItem item = navigation.getMenu().findItem(R.id.nav_btn_lock);
+ if (item != null) item.setVisible(visible);
+ }
+
@SuppressWarnings("ConstantConditions")
private void showExpiryWarning(ExpiryWarning expiry) {
int daysUntilExpiry = getDaysUntilExpiry();
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 d2d883e90..b1810c21b 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
@@ -14,6 +14,10 @@ public interface NavDrawerController extends ActivityLifecycleController {
boolean isTransportRunning(TransportId transportId);
+ void isLockable(ResultHandler handler);
+
+ void lock();
+
void showExpiryWarning(ResultHandler handler);
void expiryWarningDismissed();
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 2f851569c..cc35db491 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
@@ -3,6 +3,7 @@ package org.briarproject.briar.android.navdrawer;
import android.app.Activity;
import android.content.Context;
+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.event.Event;
@@ -36,6 +37,7 @@ import static org.briarproject.briar.android.controller.BriarControllerImpl.DOZE
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;
+import static org.briarproject.briar.android.settings.SettingsFragment.PREF_SCREEN_LOCK;
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
@@ -51,6 +53,7 @@ public class NavDrawerControllerImpl extends DbControllerImpl
private final PluginManager pluginManager;
private final SettingsManager settingsManager;
+ private final AccountManager accountManager;
private final EventBus eventBus;
private volatile TransportStateListener listener;
@@ -58,10 +61,12 @@ public class NavDrawerControllerImpl extends DbControllerImpl
@Inject
NavDrawerControllerImpl(@DatabaseExecutor Executor dbExecutor,
LifecycleManager lifecycleManager, PluginManager pluginManager,
- SettingsManager settingsManager, EventBus eventBus) {
+ SettingsManager settingsManager, AccountManager accountManager,
+ EventBus eventBus) {
super(dbExecutor, lifecycleManager);
this.pluginManager = pluginManager;
this.settingsManager = settingsManager;
+ this.accountManager = accountManager;
this.eventBus = eventBus;
}
@@ -107,6 +112,25 @@ public class NavDrawerControllerImpl extends DbControllerImpl
() -> listener.stateUpdate(id, enabled));
}
+ @Override
+ public void isLockable(ResultHandler handler) {
+ runOnDbThread(() -> {
+ try {
+ Settings settings =
+ settingsManager.getSettings(SETTINGS_NAMESPACE);
+ boolean ask = settings.getBoolean(PREF_SCREEN_LOCK, false);
+ handler.onResult(ask);
+ } catch (DbException e) {
+ logException(LOG, WARNING, e);
+ }
+ });
+ }
+
+ @Override
+ public void lock() {
+ accountManager.setLocked(true);
+ }
+
@Override
public void showExpiryWarning(ResultHandler handler) {
if (!IS_DEBUG_BUILD && !IS_BETA_BUILD) {
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsFragment.java
index 3fd878376..e263d40ed 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsFragment.java
@@ -82,10 +82,12 @@ import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now;
import static org.briarproject.bramble.util.StringUtils.join;
import static org.briarproject.briar.android.TestingConstants.FEATURE_FLAG_DARK_THEME;
+import static org.briarproject.briar.android.TestingConstants.FEATURE_FLAG_PIN_LOCK;
import static org.briarproject.briar.android.TestingConstants.FEATURE_FLAG_SIGN_IN_REMINDER;
import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_RINGTONE;
import static org.briarproject.briar.android.navdrawer.NavDrawerActivity.INTENT_SIGN_OUT;
+import static org.briarproject.briar.android.util.UiUtils.hasScreenLock;
import static org.briarproject.briar.api.android.AndroidNotificationManager.BLOG_CHANNEL_ID;
import static org.briarproject.briar.api.android.AndroidNotificationManager.CONTACT_CHANNEL_ID;
import static org.briarproject.briar.api.android.AndroidNotificationManager.FORUM_CHANNEL_ID;
@@ -109,6 +111,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
public static final String BT_NAMESPACE = BluetoothConstants.ID.getString();
public static final String TOR_NAMESPACE = TorConstants.ID.getString();
public static final String LANGUAGE = "pref_key_language";
+ public static final String PREF_SCREEN_LOCK = "pref_key_lock";
public static final String NOTIFY_SIGN_IN = "pref_key_notify_sign_in";
public static final String TOR_LOCATION = "pref_key_tor_location";
@@ -120,6 +123,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
private ListPreference enableBluetooth;
private ListPreference torNetwork;
private CheckBoxPreference torBlocked;
+ private CheckBoxPreference screenLock;
private CheckBoxPreference notifyPrivateMessages;
private CheckBoxPreference notifyGroupMessages;
private CheckBoxPreference notifyForumPosts;
@@ -162,6 +166,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
setBlockedCountries();
CheckBoxPreference notifySignIn =
(CheckBoxPreference) findPreference(NOTIFY_SIGN_IN);
+ screenLock = (CheckBoxPreference) findPreference(PREF_SCREEN_LOCK);
notifyPrivateMessages = (CheckBoxPreference) findPreference(
"pref_key_notify_private_messages");
notifyGroupMessages = (CheckBoxPreference) findPreference(
@@ -200,6 +205,12 @@ public class SettingsFragment extends PreferenceFragmentCompat
enableBluetooth.setOnPreferenceChangeListener(this);
torNetwork.setOnPreferenceChangeListener(this);
torBlocked.setOnPreferenceChangeListener(this);
+ if (getActivity() != null && hasScreenLock(getActivity())) {
+ screenLock.setVisible(FEATURE_FLAG_PIN_LOCK);
+ screenLock.setOnPreferenceChangeListener(this);
+ } else {
+ screenLock.setVisible(false);
+ }
if (SDK_INT >= 21) {
notifyLockscreen.setVisible(true);
notifyLockscreen.setOnPreferenceChangeListener(this);
@@ -340,8 +351,10 @@ public class SettingsFragment extends PreferenceFragmentCompat
PREF_TOR_NETWORK_ALWAYS);
boolean torBlockedSetting =
torSettings.getBoolean(PREF_TOR_DISABLE_BLOCKED, true);
- displaySettings(btSetting, torNetworkSetting,
- torBlockedSetting);
+ boolean screenLockSetting =
+ settings.getBoolean(PREF_SCREEN_LOCK, false);
+ displaySettings(btSetting, torNetworkSetting, torBlockedSetting,
+ screenLockSetting);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
@@ -349,11 +362,12 @@ public class SettingsFragment extends PreferenceFragmentCompat
}
private void displaySettings(boolean btSetting, int torNetworkSetting,
- boolean torBlockedSetting) {
+ boolean torBlockedSetting, boolean screenLockSetting) {
listener.runOnUiThreadUnlessDestroyed(() -> {
enableBluetooth.setValue(Boolean.toString(btSetting));
torNetwork.setValue(Integer.toString(torNetworkSetting));
torBlocked.setChecked(torBlockedSetting);
+ screenLock.setChecked(screenLockSetting);
if (SDK_INT < 26) {
notifyPrivateMessages.setChecked(settings.getBoolean(
@@ -414,6 +428,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
enableBluetooth.setEnabled(enabled);
torNetwork.setEnabled(enabled);
torBlocked.setEnabled(enabled);
+ screenLock.setEnabled(enabled);
notifyPrivateMessages.setEnabled(enabled);
notifyGroupMessages.setEnabled(enabled);
notifyForumPosts.setEnabled(enabled);
@@ -478,6 +493,10 @@ public class SettingsFragment extends PreferenceFragmentCompat
} else if (preference == torBlocked) {
boolean torBlockedSetting = (Boolean) newValue;
storeTorBlockedSetting(torBlockedSetting);
+ } else if (preference == screenLock) {
+ Settings s = new Settings();
+ s.putBoolean(PREF_SCREEN_LOCK, (Boolean) newValue);
+ storeSettings(s);
} else if (preference == notifyPrivateMessages) {
Settings s = new Settings();
s.putBoolean(PREF_NOTIFY_PRIVATE, (Boolean) newValue);
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/splash/SplashScreenActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/splash/SplashScreenActivity.java
index e878d2376..4a6f56485 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/splash/SplashScreenActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/splash/SplashScreenActivity.java
@@ -14,6 +14,7 @@ import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BaseActivity;
import org.briarproject.briar.android.login.OpenDatabaseActivity;
import org.briarproject.briar.android.login.SetupActivity;
+import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
import java.util.logging.Logger;
@@ -44,7 +45,15 @@ public class SplashScreenActivity extends BaseActivity {
setContentView(R.layout.splash);
if (accountManager.hasDatabaseKey()) {
- startActivity(new Intent(this, OpenDatabaseActivity.class));
+ Intent i;
+ if (accountManager.isLocked()) {
+ // The database is already open, so start main activity which
+ // will open the activity to unlock, then brings main to front.
+ i = new Intent(this, NavDrawerActivity.class);
+ } else {
+ i = new Intent(this, OpenDatabaseActivity.class);
+ }
+ startActivity(i);
finish();
} else {
new Handler().postDelayed(() -> {
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java b/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java
index ee30d8d37..0daf3a8ae 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java
@@ -2,6 +2,7 @@ package org.briarproject.briar.android.util;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
+import android.app.KeyguardManager;
import android.content.Context;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
@@ -229,4 +230,13 @@ public class UiUtils {
return ContextCompat.getColor(ctx, color);
}
+ public static boolean hasScreenLock(Context ctx) {
+ KeyguardManager keyguardManager = (KeyguardManager) ctx
+ .getSystemService(Context.KEYGUARD_SERVICE);
+ if (keyguardManager == null || SDK_INT < 21) return false;
+ // check if there's a lock mechanism we can use, try to ignore SIM
+ return (SDK_INT < 23 && keyguardManager.isKeyguardSecure()) ||
+ (SDK_INT >= 23 && keyguardManager.isDeviceSecure());
+ }
+
}
diff --git a/briar-android/src/main/res/layout/activity_unlock.xml b/briar-android/src/main/res/layout/activity_unlock.xml
new file mode 100644
index 000000000..c4c3086f0
--- /dev/null
+++ b/briar-android/src/main/res/layout/activity_unlock.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/briar-android/src/main/res/menu/navigation_drawer.xml b/briar-android/src/main/res/menu/navigation_drawer.xml
index befb4faa2..6f3606d0f 100644
--- a/briar-android/src/main/res/menu/navigation_drawer.xml
+++ b/briar-android/src/main/res/menu/navigation_drawer.xml
@@ -26,6 +26,11 @@
android:id="@+id/nav_btn_settings"
android:icon="@drawable/ic_settings_black_24dp"
android:title="@string/settings_button"/>
+
- Private Groups
Forums
Blogs
+ Lock App
Settings
Sign Out
@@ -356,6 +357,8 @@
Security
+ Screen Lock
+ Lock app access with Android screen lock or fingerprint
Change password
Current password
New password
@@ -444,4 +447,10 @@
Camera permission was not granted
QR code
Show QR code fullscreen
+
+
+ Unlock Briar
+ Briar is locked
+ Tap to unlock
+
diff --git a/briar-android/src/main/res/xml/settings.xml b/briar-android/src/main/res/xml/settings.xml
index 7f943ba89..bc5a2a3f7 100644
--- a/briar-android/src/main/res/xml/settings.xml
+++ b/briar-android/src/main/res/xml/settings.xml
@@ -56,6 +56,13 @@
android:layout="@layout/preferences_category"
android:title="@string/security_settings_title">
+
+