Loading res/values/styles.xml +6 −1 Original line number Diff line number Diff line Loading @@ -955,11 +955,16 @@ <item name="biometricsEnrollProgressHelpWithTalkback">@color/udfps_enroll_progress_help_with_talkback</item> </style> <style name="ScreenLockPasswordHintTextFontStyle"> <style name="ScreenLockPasswordHintTextFontStyleError"> <item name="android:textColor">?android:attr/colorError</item> <item name="android:fontFamily">google-sans-text</item> </style> <style name="ScreenLockPasswordHintTextFontStyle"> <item name="android:textColor">?android:attr/textColorPrimary</item> <item name="android:fontFamily">google-sans-text</item> </style> <style name="PrivateSpaceSetupTextFontStyle" parent="@android:style/TextAppearance.DeviceDefault"> <item name="android:textColor">?android:attr/textColorPrimary</item> <item name="android:fontFamily">google-sans-text</item> Loading src/com/android/settings/password/ChooseLockPassword.java +11 −1 Original line number Diff line number Diff line Loading @@ -271,6 +271,8 @@ public class ChooseLockPassword extends SettingsActivity { private static final int CONFIRM_EXISTING_REQUEST = 58; static final int RESULT_FINISHED = RESULT_FIRST_USER; private boolean mIsErrorTooShort = true; /** Used to store the profile type for which pin/password is being set */ protected enum ProfileType { None, Loading Loading @@ -672,6 +674,11 @@ public class ChooseLockPassword extends SettingsActivity { view.addView(mPasswordRestrictionView); } @VisibleForTesting View getPasswordRequirementsView() { return mPasswordRestrictionView; } private void createHintMessageView(ViewGroup view) { if (mPasswordRestrictionView != null) { return; Loading Loading @@ -855,6 +862,7 @@ public class ChooseLockPassword extends SettingsActivity { */ String[] convertErrorCodeToMessages() { List<String> messages = new ArrayList<>(); mIsErrorTooShort = false; for (PasswordValidationError error : mValidationErrors) { switch (error.errorCode) { case CONTAINS_INVALID_CHARACTERS: Loading Loading @@ -889,6 +897,7 @@ public class ChooseLockPassword extends SettingsActivity { R.string.lockpassword_password_requires_nonnumerical)); break; case TOO_SHORT: mIsErrorTooShort = true; String message = StringUtil.getIcuPluralsString(getContext(), error.requirement, mIsAlphaMode Loading Loading @@ -951,12 +960,13 @@ public class ChooseLockPassword extends SettingsActivity { ? LockscreenCredential.createPassword(mPasswordEntry.getText()) : LockscreenCredential.createPin(mPasswordEntry.getText()); final int length = password.size(); if (mUiStage == Stage.Introduction) { mPasswordRestrictionView.setVisibility(View.VISIBLE); final boolean passwordCompliant = validatePassword(password); String[] messages = convertErrorCodeToMessages(); // Update the fulfillment of requirements. mPasswordRequirementAdapter.setRequirements(messages); mPasswordRequirementAdapter.setRequirements(messages, mIsErrorTooShort); // set the visibility of pin_auto_confirm option accordingly setAutoPinConfirmOption(passwordCompliant, length); // Enable/Disable the next button accordingly. Loading src/com/android/settings/password/PasswordRequirementAdapter.java +9 −2 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ public class PasswordRequirementAdapter extends private String[] mRequirements; private Context mContext; private boolean mIsTooShortError = true; public PasswordRequirementAdapter(Context context) { mContext = context; Loading @@ -54,8 +55,9 @@ public class PasswordRequirementAdapter extends return mRequirements.length; } public void setRequirements(String[] requirements) { public void setRequirements(String[] requirements, boolean isPasswordShort) { mRequirements = requirements; mIsTooShortError = isPasswordShort; notifyDataSetChanged(); } Loading @@ -74,7 +76,12 @@ public class PasswordRequirementAdapter extends final int fontSize = mContext.getResources().getDimensionPixelSize( R.dimen.password_requirement_font_size); holder.mDescriptionText.setText(mRequirements[position]); if (mIsTooShortError) { holder.mDescriptionText.setTextAppearance(R.style.ScreenLockPasswordHintTextFontStyle); } else { holder.mDescriptionText. setTextAppearance(R.style.ScreenLockPasswordHintTextFontStyleError); } holder.mDescriptionText.setTextSize(fontSize / mContext.getResources() .getDisplayMetrics().scaledDensity); } Loading tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java +53 −1 Original line number Diff line number Diff line Loading @@ -36,19 +36,25 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static org.robolectric.RuntimeEnvironment.application; import static org.robolectric.Shadows.shadowOf; import android.annotation.ColorInt; 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.Looper; import android.os.UserHandle; import android.view.View; import android.widget.CheckBox; import android.widget.TextView; import androidx.recyclerview.widget.RecyclerView; import com.android.internal.widget.LockscreenCredential; import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.password.ChooseLockPassword.ChooseLockPasswordFragment; import com.android.settings.password.ChooseLockPassword.IntentBuilder; import com.android.settings.testutils.shadow.SettingsShadowResources; Loading Loading @@ -515,6 +521,52 @@ public class ChooseLockPasswordTest { assertThat(pinAutoConfirmOption.isChecked()).isFalse(); } @Test public void defaultMessage_shouldBeInTextColorPrimary() { final ChooseLockPassword passwordActivity = setupActivityWithPinTypeAndDefaultPolicy(); final ChooseLockPasswordFragment fragment = getChooseLockPasswordFragment(passwordActivity); final ScrollToParentEditText passwordEntry = passwordActivity.findViewById(R.id.password_entry); final RecyclerView view = (RecyclerView) fragment.getPasswordRequirementsView(); @ColorInt final int textColorPrimary = Utils.getColorAttrDefaultColor(passwordActivity, android.R.attr.textColorPrimary); passwordEntry.setText(""); fragment.updateUi(); shadowOf(Looper.getMainLooper()).idle(); TextView textView = (TextView)view.getLayoutManager().findViewByPosition(0); assertThat(textView.getCurrentTextColor()).isEqualTo(textColorPrimary); } @Test public void errorMessage_shouldBeColorError() { final ChooseLockPassword passwordActivity = setupActivityWithPinTypeAndDefaultPolicy(); final ChooseLockPasswordFragment fragment = getChooseLockPasswordFragment(passwordActivity); final ScrollToParentEditText passwordEntry = passwordActivity.findViewById(R.id.password_entry); final RecyclerView view = (RecyclerView) fragment.getPasswordRequirementsView(); @ColorInt final int textColorPrimary = Utils.getColorAttrDefaultColor(passwordActivity, android.R.attr.textColorPrimary); @ColorInt final int colorError = Utils.getColorAttrDefaultColor(passwordActivity, android.R.attr.colorError); passwordEntry.setText(""); fragment.updateUi(); shadowOf(Looper.getMainLooper()).idle(); TextView textView = (TextView)view.getLayoutManager().findViewByPosition(0); assertThat(textView.getCurrentTextColor()).isEqualTo(textColorPrimary); // Password must be fewer than 17 digits, so this should give an error. passwordEntry.setText("a".repeat(17)); fragment.updateUi(); shadowOf(Looper.getMainLooper()).idle(); textView = (TextView)view.getLayoutManager().findViewByPosition(0); assertThat(textView.getCurrentTextColor()).isEqualTo(colorError); } private ChooseLockPassword setupActivityWithPinTypeAndDefaultPolicy() { PasswordPolicy policy = new PasswordPolicy(); policy.quality = PASSWORD_QUALITY_UNSPECIFIED; Loading Loading @@ -543,7 +595,7 @@ public class ChooseLockPasswordTest { .setForFingerprint(addFingerprintExtra) .build()); ChooseLockPasswordFragment fragment = getChooseLockPasswordFragment(passwordActivity); return Shadows.shadowOf(((GlifLayout) fragment.getView()).getIcon()); return shadowOf(((GlifLayout) fragment.getView()).getIcon()); } private void assertPasswordValidationResult(PasswordMetrics minMetrics, Loading Loading
res/values/styles.xml +6 −1 Original line number Diff line number Diff line Loading @@ -955,11 +955,16 @@ <item name="biometricsEnrollProgressHelpWithTalkback">@color/udfps_enroll_progress_help_with_talkback</item> </style> <style name="ScreenLockPasswordHintTextFontStyle"> <style name="ScreenLockPasswordHintTextFontStyleError"> <item name="android:textColor">?android:attr/colorError</item> <item name="android:fontFamily">google-sans-text</item> </style> <style name="ScreenLockPasswordHintTextFontStyle"> <item name="android:textColor">?android:attr/textColorPrimary</item> <item name="android:fontFamily">google-sans-text</item> </style> <style name="PrivateSpaceSetupTextFontStyle" parent="@android:style/TextAppearance.DeviceDefault"> <item name="android:textColor">?android:attr/textColorPrimary</item> <item name="android:fontFamily">google-sans-text</item> Loading
src/com/android/settings/password/ChooseLockPassword.java +11 −1 Original line number Diff line number Diff line Loading @@ -271,6 +271,8 @@ public class ChooseLockPassword extends SettingsActivity { private static final int CONFIRM_EXISTING_REQUEST = 58; static final int RESULT_FINISHED = RESULT_FIRST_USER; private boolean mIsErrorTooShort = true; /** Used to store the profile type for which pin/password is being set */ protected enum ProfileType { None, Loading Loading @@ -672,6 +674,11 @@ public class ChooseLockPassword extends SettingsActivity { view.addView(mPasswordRestrictionView); } @VisibleForTesting View getPasswordRequirementsView() { return mPasswordRestrictionView; } private void createHintMessageView(ViewGroup view) { if (mPasswordRestrictionView != null) { return; Loading Loading @@ -855,6 +862,7 @@ public class ChooseLockPassword extends SettingsActivity { */ String[] convertErrorCodeToMessages() { List<String> messages = new ArrayList<>(); mIsErrorTooShort = false; for (PasswordValidationError error : mValidationErrors) { switch (error.errorCode) { case CONTAINS_INVALID_CHARACTERS: Loading Loading @@ -889,6 +897,7 @@ public class ChooseLockPassword extends SettingsActivity { R.string.lockpassword_password_requires_nonnumerical)); break; case TOO_SHORT: mIsErrorTooShort = true; String message = StringUtil.getIcuPluralsString(getContext(), error.requirement, mIsAlphaMode Loading Loading @@ -951,12 +960,13 @@ public class ChooseLockPassword extends SettingsActivity { ? LockscreenCredential.createPassword(mPasswordEntry.getText()) : LockscreenCredential.createPin(mPasswordEntry.getText()); final int length = password.size(); if (mUiStage == Stage.Introduction) { mPasswordRestrictionView.setVisibility(View.VISIBLE); final boolean passwordCompliant = validatePassword(password); String[] messages = convertErrorCodeToMessages(); // Update the fulfillment of requirements. mPasswordRequirementAdapter.setRequirements(messages); mPasswordRequirementAdapter.setRequirements(messages, mIsErrorTooShort); // set the visibility of pin_auto_confirm option accordingly setAutoPinConfirmOption(passwordCompliant, length); // Enable/Disable the next button accordingly. Loading
src/com/android/settings/password/PasswordRequirementAdapter.java +9 −2 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ public class PasswordRequirementAdapter extends private String[] mRequirements; private Context mContext; private boolean mIsTooShortError = true; public PasswordRequirementAdapter(Context context) { mContext = context; Loading @@ -54,8 +55,9 @@ public class PasswordRequirementAdapter extends return mRequirements.length; } public void setRequirements(String[] requirements) { public void setRequirements(String[] requirements, boolean isPasswordShort) { mRequirements = requirements; mIsTooShortError = isPasswordShort; notifyDataSetChanged(); } Loading @@ -74,7 +76,12 @@ public class PasswordRequirementAdapter extends final int fontSize = mContext.getResources().getDimensionPixelSize( R.dimen.password_requirement_font_size); holder.mDescriptionText.setText(mRequirements[position]); if (mIsTooShortError) { holder.mDescriptionText.setTextAppearance(R.style.ScreenLockPasswordHintTextFontStyle); } else { holder.mDescriptionText. setTextAppearance(R.style.ScreenLockPasswordHintTextFontStyleError); } holder.mDescriptionText.setTextSize(fontSize / mContext.getResources() .getDisplayMetrics().scaledDensity); } Loading
tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java +53 −1 Original line number Diff line number Diff line Loading @@ -36,19 +36,25 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static org.robolectric.RuntimeEnvironment.application; import static org.robolectric.Shadows.shadowOf; import android.annotation.ColorInt; 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.Looper; import android.os.UserHandle; import android.view.View; import android.widget.CheckBox; import android.widget.TextView; import androidx.recyclerview.widget.RecyclerView; import com.android.internal.widget.LockscreenCredential; import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.password.ChooseLockPassword.ChooseLockPasswordFragment; import com.android.settings.password.ChooseLockPassword.IntentBuilder; import com.android.settings.testutils.shadow.SettingsShadowResources; Loading Loading @@ -515,6 +521,52 @@ public class ChooseLockPasswordTest { assertThat(pinAutoConfirmOption.isChecked()).isFalse(); } @Test public void defaultMessage_shouldBeInTextColorPrimary() { final ChooseLockPassword passwordActivity = setupActivityWithPinTypeAndDefaultPolicy(); final ChooseLockPasswordFragment fragment = getChooseLockPasswordFragment(passwordActivity); final ScrollToParentEditText passwordEntry = passwordActivity.findViewById(R.id.password_entry); final RecyclerView view = (RecyclerView) fragment.getPasswordRequirementsView(); @ColorInt final int textColorPrimary = Utils.getColorAttrDefaultColor(passwordActivity, android.R.attr.textColorPrimary); passwordEntry.setText(""); fragment.updateUi(); shadowOf(Looper.getMainLooper()).idle(); TextView textView = (TextView)view.getLayoutManager().findViewByPosition(0); assertThat(textView.getCurrentTextColor()).isEqualTo(textColorPrimary); } @Test public void errorMessage_shouldBeColorError() { final ChooseLockPassword passwordActivity = setupActivityWithPinTypeAndDefaultPolicy(); final ChooseLockPasswordFragment fragment = getChooseLockPasswordFragment(passwordActivity); final ScrollToParentEditText passwordEntry = passwordActivity.findViewById(R.id.password_entry); final RecyclerView view = (RecyclerView) fragment.getPasswordRequirementsView(); @ColorInt final int textColorPrimary = Utils.getColorAttrDefaultColor(passwordActivity, android.R.attr.textColorPrimary); @ColorInt final int colorError = Utils.getColorAttrDefaultColor(passwordActivity, android.R.attr.colorError); passwordEntry.setText(""); fragment.updateUi(); shadowOf(Looper.getMainLooper()).idle(); TextView textView = (TextView)view.getLayoutManager().findViewByPosition(0); assertThat(textView.getCurrentTextColor()).isEqualTo(textColorPrimary); // Password must be fewer than 17 digits, so this should give an error. passwordEntry.setText("a".repeat(17)); fragment.updateUi(); shadowOf(Looper.getMainLooper()).idle(); textView = (TextView)view.getLayoutManager().findViewByPosition(0); assertThat(textView.getCurrentTextColor()).isEqualTo(colorError); } private ChooseLockPassword setupActivityWithPinTypeAndDefaultPolicy() { PasswordPolicy policy = new PasswordPolicy(); policy.quality = PASSWORD_QUALITY_UNSPECIFIED; Loading Loading @@ -543,7 +595,7 @@ public class ChooseLockPasswordTest { .setForFingerprint(addFingerprintExtra) .build()); ChooseLockPasswordFragment fragment = getChooseLockPasswordFragment(passwordActivity); return Shadows.shadowOf(((GlifLayout) fragment.getView()).getIcon()); return shadowOf(((GlifLayout) fragment.getView()).getIcon()); } private void assertPasswordValidationResult(PasswordMetrics minMetrics, Loading