From 641c9fc23a54519bd6ea7972a9dd89898a84851b Mon Sep 17 00:00:00 2001 From: Charles He Date: Wed, 26 Apr 2017 18:45:48 +0100 Subject: [PATCH] Make failed ConfirmCredential attempts count towards wipe Previously, failed ConfirmDeviceCredential attempts only counted towards the wipe limit if it is used as a separate work challenge. In this CL, we additionally make these failed attempts count towards the total failures in the following scenarios: 1) when unified work challenge is enabled 2) for the primary user (e.g. when a wipe limit is set by a DO) 3) for secondary users Bug: 27238008 Test: manual, by entering wrong credentials multiple times Test: make SettingsRoboTests Change-Id: Ie5a099bb3fd46245c13ccf4c8f91c4d935412a4e --- res/values/strings.xml | 44 +++++--- .../ConfirmDeviceCredentialBaseFragment.java | 119 +++++++++++++-------- .../settings/password/ConfirmLockPassword.java | 31 +++--- .../settings/password/ConfirmLockPattern.java | 21 ++-- 4 files changed, 140 insertions(+), 75 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index afa207b8f0..c55e19921b 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1227,20 +1227,38 @@ Change unlock password - - Try again. Attempt %1$d of %2$d. - - Last try - - If you enter an incorrect work pattern on this attempt, your work profile and associated data will be removed from this device. - - If you enter an incorrect work PIN on this attempt, your work profile and associated data will be removed from this device. - - If you enter an incorrect work password on this attempt, your work profile and associated data will be removed from this device. - - Too many incorrect attempts. Your work profile and associated data will be removed from this device. + + Try again. Attempt %1$d of %2$d. + + + Your data will be deleted + + If you enter an incorrect pattern on the next attempt, this device's data will be deleted + + If you enter an incorrect PIN on the next attempt, this device's data will be deleted + + If you enter an incorrect password on the next attempt, this device's data will be deleted + + If you enter an incorrect pattern on the next attempt, this user will be deleted + + If you enter an incorrect PIN on the next attempt, this user will be deleted + + If you enter an incorrect password on the next attempt, this user will be deleted + + If you enter an incorrect pattern on the next attempt, your work profile and its data will be deleted + + If you enter an incorrect PIN on the next attempt, your work profile and its data will be deleted + + If you enter an incorrect password on the next attempt, your work profile and its data will be deleted + + + Too many incorrect attempts. This device's data will be deleted. + + Too many incorrect attempts. This user will be deleted. + + Too many incorrect attempts. This work profile and its data will be deleted. - Dismiss + Dismiss Must be at least %d characters diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java b/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java index ae2dd42691..0c36dba76a 100644 --- a/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java +++ b/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java @@ -31,6 +31,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentSender; +import android.content.pm.UserInfo; import android.graphics.Point; import android.graphics.PorterDuff; import android.graphics.drawable.ColorDrawable; @@ -70,6 +71,10 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends OptionsMenuFra public static final String SHOW_WHEN_LOCKED = PACKAGE + ".ConfirmCredentials.showWhenLocked"; + protected static final int USER_TYPE_PRIMARY = 1; + protected static final int USER_TYPE_MANAGED_PROFILE = 2; + protected static final int USER_TYPE_SECONDARY = 3; + private FingerprintUiHelper mFingerprintHelper; protected boolean mReturnCredentials = false; protected Button mCancelButton; @@ -78,6 +83,7 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends OptionsMenuFra protected int mUserId; protected UserManager mUserManager; protected LockPatternUtils mLockPatternUtils; + protected DevicePolicyManager mDevicePolicyManager; protected TextView mErrorTextView; protected final Handler mHandler = new Handler(); @@ -92,6 +98,8 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends OptionsMenuFra mUserManager = UserManager.get(getActivity()); mEffectiveUserId = mUserManager.getCredentialOwnerProfile(mUserId); mLockPatternUtils = new LockPatternUtils(getActivity()); + mDevicePolicyManager = (DevicePolicyManager) getActivity().getSystemService( + Context.DEVICE_POLICY_SERVICE); } @Override @@ -122,9 +130,8 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends OptionsMenuFra } private boolean isFingerprintDisabledByAdmin() { - DevicePolicyManager dpm = (DevicePolicyManager) getActivity().getSystemService( - Context.DEVICE_POLICY_SERVICE); - final int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, mEffectiveUserId); + final int disabledFeatures = + mDevicePolicyManager.getKeyguardDisabledFeatures(null, mEffectiveUserId); return (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0; } @@ -158,10 +165,7 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends OptionsMenuFra mFingerprintHelper.stopListening(); } } - if (isProfileChallenge()) { - updateErrorMessage(mLockPatternUtils.getCurrentFailedPasswordAttempts( - mEffectiveUserId)); - } + updateErrorMessage(mLockPatternUtils.getCurrentFailedPasswordAttempts(mEffectiveUserId)); } protected void setAccessibilityTitle(CharSequence supplementalText) { @@ -245,9 +249,8 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends OptionsMenuFra mainContent.setPadding(0, 0, 0, 0); } - DevicePolicyManager dpm = (DevicePolicyManager) getActivity().getSystemService( - Context.DEVICE_POLICY_SERVICE); - baseView.setBackground(new ColorDrawable(dpm.getOrganizationColorForUser(userId))); + baseView.setBackground( + new ColorDrawable(mDevicePolicyManager.getOrganizationColorForUser(userId))); ImageView imageView = (ImageView) baseView.findViewById(R.id.background_image); if (imageView != null) { Drawable image = getResources().getDrawable(R.drawable.work_challenge_background); @@ -263,13 +266,9 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends OptionsMenuFra } } - protected boolean isProfileChallenge() { - return mUserManager.isManagedProfile(mEffectiveUserId); - } - - protected void reportSuccessfullAttempt() { - if (isProfileChallenge()) { - mLockPatternUtils.reportSuccessfulPasswordAttempt(mEffectiveUserId); + protected void reportSuccessfulAttempt() { + mLockPatternUtils.reportSuccessfulPasswordAttempt(mEffectiveUserId); + if (mUserManager.isManagedProfile(mEffectiveUserId)) { // Keyguard is responsible to disable StrongAuth for primary user. Disable StrongAuth // for work challenge only here. mLockPatternUtils.userPresent(mEffectiveUserId); @@ -277,40 +276,73 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends OptionsMenuFra } protected void reportFailedAttempt() { - if (isProfileChallenge()) { - // + 1 for this attempt. - updateErrorMessage( - mLockPatternUtils.getCurrentFailedPasswordAttempts(mEffectiveUserId) + 1); - mLockPatternUtils.reportFailedPasswordAttempt(mEffectiveUserId); - } + 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); - LastTryDialog.show(getFragmentManager(), title, getLastTryErrorMessage(), - android.R.string.ok, false /* dismiss */); - } else if (remainingAttempts <= 0) { - // Profile is wiped - LastTryDialog.show(getFragmentManager(), null /* title */, - R.string.lock_profile_wipe_content, 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); - } + if (maxAttempts <= 0 || numAttempts <= 0) { + return; + } + + // Update the on-screen error string + if (mErrorTextView != null) { + final String message = getActivity().getString( + R.string.lock_failed_attempts_before_wipe, numAttempts, maxAttempts); + showError(message, 0); + } + + // Only show popup dialog before the last attempt and before wipe + final int remainingAttempts = maxAttempts - numAttempts; + if (remainingAttempts > 1) { + return; + } + final FragmentManager fragmentManager = getChildFragmentManager(); + final int userType = getUserTypeForWipe(); + if (remainingAttempts == 1) { + // Last try + final String title = getActivity().getString( + R.string.lock_last_attempt_before_wipe_warning_title); + final int messageId = getLastTryErrorMessage(userType); + LastTryDialog.show(fragmentManager, title, messageId, + android.R.string.ok, false /* dismiss */); + } else { + // Device, profile, or secondary user is wiped + final int messageId = getWipeMessage(userType); + LastTryDialog.show(fragmentManager, null /* title */, messageId, + R.string.lock_failed_attempts_now_wiping_dialog_dismiss, true /* dismiss */); } } - protected abstract int getLastTryErrorMessage(); + private int getUserTypeForWipe() { + final UserInfo userToBeWiped = mUserManager.getUserInfo( + mDevicePolicyManager.getProfileWithMinimumFailedPasswordsForWipe(mEffectiveUserId)); + if (userToBeWiped == null || userToBeWiped.isPrimary()) { + return USER_TYPE_PRIMARY; + } else if (userToBeWiped.isManagedProfile()) { + return USER_TYPE_MANAGED_PROFILE; + } else { + return USER_TYPE_SECONDARY; + } + } + + protected abstract int getLastTryErrorMessage(int userType); + + private int getWipeMessage(int userType) { + switch (userType) { + case USER_TYPE_PRIMARY: + return R.string.lock_failed_attempts_now_wiping_device; + case USER_TYPE_MANAGED_PROFILE: + return R.string.lock_failed_attempts_now_wiping_profile; + case USER_TYPE_SECONDARY: + return R.string.lock_failed_attempts_now_wiping_user; + default: + throw new IllegalArgumentException("Unrecognized user type:" + userType); + } + } private final Runnable mResetErrorRunnable = new Runnable() { @Override @@ -357,6 +389,7 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends OptionsMenuFra DialogFragment dialog = new LastTryDialog(); dialog.setArguments(args); dialog.show(from, TAG); + from.executePendingTransactions(); return true; } diff --git a/src/com/android/settings/password/ConfirmLockPassword.java b/src/com/android/settings/password/ConfirmLockPassword.java index ef11521865..a91f572b09 100644 --- a/src/com/android/settings/password/ConfirmLockPassword.java +++ b/src/com/android/settings/password/ConfirmLockPassword.java @@ -211,9 +211,20 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity { } @Override - protected int getLastTryErrorMessage() { - return mIsAlpha ? R.string.lock_profile_wipe_warning_content_password - : R.string.lock_profile_wipe_warning_content_pin; + protected int getLastTryErrorMessage(int userType) { + switch (userType) { + case USER_TYPE_PRIMARY: + return mIsAlpha ? R.string.lock_last_password_attempt_before_wipe_device + : R.string.lock_last_pin_attempt_before_wipe_device; + case USER_TYPE_MANAGED_PROFILE: + return mIsAlpha ? R.string.lock_last_password_attempt_before_wipe_profile + : R.string.lock_last_pin_attempt_before_wipe_profile; + case USER_TYPE_SECONDARY: + return mIsAlpha ? R.string.lock_last_password_attempt_before_wipe_user + : R.string.lock_last_pin_attempt_before_wipe_user; + default: + throw new IllegalArgumentException("Unrecognized user type:" + userType); + } } @Override @@ -278,10 +289,8 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity { } else { resetState(); mErrorTextView.setText(""); - if (isProfileChallenge()) { - updateErrorMessage(mLockPatternUtils.getCurrentFailedPasswordAttempts( - mEffectiveUserId)); - } + updateErrorMessage( + mLockPatternUtils.getCurrentFailedPasswordAttempts(mEffectiveUserId)); } mCredentialCheckResultTracker.setListener(this); } @@ -444,7 +453,7 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity { mPasswordEntryInputDisabler.setInputEnabled(true); if (matched) { if (newResult) { - reportSuccessfullAttempt(); + reportSuccessfulAttempt(); } startDisappearAnimation(intent); checkForPendingIntent(); @@ -493,10 +502,8 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity { public void onFinish() { resetState(); mErrorTextView.setText(""); - if (isProfileChallenge()) { - updateErrorMessage(mLockPatternUtils.getCurrentFailedPasswordAttempts( - mEffectiveUserId)); - } + updateErrorMessage( + mLockPatternUtils.getCurrentFailedPasswordAttempts(mEffectiveUserId)); } }.start(); } diff --git a/src/com/android/settings/password/ConfirmLockPattern.java b/src/com/android/settings/password/ConfirmLockPattern.java index b66edfec01..c16b55ab9e 100644 --- a/src/com/android/settings/password/ConfirmLockPattern.java +++ b/src/com/android/settings/password/ConfirmLockPattern.java @@ -299,10 +299,8 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity { mDetailsTextView.setText(getDefaultDetails()); } mErrorTextView.setText(""); - if (isProfileChallenge()) { - updateErrorMessage(mLockPatternUtils.getCurrentFailedPasswordAttempts( - mEffectiveUserId)); - } + updateErrorMessage( + mLockPatternUtils.getCurrentFailedPasswordAttempts(mEffectiveUserId)); mLockPatternView.setEnabled(true); mLockPatternView.enableInput(); @@ -497,7 +495,7 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity { mLockPatternView.setEnabled(true); if (matched) { if (newResult) { - reportSuccessfullAttempt(); + reportSuccessfulAttempt(); } startDisappearAnimation(intent); checkForPendingIntent(); @@ -524,8 +522,17 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity { } @Override - protected int getLastTryErrorMessage() { - return R.string.lock_profile_wipe_warning_content_pattern; + protected int getLastTryErrorMessage(int userType) { + switch (userType) { + case USER_TYPE_PRIMARY: + return R.string.lock_last_pattern_attempt_before_wipe_device; + case USER_TYPE_MANAGED_PROFILE: + return R.string.lock_last_pattern_attempt_before_wipe_profile; + case USER_TYPE_SECONDARY: + return R.string.lock_last_pattern_attempt_before_wipe_user; + default: + throw new IllegalArgumentException("Unrecognized user type:" + userType); + } } private void handleAttemptLockout(long elapsedRealtimeDeadline) { -- 2.11.0