Commit d79f1b66 authored by Torsten Grote's avatar Torsten Grote

Move app locking logic into dedicatd LockManager

parent 633f5a8b
......@@ -67,8 +67,4 @@ public interface AccountManager {
* and stored.
*/
boolean changePassword(String oldPassword, String newPassword);
boolean isLocked();
void setLocked(boolean locked);
}
......@@ -45,7 +45,6 @@ class AccountManagerImpl implements AccountManager {
@Nullable
private volatile SecretKey databaseKey = null;
private volatile boolean locked = false;
@Inject
AccountManagerImpl(DatabaseConfig databaseConfig, CryptoComponent crypto,
......@@ -219,16 +218,4 @@ 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;
}
}
}
......@@ -9,26 +9,16 @@ import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.briar.R;
import org.briarproject.briar.android.Localizer;
import org.briarproject.briar.android.util.UiUtils;
import org.briarproject.briar.api.android.AndroidNotificationManager;
import javax.inject.Inject;
class BriarAccountManager extends AndroidAccountManager {
private final AndroidNotificationManager notificationManager;
@Inject
BriarAccountManager(DatabaseConfig databaseConfig, CryptoComponent crypto,
IdentityManager identityManager, SharedPreferences prefs,
Application app, AndroidNotificationManager notificationManager) {
Application app) {
super(databaseConfig, crypto, identityManager, prefs, app);
this.notificationManager = notificationManager;
}
@Override
public void setLocked(boolean locked) {
super.setLocked(locked);
notificationManager.updateForegroundNotification(true, locked);
}
@Override
......
......@@ -28,6 +28,7 @@ import org.briarproject.briar.android.login.SignInReminderReceiver;
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.LockManager;
import org.briarproject.briar.api.android.ScreenFilterMonitor;
import org.briarproject.briar.api.blog.BlogManager;
import org.briarproject.briar.api.blog.BlogPostFactory;
......@@ -146,6 +147,8 @@ public interface AndroidComponent
AccountManager accountManager();
LockManager lockManager();
void inject(SignInReminderReceiver briarService);
void inject(BriarService briarService);
......
......@@ -177,8 +177,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
nc.setLockscreenVisibility(VISIBILITY_SECRET);
nc.enableVibration(true);
nc.enableLights(true);
nc.setLightColor(
getColor(appContext, R.color.briar_green_light));
nc.setLightColor(getColor(appContext, R.color.briar_green_light));
notificationManager.createNotificationChannel(nc);
}
......
......@@ -29,8 +29,10 @@ import org.briarproject.bramble.plugin.tor.AndroidTorPluginFactory;
import org.briarproject.bramble.plugin.tor.CircumventionProvider;
import org.briarproject.bramble.util.AndroidUtils;
import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.android.account.LockManagerImpl;
import org.briarproject.briar.api.android.AndroidNotificationManager;
import org.briarproject.briar.api.android.DozeWatchdog;
import org.briarproject.briar.api.android.LockManager;
import org.briarproject.briar.api.android.ScreenFilterMonitor;
import java.io.File;
......@@ -200,4 +202,12 @@ public class AppModule {
return dozeWatchdog;
}
@Provides
@Singleton
LockManager provideLockManager(LifecycleManager lifecycleManager,
LockManagerImpl lockManager) {
lifecycleManager.registerService(lockManager);
return lockManager;
}
}
package org.briarproject.briar.android.account;
import android.app.Application;
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.MutableLiveData;
import android.content.Context;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.settings.SettingsManager;
import org.briarproject.briar.api.android.AndroidNotificationManager;
import org.briarproject.briar.api.android.LockManager;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
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.hasScreenLock;
@ThreadSafe
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class LockManagerImpl implements LockManager, Service {
private static final Logger LOG =
Logger.getLogger(LockManagerImpl.class.getSimpleName());
private final Context appContext;
private final SettingsManager settingsManager;
private final AndroidNotificationManager notificationManager;
@DatabaseExecutor
private final Executor dbExecutor;
private final MutableLiveData<Boolean> locked = new MutableLiveData<>();
private final MutableLiveData<Boolean> lockable = new MutableLiveData<>();
@Inject
public LockManagerImpl(Application app, SettingsManager settingsManager,
AndroidNotificationManager notificationManager,
@DatabaseExecutor Executor dbExecutor) {
this.appContext = app.getApplicationContext();
this.settingsManager = settingsManager;
this.notificationManager = notificationManager;
this.dbExecutor = dbExecutor;
this.locked.setValue(false);
this.lockable.setValue(false);
}
@Override
public void startService() {
lockable.observeForever(this::onLockableChanged);
if (hasScreenLock(appContext)) {
dbExecutor.execute(() -> {
try {
Settings settings =
settingsManager.getSettings(SETTINGS_NAMESPACE);
boolean lockable =
settings.getBoolean(PREF_SCREEN_LOCK, false);
this.lockable.postValue(lockable);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
});
} else {
lockable.postValue(false);
}
}
@Override
public void stopService() {
lockable.removeObserver(this::onLockableChanged);
}
private void onLockableChanged(boolean lockable) {
notificationManager
.updateForegroundNotification(lockable, locked.getValue());
}
@Override
public LiveData<Boolean> isLockable() {
return lockable;
}
@Override
public void recheckLockable() {
boolean oldValue = this.lockable.getValue();
boolean newValue = hasScreenLock(appContext) && lockable.getValue();
if (oldValue != newValue) {
this.lockable.setValue(newValue);
}
}
@Override
public void updateLockableSetting(boolean lockable) {
boolean oldValue = this.lockable.getValue();
boolean newValue = hasScreenLock(appContext) && lockable;
if (oldValue != newValue) {
this.lockable.setValue(newValue);
}
}
@Override
public LiveData<Boolean> isLocked() {
return locked;
}
@Override
public void setLocked(boolean locked) {
this.locked.setValue(locked);
notificationManager
.updateForegroundNotification(lockable.getValue(), locked);
}
}
......@@ -18,6 +18,7 @@ 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 org.briarproject.briar.api.android.LockManager;
import java.util.logging.Logger;
......@@ -46,10 +47,11 @@ public abstract class BriarActivity extends BaseActivity {
@Inject
BriarController briarController;
@Deprecated
@Inject
DbController dbController;
@Inject
protected LockManager lockManager;
@Override
protected void onActivityResult(int request, int result, Intent data) {
......@@ -68,7 +70,7 @@ 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()) {
} else if(lockManager.isLocked().getValue()) {
Intent i = new Intent(this, UnlockActivity.class);
startActivityForResult(i, REQUEST_UNLOCK);
} else if (SDK_INT >= 23) {
......@@ -82,6 +84,7 @@ public abstract class BriarActivity extends BaseActivity {
}
});
}
lockManager.recheckLockable();
}
public void setSceneTransitionAnimation() {
......@@ -122,6 +125,10 @@ public abstract class BriarActivity extends BaseActivity {
return toolbar;
}
protected void onLockableChanged(boolean lockable) {
}
protected void showDozeDialog(String message) {
AlertDialog.Builder b =
new AlertDialog.Builder(this, R.style.BriarDialogTheme);
......
......@@ -8,8 +8,6 @@ public interface BriarController extends ActivityLifecycleController {
boolean accountSignedIn();
boolean isLocked();
/**
* Returns true via the handler when the app has dozed
* without being white-listed.
......
......@@ -87,11 +87,6 @@ public class BriarControllerImpl implements BriarController {
return accountManager.hasDatabaseKey();
}
@Override
public boolean isLocked() {
return accountManager.isLocked();
}
@Override
public void hasDozed(ResultHandler<Boolean> handler) {
if (!dozeWatchdog.getAndResetDozeFlag()
......
......@@ -15,6 +15,7 @@ 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 org.briarproject.briar.api.android.LockManager;
import java.util.logging.Logger;
......@@ -33,6 +34,8 @@ public class UnlockActivity extends BaseActivity {
@Inject
AccountManager accountManager;
@Inject
LockManager lockManager;
@Override
public void injectActivity(ActivityComponent component) {
......@@ -48,7 +51,7 @@ public class UnlockActivity extends BaseActivity {
Intent intent = getIntent();
if (intent != null && ACTION_LOCK.equals(intent.getAction())) {
accountManager.setLocked(true);
lockManager.setLocked(true);
} else {
requestKeyguardUnlock();
}
......@@ -80,7 +83,7 @@ public class UnlockActivity extends BaseActivity {
}
private void unlock() {
accountManager.setLocked(false);
lockManager.setLocked(false);
setResult(RESULT_OK);
ActivityCompat.finishAfterTransition(this);
}
......
......@@ -42,7 +42,6 @@ import org.briarproject.briar.android.logout.SignOutFragment;
import org.briarproject.briar.android.navdrawer.NavDrawerController.ExpiryWarning;
import org.briarproject.briar.android.privategroup.list.GroupListFragment;
import org.briarproject.briar.android.settings.SettingsActivity;
import org.briarproject.briar.api.android.AndroidNotificationManager;
import java.util.ArrayList;
import java.util.List;
......@@ -61,7 +60,6 @@ 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,
......@@ -82,8 +80,6 @@ public class NavDrawerActivity extends BriarActivity implements
NavDrawerController controller;
@Inject
LifecycleManager lifecycleManager;
@Inject
AndroidNotificationManager notificationManager;
private DrawerLayout drawerLayout;
private NavigationView navigation;
......@@ -141,6 +137,8 @@ public class NavDrawerActivity extends BriarActivity implements
initializeTransports(getLayoutInflater());
transportsView.setAdapter(transportsAdapter);
lockManager.isLockable().observe(this, this::setLockVisible);
if (lifecycleManager.getLifecycleState().isAfter(RUNNING)) {
showSignOutFragment();
} else if (state == null) {
......@@ -157,14 +155,6 @@ public class NavDrawerActivity extends BriarActivity implements
public void onStart() {
super.onStart();
updateTransports();
if (hasScreenLock(this)) {
controller.isLockable(new UiResultHandler<Boolean>(this) {
@Override
public void onResultUi(@NonNull Boolean lockable) {
setLockVisible(lockable);
}
});
} else setLockVisible(false);
controller.showExpiryWarning(new UiResultHandler<ExpiryWarning>(this) {
@Override
public void onResultUi(ExpiryWarning expiry) {
......@@ -227,7 +217,7 @@ public class NavDrawerActivity extends BriarActivity implements
drawerLayout.closeDrawer(START);
clearBackStack();
if (item.getItemId() == R.id.nav_btn_lock) {
controller.lock();
lockManager.setLocked(true);
ActivityCompat.finishAfterTransition(this);
return false;
} else {
......@@ -323,7 +313,6 @@ public class NavDrawerActivity extends BriarActivity implements
private void setLockVisible(boolean visible) {
MenuItem item = navigation.getMenu().findItem(R.id.nav_btn_lock);
if (item != null) item.setVisible(visible);
notificationManager.updateForegroundNotification(visible, false);
}
@SuppressWarnings("ConstantConditions")
......
......@@ -14,10 +14,6 @@ public interface NavDrawerController extends ActivityLifecycleController {
boolean isTransportRunning(TransportId transportId);
void isLockable(ResultHandler<Boolean> handler);
void lock();
void showExpiryWarning(ResultHandler<ExpiryWarning> handler);
void expiryWarningDismissed();
......
......@@ -3,7 +3,6 @@ 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;
......@@ -37,7 +36,6 @@ 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;
......@@ -53,7 +51,6 @@ 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;
......@@ -61,12 +58,10 @@ public class NavDrawerControllerImpl extends DbControllerImpl
@Inject
NavDrawerControllerImpl(@DatabaseExecutor Executor dbExecutor,
LifecycleManager lifecycleManager, PluginManager pluginManager,
SettingsManager settingsManager, AccountManager accountManager,
EventBus eventBus) {
SettingsManager settingsManager, EventBus eventBus) {
super(dbExecutor, lifecycleManager);
this.pluginManager = pluginManager;
this.settingsManager = settingsManager;
this.accountManager = accountManager;
this.eventBus = eventBus;
}
......@@ -112,25 +107,6 @@ public class NavDrawerControllerImpl extends DbControllerImpl
() -> listener.stateUpdate(id, enabled));
}
@Override
public void isLockable(ResultHandler<Boolean> 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<ExpiryWarning> handler) {
if (!IS_DEBUG_BUILD && !IS_BETA_BUILD) {
......
......@@ -41,6 +41,7 @@ import org.briarproject.briar.android.Localizer;
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
import org.briarproject.briar.android.util.UiUtils;
import org.briarproject.briar.android.util.UserFeedback;
import org.briarproject.briar.api.android.LockManager;
import java.util.ArrayList;
import java.util.Collections;
......@@ -140,6 +141,8 @@ public class SettingsFragment extends PreferenceFragmentCompat
@Inject
volatile EventBus eventBus;
@Inject
LockManager lockManager;
@Inject
AndroidExecutor androidExecutor;
......@@ -495,6 +498,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
boolean torBlockedSetting = (Boolean) newValue;
storeTorBlockedSetting(torBlockedSetting);
} else if (preference == screenLock) {
lockManager.updateLockableSetting((Boolean) newValue);
Settings s = new Settings();
s.putBoolean(PREF_SCREEN_LOCK, (Boolean) newValue);
storeSettings(s);
......
......@@ -15,6 +15,7 @@ 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 org.briarproject.briar.api.android.LockManager;
import java.util.logging.Logger;
......@@ -30,6 +31,8 @@ public class SplashScreenActivity extends BaseActivity {
@Inject
protected AccountManager accountManager;
@Inject
protected LockManager lockManager;
@Inject
protected AndroidExecutor androidExecutor;
@Override
......@@ -46,7 +49,7 @@ public class SplashScreenActivity extends BaseActivity {
if (accountManager.hasDatabaseKey()) {
Intent i;
if (accountManager.isLocked()) {
if (lockManager.isLocked().getValue()) {
// 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);
......
......@@ -231,9 +231,10 @@ public class UiUtils {
}
public static boolean hasScreenLock(Context ctx) {
if (SDK_INT < 21) return false;
KeyguardManager keyguardManager = (KeyguardManager) ctx
.getSystemService(Context.KEYGUARD_SERVICE);
if (keyguardManager == null || SDK_INT < 21) return false;
if (keyguardManager == null) 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());
......
package org.briarproject.briar.api.android;
import android.arch.lifecycle.LiveData;
public interface LockManager {
LiveData<Boolean> isLockable();
void recheckLockable();
void updateLockableSetting(boolean lockable);
LiveData<Boolean> isLocked();
void setLocked(boolean locked);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment