Merge "Call reportFailedPasswordAttempt from Work Challenge" into nyc-dev

This commit is contained in:
Clara Bayarri
2016-02-18 11:16:26 +00:00
committed by Android (Google) Code Review
5 changed files with 162 additions and 43 deletions

View File

@@ -1130,6 +1130,21 @@
<!-- Title shown on security settings to allow the user to change their lockscreen password [CHAR LIMIT=22]--> <!-- 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> <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 --> <!-- Hint shown in dialog screen when password is too short -->
<string name="lockpassword_password_too_short">Password must be at least %d characters</string> <string name="lockpassword_password_too_short">Password must be at least %d characters</string>
<!-- Hint shown in dialog screen when PIN is too short --> <!-- Hint shown in dialog screen when PIN is too short -->

View File

@@ -20,10 +20,13 @@ import android.annotation.Nullable;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.ActivityManagerNative; import android.app.ActivityManagerNative;
import android.app.ActivityOptions; import android.app.ActivityOptions;
import android.app.AlertDialog;
import android.app.IActivityManager; import android.app.IActivityManager;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager; import android.app.trust.TrustManager;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent; import android.content.Intent;
import android.content.IntentSender; import android.content.IntentSender;
import android.graphics.Point; import android.graphics.Point;
@@ -31,7 +34,9 @@ import android.graphics.PorterDuff;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -40,6 +45,7 @@ import android.widget.FrameLayout;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.fingerprint.FingerprintUiHelper; import com.android.settings.fingerprint.FingerprintUiHelper;
/** /**
@@ -65,6 +71,9 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
protected Button mCancelButton; protected Button mCancelButton;
protected ImageView mFingerprintIcon; protected ImageView mFingerprintIcon;
protected int mEffectiveUserId; protected int mEffectiveUserId;
protected LockPatternUtils mLockPatternUtils;
protected TextView mErrorTextView;
protected final Handler mHandler = new Handler();
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { 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. // Only take this argument into account if it belongs to the current profile.
Intent intent = getActivity().getIntent(); Intent intent = getActivity().getIntent();
mEffectiveUserId = Utils.getUserIdFromBundle(getActivity(), intent.getExtras()); mEffectiveUserId = Utils.getUserIdFromBundle(getActivity(), intent.getExtras());
mLockPatternUtils = new LockPatternUtils(getActivity());
} }
@Override @Override
@@ -109,6 +119,10 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
if (mAllowFpAuthentication) { if (mAllowFpAuthentication) {
mFingerprintHelper.startListening(); mFingerprintHelper.startListening();
} }
if (isProfileChallenge()) {
updateErrorMessage(mLockPatternUtils.getCurrentFailedPasswordAttempts(
mEffectiveUserId));
}
} }
protected void setAccessibilityTitle(CharSequence suplementalText) { protected void setAccessibilityTitle(CharSequence suplementalText) {
@@ -200,4 +214,87 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
screenSize.y)); 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();
}
} }

View File

@@ -20,11 +20,9 @@ import android.app.Fragment;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentSender;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.os.CountDownTimer; import android.os.CountDownTimer;
import android.os.Handler;
import android.os.SystemClock; import android.os.SystemClock;
import android.os.UserManager; import android.os.UserManager;
import android.os.storage.StorageManager; 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 static final String FRAGMENT_TAG_CHECK_LOCK_RESULT = "check_lock_result";
private TextView mPasswordEntry; private TextView mPasswordEntry;
private TextViewInputDisabler mPasswordEntryInputDisabler; private TextViewInputDisabler mPasswordEntryInputDisabler;
private LockPatternUtils mLockPatternUtils;
private AsyncTask<?, ?, ?> mPendingLockCheck; private AsyncTask<?, ?, ?> mPendingLockCheck;
private CredentialCheckResultTracker mCredentialCheckResultTracker; private CredentialCheckResultTracker mCredentialCheckResultTracker;
private boolean mDisappearing = false; private boolean mDisappearing = false;
private TextView mHeaderTextView; private TextView mHeaderTextView;
private TextView mDetailsTextView; private TextView mDetailsTextView;
private TextView mErrorTextView;
private Handler mHandler = new Handler();
private CountDownTimer mCountdownTimer; private CountDownTimer mCountdownTimer;
private boolean mIsAlpha; private boolean mIsAlpha;
private InputMethodManager mImm; private InputMethodManager mImm;
@@ -108,7 +103,6 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mLockPatternUtils = new LockPatternUtils(getActivity());
} }
@Override @Override
@@ -193,6 +187,12 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
: R.string.lockpassword_invalid_pin; : 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 @Override
public void prepareEnterAnimation() { public void prepareEnterAnimation() {
super.prepareEnterAnimation(); super.prepareEnterAnimation();
@@ -406,9 +406,12 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
} }
private void onPasswordChecked(boolean matched, Intent intent, int timeoutMs, private void onPasswordChecked(boolean matched, Intent intent, int timeoutMs,
int effectiveUserId) { int effectiveUserId, boolean newResult) {
mPasswordEntryInputDisabler.setInputEnabled(true); mPasswordEntryInputDisabler.setInputEnabled(true);
if (matched) { if (matched) {
if (newResult) {
reportSuccessfullAttempt();
}
startDisappearAnimation(intent); startDisappearAnimation(intent);
checkForPendingIntent(); checkForPendingIntent();
} else { } else {
@@ -417,15 +420,23 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
effectiveUserId, timeoutMs); effectiveUserId, timeoutMs);
handleAttemptLockout(deadline); handleAttemptLockout(deadline);
} else { } else {
showError(getErrorMessage()); showError(getErrorMessage(), ERROR_MESSAGE_TIMEOUT);
}
if (newResult) {
reportFailedAttempt();
} }
} }
} }
@Override @Override
public void onCredentialChecked(boolean matched, Intent intent, int timeoutMs, public void onCredentialChecked(boolean matched, Intent intent, int timeoutMs,
int effectiveUserId) { int effectiveUserId, boolean newResult) {
onPasswordChecked(matched, intent, timeoutMs, effectiveUserId); onPasswordChecked(matched, intent, timeoutMs, effectiveUserId, newResult);
}
@Override
protected void onShowError() {
mPasswordEntry.setText(null);
} }
private void handleAttemptLockout(long elapsedRealtimeDeadline) { private void handleAttemptLockout(long elapsedRealtimeDeadline) {
@@ -447,6 +458,10 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
public void onFinish() { public void onFinish() {
resetState(); resetState();
mErrorTextView.setText(""); mErrorTextView.setText("");
if (isProfileChallenge()) {
updateErrorMessage(mLockPatternUtils.getCurrentFailedPasswordAttempts(
mEffectiveUserId));
}
} }
}.start(); }.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. // {@link OnEditorActionListener} methods.
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
// Check if this was the result of hitting the enter or "done" key // Check if this was the result of hitting the enter or "done" key

View File

@@ -18,7 +18,6 @@ package com.android.settings;
import android.app.Activity; import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.content.IntentSender;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.os.CountDownTimer; 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 static final String FRAGMENT_TAG_CHECK_LOCK_RESULT = "check_lock_result";
private LockPatternView mLockPatternView; private LockPatternView mLockPatternView;
private LockPatternUtils mLockPatternUtils;
private AsyncTask<?, ?, ?> mPendingLockCheck; private AsyncTask<?, ?, ?> mPendingLockCheck;
private CredentialCheckResultTracker mCredentialCheckResultTracker; private CredentialCheckResultTracker mCredentialCheckResultTracker;
private boolean mDisappearing = false; private boolean mDisappearing = false;
@@ -93,7 +91,6 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
private TextView mHeaderTextView; private TextView mHeaderTextView;
private TextView mDetailsTextView; private TextView mDetailsTextView;
private TextView mErrorTextView;
private View mLeftSpacerLandscape; private View mLeftSpacerLandscape;
private View mRightSpacerLandscape; private View mRightSpacerLandscape;
@@ -112,7 +109,6 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mLockPatternUtils = new LockPatternUtils(getActivity());
} }
@Override @Override
@@ -220,6 +216,10 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
mCredentialCheckResultTracker.setListener(this); mCredentialCheckResultTracker.setListener(this);
} }
@Override
protected void onShowError() {
}
@Override @Override
public void prepareEnterAnimation() { public void prepareEnterAnimation() {
super.prepareEnterAnimation(); super.prepareEnterAnimation();
@@ -284,6 +284,10 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
R.string.lockpassword_confirm_your_pattern_generic_profile); R.string.lockpassword_confirm_your_pattern_generic_profile);
} }
mErrorTextView.setText(""); mErrorTextView.setText("");
if (isProfileChallenge()) {
updateErrorMessage(mLockPatternUtils.getCurrentFailedPasswordAttempts(
mEffectiveUserId));
}
mLockPatternView.setEnabled(true); mLockPatternView.setEnabled(true);
mLockPatternView.enableInput(); mLockPatternView.enableInput();
@@ -470,9 +474,12 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
}; };
private void onPatternChecked(boolean matched, Intent intent, int timeoutMs, private void onPatternChecked(boolean matched, Intent intent, int timeoutMs,
int effectiveUserId) { int effectiveUserId, boolean newResult) {
mLockPatternView.setEnabled(true); mLockPatternView.setEnabled(true);
if (matched) { if (matched) {
if (newResult) {
reportSuccessfullAttempt();
}
startDisappearAnimation(intent); startDisappearAnimation(intent);
checkForPendingIntent(); checkForPendingIntent();
} else { } else {
@@ -484,13 +491,21 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
updateStage(Stage.NeedToUnlockWrong); updateStage(Stage.NeedToUnlockWrong);
postClearPatternRunnable(); postClearPatternRunnable();
} }
if (newResult) {
reportFailedAttempt();
}
} }
} }
@Override @Override
public void onCredentialChecked(boolean matched, Intent intent, int timeoutMs, public void onCredentialChecked(boolean matched, Intent intent, int timeoutMs,
int effectiveUserId) { int effectiveUserId, boolean newResult) {
onPatternChecked(matched, intent, timeoutMs, effectiveUserId); onPatternChecked(matched, intent, timeoutMs, effectiveUserId, newResult);
}
@Override
protected int getLastTryErrorMessage() {
return R.string.lock_profile_wipe_warning_content_pattern;
} }
private void handleAttemptLockout(long elapsedRealtimeDeadline) { private void handleAttemptLockout(long elapsedRealtimeDeadline) {

View File

@@ -47,7 +47,7 @@ public class CredentialCheckResultTracker extends Fragment {
mListener = listener; mListener = listener;
if (mListener != null && mHasResult) { if (mListener != null && mHasResult) {
mListener.onCredentialChecked(mResultMatched, mResultData, mResultTimeoutMs, mListener.onCredentialChecked(mResultMatched, mResultData, mResultTimeoutMs,
mResultEffectiveUserId); mResultEffectiveUserId, false /* newResult */);
} }
} }
@@ -60,7 +60,7 @@ public class CredentialCheckResultTracker extends Fragment {
mHasResult = true; mHasResult = true;
if (mListener != null) { if (mListener != null) {
mListener.onCredentialChecked(mResultMatched, mResultData, mResultTimeoutMs, mListener.onCredentialChecked(mResultMatched, mResultData, mResultTimeoutMs,
mResultEffectiveUserId); mResultEffectiveUserId, true /* newResult */);
} }
} }
@@ -74,6 +74,6 @@ public class CredentialCheckResultTracker extends Fragment {
interface Listener { interface Listener {
public void onCredentialChecked(boolean matched, Intent intent, int timeoutMs, public void onCredentialChecked(boolean matched, Intent intent, int timeoutMs,
int effectiveUserId); int effectiveUserId, boolean newResult);
} }
} }