Add new "pin complex" type to supported keyguard PINs

This adds a feature to allow DevicePolicyAdmins to prevent using
simple PINs, which are defined as those containing more than 3
repeated values. Examples include '1234', '2468', '1111', '9876', etc.

Bug 12081139

Change-Id: I68d8fe2459837cb5e083724e1740e65f0519f7e1
diff --git a/res/values/strings.xml b/res/values/strings.xml
index bf975e2..3f3d765 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -996,6 +996,9 @@
     <!-- Error shown when in PASSWORD mode and password has been used recently. Please keep this string short! -->
     <string name="lockpassword_password_recently_used">Device administrator doesn\'t allow using a recent password.</string>
 
+    <!-- [CHAR_LIMIT=NONE] Error shown when the user tries to set an ascending or descending sequence of digits -->
+    <string name="lockpassword_pin_no_sequential_digits">An ascending, descending or repeated sequence of digits is forbidden</string>
+
     <!-- Label for ChoosePassword/PIN OK button -->
     <string name="lockpassword_ok_label">OK</string>
 
diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java
index 30a72ef..c444dc4 100644
--- a/src/com/android/settings/ChooseLockGeneric.java
+++ b/src/com/android/settings/ChooseLockGeneric.java
@@ -278,7 +278,7 @@
                     } else if (KEY_UNLOCK_SET_PATTERN.equals(key)) {
                         enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
                     } else if (KEY_UNLOCK_SET_PIN.equals(key)) {
-                        enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
+                        enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
                     } else if (KEY_UNLOCK_SET_PASSWORD.equals(key)) {
                         enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
                     }
diff --git a/src/com/android/settings/ChooseLockPassword.java b/src/com/android/settings/ChooseLockPassword.java
index 90cd251..6dfb0f7 100644
--- a/src/com/android/settings/ChooseLockPassword.java
+++ b/src/com/android/settings/ChooseLockPassword.java
@@ -329,10 +329,18 @@
                 }
             }
             if (DevicePolicyManager.PASSWORD_QUALITY_NUMERIC == mRequestedQuality
-                    && (letters > 0 || symbols > 0)) {
-                // This shouldn't be possible unless user finds some way to bring up
-                // soft keyboard
-                return getString(R.string.lockpassword_pin_contains_non_digits);
+                    || DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX == mRequestedQuality) {
+                if (letters > 0 || symbols > 0) {
+                    // This shouldn't be possible unless user finds some way to bring up
+                    // soft keyboard
+                    return getString(R.string.lockpassword_pin_contains_non_digits);
+                }
+                // Check for repeated characters or sequences (e.g. '1234', '0000', '2468')
+                final int sequence = LockPatternUtils.maxLengthSequence(password);
+                if (DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX == mRequestedQuality
+                        && sequence > LockPatternUtils.MAX_ALLOWED_SEQUENCE) {
+                    return getString(R.string.lockpassword_pin_no_sequential_digits);
+                }
             } else if (DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == mRequestedQuality) {
                 if (letters < mPasswordMinLetters) {
                     return String.format(getResources().getQuantityString(
@@ -375,6 +383,7 @@
                 return getString(mIsAlphaMode ? R.string.lockpassword_password_recently_used
                         : R.string.lockpassword_pin_recently_used);
             }
+
             return null;
         }
 
diff --git a/src/com/android/settings/ChooseLockSettingsHelper.java b/src/com/android/settings/ChooseLockSettingsHelper.java
index 15d1203..d59fefb 100644
--- a/src/com/android/settings/ChooseLockSettingsHelper.java
+++ b/src/com/android/settings/ChooseLockSettingsHelper.java
@@ -60,6 +60,7 @@
                 launched = confirmPattern(request, message, details);
                 break;
             case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
+            case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
             case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
             case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
             case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index 0af022a..6961b2a 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -151,6 +151,7 @@
                     resid = R.xml.security_settings_pattern;
                     break;
                 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
+                case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
                     resid = R.xml.security_settings_pin;
                     break;
                 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: