From 670bf15d31c189b0297a55c68b1faf17317598ea Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Fri, 22 Jan 2021 14:07:10 -0300 Subject: [PATCH] Move security settings into own screen --- .../briar/android/AndroidComponent.java | 3 + .../android/account/LockManagerImpl.java | 4 +- .../android/settings/SecurityFragment.java | 104 ++++++++++++++++++ .../android/settings/SettingsFragment.java | 67 +---------- .../briar/android/settings/SettingsStore.java | 5 + .../android/settings/SettingsViewModel.java | 32 +++++- .../res/drawable/ic_settings_security.xml | 10 ++ briar-android/src/main/res/xml/settings.xml | 56 +--------- .../src/main/res/xml/settings_security.xml | 54 +++++++++ 9 files changed, 214 insertions(+), 121 deletions(-) create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/settings/SecurityFragment.java create mode 100644 briar-android/src/main/res/drawable/ic_settings_security.xml create mode 100644 briar-android/src/main/res/xml/settings_security.xml 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 417e1a5a3..8a9315e3a 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 @@ -37,6 +37,7 @@ import org.briarproject.briar.android.conversation.glide.BriarModelLoader; import org.briarproject.briar.android.logging.CachingLogHandler; import org.briarproject.briar.android.login.SignInReminderReceiver; import org.briarproject.briar.android.settings.ConnectionsFragment; +import org.briarproject.briar.android.settings.SecurityFragment; import org.briarproject.briar.android.view.EmojiTextInputView; import org.briarproject.briar.api.android.AndroidNotificationManager; import org.briarproject.briar.api.android.DozeWatchdog; @@ -196,4 +197,6 @@ public interface AndroidComponent void inject(BriarModelLoader briarModelLoader); void inject(ConnectionsFragment connectionsFragment); + + void inject(SecurityFragment securityFragment); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/account/LockManagerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/account/LockManagerImpl.java index fb978bd6a..e2e396958 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/account/LockManagerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/account/LockManagerImpl.java @@ -40,8 +40,8 @@ import static android.os.SystemClock.elapsedRealtime; import static java.util.concurrent.TimeUnit.MINUTES; 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.PREF_SCREEN_LOCK_TIMEOUT; +import static org.briarproject.briar.android.settings.SecurityFragment.PREF_SCREEN_LOCK; +import static org.briarproject.briar.android.settings.SecurityFragment.PREF_SCREEN_LOCK_TIMEOUT; import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE; import static org.briarproject.briar.android.util.UiUtils.hasScreenLock; diff --git a/briar-android/src/main/java/org/briarproject/briar/android/settings/SecurityFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/settings/SecurityFragment.java new file mode 100644 index 000000000..241e5812d --- /dev/null +++ b/briar-android/src/main/java/org/briarproject/briar/android/settings/SecurityFragment.java @@ -0,0 +1,104 @@ +package org.briarproject.briar.android.settings; + +import android.content.Context; +import android.os.Bundle; +import android.view.View; + +import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; +import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; +import org.briarproject.briar.R; + +import javax.inject.Inject; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.ViewModelProvider; +import androidx.preference.ListPreference; +import androidx.preference.PreferenceFragmentCompat; +import androidx.preference.SwitchPreference; + +import static android.os.Build.VERSION.SDK_INT; +import static java.util.Objects.requireNonNull; +import static org.briarproject.briar.android.AppModule.getAndroidComponent; +import static org.briarproject.briar.android.settings.SettingsActivity.enableAndPersist; +import static org.briarproject.briar.android.util.UiUtils.hasScreenLock; + +@MethodsNotNullByDefault +@ParametersNotNullByDefault +public class SecurityFragment extends PreferenceFragmentCompat { + + public static final String PREF_SCREEN_LOCK = "pref_key_lock"; + public static final String PREF_SCREEN_LOCK_TIMEOUT = + "pref_key_lock_timeout"; + + @Inject + ViewModelProvider.Factory viewModelFactory; + + private SettingsViewModel viewModel; + private SwitchPreference screenLock; + private ListPreference screenLockTimeout; + + @Override + public void onAttach(@NonNull Context context) { + super.onAttach(context); + getAndroidComponent(context).inject(this); + viewModel = new ViewModelProvider(requireActivity(), viewModelFactory) + .get(SettingsViewModel.class); + } + + @Override + public void onCreatePreferences(Bundle bundle, String s) { + addPreferencesFromResource(R.xml.settings_security); + getPreferenceManager().setPreferenceDataStore(viewModel.settingsStore); + + screenLock = findPreference(PREF_SCREEN_LOCK); + screenLockTimeout = + requireNonNull(findPreference(PREF_SCREEN_LOCK_TIMEOUT)); + + screenLockTimeout.setSummaryProvider(preference -> { + CharSequence timeout = screenLockTimeout.getValue(); + String never = getString(R.string.pref_lock_timeout_value_never); + if (timeout.equals(never)) { + return getString(R.string.pref_lock_timeout_never_summary); + } else { + return getString(R.string.pref_lock_timeout_summary, + screenLockTimeout.getEntry()); + } + }); + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + if (SDK_INT < 21) { + screenLock.setVisible(false); + screenLockTimeout.setVisible(false); + } else { + LifecycleOwner lifecycleOwner = getViewLifecycleOwner(); + if (getActivity() != null && hasScreenLock(getActivity())) { + viewModel.getScreenLockEnabled().observe(lifecycleOwner, on -> { + screenLock.setChecked(on); + enableAndPersist(screenLock); + }); + screenLock.setSummary(R.string.pref_lock_summary); + } else { + screenLock.setEnabled(false); + screenLock.setChecked(false); + screenLock.setSummary(R.string.pref_lock_disabled_summary); + } + // timeout depends on screenLock and gets disabled automatically + viewModel.getScreenLockTimeout().observe(lifecycleOwner, value -> { + screenLockTimeout.setValue(value); + enableAndPersist(screenLockTimeout); + }); + } + } + + @Override + public void onStart() { + super.onStart(); + requireActivity().setTitle(R.string.security_settings_title); + } + +} 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 2f6d70c6b..d45014313 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 @@ -32,7 +32,6 @@ import javax.inject.Inject; import androidx.annotation.Nullable; import androidx.annotation.StringRes; import androidx.core.content.ContextCompat; -import androidx.preference.ListPreference; import androidx.preference.Preference; import androidx.preference.Preference.OnPreferenceChangeListener; import androidx.preference.PreferenceFragmentCompat; @@ -61,7 +60,6 @@ import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.LogUtils.now; 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.util.UiUtils.hasScreenLock; import static org.briarproject.briar.android.util.UiUtils.triggerFeedback; import static org.briarproject.briar.api.android.AndroidNotificationManager.BLOG_CHANNEL_ID; import static org.briarproject.briar.api.android.AndroidNotificationManager.CONTACT_CHANNEL_ID; @@ -82,17 +80,12 @@ public class SettingsFragment extends PreferenceFragmentCompat implements EventListener, OnPreferenceChangeListener { public static final String SETTINGS_NAMESPACE = "android-ui"; - public static final String PREF_SCREEN_LOCK = "pref_key_lock"; - public static final String PREF_SCREEN_LOCK_TIMEOUT = - "pref_key_lock_timeout"; public static final String NOTIFY_SIGN_IN = "pref_key_notify_sign_in"; private static final Logger LOG = Logger.getLogger(SettingsFragment.class.getName()); private SettingsActivity listener; - private SwitchPreference screenLock; - private ListPreference screenLockTimeout; private SwitchPreference notifyPrivateMessages; private SwitchPreference notifyGroupMessages; private SwitchPreference notifyForumPosts; @@ -121,8 +114,6 @@ public class SettingsFragment extends PreferenceFragmentCompat public void onCreatePreferences(Bundle bundle, String s) { addPreferencesFromResource(R.xml.settings); - screenLock = findPreference(PREF_SCREEN_LOCK); - screenLockTimeout = findPreference(PREF_SCREEN_LOCK_TIMEOUT); notifyPrivateMessages = findPreference("pref_key_notify_private_messages"); notifyGroupMessages = findPreference("pref_key_notify_group_messages"); @@ -131,9 +122,6 @@ public class SettingsFragment extends PreferenceFragmentCompat notifyVibration = findPreference("pref_key_notify_vibration"); notifySound = findPreference("pref_key_notify_sound"); - screenLock.setOnPreferenceChangeListener(this); - screenLockTimeout.setOnPreferenceChangeListener(this); - Preference prefFeedback = requireNonNull(findPreference("pref_key_send_feedback")); prefFeedback.setOnPreferenceClickListener(preference -> { @@ -200,8 +188,6 @@ public class SettingsFragment extends PreferenceFragmentCompat // due to events, we might try to display before a load completed if (!settingsLoaded) return; - displayScreenLockSetting(); - if (SDK_INT < 26) { notifyPrivateMessages.setChecked(settings.getBoolean( PREF_NOTIFY_PRIVATE, true)); @@ -253,12 +239,7 @@ public class SettingsFragment extends PreferenceFragmentCompat private void setSettingsEnabled(boolean enabled) { // preferences not needed here, because handled by SharedPreferences: - // - pref_key_theme // - pref_key_notify_sign_in - // preferences partly needed here, because they have their own logic - // - pref_key_lock (screenLock -> displayScreenLockSetting()) - // - pref_key_lock_timeout (screenLockTimeout) - if (!enabled) screenLock.setEnabled(false); notifyPrivateMessages.setEnabled(enabled); notifyGroupMessages.setEnabled(enabled); notifyForumPosts.setEnabled(enabled); @@ -267,42 +248,6 @@ public class SettingsFragment extends PreferenceFragmentCompat notifySound.setEnabled(enabled); } - private void displayScreenLockSetting() { - if (SDK_INT < 21) { - screenLock.setVisible(false); - screenLockTimeout.setVisible(false); - } else { - if (getActivity() != null && hasScreenLock(getActivity())) { - screenLock.setEnabled(true); - screenLock.setChecked( - settings.getBoolean(PREF_SCREEN_LOCK, false)); - screenLock.setSummary(R.string.pref_lock_summary); - } else { - screenLock.setEnabled(false); - screenLock.setChecked(false); - screenLock.setSummary(R.string.pref_lock_disabled_summary); - } - // timeout depends on screenLock and gets disabled automatically - int timeout = settings.getInt(PREF_SCREEN_LOCK_TIMEOUT, - Integer.valueOf(getString( - R.string.pref_lock_timeout_value_default))); - String newValue = String.valueOf(timeout); - screenLockTimeout.setValue(newValue); - setScreenLockTimeoutSummary(newValue); - } - } - - private void setScreenLockTimeoutSummary(String timeout) { - String never = getString(R.string.pref_lock_timeout_value_never); - if (timeout.equals(never)) { - screenLockTimeout - .setSummary(R.string.pref_lock_timeout_never_summary); - } else { - screenLockTimeout - .setSummary(R.string.pref_lock_timeout_summary); - } - } - @TargetApi(26) private void setupNotificationPreference(SwitchPreference pref, String channelId, @StringRes int summary) { @@ -352,17 +297,7 @@ public class SettingsFragment extends PreferenceFragmentCompat @Override public boolean onPreferenceChange(Preference preference, Object newValue) { - if (preference == screenLock) { - Settings s = new Settings(); - s.putBoolean(PREF_SCREEN_LOCK, (Boolean) newValue); - storeSettings(s); - } else if (preference == screenLockTimeout) { - Settings s = new Settings(); - String value = (String) newValue; - s.putInt(PREF_SCREEN_LOCK_TIMEOUT, Integer.parseInt(value)); - storeSettings(s); - setScreenLockTimeoutSummary(value); - } else if (preference == notifyPrivateMessages) { + if (preference == notifyPrivateMessages) { Settings s = new Settings(); s.putBoolean(PREF_NOTIFY_PRIVATE, (Boolean) newValue); storeSettings(s); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsStore.java b/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsStore.java index c009cdef4..23f9f3a11 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsStore.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsStore.java @@ -12,6 +12,7 @@ import androidx.annotation.Nullable; import androidx.preference.PreferenceDataStore; import static java.util.Objects.requireNonNull; +import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import static java.util.logging.Logger.getLogger; import static org.briarproject.bramble.util.LogUtils.logDuration; @@ -42,6 +43,8 @@ class SettingsStore extends PreferenceDataStore { @Override public void putBoolean(String key, boolean value) { + if (LOG.isLoggable(INFO)) + LOG.info("Store bool setting: " + key + "=" + value); Settings s = new Settings(); s.putBoolean(key, value); storeSettings(s); @@ -49,6 +52,8 @@ class SettingsStore extends PreferenceDataStore { @Override public void putInt(String key, int value) { + if (LOG.isLoggable(INFO)) + LOG.info("Store int setting: " + key + "=" + value); Settings s = new Settings(); s.putInt(key, value); storeSettings(s); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsViewModel.java index 23f114c95..805c854d5 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsViewModel.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsViewModel.java @@ -24,6 +24,7 @@ import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent; import org.briarproject.bramble.api.system.AndroidExecutor; import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.plugin.tor.CircumventionProvider; +import org.briarproject.briar.R; import org.briarproject.briar.android.attachment.UnsupportedMimeTypeException; import org.briarproject.briar.android.attachment.media.ImageCompressor; import org.briarproject.briar.android.viewmodel.DbViewModel; @@ -50,6 +51,8 @@ import static org.briarproject.bramble.util.AndroidUtils.getSupportedImageConten import static org.briarproject.bramble.util.LogUtils.logDuration; import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.LogUtils.now; +import static org.briarproject.briar.android.settings.SecurityFragment.PREF_SCREEN_LOCK; +import static org.briarproject.briar.android.settings.SecurityFragment.PREF_SCREEN_LOCK_TIMEOUT; @NotNullByDefault class SettingsViewModel extends DbViewModel implements EventListener { @@ -81,6 +84,10 @@ class SettingsViewModel extends DbViewModel implements EventListener { new MutableLiveData<>(); private final MutableLiveEvent setAvatarFailed = new MutableLiveEvent<>(); + private final MutableLiveData screenLockEnabled = + new MutableLiveData<>(); + private final MutableLiveData screenLockTimeout = + new MutableLiveData<>(); @Inject SettingsViewModel(Application application, @@ -128,6 +135,7 @@ class SettingsViewModel extends DbViewModel implements EventListener { try { long start = now(); settings = settingsManager.getSettings(SETTINGS_NAMESPACE); + updateSettings(settings); connectionsManager.updateBtSetting( settingsManager.getSettings(BT_NAMESPACE)); connectionsManager.updateWifiSettings( @@ -159,7 +167,11 @@ class SettingsViewModel extends DbViewModel implements EventListener { if (e instanceof SettingsUpdatedEvent) { SettingsUpdatedEvent s = (SettingsUpdatedEvent) e; String namespace = s.getNamespace(); - if (namespace.equals(BT_NAMESPACE)) { + if (namespace.equals(SETTINGS_NAMESPACE)) { + LOG.info("Settings updated"); + settings = s.getSettings(); + updateSettings(settings); + } else if (namespace.equals(BT_NAMESPACE)) { LOG.info("Bluetooth settings updated"); connectionsManager.updateBtSetting(s.getSettings()); } else if (namespace.equals(WIFI_NAMESPACE)) { @@ -172,6 +184,16 @@ class SettingsViewModel extends DbViewModel implements EventListener { } } + private void updateSettings(Settings settings) { + screenLockEnabled.postValue(settings.getBoolean(PREF_SCREEN_LOCK, + false)); + int defaultTimeout = Integer.parseInt(getApplication() + .getString(R.string.pref_lock_timeout_value_default)); + screenLockTimeout.postValue(String.valueOf( + settings.getInt(PREF_SCREEN_LOCK_TIMEOUT, defaultTimeout) + )); + } + void setAvatar(Uri uri) { ioExecutor.execute(() -> { try { @@ -215,6 +237,14 @@ class SettingsViewModel extends DbViewModel implements EventListener { return setAvatarFailed; } + LiveData getScreenLockEnabled() { + return screenLockEnabled; + } + + LiveData getScreenLockTimeout() { + return screenLockTimeout; + } + ConnectionsManager getConnectionsManager() { return connectionsManager; } diff --git a/briar-android/src/main/res/drawable/ic_settings_security.xml b/briar-android/src/main/res/drawable/ic_settings_security.xml new file mode 100644 index 000000000..f44f9f25d --- /dev/null +++ b/briar-android/src/main/res/drawable/ic_settings_security.xml @@ -0,0 +1,10 @@ + + + diff --git a/briar-android/src/main/res/xml/settings.xml b/briar-android/src/main/res/xml/settings.xml index 153ae5bed..566d73023 100644 --- a/briar-android/src/main/res/xml/settings.xml +++ b/briar-android/src/main/res/xml/settings.xml @@ -12,58 +12,10 @@ app:fragment="org.briarproject.briar.android.settings.ConnectionsFragment" app:icon="@drawable/ic_connect_without_contact" /> - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + +