mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-21 02:08:40 +00:00
Add lock screen help dialog.
This commit is contained in:
committed by
Cody Henthorne
parent
058c523329
commit
47cd1b568f
@@ -661,7 +661,7 @@
|
||||
|
||||
<activity android:name=".PassphrasePromptActivity"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/TextSecure.LightIntroTheme"
|
||||
android:theme="@style/Theme.Signal.DayNight.NoActionBar"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
||||
android:exported="false"/>
|
||||
|
||||
|
||||
@@ -44,10 +44,13 @@ import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.biometric.BiometricManager;
|
||||
import androidx.biometric.BiometricPrompt;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
|
||||
import org.signal.core.util.ThreadUtil;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.animation.AnimationCompleteListener;
|
||||
@@ -55,6 +58,7 @@ 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.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.logsubmit.SubmitDebugLogActivity;
|
||||
import org.thoughtcrime.securesms.util.CommunicationActions;
|
||||
import org.thoughtcrime.securesms.util.DynamicIntroTheme;
|
||||
@@ -74,7 +78,8 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||
private static final String TAG = Log.tag(PassphrasePromptActivity.class);
|
||||
private static final short AUTHENTICATE_REQUEST_CODE = 1007;
|
||||
private static final String BUNDLE_ALREADY_SHOWN = "bundle_already_shown";
|
||||
public static final String FROM_FOREGROUND = "from_foreground";
|
||||
public static final String FROM_FOREGROUND = "from_foreground";
|
||||
private static final int HELP_COUNT_THRESHOLD = 3;
|
||||
|
||||
private DynamicIntroTheme dynamicTheme = new DynamicIntroTheme();
|
||||
private DynamicLanguage dynamicLanguage = new DynamicLanguage();
|
||||
@@ -188,6 +193,7 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||
} else {
|
||||
Log.w(TAG, "Authentication failed");
|
||||
hadFailure = true;
|
||||
incrementAttemptCountAndShowHelpIfNecessary();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,6 +213,7 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||
passphraseText.setText("");
|
||||
passphraseText.setError(
|
||||
getString(R.string.PassphrasePromptActivity_invalid_passphrase_exclamation));
|
||||
incrementAttemptCountAndShowHelpIfNecessary();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,6 +223,7 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||
|
||||
MasterSecret masterSecret = MasterSecretUtil.getMasterSecret(this, MasterSecretUtil.UNENCRYPTED_PASSPHRASE);
|
||||
setMasterSecret(masterSecret);
|
||||
SignalStore.misc().setLockScreenAttemptCount(0);
|
||||
} catch (InvalidPassphraseException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
@@ -272,6 +280,10 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.core_ultramarine), PorterDuff.Mode.SRC_IN);
|
||||
|
||||
lockScreenButton.setOnClickListener(v -> resumeScreenLock(true));
|
||||
|
||||
if (SignalStore.misc().getLockScreenAttemptCount() > HELP_COUNT_THRESHOLD) {
|
||||
showHelpDialogAndResetAttemptCount(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void setLockTypeVisibility() {
|
||||
@@ -288,6 +300,10 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||
}
|
||||
|
||||
private void resumeScreenLock(boolean force) {
|
||||
if (incrementAttemptCountAndShowHelpIfNecessary(() -> resumeScreenLock(force))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!biometricAuth.authenticate(getApplicationContext(), force, this::showConfirmDeviceCredentialIntent)) {
|
||||
handleAuthenticated();
|
||||
}
|
||||
@@ -312,6 +328,33 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
|
||||
private boolean incrementAttemptCountAndShowHelpIfNecessary() {
|
||||
return incrementAttemptCountAndShowHelpIfNecessary(null);
|
||||
}
|
||||
|
||||
private boolean incrementAttemptCountAndShowHelpIfNecessary(Runnable onDismissed) {
|
||||
SignalStore.misc().incrementLockScreenAttemptCount();
|
||||
|
||||
if (SignalStore.misc().getLockScreenAttemptCount() > HELP_COUNT_THRESHOLD) {
|
||||
showHelpDialogAndResetAttemptCount(onDismissed);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void showHelpDialogAndResetAttemptCount(@Nullable Runnable onDismissed) {
|
||||
new MaterialAlertDialogBuilder(this)
|
||||
.setMessage(R.string.PassphrasePromptActivity_help_prompt_body)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||
SignalStore.misc().setLockScreenAttemptCount(0);
|
||||
if (onDismissed != null) {
|
||||
onDismissed.run();
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
private class PassphraseActionListener implements TextView.OnEditorActionListener {
|
||||
@Override
|
||||
public boolean onEditorAction(TextView exampleView, int actionId, KeyEvent keyEvent) {
|
||||
@@ -366,6 +409,8 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||
Log.w(TAG, "Authentication error: " + errorCode);
|
||||
hadFailure = true;
|
||||
|
||||
incrementAttemptCountAndShowHelpIfNecessary();
|
||||
|
||||
if (errorCode != BiometricPrompt.ERROR_CANCELED && errorCode != BiometricPrompt.ERROR_USER_CANCELED) {
|
||||
onAuthenticationFailed();
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ class MiscellaneousValues internal constructor(store: KeyValueStore) : SignalSto
|
||||
private const val LINKED_DEVICE_LAST_ACTIVE_CHECK_TIME = "misc.linked_device.last_active_check_time"
|
||||
private const val LEAST_ACTIVE_LINKED_DEVICE = "misc.linked_device.least_active"
|
||||
private const val NEXT_DATABASE_ANALYSIS_TIME = "misc.next_database_analysis_time"
|
||||
private const val LOCK_SCREEN_ATTEMPT_COUNT = "misc.lock_screen_attempt_count"
|
||||
}
|
||||
|
||||
public override fun onFirstEverAppLaunch() {
|
||||
@@ -248,4 +249,13 @@ class MiscellaneousValues internal constructor(store: KeyValueStore) : SignalSto
|
||||
* When the next scheduled database analysis is.
|
||||
*/
|
||||
var nextDatabaseAnalysisTime: Long by longValue(NEXT_DATABASE_ANALYSIS_TIME, 0)
|
||||
|
||||
/**
|
||||
* How many times the lock screen has been seen and _not_ unlocked. Used to determine if the user is confused by how to bypass the lock screen.
|
||||
*/
|
||||
var lockScreenAttemptCount: Int by integerValue(LOCK_SCREEN_ATTEMPT_COUNT, 0)
|
||||
|
||||
fun incrementLockScreenAttemptCount() {
|
||||
lockScreenAttemptCount++
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7127,6 +7127,8 @@
|
||||
<string name="RemoteBackupsSettingsFragment__monthly">Monthly</string>
|
||||
<!-- Title for frequency option DAILY for backup frequency -->
|
||||
<string name="RemoteBackupsSettingsFragment__manually_back_up">Manually back up</string>
|
||||
<!-- The body of an alert dialog shown when we detect the user may be confused by the lock screen -->
|
||||
<string name="PassphrasePromptActivity_help_prompt_body">Please enter your device pin, password or pattern.</string>
|
||||
|
||||
<!-- EOF -->
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user