Merge "Call reportFailedPasswordAttempt from Work Challenge" into nyc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
42ed344f4b
@@ -1130,6 +1130,21 @@
|
||||
<!-- Title shown on security settings to allow the user to change their lockscreen password [CHAR LIMIT=22]-->
|
||||
<string name="unlock_change_lock_password_title">Change unlock password</string>
|
||||
|
||||
<!-- Message shown when the user incorrectly enters their lock and it counts towards the max attempts before wiping the work profile. -->
|
||||
<string name="lock_profile_wipe_attempts">Try again. Attempt <xliff:g id="current_attempts">%1$d</xliff:g> of <xliff:g id="total_attempts">%2$d</xliff:g>.</string>
|
||||
<!-- Title of a dialog shown when the user only has one attempt left to provide the lock before the work profile is wiped. -->
|
||||
<string name="lock_profile_wipe_warning_title">Last try</string>
|
||||
<!-- Content of the dialog shown when the user only has one attempt left to provide the work pattern before the work profile is wiped. -->
|
||||
<string name="lock_profile_wipe_warning_content_pattern">If you enter an incorrect work pattern on this attempt, your work profile and associated data will be removed from this device.</string>
|
||||
<!-- Content of the dialog shown when the user only has one attempt left to provide the work PIN before the work profile is wiped. -->
|
||||
<string name="lock_profile_wipe_warning_content_pin">If you enter an incorrect work PIN on this attempt, your work profile and associated data will be removed from this device.</string>
|
||||
<!-- Content of the dialog shown when the user only has one attempt left to provide the work password before the work profile is wiped. -->
|
||||
<string name="lock_profile_wipe_warning_content_password">If you enter an incorrect work password on this attempt, your work profile and associated data will be removed from this device.</string>
|
||||
<!-- Content of the dialog shown when the user has failed to provide the work lock too many times and the work profile is wiped. -->
|
||||
<string name="lock_profile_wipe_content">Too many incorrect attempts. Your work profile and associated data will be removed from this device.</string>
|
||||
<!-- Button label to dismiss the dialog telling the user the work profile has been wiped. [CHAR LIMIT=40] -->
|
||||
<string name="lock_profile_wipe_dismiss">Dismiss</string>
|
||||
|
||||
<!-- Hint shown in dialog screen when password is too short -->
|
||||
<string name="lockpassword_password_too_short">Password must be at least %d characters</string>
|
||||
<!-- Hint shown in dialog screen when PIN is too short -->
|
||||
|
@@ -20,10 +20,13 @@ import android.annotation.Nullable;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManagerNative;
|
||||
import android.app.ActivityOptions;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.IActivityManager;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.trust.TrustManager;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
import android.graphics.Point;
|
||||
@@ -31,7 +34,9 @@ import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -40,6 +45,7 @@ import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.settings.fingerprint.FingerprintUiHelper;
|
||||
|
||||
/**
|
||||
@@ -65,6 +71,9 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
|
||||
protected Button mCancelButton;
|
||||
protected ImageView mFingerprintIcon;
|
||||
protected int mEffectiveUserId;
|
||||
protected LockPatternUtils mLockPatternUtils;
|
||||
protected TextView mErrorTextView;
|
||||
protected final Handler mHandler = new Handler();
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
@@ -74,6 +83,7 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
|
||||
// Only take this argument into account if it belongs to the current profile.
|
||||
Intent intent = getActivity().getIntent();
|
||||
mEffectiveUserId = Utils.getUserIdFromBundle(getActivity(), intent.getExtras());
|
||||
mLockPatternUtils = new LockPatternUtils(getActivity());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -109,6 +119,10 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
|
||||
if (mAllowFpAuthentication) {
|
||||
mFingerprintHelper.startListening();
|
||||
}
|
||||
if (isProfileChallenge()) {
|
||||
updateErrorMessage(mLockPatternUtils.getCurrentFailedPasswordAttempts(
|
||||
mEffectiveUserId));
|
||||
}
|
||||
}
|
||||
|
||||
protected void setAccessibilityTitle(CharSequence suplementalText) {
|
||||
@@ -200,4 +214,87 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
|
||||
screenSize.y));
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isProfileChallenge() {
|
||||
return UserHandle.myUserId() != mEffectiveUserId;
|
||||
}
|
||||
|
||||
protected void reportSuccessfullAttempt() {
|
||||
if (isProfileChallenge()) {
|
||||
mLockPatternUtils.reportSuccessfulPasswordAttempt(mEffectiveUserId);
|
||||
}
|
||||
}
|
||||
|
||||
protected void reportFailedAttempt() {
|
||||
if (isProfileChallenge()) {
|
||||
// + 1 for this attempt.
|
||||
updateErrorMessage(
|
||||
mLockPatternUtils.getCurrentFailedPasswordAttempts(mEffectiveUserId) + 1);
|
||||
mLockPatternUtils.reportFailedPasswordAttempt(mEffectiveUserId);
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateErrorMessage(int numAttempts) {
|
||||
final int maxAttempts =
|
||||
mLockPatternUtils.getMaximumFailedPasswordsForWipe(mEffectiveUserId);
|
||||
if (maxAttempts > 0 && numAttempts > 0) {
|
||||
int remainingAttempts = maxAttempts - numAttempts;
|
||||
if (remainingAttempts == 1) {
|
||||
// Last try
|
||||
final String title = getActivity().getString(
|
||||
R.string.lock_profile_wipe_warning_title);
|
||||
final String message = getActivity().getString(getLastTryErrorMessage());
|
||||
showDialog(title, message, android.R.string.ok, false /* dismiss */);
|
||||
} else if (remainingAttempts <= 0) {
|
||||
// Profile is wiped
|
||||
final String message = getActivity().getString(R.string.lock_profile_wipe_content);
|
||||
showDialog(null, message, R.string.lock_profile_wipe_dismiss, true /* dismiss */);
|
||||
}
|
||||
if (mErrorTextView != null) {
|
||||
final String message = getActivity().getString(R.string.lock_profile_wipe_attempts,
|
||||
numAttempts, maxAttempts);
|
||||
showError(message, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract int getLastTryErrorMessage();
|
||||
|
||||
private final Runnable mResetErrorRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mErrorTextView.setText("");
|
||||
}
|
||||
};
|
||||
|
||||
protected void showError(CharSequence msg, long timeout) {
|
||||
mErrorTextView.setText(msg);
|
||||
onShowError();
|
||||
mHandler.removeCallbacks(mResetErrorRunnable);
|
||||
if (timeout != 0) {
|
||||
mHandler.postDelayed(mResetErrorRunnable, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void onShowError();
|
||||
|
||||
protected void showError(int msg, long timeout) {
|
||||
showError(getText(msg), timeout);
|
||||
}
|
||||
|
||||
private void showDialog(String title, String message, int buttonString, final boolean dismiss) {
|
||||
final AlertDialog dialog = new AlertDialog.Builder(getActivity())
|
||||
.setTitle(title)
|
||||
.setMessage(message)
|
||||
.setPositiveButton(buttonString, new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (dismiss) {
|
||||
getActivity().finish();
|
||||
}
|
||||
}
|
||||
})
|
||||
.create();
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
|
@@ -20,11 +20,9 @@ import android.app.Fragment;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.CountDownTimer;
|
||||
import android.os.Handler;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserManager;
|
||||
import android.os.storage.StorageManager;
|
||||
@@ -84,14 +82,11 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
private static final String FRAGMENT_TAG_CHECK_LOCK_RESULT = "check_lock_result";
|
||||
private TextView mPasswordEntry;
|
||||
private TextViewInputDisabler mPasswordEntryInputDisabler;
|
||||
private LockPatternUtils mLockPatternUtils;
|
||||
private AsyncTask<?, ?, ?> mPendingLockCheck;
|
||||
private CredentialCheckResultTracker mCredentialCheckResultTracker;
|
||||
private boolean mDisappearing = false;
|
||||
private TextView mHeaderTextView;
|
||||
private TextView mDetailsTextView;
|
||||
private TextView mErrorTextView;
|
||||
private Handler mHandler = new Handler();
|
||||
private CountDownTimer mCountdownTimer;
|
||||
private boolean mIsAlpha;
|
||||
private InputMethodManager mImm;
|
||||
@@ -108,7 +103,6 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mLockPatternUtils = new LockPatternUtils(getActivity());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -193,6 +187,12 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
: R.string.lockpassword_invalid_pin;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLastTryErrorMessage() {
|
||||
return mIsAlpha ? R.string.lock_profile_wipe_warning_content_password
|
||||
: R.string.lock_profile_wipe_warning_content_pin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareEnterAnimation() {
|
||||
super.prepareEnterAnimation();
|
||||
@@ -406,9 +406,12 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
}
|
||||
|
||||
private void onPasswordChecked(boolean matched, Intent intent, int timeoutMs,
|
||||
int effectiveUserId) {
|
||||
int effectiveUserId, boolean newResult) {
|
||||
mPasswordEntryInputDisabler.setInputEnabled(true);
|
||||
if (matched) {
|
||||
if (newResult) {
|
||||
reportSuccessfullAttempt();
|
||||
}
|
||||
startDisappearAnimation(intent);
|
||||
checkForPendingIntent();
|
||||
} else {
|
||||
@@ -417,15 +420,23 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
effectiveUserId, timeoutMs);
|
||||
handleAttemptLockout(deadline);
|
||||
} else {
|
||||
showError(getErrorMessage());
|
||||
showError(getErrorMessage(), ERROR_MESSAGE_TIMEOUT);
|
||||
}
|
||||
if (newResult) {
|
||||
reportFailedAttempt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCredentialChecked(boolean matched, Intent intent, int timeoutMs,
|
||||
int effectiveUserId) {
|
||||
onPasswordChecked(matched, intent, timeoutMs, effectiveUserId);
|
||||
int effectiveUserId, boolean newResult) {
|
||||
onPasswordChecked(matched, intent, timeoutMs, effectiveUserId, newResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShowError() {
|
||||
mPasswordEntry.setText(null);
|
||||
}
|
||||
|
||||
private void handleAttemptLockout(long elapsedRealtimeDeadline) {
|
||||
@@ -447,6 +458,10 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
public void onFinish() {
|
||||
resetState();
|
||||
mErrorTextView.setText("");
|
||||
if (isProfileChallenge()) {
|
||||
updateErrorMessage(mLockPatternUtils.getCurrentFailedPasswordAttempts(
|
||||
mEffectiveUserId));
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
@@ -464,29 +479,6 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
}
|
||||
}
|
||||
|
||||
private void showError(int msg) {
|
||||
showError(msg, ERROR_MESSAGE_TIMEOUT);
|
||||
}
|
||||
|
||||
private final Runnable mResetErrorRunnable = new Runnable() {
|
||||
public void run() {
|
||||
mErrorTextView.setText("");
|
||||
}
|
||||
};
|
||||
|
||||
private void showError(CharSequence msg, long timeout) {
|
||||
mErrorTextView.setText(msg);
|
||||
mPasswordEntry.setText(null);
|
||||
mHandler.removeCallbacks(mResetErrorRunnable);
|
||||
if (timeout != 0) {
|
||||
mHandler.postDelayed(mResetErrorRunnable, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
private void showError(int msg, long timeout) {
|
||||
showError(getText(msg), timeout);
|
||||
}
|
||||
|
||||
// {@link OnEditorActionListener} methods.
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
// Check if this was the result of hitting the enter or "done" key
|
||||
|
@@ -18,7 +18,6 @@ package com.android.settings;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.CountDownTimer;
|
||||
@@ -85,7 +84,6 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
|
||||
private static final String FRAGMENT_TAG_CHECK_LOCK_RESULT = "check_lock_result";
|
||||
|
||||
private LockPatternView mLockPatternView;
|
||||
private LockPatternUtils mLockPatternUtils;
|
||||
private AsyncTask<?, ?, ?> mPendingLockCheck;
|
||||
private CredentialCheckResultTracker mCredentialCheckResultTracker;
|
||||
private boolean mDisappearing = false;
|
||||
@@ -93,7 +91,6 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
|
||||
|
||||
private TextView mHeaderTextView;
|
||||
private TextView mDetailsTextView;
|
||||
private TextView mErrorTextView;
|
||||
private View mLeftSpacerLandscape;
|
||||
private View mRightSpacerLandscape;
|
||||
|
||||
@@ -112,7 +109,6 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mLockPatternUtils = new LockPatternUtils(getActivity());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -220,6 +216,10 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
|
||||
mCredentialCheckResultTracker.setListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShowError() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareEnterAnimation() {
|
||||
super.prepareEnterAnimation();
|
||||
@@ -284,6 +284,10 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
|
||||
R.string.lockpassword_confirm_your_pattern_generic_profile);
|
||||
}
|
||||
mErrorTextView.setText("");
|
||||
if (isProfileChallenge()) {
|
||||
updateErrorMessage(mLockPatternUtils.getCurrentFailedPasswordAttempts(
|
||||
mEffectiveUserId));
|
||||
}
|
||||
|
||||
mLockPatternView.setEnabled(true);
|
||||
mLockPatternView.enableInput();
|
||||
@@ -470,9 +474,12 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
|
||||
};
|
||||
|
||||
private void onPatternChecked(boolean matched, Intent intent, int timeoutMs,
|
||||
int effectiveUserId) {
|
||||
int effectiveUserId, boolean newResult) {
|
||||
mLockPatternView.setEnabled(true);
|
||||
if (matched) {
|
||||
if (newResult) {
|
||||
reportSuccessfullAttempt();
|
||||
}
|
||||
startDisappearAnimation(intent);
|
||||
checkForPendingIntent();
|
||||
} else {
|
||||
@@ -484,13 +491,21 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
|
||||
updateStage(Stage.NeedToUnlockWrong);
|
||||
postClearPatternRunnable();
|
||||
}
|
||||
if (newResult) {
|
||||
reportFailedAttempt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCredentialChecked(boolean matched, Intent intent, int timeoutMs,
|
||||
int effectiveUserId) {
|
||||
onPatternChecked(matched, intent, timeoutMs, effectiveUserId);
|
||||
int effectiveUserId, boolean newResult) {
|
||||
onPatternChecked(matched, intent, timeoutMs, effectiveUserId, newResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLastTryErrorMessage() {
|
||||
return R.string.lock_profile_wipe_warning_content_pattern;
|
||||
}
|
||||
|
||||
private void handleAttemptLockout(long elapsedRealtimeDeadline) {
|
||||
|
@@ -47,7 +47,7 @@ public class CredentialCheckResultTracker extends Fragment {
|
||||
mListener = listener;
|
||||
if (mListener != null && mHasResult) {
|
||||
mListener.onCredentialChecked(mResultMatched, mResultData, mResultTimeoutMs,
|
||||
mResultEffectiveUserId);
|
||||
mResultEffectiveUserId, false /* newResult */);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ public class CredentialCheckResultTracker extends Fragment {
|
||||
mHasResult = true;
|
||||
if (mListener != null) {
|
||||
mListener.onCredentialChecked(mResultMatched, mResultData, mResultTimeoutMs,
|
||||
mResultEffectiveUserId);
|
||||
mResultEffectiveUserId, true /* newResult */);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,6 @@ public class CredentialCheckResultTracker extends Fragment {
|
||||
|
||||
interface Listener {
|
||||
public void onCredentialChecked(boolean matched, Intent intent, int timeoutMs,
|
||||
int effectiveUserId);
|
||||
int effectiveUserId, boolean newResult);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user