diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java index 8b0c2c92ec5..90c9859cdca 100644 --- a/src/com/android/settings/password/ChooseLockGeneric.java +++ b/src/com/android/settings/password/ChooseLockGeneric.java @@ -25,6 +25,7 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE; import static com.android.settings.password.ChooseLockPassword.ChooseLockPasswordFragment.RESULT_FINISHED; import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_CALLER_APP_NAME; +import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY; import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_IS_CALLING_APP_ADMIN; import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY; @@ -162,6 +163,8 @@ public class ChooseLockGeneric extends SettingsActivity { /** * From intent extra {@link ChooseLockSettingsHelper#EXTRA_KEY_REQUESTED_MIN_COMPLEXITY}. + * Only contains complexity requested by calling app, not complexity enforced by device + * admins. */ @PasswordComplexity private int mRequestedMinComplexity; @@ -178,6 +181,8 @@ public class ChooseLockGeneric extends SettingsActivity { protected boolean mForFace = false; protected boolean mForBiometrics = false; + private boolean mOnlyEnforceDevicePasswordRequirement = false; + @Override public int getMetricsCategory() { return SettingsEnums.CHOOSE_LOCK_GENERIC; @@ -221,20 +226,11 @@ public class ChooseLockGeneric extends SettingsActivity { mForBiometrics = intent.getBooleanExtra( ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, false); - final int complexityFromIntent = intent - .getIntExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_NONE); - final int complexityFromAdmin = mLockPatternUtils.getRequestedPasswordComplexity( - mUserId); - mRequestedMinComplexity = Math.max(complexityFromIntent, complexityFromAdmin); - final boolean isComplexityProvidedByAdmin = (complexityFromAdmin > complexityFromIntent) - && mRequestedMinComplexity > PASSWORD_COMPLEXITY_NONE; + mRequestedMinComplexity = intent.getIntExtra( + EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_NONE); + mOnlyEnforceDevicePasswordRequirement = intent.getBooleanExtra( + ChooseLockSettingsHelper.EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY, false); - // If the complexity is provided by the admin, do not get the caller app's name. - // If the app requires, for example, low complexity, and the admin requires high - // complexity, it does not make sense to show a footer telling the user it's the app - // requesting a particular complexity because the admin-set complexity will override it. - mCallerAppName = isComplexityProvidedByAdmin ? null : - intent.getStringExtra(EXTRA_KEY_CALLER_APP_NAME); mIsCallingAppAdmin = intent .getBooleanExtra(EXTRA_KEY_IS_CALLING_APP_ADMIN, /* defValue= */ false); mForChangeCredRequiredForBoot = arguments != null && arguments.getBoolean( @@ -268,7 +264,22 @@ public class ChooseLockGeneric extends SettingsActivity { arguments, intent.getExtras()).getIdentifier(); mController = new ChooseLockGenericController( - getContext(), mUserId, mRequestedMinComplexity, mLockPatternUtils); + getContext(), mUserId, mRequestedMinComplexity, + mOnlyEnforceDevicePasswordRequirement, + mLockPatternUtils); + + final int aggregatedComplexity = mController.getAggregatedPasswordComplexity(); + final boolean isComplexityProvidedByAdmin = + aggregatedComplexity > mRequestedMinComplexity + && aggregatedComplexity > PASSWORD_COMPLEXITY_NONE; + + // If the complexity is provided by the admin, do not get the caller app's name. + // If the app requires, for example, low complexity, and the admin requires high + // complexity, it does not make sense to show a footer telling the user it's the app + // requesting a particular complexity because the admin-set complexity will override it. + mCallerAppName = isComplexityProvidedByAdmin ? null : + intent.getStringExtra(EXTRA_KEY_CALLER_APP_NAME); + if (ACTION_SET_NEW_PASSWORD.equals(chooseLockAction) && UserManager.get(activity).isManagedProfile(mUserId) && mLockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) { @@ -356,6 +367,8 @@ public class ChooseLockGeneric extends SettingsActivity { chooseLockGenericIntent.putExtra(CONFIRM_CREDENTIALS, !mPasswordConfirmed); chooseLockGenericIntent.putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, mRequestedMinComplexity); + chooseLockGenericIntent.putExtra(EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY, + mOnlyEnforceDevicePasswordRequirement); chooseLockGenericIntent.putExtra(EXTRA_KEY_CALLER_APP_NAME, mCallerAppName); if (mUserPassword != null) { chooseLockGenericIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, @@ -557,7 +570,7 @@ public class ChooseLockGeneric extends SettingsActivity { private String getFooterString() { @StringRes int stringId; - switch (mRequestedMinComplexity) { + switch (mController.getAggregatedPasswordComplexity()) { case PASSWORD_COMPLEXITY_HIGH: stringId = R.string.unlock_footer_high_complexity_requested; break; @@ -678,7 +691,9 @@ public class ChooseLockGeneric extends SettingsActivity { boolean hideDisabled) { final PreferenceScreen entries = getPreferenceScreen(); - int adminEnforcedQuality = mDpm.getPasswordQuality(null, mUserId); + int adminEnforcedQuality = LockPatternUtils.credentialTypeToPasswordQuality( + mLockPatternUtils.getRequestedPasswordMetrics( + mUserId, mOnlyEnforceDevicePasswordRequirement).credType); EnforcedAdmin enforcedAdmin = RestrictedLockUtilsInternal.checkIfPasswordQualityIsSet(getActivity(), mUserId); @@ -753,8 +768,10 @@ public class ChooseLockGeneric extends SettingsActivity { protected Intent getLockPasswordIntent(int quality) { ChooseLockPassword.IntentBuilder builder = new ChooseLockPassword.IntentBuilder(getContext()) - .setPasswordQuality(quality) - .setRequestedMinComplexity(mRequestedMinComplexity) + .setPasswordType(quality) + .setPasswordRequirement( + mController.getAggregatedPasswordComplexity(), + mController.getAggregatedPasswordMetrics()) .setForFingerprint(mForFingerprint) .setForFace(mForFace) .setForBiometrics(mForBiometrics) diff --git a/src/com/android/settings/password/ChooseLockGenericController.java b/src/com/android/settings/password/ChooseLockGenericController.java index 1bfdac95569..88b35f9c248 100644 --- a/src/com/android/settings/password/ChooseLockGenericController.java +++ b/src/com/android/settings/password/ChooseLockGenericController.java @@ -18,7 +18,6 @@ package com.android.settings.password; import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE; -import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager.PasswordComplexity; import android.app.admin.PasswordMetrics; import android.content.Context; @@ -42,8 +41,8 @@ public class ChooseLockGenericController { private final Context mContext; private final int mUserId; @PasswordComplexity private final int mRequestedMinComplexity; + private final boolean mDevicePasswordRequirementOnly; private ManagedLockPasswordProvider mManagedPasswordProvider; - private DevicePolicyManager mDpm; private final LockPatternUtils mLockPatternUtils; public ChooseLockGenericController(Context context, int userId) { @@ -51,6 +50,7 @@ public class ChooseLockGenericController { context, userId, PASSWORD_COMPLEXITY_NONE, + /* mOnlyEnforceDevicePasswordRequirement */ false, new LockPatternUtils(context)); } @@ -59,12 +59,14 @@ public class ChooseLockGenericController { * when determining the available screen lock types */ public ChooseLockGenericController(Context context, int userId, - @PasswordComplexity int requestedMinComplexity, LockPatternUtils lockPatternUtils) { + @PasswordComplexity int requestedMinComplexity, + boolean devicePasswordRequirementOnly, + LockPatternUtils lockPatternUtils) { this( context, userId, requestedMinComplexity, - context.getSystemService(DevicePolicyManager.class), + devicePasswordRequirementOnly, ManagedLockPasswordProvider.get(context, userId), lockPatternUtils); } @@ -74,28 +76,29 @@ public class ChooseLockGenericController { Context context, int userId, @PasswordComplexity int requestedMinComplexity, - DevicePolicyManager dpm, + boolean devicePasswordRequirementOnly, ManagedLockPasswordProvider managedLockPasswordProvider, LockPatternUtils lockPatternUtils) { mContext = context; mUserId = userId; mRequestedMinComplexity = requestedMinComplexity; + mDevicePasswordRequirementOnly = devicePasswordRequirementOnly; mManagedPasswordProvider = managedLockPasswordProvider; - mDpm = dpm; mLockPatternUtils = lockPatternUtils; } /** - * Returns the highest quality among the specified {@code quality}, the quality required by - * {@link DevicePolicyManager#getPasswordQuality}, and the quality required by min password - * complexity. + * Returns the highest quality among the specified {@code quality}, the password requiremnet + * set by device admins (legacy password quality metrics and password complexity), and the + * min password complexity requested by the calling app. */ public int upgradeQuality(int quality) { // Compare specified quality and dpm quality // TODO(b/142781408): convert from quality to credential type once PIN is supported. - int dpmUpgradedQuality = Math.max(quality, mDpm.getPasswordQuality(null, mUserId)); + int dpmUpgradedQuality = Math.max(quality, LockPatternUtils.credentialTypeToPasswordQuality( + getAggregatedPasswordMetrics().credType)); return Math.max(dpmUpgradedQuality, - PasswordMetrics.complexityLevelToMinQuality(mRequestedMinComplexity)); + PasswordMetrics.complexityLevelToMinQuality(getAggregatedPasswordComplexity())); } /** @@ -193,4 +196,15 @@ public class ChooseLockGenericController { } return locks; } + + public PasswordMetrics getAggregatedPasswordMetrics() { + return mLockPatternUtils.getRequestedPasswordMetrics(mUserId, + mDevicePasswordRequirementOnly); + } + + public int getAggregatedPasswordComplexity() { + return Math.max(mRequestedMinComplexity, + mLockPatternUtils.getRequestedPasswordComplexity( + mUserId, mDevicePasswordRequirementOnly)); + } } diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java index f5e23fa04f2..35d624b0d7c 100644 --- a/src/com/android/settings/password/ChooseLockPassword.java +++ b/src/com/android/settings/password/ChooseLockPassword.java @@ -19,6 +19,7 @@ package com.android.settings.password; import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; +import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE; import static com.android.internal.widget.PasswordValidationError.CONTAINS_INVALID_CHARACTERS; import static com.android.internal.widget.PasswordValidationError.CONTAINS_SEQUENCE; import static com.android.internal.widget.PasswordValidationError.NOT_ENOUGH_DIGITS; @@ -31,7 +32,6 @@ import static com.android.internal.widget.PasswordValidationError.NOT_ENOUGH_UPP import static com.android.internal.widget.PasswordValidationError.RECENTLY_USED; import static com.android.internal.widget.PasswordValidationError.TOO_LONG; import static com.android.internal.widget.PasswordValidationError.TOO_SHORT; -import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY; import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL; import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_ID; @@ -96,6 +96,9 @@ import java.util.List; public class ChooseLockPassword extends SettingsActivity { private static final String TAG = "ChooseLockPassword"; + static final String EXTRA_KEY_MIN_METRICS = "min_metrics"; + static final String EXTRA_KEY_MIN_COMPLEXITY = "min_complexity"; + @Override public Intent getIntent() { Intent modIntent = new Intent(super.getIntent()); @@ -119,8 +122,13 @@ public class ChooseLockPassword extends SettingsActivity { mIntent.putExtra(EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, false); } - public IntentBuilder setPasswordQuality(int quality) { - mIntent.putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, quality); + /** + * Sets the intended credential type i.e. whether it's numeric PIN or general password + * @param passwordType password type represented by one of the {@code PASSWORD_QUALITY_} + * constants. + */ + public IntentBuilder setPasswordType(int passwordType) { + mIntent.putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, passwordType); return this; } @@ -156,8 +164,11 @@ public class ChooseLockPassword extends SettingsActivity { return this; } - public IntentBuilder setRequestedMinComplexity(@PasswordComplexity int level) { - mIntent.putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, level); + /** Sets the minimum password requirement in terms of complexity and metrics */ + public IntentBuilder setPasswordRequirement(@PasswordComplexity int level, + PasswordMetrics metrics) { + mIntent.putExtra(EXTRA_KEY_MIN_COMPLEXITY, level); + mIntent.putExtra(EXTRA_KEY_MIN_METRICS, metrics); return this; } @@ -240,7 +251,7 @@ public class ChooseLockPassword extends SettingsActivity { private LockPatternUtils mLockPatternUtils; private SaveAndFinishWorker mSaveAndFinishWorker; - private int mRequestedQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; + private int mPasswordType = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; protected Stage mUiStage = Stage.Introduction; private PasswordRequirementAdapter mPasswordRequirementAdapter; private GlifLayout mLayout; @@ -410,19 +421,22 @@ public class ChooseLockPassword extends SettingsActivity { mForFace = intent.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, false); mForBiometrics = intent.getBooleanExtra( ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, false); - mMinComplexity = intent.getIntExtra( - EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_NONE); - mRequestedQuality = intent.getIntExtra( + mPasswordType = intent.getIntExtra( LockPatternUtils.PASSWORD_TYPE_KEY, PASSWORD_QUALITY_NUMERIC); mUnificationProfileId = intent.getIntExtra( EXTRA_KEY_UNIFICATION_PROFILE_ID, UserHandle.USER_NULL); - mMinMetrics = mLockPatternUtils.getRequestedPasswordMetrics(mUserId); + mMinComplexity = intent.getIntExtra(EXTRA_KEY_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_NONE); + mMinMetrics = intent.getParcelableExtra(EXTRA_KEY_MIN_METRICS); + if (mMinMetrics == null) mMinMetrics = new PasswordMetrics(CREDENTIAL_TYPE_NONE); // If we are to unify a work challenge at the end of the credential enrollment, manually // merge any password policy from that profile here, so we are enrolling a compliant // password. This is because once unified, the profile's password policy will // be enforced on the new credential. + //TODO: Move this logic to ChooseLockGeneric; let ChooseLockGeneric be the only place + //where password requirement mixing happens. ChooseLockPassword simply enforces what's + //set via IntentBuilder.setPasswordRequirement() if (mUnificationProfileId != UserHandle.USER_NULL) { mMinMetrics.maxWith( mLockPatternUtils.getRequestedPasswordMetrics(mUnificationProfileId)); @@ -494,9 +508,9 @@ public class ChooseLockPassword extends SettingsActivity { mLayout.setIcon(getActivity().getDrawable(R.drawable.ic_lock)); } - mIsAlphaMode = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == mRequestedQuality - || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == mRequestedQuality - || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == mRequestedQuality; + mIsAlphaMode = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == mPasswordType + || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == mPasswordType + || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == mPasswordType; setupPasswordRequirementsView(view); diff --git a/src/com/android/settings/password/ChooseLockSettingsHelper.java b/src/com/android/settings/password/ChooseLockSettingsHelper.java index 1e1f59fddf9..13d39120fae 100644 --- a/src/com/android/settings/password/ChooseLockSettingsHelper.java +++ b/src/com/android/settings/password/ChooseLockSettingsHelper.java @@ -99,6 +99,12 @@ public final class ChooseLockSettingsHelper { */ public static final String EXTRA_KEY_ALLOW_ANY_USER = "allow_any_user"; + /** + * + */ + public static final String EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY = + "device_password_requirement_only"; + @VisibleForTesting @NonNull LockPatternUtils mLockPatternUtils; @NonNull private final Activity mActivity; @Nullable private final Fragment mFragment; diff --git a/src/com/android/settings/password/SetNewPasswordActivity.java b/src/com/android/settings/password/SetNewPasswordActivity.java index 19f2941cc7a..bd7b14d4b25 100644 --- a/src/com/android/settings/password/SetNewPasswordActivity.java +++ b/src/com/android/settings/password/SetNewPasswordActivity.java @@ -19,10 +19,12 @@ package com.android.settings.password; import static android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY; import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD; import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD; +import static android.app.admin.DevicePolicyManager.EXTRA_DEVICE_PASSWORD_REQUIREMENT_ONLY; import static android.app.admin.DevicePolicyManager.EXTRA_PASSWORD_COMPLEXITY; import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE; import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_CALLER_APP_NAME; +import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY; import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_IS_CALLING_APP_ADMIN; import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY; @@ -62,6 +64,8 @@ public class SetNewPasswordActivity extends Activity implements SetNewPasswordCo */ private @PasswordComplexity int mRequestedMinComplexity = PASSWORD_COMPLEXITY_NONE; + private boolean mDevicePasswordRequirementOnly = false; + /** * Label of the app which launches this activity. * @@ -72,27 +76,27 @@ public class SetNewPasswordActivity extends Activity implements SetNewPasswordCo @Override protected void onCreate(Bundle savedState) { super.onCreate(savedState); + final Intent intent = getIntent(); - mNewPasswordAction = getIntent().getAction(); + mNewPasswordAction = intent.getAction(); if (!ACTION_SET_NEW_PASSWORD.equals(mNewPasswordAction) && !ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(mNewPasswordAction)) { Log.e(TAG, "Unexpected action to launch this activity"); finish(); return; } - logSetNewPasswordIntent(); final IBinder activityToken = getActivityToken(); mCallerAppName = (String) PasswordUtils.getCallingAppLabel(this, activityToken); if (ACTION_SET_NEW_PASSWORD.equals(mNewPasswordAction) - && getIntent().hasExtra(EXTRA_PASSWORD_COMPLEXITY)) { + && intent.hasExtra(EXTRA_PASSWORD_COMPLEXITY)) { final boolean hasPermission = PasswordUtils.isCallingAppPermitted( this, activityToken, REQUEST_PASSWORD_COMPLEXITY); if (hasPermission) { mRequestedMinComplexity = - PasswordMetrics.sanitizeComplexityLevel(getIntent() - .getIntExtra(EXTRA_PASSWORD_COMPLEXITY, PASSWORD_COMPLEXITY_NONE)); + PasswordMetrics.sanitizeComplexityLevel(intent.getIntExtra( + EXTRA_PASSWORD_COMPLEXITY, PASSWORD_COMPLEXITY_NONE)); } else { PasswordUtils.crashCallingApplication(activityToken, "Must have permission " @@ -102,9 +106,14 @@ public class SetNewPasswordActivity extends Activity implements SetNewPasswordCo return; } } - + if (ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(mNewPasswordAction)) { + mDevicePasswordRequirementOnly = intent.getBooleanExtra( + EXTRA_DEVICE_PASSWORD_REQUIREMENT_ONLY, false); + Log.i(TAG, String.format("DEVICE_PASSWORD_REQUIREMENT_ONLY: %b", + mDevicePasswordRequirementOnly)); + } mSetNewPasswordController = SetNewPasswordController.create( - this, this, getIntent(), getActivityToken()); + this, this, intent, activityToken); mSetNewPasswordController.dispatchSetNewPasswordIntent(); } @@ -124,6 +133,7 @@ public class SetNewPasswordActivity extends Activity implements SetNewPasswordCo if (isCallingAppAdmin()) { intent.putExtra(EXTRA_KEY_IS_CALLING_APP_ADMIN, true); } + intent.putExtra(EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY, mDevicePasswordRequirementOnly); startActivity(intent); finish(); } diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockGenericControllerTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockGenericControllerTest.java index 5067de6370e..02b89cba845 100644 --- a/tests/robotests/src/com/android/settings/password/ChooseLockGenericControllerTest.java +++ b/tests/robotests/src/com/android/settings/password/ChooseLockGenericControllerTest.java @@ -26,14 +26,13 @@ import static com.google.common.truth.Truth.assertWithMessage; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.when; import static org.robolectric.RuntimeEnvironment.application; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager.PasswordComplexity; -import android.content.ComponentName; +import android.app.admin.PasswordPolicy; import com.android.internal.widget.LockPatternUtils; import com.android.settings.R; @@ -60,9 +59,6 @@ public class ChooseLockGenericControllerTest { @Mock private ManagedLockPasswordProvider mManagedLockPasswordProvider; - @Mock - private DevicePolicyManager mDevicePolicyManager; - @Mock private LockPatternUtils mLockPatternUtils; @@ -71,6 +67,7 @@ public class ChooseLockGenericControllerTest { MockitoAnnotations.initMocks(this); when(mLockPatternUtils.hasSecureLockScreen()).thenReturn(true); + setDevicePolicyPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED); mController = createController(PASSWORD_COMPLEXITY_NONE); SettingsShadowResources.overrideResource(R.bool.config_hide_none_security_option, false); SettingsShadowResources.overrideResource(R.bool.config_hide_swipe_security_option, false); @@ -206,9 +203,7 @@ public class ChooseLockGenericControllerTest { @Test public void upgradeQuality_noDpmRequirement_shouldReturnQuality() { - doReturn(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) - .when(mDevicePolicyManager) - .getPasswordQuality(nullable(ComponentName.class), anyInt()); + setDevicePolicyPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED); final int upgradedQuality = mController.upgradeQuality(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC); @@ -218,9 +213,7 @@ public class ChooseLockGenericControllerTest { @Test public void upgradeQuality_dpmRequirement_shouldReturnRequiredQuality() { - doReturn(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC) - .when(mDevicePolicyManager) - .getPasswordQuality(nullable(ComponentName.class), anyInt()); + setDevicePolicyPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC); final int upgradedQuality = mController.upgradeQuality(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); @@ -230,8 +223,7 @@ public class ChooseLockGenericControllerTest { @Test public void upgradeQuality_complexityHigh_minQualityNumericComplex() { - when(mDevicePolicyManager.getPasswordQuality(nullable(ComponentName.class), anyInt())) - .thenReturn(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED); + setDevicePolicyPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED); ChooseLockGenericController controller = createController(PASSWORD_COMPLEXITY_HIGH); assertThat(controller.upgradeQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED)) @@ -240,8 +232,7 @@ public class ChooseLockGenericControllerTest { @Test public void upgradeQuality_complexityMedium_minQualityNumericComplex() { - when(mDevicePolicyManager.getPasswordQuality(nullable(ComponentName.class), anyInt())) - .thenReturn(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED); + setDevicePolicyPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED); ChooseLockGenericController controller = createController(PASSWORD_COMPLEXITY_MEDIUM); assertThat(controller.upgradeQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED)) @@ -250,21 +241,28 @@ public class ChooseLockGenericControllerTest { @Test public void upgradeQuality_complexityLow_minQualitySomething() { - when(mDevicePolicyManager.getPasswordQuality(nullable(ComponentName.class), anyInt())) - .thenReturn(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED); + setDevicePolicyPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED); ChooseLockGenericController controller = createController(PASSWORD_COMPLEXITY_LOW); assertThat(controller.upgradeQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED)) .isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); } + private void setDevicePolicyPasswordQuality(int quality) { + PasswordPolicy policy = new PasswordPolicy(); + policy.quality = quality; + + when(mLockPatternUtils.getRequestedPasswordMetrics(anyInt(), anyBoolean())) + .thenReturn(policy.getMinMetrics()); + } + private ChooseLockGenericController createController( @PasswordComplexity int minPasswordComplexity) { return new ChooseLockGenericController( application, 0 /* userId */, minPasswordComplexity, - mDevicePolicyManager, + false, mManagedLockPasswordProvider, mLockPatternUtils); } diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java index 60979805c25..03ce25aaea7 100644 --- a/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java +++ b/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java @@ -21,10 +21,14 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH; import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_LOW; import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_MEDIUM; import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE; +import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; +import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; +import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE; import static com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment.KEY_LOCK_SETTINGS_FOOTER; import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_CALLER_APP_NAME; +import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY; import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_IS_CALLING_APP_ADMIN; import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY; @@ -35,6 +39,8 @@ import static org.robolectric.Shadows.shadowOf; import android.app.Activity; import android.app.admin.DevicePolicyManager; +import android.app.admin.PasswordMetrics; +import android.app.admin.PasswordPolicy; import android.content.Context; import android.content.Intent; import android.os.Bundle; @@ -301,8 +307,8 @@ public class ChooseLockGenericTest { assertThat(result).isTrue(); Intent actualIntent = shadowOf(mActivity).getNextStartedActivityForResult().intent; assertThat(actualIntent.hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)).isTrue(); - assertThat(actualIntent.getIntExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_NONE)) - .isEqualTo(PASSWORD_COMPLEXITY_HIGH); + assertThat(actualIntent.getIntExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, + PASSWORD_COMPLEXITY_NONE)).isEqualTo(PASSWORD_COMPLEXITY_HIGH); assertThat(actualIntent.hasExtra(EXTRA_KEY_CALLER_APP_NAME)).isTrue(); assertThat(actualIntent.getStringExtra(EXTRA_KEY_CALLER_APP_NAME)) .isEqualTo("app name"); @@ -322,8 +328,8 @@ public class ChooseLockGenericTest { assertThat(result).isTrue(); Intent actualIntent = shadowOf(mActivity).getNextStartedActivityForResult().intent; assertThat(actualIntent.hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)).isTrue(); - assertThat(actualIntent.getIntExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_NONE)) - .isEqualTo(PASSWORD_COMPLEXITY_HIGH); + assertThat(actualIntent.getIntExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, + PASSWORD_COMPLEXITY_NONE)).isEqualTo(PASSWORD_COMPLEXITY_HIGH); assertThat(actualIntent.hasExtra(EXTRA_KEY_CALLER_APP_NAME)).isTrue(); assertThat(actualIntent.getStringExtra(EXTRA_KEY_CALLER_APP_NAME)) .isEqualTo("app name"); @@ -391,7 +397,7 @@ public class ChooseLockGenericTest { assertThat(footer.getTitle()).isEqualTo(null); Intent intent = mFragment.getLockPasswordIntent(PASSWORD_QUALITY_COMPLEX); - assertThat(intent.getIntExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, + assertThat(intent.getIntExtra(ChooseLockPassword.EXTRA_KEY_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_NONE)).isEqualTo(PASSWORD_COMPLEXITY_HIGH); } @@ -411,7 +417,7 @@ public class ChooseLockGenericTest { assertThat(footer.getTitle()).isEqualTo(null); Intent passwordIntent = mFragment.getLockPasswordIntent(PASSWORD_QUALITY_COMPLEX); - assertThat(passwordIntent.getIntExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, + assertThat(passwordIntent.getIntExtra(ChooseLockPassword.EXTRA_KEY_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_NONE)).isEqualTo(PASSWORD_COMPLEXITY_HIGH); } @@ -433,10 +439,66 @@ public class ChooseLockGenericTest { assertThat(footer.getTitle()).isEqualTo(expectedTitle); Intent passwordIntent = mFragment.getLockPasswordIntent(PASSWORD_QUALITY_COMPLEX); - assertThat(passwordIntent.getIntExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, + assertThat(passwordIntent.getIntExtra(ChooseLockPassword.EXTRA_KEY_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_NONE)).isEqualTo(PASSWORD_COMPLEXITY_HIGH); } + @Test + public void getLockPasswordIntent_DevicePasswordRequirementOnly_PasswordComplexityPassedOn() { + ShadowLockPatternUtils.setRequiredPasswordComplexity(PASSWORD_COMPLEXITY_LOW); + ShadowLockPatternUtils.setRequiredProfilePasswordComplexity(PASSWORD_COMPLEXITY_HIGH); + + Intent intent = new Intent() + .putExtra(EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY, true); + initActivity(intent); + + Intent passwordIntent = mFragment.getLockPasswordIntent(PASSWORD_QUALITY_ALPHABETIC); + assertThat(passwordIntent.getIntExtra(ChooseLockPassword.EXTRA_KEY_MIN_COMPLEXITY, + PASSWORD_COMPLEXITY_NONE)).isEqualTo(PASSWORD_COMPLEXITY_LOW); + assertThat(passwordIntent.getParcelableExtra( + ChooseLockPassword.EXTRA_KEY_MIN_METRICS)).isEqualTo( + new PasswordMetrics(CREDENTIAL_TYPE_NONE)); + } + + @Test + public void getLockPasswordIntent_DevicePasswordRequirementOnly_PasswordQualityPassedOn() { + PasswordPolicy policy = new PasswordPolicy(); + policy.quality = PASSWORD_QUALITY_SOMETHING; + ShadowLockPatternUtils.setRequestedPasswordMetrics(policy.getMinMetrics()); + PasswordPolicy profilePolicy = new PasswordPolicy(); + profilePolicy.quality = PASSWORD_QUALITY_ALPHABETIC; + ShadowLockPatternUtils.setRequestedProfilePasswordMetrics(profilePolicy.getMinMetrics()); + + Intent intent = new Intent() + .putExtra(EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY, true); + initActivity(intent); + + Intent passwordIntent = mFragment.getLockPasswordIntent(PASSWORD_QUALITY_ALPHABETIC); + assertThat(passwordIntent.getIntExtra(ChooseLockPassword.EXTRA_KEY_MIN_COMPLEXITY, + PASSWORD_COMPLEXITY_NONE)).isEqualTo(PASSWORD_COMPLEXITY_NONE); + assertThat(passwordIntent.getParcelableExtra( + ChooseLockPassword.EXTRA_KEY_MIN_METRICS)).isEqualTo(policy.getMinMetrics()); + } + + @Test + public void getLockPasswordIntent_DevicePasswordRequirementOnly_ComplexityAndQualityPassedOn() { + ShadowLockPatternUtils.setRequiredPasswordComplexity(PASSWORD_COMPLEXITY_LOW); + PasswordPolicy policy = new PasswordPolicy(); + policy.quality = PASSWORD_QUALITY_ALPHABETIC; + ShadowLockPatternUtils.setRequestedProfilePasswordMetrics(policy.getMinMetrics()); + + Intent intent = new Intent() + .putExtra(EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY, true); + initActivity(intent); + + Intent passwordIntent = mFragment.getLockPasswordIntent(PASSWORD_QUALITY_ALPHABETIC); + assertThat(passwordIntent.getIntExtra(ChooseLockPassword.EXTRA_KEY_MIN_COMPLEXITY, + PASSWORD_COMPLEXITY_NONE)).isEqualTo(PASSWORD_COMPLEXITY_LOW); + assertThat(passwordIntent.getParcelableExtra( + ChooseLockPassword.EXTRA_KEY_MIN_METRICS)).isEqualTo( + new PasswordMetrics(CREDENTIAL_TYPE_NONE)); + } + private void initActivity(@Nullable Intent intent) { if (intent == null) { intent = new Intent(); diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java index 0ca6a3ee114..2233f1d1d00 100644 --- a/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java +++ b/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java @@ -30,7 +30,6 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED import static com.android.internal.widget.LockPatternUtils.PASSWORD_TYPE_KEY; import static com.android.settings.password.ChooseLockGeneric.CONFIRM_CREDENTIALS; -import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY; import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_ID; import static com.google.common.truth.Truth.assertThat; @@ -40,6 +39,8 @@ import static org.robolectric.RuntimeEnvironment.application; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager.PasswordComplexity; +import android.app.admin.PasswordMetrics; +import android.app.admin.PasswordPolicy; import android.content.Intent; import android.os.UserHandle; @@ -93,7 +94,7 @@ public class ChooseLockPasswordTest { public void intentBuilder_setPassword_shouldAddExtras() { Intent intent = new IntentBuilder(application) .setPassword(LockscreenCredential.createPassword("password")) - .setPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) + .setPasswordType(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) .setUserId(123) .build(); @@ -114,7 +115,7 @@ public class ChooseLockPasswordTest { public void intentBuilder_setRequestGatekeeperPassword_shouldAddExtras() { Intent intent = new IntentBuilder(application) .setRequestGatekeeperPasswordHandle(true) - .setPasswordQuality(PASSWORD_QUALITY_ALPHANUMERIC) + .setPasswordType(PASSWORD_QUALITY_ALPHANUMERIC) .setUserId(123) .build(); @@ -131,11 +132,12 @@ public class ChooseLockPasswordTest { @Test public void intentBuilder_setMinComplexityMedium_hasMinComplexityExtraMedium() { Intent intent = new IntentBuilder(application) - .setRequestedMinComplexity(PASSWORD_COMPLEXITY_MEDIUM) + .setPasswordRequirement(PASSWORD_COMPLEXITY_MEDIUM, null) .build(); - assertThat(intent.hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)).isTrue(); - assertThat(intent.getIntExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_NONE)) + assertThat(intent.hasExtra(ChooseLockPassword.EXTRA_KEY_MIN_COMPLEXITY)).isTrue(); + assertThat(intent.getIntExtra( + ChooseLockPassword.EXTRA_KEY_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_NONE)) .isEqualTo(PASSWORD_COMPLEXITY_MEDIUM); } @@ -143,7 +145,7 @@ public class ChooseLockPasswordTest { public void intentBuilder_setMinComplexityNotCalled() { Intent intent = new IntentBuilder(application).build(); - assertThat(intent.hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)).isFalse(); + assertThat(intent.hasExtra(ChooseLockPassword.EXTRA_KEY_MIN_COMPLEXITY)).isFalse(); } @Test @@ -163,10 +165,12 @@ public class ChooseLockPasswordTest { @Test public void processAndValidatePasswordRequirements_noMinPasswordComplexity() { - mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_ALPHABETIC); - mShadowDpm.setPasswordMinimumLength(10); + PasswordPolicy policy = new PasswordPolicy(); + policy.quality = PASSWORD_QUALITY_ALPHABETIC; + policy.length = 10; assertPasswordValidationResult( + /* minMetrics */ policy.getMinMetrics(), /* minComplexity= */ PASSWORD_COMPLEXITY_NONE, /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC, /* userEnteredPassword= */ LockscreenCredential.createNone(), @@ -176,9 +180,11 @@ public class ChooseLockPasswordTest { @Test public void processAndValidatePasswordRequirements_minPasswordComplexityStricter_pin() { - mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_SOMETHING); + PasswordPolicy policy = new PasswordPolicy(); + policy.quality = PASSWORD_QUALITY_SOMETHING; assertPasswordValidationResult( + /* minMetrics */ policy.getMinMetrics(), /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH, /* passwordType= */ PASSWORD_QUALITY_NUMERIC, /* userEnteredPassword= */ LockscreenCredential.createNone(), @@ -188,9 +194,11 @@ public class ChooseLockPasswordTest { @Test @Ignore public void processAndValidatePasswordRequirements_minPasswordComplexityStricter_password() { - mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_SOMETHING); + PasswordPolicy policy = new PasswordPolicy(); + policy.quality = PASSWORD_QUALITY_SOMETHING; assertPasswordValidationResult( + /* minMetrics */ policy.getMinMetrics(), /* minComplexity= */ PASSWORD_COMPLEXITY_MEDIUM, /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC, /* userEnteredPassword= */ LockscreenCredential.createNone(), @@ -200,10 +208,12 @@ public class ChooseLockPasswordTest { @Test public void processAndValidatePasswordRequirements_dpmRestrictionsStricter_password() { - mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_ALPHANUMERIC); - mShadowDpm.setPasswordMinimumLength(9); + PasswordPolicy policy = new PasswordPolicy(); + policy.quality = PASSWORD_QUALITY_ALPHANUMERIC; + policy.length = 9; assertPasswordValidationResult( + /* minMetrics */ policy.getMinMetrics(), /* minComplexity= */ PASSWORD_COMPLEXITY_LOW, /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC, /* userEnteredPassword= */ LockscreenCredential.createNone(), @@ -214,10 +224,12 @@ public class ChooseLockPasswordTest { @Test public void processAndValidatePasswordRequirements_dpmLengthLonger_pin() { - mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_NUMERIC); - mShadowDpm.setPasswordMinimumLength(11); + PasswordPolicy policy = new PasswordPolicy(); + policy.quality = PASSWORD_QUALITY_NUMERIC; + policy.length = 11; assertPasswordValidationResult( + /* minMetrics */ policy.getMinMetrics(), /* minComplexity= */ PASSWORD_COMPLEXITY_MEDIUM, /* passwordType= */ PASSWORD_QUALITY_NUMERIC, /* userEnteredPassword= */ LockscreenCredential.createNone(), @@ -226,10 +238,12 @@ public class ChooseLockPasswordTest { @Test public void processAndValidatePasswordRequirements_dpmQualityComplex() { - mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_COMPLEX); - mShadowDpm.setPasswordMinimumSymbols(2); + PasswordPolicy policy = new PasswordPolicy(); + policy.quality = PASSWORD_QUALITY_COMPLEX; + policy.symbols = 2; assertPasswordValidationResult( + /* minMetrics */ policy.getMinMetrics(), /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH, /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC, /* userEnteredPassword= */ LockscreenCredential.createNone(), @@ -242,9 +256,11 @@ public class ChooseLockPasswordTest { @Test @Config(shadows = ShadowLockPatternUtils.class) public void processAndValidatePasswordRequirements_numericComplexNoMinComplexity_pinRequested() { - mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_NUMERIC_COMPLEX); + PasswordPolicy policy = new PasswordPolicy(); + policy.quality = PASSWORD_QUALITY_NUMERIC_COMPLEX; assertPasswordValidationResult( + /* minMetrics */ policy.getMinMetrics(), /* minComplexity= */ PASSWORD_COMPLEXITY_NONE, /* passwordType= */ PASSWORD_QUALITY_NUMERIC, /* userEnteredPassword= */ LockscreenCredential.createPassword("12345678"), @@ -254,9 +270,11 @@ public class ChooseLockPasswordTest { @Test @Config(shadows = ShadowLockPatternUtils.class) public void processAndValidatePasswordRequirements_numericComplexNoMinComplexity_passwordRequested() { - mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_NUMERIC_COMPLEX); + PasswordPolicy policy = new PasswordPolicy(); + policy.quality = PASSWORD_QUALITY_NUMERIC_COMPLEX; assertPasswordValidationResult( + /* minMetrics */ policy.getMinMetrics(), /* minComplexity= */ PASSWORD_COMPLEXITY_NONE, /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC, /* userEnteredPassword= */ LockscreenCredential.createPassword("12345678"), @@ -266,9 +284,11 @@ public class ChooseLockPasswordTest { @Test @Config(shadows = ShadowLockPatternUtils.class) public void processAndValidatePasswordRequirements_numericComplexHighComplexity_pinRequested() { - mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_NUMERIC_COMPLEX); + PasswordPolicy policy = new PasswordPolicy(); + policy.quality = PASSWORD_QUALITY_NUMERIC_COMPLEX; assertPasswordValidationResult( + /* minMetrics */ policy.getMinMetrics(), /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH, /* passwordType= */ PASSWORD_QUALITY_NUMERIC, /* userEnteredPassword= */ LockscreenCredential.createPassword("12345678"), @@ -278,9 +298,11 @@ public class ChooseLockPasswordTest { @Test @Config(shadows = ShadowLockPatternUtils.class) public void processAndValidatePasswordRequirements_numericHighComplexity_pinRequested() { - mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_NUMERIC); + PasswordPolicy policy = new PasswordPolicy(); + policy.quality = PASSWORD_QUALITY_NUMERIC_COMPLEX; assertPasswordValidationResult( + /* minMetrics */ policy.getMinMetrics(), /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH, /* passwordType= */ PASSWORD_QUALITY_NUMERIC, /* userEnteredPassword= */ LockscreenCredential.createPassword("12345678"), @@ -290,9 +312,11 @@ public class ChooseLockPasswordTest { @Test @Config(shadows = ShadowLockPatternUtils.class) public void processAndValidatePasswordRequirements_numericComplexLowComplexity_passwordRequested() { - mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_NUMERIC_COMPLEX); + PasswordPolicy policy = new PasswordPolicy(); + policy.quality = PASSWORD_QUALITY_NUMERIC_COMPLEX; assertPasswordValidationResult( + /* minMetrics */ policy.getMinMetrics(), /* minComplexity= */ PASSWORD_COMPLEXITY_LOW, /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC, /* userEnteredPassword= */ LockscreenCredential.createPassword("12345678"), @@ -302,9 +326,11 @@ public class ChooseLockPasswordTest { @Test @Ignore public void processAndValidatePasswordRequirements_requirementsUpdateAccordingToMinComplexityAndUserInput_empty() { - mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED); + PasswordPolicy policy = new PasswordPolicy(); + policy.quality = PASSWORD_QUALITY_UNSPECIFIED; assertPasswordValidationResult( + /* minMetrics */ policy.getMinMetrics(), /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH, /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC, /* userEnteredPassword= */ LockscreenCredential.createNone(), @@ -315,9 +341,11 @@ public class ChooseLockPasswordTest { @Test @Ignore public void processAndValidatePasswordRequirements_requirementsUpdateAccordingToMinComplexityAndUserInput_numeric() { - mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED); + PasswordPolicy policy = new PasswordPolicy(); + policy.quality = PASSWORD_QUALITY_UNSPECIFIED; assertPasswordValidationResult( + /* minMetrics */ policy.getMinMetrics(), /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH, /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC, /* userEnteredPassword= */ LockscreenCredential.createPassword("1"), @@ -327,9 +355,11 @@ public class ChooseLockPasswordTest { @Test public void processAndValidatePasswordRequirements_requirementsUpdateAccordingToMinComplexityAndUserInput_alphabetic() { - mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED); + PasswordPolicy policy = new PasswordPolicy(); + policy.quality = PASSWORD_QUALITY_UNSPECIFIED; assertPasswordValidationResult( + /* minMetrics */ policy.getMinMetrics(), /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH, /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC, /* userEnteredPassword= */ LockscreenCredential.createPassword("b"), @@ -338,9 +368,11 @@ public class ChooseLockPasswordTest { @Test public void processAndValidatePasswordRequirements_requirementsUpdateAccordingToMinComplexityAndUserInput_alphanumeric() { - mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED); + PasswordPolicy policy = new PasswordPolicy(); + policy.quality = PASSWORD_QUALITY_UNSPECIFIED; assertPasswordValidationResult( + /* minMetrics */ policy.getMinMetrics(), /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH, /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC, /* userEnteredPassword= */ LockscreenCredential.createPassword("b1"), @@ -349,9 +381,11 @@ public class ChooseLockPasswordTest { @Test public void processAndValidatePasswordRequirements_defaultPinMinimumLength() { - mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED); + PasswordPolicy policy = new PasswordPolicy(); + policy.quality = PASSWORD_QUALITY_UNSPECIFIED; assertPasswordValidationResult( + /* minMetrics */ policy.getMinMetrics(), /* minComplexity= */ PASSWORD_COMPLEXITY_NONE, /* passwordType= */ PASSWORD_QUALITY_NUMERIC, /* userEnteredPassword= */ LockscreenCredential.createPassword("11"), @@ -360,9 +394,11 @@ public class ChooseLockPasswordTest { @Test public void processAndValidatePasswordRequirements_maximumLength() { - mShadowDpm.setPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED); + PasswordPolicy policy = new PasswordPolicy(); + policy.quality = PASSWORD_QUALITY_UNSPECIFIED; assertPasswordValidationResult( + /* minMetrics */ policy.getMinMetrics(), /* minComplexity= */ PASSWORD_COMPLEXITY_NONE, /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC, LockscreenCredential.createPassword("01234567890123456789"), @@ -386,6 +422,7 @@ public class ChooseLockPasswordTest { ShadowLockPatternUtils.setRequiredPasswordComplexity(PASSWORD_COMPLEXITY_LOW); assertPasswordValidationResult( + /* minMetrics */ null, /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH, /* passwordType= */ PASSWORD_QUALITY_NUMERIC, /* userEnteredPassword= */ LockscreenCredential.createNone(), @@ -397,7 +434,7 @@ public class ChooseLockPasswordTest { ShadowLockPatternUtils.setRequiredPasswordComplexity(PASSWORD_COMPLEXITY_LOW); ShadowLockPatternUtils.setRequiredPasswordComplexity(123, PASSWORD_COMPLEXITY_HIGH); - Intent intent = createIntentForPasswordValidation(PASSWORD_COMPLEXITY_NONE, + Intent intent = createIntentForPasswordValidation(null, PASSWORD_COMPLEXITY_NONE, PASSWORD_QUALITY_NUMERIC); intent.putExtra(EXTRA_KEY_UNIFICATION_PROFILE_ID, 123); assertPasswordValidationResultForIntent(LockscreenCredential.createNone(), intent, @@ -423,10 +460,11 @@ public class ChooseLockPasswordTest { return Shadows.shadowOf(((GlifLayout) fragment.getView()).getIcon()); } - private void assertPasswordValidationResult(@PasswordComplexity int minComplexity, + private void assertPasswordValidationResult(PasswordMetrics minMetrics, + @PasswordComplexity int minComplexity, int passwordType, LockscreenCredential userEnteredPassword, String... expectedValidationResult) { - Intent intent = createIntentForPasswordValidation(minComplexity, passwordType); + Intent intent = createIntentForPasswordValidation(minMetrics, minComplexity, passwordType); assertPasswordValidationResultForIntent(userEnteredPassword, intent, expectedValidationResult); } @@ -441,12 +479,14 @@ public class ChooseLockPasswordTest { } private Intent createIntentForPasswordValidation( + PasswordMetrics minMetrics, @PasswordComplexity int minComplexity, int passwordType) { Intent intent = new Intent(); intent.putExtra(CONFIRM_CREDENTIALS, false); intent.putExtra(PASSWORD_TYPE_KEY, passwordType); - intent.putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, minComplexity); + intent.putExtra(ChooseLockPassword.EXTRA_KEY_MIN_METRICS, minMetrics); + intent.putExtra(ChooseLockPassword.EXTRA_KEY_MIN_COMPLEXITY, minComplexity); return intent; } } diff --git a/tests/robotests/src/com/android/settings/password/SetNewPasswordActivityTest.java b/tests/robotests/src/com/android/settings/password/SetNewPasswordActivityTest.java index f25ef67e17f..a5bc845375a 100644 --- a/tests/robotests/src/com/android/settings/password/SetNewPasswordActivityTest.java +++ b/tests/robotests/src/com/android/settings/password/SetNewPasswordActivityTest.java @@ -24,6 +24,7 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH; import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE; import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_CALLER_APP_NAME; +import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY; import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_IS_CALLING_APP_ADMIN; import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY; @@ -300,6 +301,8 @@ public class SetNewPasswordActivityTest { Intent actualIntent = getLaunchChooseLockIntent(shadowActivity); assertThat(actualIntent.getAction()).isEqualTo(ACTION_SET_NEW_PARENT_PROFILE_PASSWORD); assertThat(actualIntent.hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)).isFalse(); + assertThat(actualIntent.getBooleanExtra( + EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY, false)).isFalse(); assertThat(actualIntent.hasExtra(EXTRA_KEY_CALLER_APP_NAME)).isTrue(); assertThat(actualIntent.getStringExtra(EXTRA_KEY_CALLER_APP_NAME)).isEqualTo(APP_LABEL); verify(mockMetricsProvider).action( @@ -309,6 +312,23 @@ public class SetNewPasswordActivityTest { PKG_NAME, Integer.MIN_VALUE); } + @Test + @Config(shadows = {ShadowPasswordUtils.class}) + public void launchChooseLock_setNewParentProfilePassword_DevicePasswordRequirementExtra() { + Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(), + Settings.Global.DEVICE_PROVISIONED, 1); + + Intent intent = new Intent(ACTION_SET_NEW_PARENT_PROFILE_PASSWORD) + .putExtra(DevicePolicyManager.EXTRA_DEVICE_PASSWORD_REQUIREMENT_ONLY, true); + SetNewPasswordActivity activity = + Robolectric.buildActivity(SetNewPasswordActivity.class, intent).create().get(); + + ShadowActivity shadowActivity = Shadows.shadowOf(activity); + Intent actualIntent = getLaunchChooseLockIntent(shadowActivity); + + assertThat(actualIntent.getBooleanExtra( + EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY, false)).isTrue(); + } @Test @Config(shadows = {ShadowPasswordUtils.class}) diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java index 3a159b209ba..20547d7a351 100644 --- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java @@ -17,6 +17,7 @@ package com.android.settings.testutils.shadow; import android.app.admin.DevicePolicyManager; +import android.app.admin.PasswordMetrics; import android.content.ComponentName; import android.os.UserHandle; @@ -36,11 +37,17 @@ public class ShadowLockPatternUtils { private static boolean sDeviceEncryptionEnabled; private static Map sUserToComplexityMap = new HashMap<>(); + private static Map sUserToProfileComplexityMap = new HashMap<>(); + private static Map sUserToMetricsMap = new HashMap<>(); + private static Map sUserToProfileMetricsMap = new HashMap<>(); @Resetter public static void reset() { sUserToComplexityMap.clear(); + sUserToProfileComplexityMap.clear(); + sUserToMetricsMap.clear(); + sUserToProfileMetricsMap.clear(); sDeviceEncryptionEnabled = false; } @@ -91,15 +98,50 @@ public class ShadowLockPatternUtils { @Implementation public @DevicePolicyManager.PasswordComplexity int getRequestedPasswordComplexity(int userId) { - return sUserToComplexityMap.getOrDefault(userId, - DevicePolicyManager.PASSWORD_COMPLEXITY_NONE); + return getRequestedPasswordComplexity(userId, false); } - public static void setRequiredPasswordComplexity(int userId, int complexity) { - sUserToComplexityMap.put(userId, complexity); + @Implementation + public @DevicePolicyManager.PasswordComplexity int getRequestedPasswordComplexity(int userId, + boolean deviceWideOnly) { + int complexity = sUserToComplexityMap.getOrDefault(userId, + DevicePolicyManager.PASSWORD_COMPLEXITY_NONE); + if (!deviceWideOnly) { + complexity = Math.max(complexity, sUserToProfileComplexityMap.getOrDefault(userId, + DevicePolicyManager.PASSWORD_COMPLEXITY_NONE)); + } + return complexity; + } + + public static void setRequiredPasswordComplexity(int userHandle, int complexity) { + sUserToComplexityMap.put(userHandle, complexity); } public static void setRequiredPasswordComplexity(int complexity) { - setRequiredPasswordComplexity(UserHandle.myUserId(), complexity); + sUserToComplexityMap.put(UserHandle.myUserId(), complexity); } + + public static void setRequiredProfilePasswordComplexity(int complexity) { + sUserToProfileComplexityMap.put(UserHandle.myUserId(), complexity); + } + + @Implementation + public PasswordMetrics getRequestedPasswordMetrics(int userId, boolean deviceWideOnly) { + PasswordMetrics metrics = sUserToMetricsMap.getOrDefault(userId, + new PasswordMetrics(LockPatternUtils.CREDENTIAL_TYPE_NONE)); + if (!deviceWideOnly) { + metrics.maxWith(sUserToProfileMetricsMap.getOrDefault(userId, + new PasswordMetrics(LockPatternUtils.CREDENTIAL_TYPE_NONE))); + } + return metrics; + } + + public static void setRequestedPasswordMetrics(PasswordMetrics metrics) { + sUserToMetricsMap.put(UserHandle.myUserId(), metrics); + } + + public static void setRequestedProfilePasswordMetrics(PasswordMetrics metrics) { + sUserToProfileMetricsMap.put(UserHandle.myUserId(), metrics); + } + }