mirror of
https://github.com/oxen-io/session-android.git
synced 2025-10-23 21:09:00 +00:00
Migrate to Android fingerprints and auth for Signal screen lock
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2011 Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
@@ -16,32 +16,47 @@
|
||||
*/
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.app.KeyguardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v4.hardware.fingerprint.FingerprintManagerCompat;
|
||||
import android.support.v4.os.CancellationSignal;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.text.SpannableString;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.RelativeSizeSpan;
|
||||
import android.text.style.TypefaceSpan;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.WindowManager;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.BounceInterpolator;
|
||||
import android.view.animation.TranslateAnimation;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.thoughtcrime.securesms.animation.AnimationCompleteListener;
|
||||
import org.thoughtcrime.securesms.components.AnimatingToggle;
|
||||
import org.thoughtcrime.securesms.crypto.InvalidPassphraseException;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
|
||||
import org.thoughtcrime.securesms.util.DynamicIntroTheme;
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
/**
|
||||
* Activity that prompts for a user's passphrase.
|
||||
@@ -50,18 +65,29 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
*/
|
||||
public class PassphrasePromptActivity extends PassphraseActivity {
|
||||
|
||||
private static final String TAG = PassphrasePromptActivity.class.getSimpleName();
|
||||
|
||||
private DynamicIntroTheme dynamicTheme = new DynamicIntroTheme();
|
||||
private DynamicLanguage dynamicLanguage = new DynamicLanguage();
|
||||
|
||||
private ImageView fingerprintPrompt;
|
||||
|
||||
private EditText passphraseText;
|
||||
private ImageButton showButton;
|
||||
private ImageButton hideButton;
|
||||
private AnimatingToggle visibilityToggle;
|
||||
|
||||
private FingerprintManagerCompat fingerprintManager;
|
||||
private CancellationSignal fingerprintCancellationSignal;
|
||||
private FingerprintListener fingerprintListener;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
Log.w(TAG, "onCreate()");
|
||||
dynamicTheme.onCreate(this);
|
||||
dynamicLanguage.onCreate(this);
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.prompt_passphrase_activity);
|
||||
@@ -73,6 +99,19 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||
super.onResume();
|
||||
dynamicTheme.onResume(this);
|
||||
dynamicLanguage.onResume(this);
|
||||
|
||||
if (TextSecurePreferences.isScreenLockEnabled(this)) {
|
||||
resumeScreenLock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
if (TextSecurePreferences.isScreenLockEnabled(this)) {
|
||||
pauseScreenLock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -101,6 +140,17 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void onActivityResult(int requestCode, int resultcode, Intent data) {
|
||||
if (requestCode != 1) return;
|
||||
|
||||
if (resultcode == RESULT_OK) {
|
||||
handleAuthenticated();
|
||||
} else {
|
||||
Log.w(TAG, "Authentication failed");
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleLogSubmit() {
|
||||
Intent intent = new Intent(this, LogSubmitActivity.class);
|
||||
startActivity(intent);
|
||||
@@ -120,6 +170,15 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||
}
|
||||
}
|
||||
|
||||
private void handleAuthenticated() {
|
||||
try {
|
||||
MasterSecret masterSecret = MasterSecretUtil.getMasterSecret(this, MasterSecretUtil.UNENCRYPTED_PASSPHRASE);
|
||||
setMasterSecret(masterSecret);
|
||||
} catch (InvalidPassphraseException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void setPassphraseVisibility(boolean visibility) {
|
||||
int cursorPosition = passphraseText.getSelectionStart();
|
||||
if (visibility) {
|
||||
@@ -133,15 +192,22 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||
}
|
||||
|
||||
private void initializeResources() {
|
||||
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
|
||||
getSupportActionBar().setCustomView(R.layout.centered_app_title);
|
||||
View passphraseAuthContainer = findViewById(R.id.password_auth_container);
|
||||
ImageButton okButton = findViewById(R.id.ok_button);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
|
||||
ImageButton okButton = (ImageButton) findViewById(R.id.ok_button);
|
||||
showButton = findViewById(R.id.passphrase_visibility);
|
||||
hideButton = findViewById(R.id.passphrase_visibility_off);
|
||||
visibilityToggle = findViewById(R.id.button_toggle);
|
||||
passphraseText = findViewById(R.id.passphrase_edit);
|
||||
fingerprintPrompt = findViewById(R.id.fingerprint_auth_container);
|
||||
fingerprintManager = FingerprintManagerCompat.from(this);
|
||||
fingerprintCancellationSignal = new CancellationSignal();
|
||||
fingerprintListener = new FingerprintListener();
|
||||
|
||||
setSupportActionBar(toolbar);
|
||||
getSupportActionBar().setTitle("");
|
||||
|
||||
showButton = (ImageButton) findViewById(R.id.passphrase_visibility);
|
||||
hideButton = (ImageButton) findViewById(R.id.passphrase_visibility_off);
|
||||
visibilityToggle = (AnimatingToggle) findViewById(R.id.button_toggle);
|
||||
passphraseText = (EditText) findViewById(R.id.passphrase_edit);
|
||||
SpannableString hint = new SpannableString(" " + getString(R.string.PassphrasePromptActivity_enter_passphrase));
|
||||
hint.setSpan(new RelativeSizeSpan(0.9f), 0, hint.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
hint.setSpan(new TypefaceSpan("sans-serif"), 0, hint.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
@@ -153,6 +219,48 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||
passphraseText.setOnEditorActionListener(new PassphraseActionListener());
|
||||
passphraseText.setImeActionLabel(getString(R.string.prompt_passphrase_activity__unlock),
|
||||
EditorInfo.IME_ACTION_DONE);
|
||||
|
||||
fingerprintPrompt.setImageResource(R.drawable.ic_fingerprint_white_48dp);
|
||||
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.signal_primary), PorterDuff.Mode.SRC_IN);
|
||||
|
||||
if (TextSecurePreferences.isScreenLockEnabled(this)) {
|
||||
passphraseAuthContainer.setVisibility(View.GONE);
|
||||
fingerprintPrompt.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
passphraseAuthContainer.setVisibility(View.VISIBLE);
|
||||
fingerprintPrompt.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void resumeScreenLock() {
|
||||
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
|
||||
|
||||
assert keyguardManager != null;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && !keyguardManager.isKeyguardSecure()) {
|
||||
Log.w(TAG ,"Keyguard not secure...");
|
||||
handleAuthenticated();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 16 && fingerprintManager.isHardwareDetected() && fingerprintManager.hasEnrolledFingerprints()) {
|
||||
Log.w(TAG, "Listening for fingerprints...");
|
||||
fingerprintCancellationSignal = new CancellationSignal();
|
||||
fingerprintManager.authenticate(null, 0, fingerprintCancellationSignal, fingerprintListener, null);
|
||||
} else if (Build.VERSION.SDK_INT >= 21){
|
||||
Log.w(TAG, "firing intent...");
|
||||
Intent intent = keyguardManager.createConfirmDeviceCredentialIntent("Unlock Signal", "");
|
||||
startActivityForResult(intent, 1);
|
||||
} else {
|
||||
Log.w(TAG, "Not compatible...");
|
||||
handleAuthenticated();
|
||||
}
|
||||
}
|
||||
|
||||
private void pauseScreenLock() {
|
||||
if (Build.VERSION.SDK_INT >= 16 && fingerprintCancellationSignal != null) {
|
||||
fingerprintCancellationSignal.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
private class PassphraseActionListener implements TextView.OnEditorActionListener {
|
||||
@@ -202,4 +310,57 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||
this.passphraseText.setText("");
|
||||
System.gc();
|
||||
}
|
||||
|
||||
private class FingerprintListener extends FingerprintManagerCompat.AuthenticationCallback {
|
||||
@Override
|
||||
public void onAuthenticationError(int errMsgId, CharSequence errString) {
|
||||
Log.w(TAG, "Authentication error: " + errMsgId + " " + errString);
|
||||
onAuthenticationFailed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) {
|
||||
Log.w(TAG, "onAuthenticationSucceeded");
|
||||
fingerprintPrompt.setImageResource(R.drawable.ic_check_white_48dp);
|
||||
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.green_500), PorterDuff.Mode.SRC_IN);
|
||||
fingerprintPrompt.animate().setInterpolator(new BounceInterpolator()).scaleX(1.1f).scaleY(1.1f).setDuration(500).setListener(new AnimationCompleteListener() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
handleAuthenticated();
|
||||
|
||||
fingerprintPrompt.setImageResource(R.drawable.ic_fingerprint_white_48dp);
|
||||
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.signal_primary), PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticationFailed() {
|
||||
Log.w(TAG, "onAuthenticatoinFailed()");
|
||||
FingerprintManagerCompat.AuthenticationCallback callback = this;
|
||||
|
||||
fingerprintPrompt.setImageResource(R.drawable.ic_close_white_48dp);
|
||||
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.red_500), PorterDuff.Mode.SRC_IN);
|
||||
|
||||
TranslateAnimation shake = new TranslateAnimation(0, 30, 0, 0);
|
||||
shake.setDuration(50);
|
||||
shake.setRepeatCount(7);
|
||||
shake.setAnimationListener(new Animation.AnimationListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) {}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
fingerprintPrompt.setImageResource(R.drawable.ic_fingerprint_white_48dp);
|
||||
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.signal_primary), PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animation animation) {}
|
||||
});
|
||||
|
||||
fingerprintPrompt.startAnimation(shake);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,10 @@
|
||||
package org.thoughtcrime.securesms.preferences;
|
||||
|
||||
import android.app.KeyguardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
@@ -18,6 +20,7 @@ import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
|
||||
import org.thoughtcrime.securesms.BlockedContactsActivity;
|
||||
import org.thoughtcrime.securesms.PassphraseChangeActivity;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
|
||||
import org.thoughtcrime.securesms.jobs.MultiDeviceReadReceiptUpdateJob;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
@@ -37,16 +40,16 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
|
||||
|
||||
disablePassphrase = (CheckBoxPreference) this.findPreference("pref_enable_passphrase_temporary");
|
||||
|
||||
this.findPreference(TextSecurePreferences.CHANGE_PASSPHRASE_PREF)
|
||||
.setOnPreferenceClickListener(new ChangePassphraseClickListener());
|
||||
this.findPreference(TextSecurePreferences.PASSPHRASE_TIMEOUT_INTERVAL_PREF)
|
||||
.setOnPreferenceClickListener(new PassphraseIntervalClickListener());
|
||||
this.findPreference(TextSecurePreferences.READ_RECEIPTS_PREF)
|
||||
.setOnPreferenceChangeListener(new ReadReceiptToggleListener());
|
||||
this.findPreference(PREFERENCE_CATEGORY_BLOCKED)
|
||||
.setOnPreferenceClickListener(new BlockedContactsClickListener());
|
||||
disablePassphrase
|
||||
.setOnPreferenceChangeListener(new DisablePassphraseClickListener());
|
||||
this.findPreference(TextSecurePreferences.SCREEN_LOCK).setOnPreferenceChangeListener(new ScreenLockListener());
|
||||
this.findPreference(TextSecurePreferences.SCREEN_LOCK_TIMEOUT).setOnPreferenceClickListener(new ScreenLockTimeoutListener());
|
||||
|
||||
this.findPreference(TextSecurePreferences.CHANGE_PASSPHRASE_PREF).setOnPreferenceClickListener(new ChangePassphraseClickListener());
|
||||
this.findPreference(TextSecurePreferences.PASSPHRASE_TIMEOUT_INTERVAL_PREF).setOnPreferenceClickListener(new PassphraseIntervalClickListener());
|
||||
this.findPreference(TextSecurePreferences.READ_RECEIPTS_PREF).setOnPreferenceChangeListener(new ReadReceiptToggleListener());
|
||||
this.findPreference(PREFERENCE_CATEGORY_BLOCKED).setOnPreferenceClickListener(new BlockedContactsClickListener());
|
||||
disablePassphrase.setOnPreferenceChangeListener(new DisablePassphraseClickListener());
|
||||
|
||||
initializeVisibility();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -59,17 +62,88 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
|
||||
super.onResume();
|
||||
((ApplicationPreferencesActivity) getActivity()).getSupportActionBar().setTitle(R.string.preferences__privacy);
|
||||
|
||||
initializeTimeoutSummary();
|
||||
if (!TextSecurePreferences.isPasswordDisabled(getContext())) initializePassphraseTimeoutSummary();
|
||||
else initializeScreenLockTimeoutSummary();
|
||||
|
||||
disablePassphrase.setChecked(!TextSecurePreferences.isPasswordDisabled(getActivity()));
|
||||
}
|
||||
|
||||
private void initializeTimeoutSummary() {
|
||||
private void initializePassphraseTimeoutSummary() {
|
||||
int timeoutMinutes = TextSecurePreferences.getPassphraseTimeoutInterval(getActivity());
|
||||
this.findPreference(TextSecurePreferences.PASSPHRASE_TIMEOUT_INTERVAL_PREF)
|
||||
.setSummary(getResources().getQuantityString(R.plurals.AppProtectionPreferenceFragment_minutes, timeoutMinutes, timeoutMinutes));
|
||||
}
|
||||
|
||||
private void initializeScreenLockTimeoutSummary() {
|
||||
long timeoutSeconds = TextSecurePreferences.getScreenLockTimeout(getContext());
|
||||
long hours = TimeUnit.SECONDS.toHours(timeoutSeconds);
|
||||
long minutes = TimeUnit.SECONDS.toMinutes(timeoutSeconds) - (TimeUnit.SECONDS.toHours(timeoutSeconds) * 60 );
|
||||
long seconds = TimeUnit.SECONDS.toSeconds(timeoutSeconds) - (TimeUnit.SECONDS.toMinutes(timeoutSeconds) * 60);
|
||||
|
||||
findPreference(TextSecurePreferences.SCREEN_LOCK_TIMEOUT)
|
||||
.setSummary(timeoutSeconds <= 0 ? getString(R.string.AppProtectionPreferenceFragment_none) :
|
||||
String.format("%02d:%02d:%02d", hours, minutes, seconds));
|
||||
}
|
||||
|
||||
private void initializeVisibility() {
|
||||
if (TextSecurePreferences.isPasswordDisabled(getContext())) {
|
||||
findPreference("pref_enable_passphrase_temporary").setVisible(false);
|
||||
findPreference(TextSecurePreferences.CHANGE_PASSPHRASE_PREF).setVisible(false);
|
||||
findPreference(TextSecurePreferences.PASSPHRASE_TIMEOUT_INTERVAL_PREF).setVisible(false);
|
||||
findPreference(TextSecurePreferences.PASSPHRASE_TIMEOUT_PREF).setVisible(false);
|
||||
|
||||
KeyguardManager keyguardManager = (KeyguardManager)getContext().getSystemService(Context.KEYGUARD_SERVICE);
|
||||
if (Build.VERSION.SDK_INT < 16 || !keyguardManager.isKeyguardSecure()) {
|
||||
((SwitchPreferenceCompat)findPreference(TextSecurePreferences.SCREEN_LOCK)).setChecked(false);
|
||||
findPreference(TextSecurePreferences.SCREEN_LOCK).setEnabled(false);
|
||||
}
|
||||
} else {
|
||||
findPreference(TextSecurePreferences.SCREEN_LOCK).setVisible(false);
|
||||
findPreference(TextSecurePreferences.SCREEN_LOCK_TIMEOUT).setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
private class ScreenLockListener implements Preference.OnPreferenceChangeListener {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
TextSecurePreferences.setScreenLockEnabled(getContext(), (Boolean)newValue);
|
||||
|
||||
Intent intent = new Intent(getContext(), KeyCachingService.class);
|
||||
intent.setAction(KeyCachingService.CLEAR_KEY_EVENT);
|
||||
getContext().startService(intent);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class ScreenLockTimeoutListener implements Preference.OnPreferenceClickListener, HmsPickerDialogFragment.HmsPickerDialogHandler {
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
int[] attributes = {R.attr.app_protect_timeout_picker_color};
|
||||
TypedArray hmsStyle = getActivity().obtainStyledAttributes(attributes);
|
||||
|
||||
new HmsPickerBuilder().setFragmentManager(getFragmentManager())
|
||||
.setStyleResId(hmsStyle.getResourceId(0, R.style.BetterPickersDialogFragment_Light))
|
||||
.addHmsPickerDialogHandler(this)
|
||||
.show();
|
||||
|
||||
hmsStyle.recycle();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDialogHmsSet(int reference, int hours, int minutes, int seconds) {
|
||||
long timeoutSeconds = Math.max(TimeUnit.HOURS.toSeconds(hours) +
|
||||
TimeUnit.MINUTES.toSeconds(minutes) +
|
||||
TimeUnit.SECONDS.toSeconds(seconds), 60);
|
||||
|
||||
TextSecurePreferences.setScreenLockTimeout(getContext(), timeoutSeconds);
|
||||
initializeScreenLockTimeoutSummary();
|
||||
}
|
||||
}
|
||||
|
||||
private class BlockedContactsClickListener implements Preference.OnPreferenceClickListener {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
@@ -118,7 +192,7 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
|
||||
(int)TimeUnit.SECONDS.toMinutes(seconds), 1);
|
||||
|
||||
TextSecurePreferences.setPassphraseTimeoutInterval(getActivity(), timeoutMinutes);
|
||||
initializeTimeoutSummary();
|
||||
initializePassphraseTimeoutSummary();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,6 +216,8 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
|
||||
Intent intent = new Intent(getActivity(), KeyCachingService.class);
|
||||
intent.setAction(KeyCachingService.DISABLE_ACTION);
|
||||
getActivity().startService(intent);
|
||||
|
||||
initializeVisibility();
|
||||
});
|
||||
builder.setNegativeButton(android.R.string.cancel, null);
|
||||
builder.show();
|
||||
@@ -171,7 +247,7 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
|
||||
final String onRes = context.getString(R.string.ApplicationPreferencesActivity_on);
|
||||
final String offRes = context.getString(R.string.ApplicationPreferencesActivity_off);
|
||||
|
||||
if (TextSecurePreferences.isPasswordDisabled(context)) {
|
||||
if (TextSecurePreferences.isPasswordDisabled(context) && !TextSecurePreferences.isScreenLockEnabled(context)) {
|
||||
if (TextSecurePreferences.isScreenSecurityEnabled(context)) {
|
||||
return context.getString(privacySummaryResId, offRes, onRes);
|
||||
} else {
|
||||
|
@@ -83,7 +83,7 @@ public class KeyCachingService extends Service {
|
||||
}
|
||||
|
||||
public static synchronized @Nullable MasterSecret getMasterSecret(Context context) {
|
||||
if (masterSecret == null && TextSecurePreferences.isPasswordDisabled(context)) {
|
||||
if (masterSecret == null && (TextSecurePreferences.isPasswordDisabled(context) && !TextSecurePreferences.isScreenLockEnabled(context))) {
|
||||
try {
|
||||
MasterSecret masterSecret = MasterSecretUtil.getMasterSecret(context, MasterSecretUtil.UNENCRYPTED_PASSPHRASE);
|
||||
Intent intent = new Intent(context, KeyCachingService.class);
|
||||
@@ -146,7 +146,7 @@ public class KeyCachingService extends Service {
|
||||
this.pending = PendingIntent.getService(this, 0, new Intent(PASSPHRASE_EXPIRED_EVENT, null,
|
||||
this, KeyCachingService.class), 0);
|
||||
|
||||
if (TextSecurePreferences.isPasswordDisabled(this)) {
|
||||
if (TextSecurePreferences.isPasswordDisabled(this) && !TextSecurePreferences.isScreenLockEnabled(this)) {
|
||||
try {
|
||||
MasterSecret masterSecret = MasterSecretUtil.getMasterSecret(this, MasterSecretUtil.UNENCRYPTED_PASSPHRASE);
|
||||
setMasterSecret(masterSecret);
|
||||
@@ -210,8 +210,11 @@ public class KeyCachingService extends Service {
|
||||
}
|
||||
|
||||
private void handleDisableService() {
|
||||
if (TextSecurePreferences.isPasswordDisabled(this))
|
||||
if (TextSecurePreferences.isPasswordDisabled(this) &&
|
||||
!TextSecurePreferences.isScreenLockEnabled(this))
|
||||
{
|
||||
stopForeground(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleLocaleChanged() {
|
||||
@@ -221,10 +224,19 @@ public class KeyCachingService extends Service {
|
||||
|
||||
private void startTimeoutIfAppropriate() {
|
||||
boolean timeoutEnabled = TextSecurePreferences.isPassphraseTimeoutEnabled(this);
|
||||
long screenTimeout = TextSecurePreferences.getScreenLockTimeout(this);
|
||||
|
||||
if ((activitiesRunning == 0) && (KeyCachingService.masterSecret != null) && timeoutEnabled && !TextSecurePreferences.isPasswordDisabled(this)) {
|
||||
long timeoutMinutes = TextSecurePreferences.getPassphraseTimeoutInterval(this);
|
||||
long timeoutMillis = TimeUnit.MINUTES.toMillis(timeoutMinutes);
|
||||
if ((activitiesRunning == 0) && (KeyCachingService.masterSecret != null) &&
|
||||
(timeoutEnabled && !TextSecurePreferences.isPasswordDisabled(this)) ||
|
||||
(screenTimeout >= 60 && TextSecurePreferences.isScreenLockEnabled(this)))
|
||||
{
|
||||
long passphraseTimeoutMinutes = TextSecurePreferences.getPassphraseTimeoutInterval(this);
|
||||
long screenLockTimeoutSeconds = TextSecurePreferences.getScreenLockTimeout(this);
|
||||
|
||||
long timeoutMillis;
|
||||
|
||||
if (!TextSecurePreferences.isPasswordDisabled(this)) timeoutMillis = TimeUnit.MINUTES.toMillis(passphraseTimeoutMinutes);
|
||||
else timeoutMillis = TimeUnit.SECONDS.toMillis(screenLockTimeoutSeconds);
|
||||
|
||||
Log.w("KeyCachingService", "Starting timeout: " + timeoutMillis);
|
||||
|
||||
@@ -280,7 +292,7 @@ public class KeyCachingService extends Service {
|
||||
}
|
||||
|
||||
private void foregroundService() {
|
||||
if (TextSecurePreferences.isPasswordDisabled(this)) {
|
||||
if (TextSecurePreferences.isPasswordDisabled(this) && !TextSecurePreferences.isScreenLockEnabled(this)) {
|
||||
stopForeground(true);
|
||||
return;
|
||||
}
|
||||
|
@@ -62,7 +62,7 @@ public class TextSecurePreferences {
|
||||
public static final String ALL_MMS_PREF = "pref_all_mms";
|
||||
public static final String ALL_SMS_PREF = "pref_all_sms";
|
||||
public static final String PASSPHRASE_TIMEOUT_INTERVAL_PREF = "pref_timeout_interval";
|
||||
private static final String PASSPHRASE_TIMEOUT_PREF = "pref_timeout_passphrase";
|
||||
public static final String PASSPHRASE_TIMEOUT_PREF = "pref_timeout_passphrase";
|
||||
public static final String SCREEN_SECURITY_PREF = "pref_screen_security";
|
||||
private static final String ENTER_SENDS_PREF = "pref_enter_sends";
|
||||
private static final String ENTER_PRESENT_PREF = "pref_enter_key";
|
||||
@@ -142,6 +142,25 @@ public class TextSecurePreferences {
|
||||
private static final String BACKUP_TIME = "pref_backup_next_time";
|
||||
public static final String BACKUP_NOW = "pref_backup_create";
|
||||
|
||||
public static final String SCREEN_LOCK = "pref_android_screen_lock";
|
||||
public static final String SCREEN_LOCK_TIMEOUT = "pref_android_screen_lock_timeout";
|
||||
|
||||
public static boolean isScreenLockEnabled(@NonNull Context context) {
|
||||
return getBooleanPreference(context, SCREEN_LOCK, false);
|
||||
}
|
||||
|
||||
public static void setScreenLockEnabled(@NonNull Context context, boolean value) {
|
||||
setBooleanPreference(context, SCREEN_LOCK, value);
|
||||
}
|
||||
|
||||
public static long getScreenLockTimeout(@NonNull Context context) {
|
||||
return getLongPreference(context, SCREEN_LOCK_TIMEOUT, 0);
|
||||
}
|
||||
|
||||
public static void setScreenLockTimeout(@NonNull Context context, long value) {
|
||||
setLongPreference(context, SCREEN_LOCK_TIMEOUT, value);
|
||||
}
|
||||
|
||||
public static void setBackupPassphrase(@NonNull Context context, @Nullable String passphrase) {
|
||||
setStringPreference(context, BACKUP_PASSPHRASE, passphrase);
|
||||
}
|
||||
|
Reference in New Issue
Block a user