Fix 2535700: Add support for enforcing password quality

Change-Id: I908b4229d46061f3d450adec72b04276fe10afc1
diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java
index 83ef952..2c611f0 100644
--- a/src/com/android/settings/ChooseLockGeneric.java
+++ b/src/com/android/settings/ChooseLockGeneric.java
@@ -39,7 +39,7 @@
         
         int quality = getIntent().getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1);
         if (quality == -1) {
-            quality = lockPatternUtils.getPasswordMode();
+            quality = lockPatternUtils.getKeyguardStoredPasswordQuality();
         }
         int minQuality = mDPM.getPasswordQuality(null);
         if (quality < minQuality) {
diff --git a/src/com/android/settings/ChooseLockPassword.java b/src/com/android/settings/ChooseLockPassword.java
index 44acf95..2271a31 100644
--- a/src/com/android/settings/ChooseLockPassword.java
+++ b/src/com/android/settings/ChooseLockPassword.java
@@ -16,20 +16,13 @@
 
 package com.android.settings;
 
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.PasswordEntryKeyboardHelper;
 import com.android.internal.widget.PasswordEntryKeyboardView;
-import com.android.settings.ChooseLockPattern.LeftButtonMode;
-import com.android.settings.ChooseLockPattern.RightButtonMode;
-import com.android.settings.ChooseLockPattern.Stage;
 
 import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
 import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.graphics.PixelFormat;
 import android.inputmethodservice.KeyboardView;
 import android.os.Bundle;
 import android.os.Handler;
@@ -56,7 +49,7 @@
     private int mPasswordMinLength = 4;
     private int mPasswordMaxLength = 16;
     private LockPatternUtils mLockPatternUtils;
-    private int mRequestedMode = LockPatternUtils.MODE_PIN;
+    private int mRequestedQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
     private ChooseLockSettingsHelper mChooseLockSettingsHelper;
     private com.android.settings.ChooseLockPassword.Stage mUiStage = Stage.Introduction;
     private TextView mHeaderText;
@@ -108,12 +101,12 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mLockPatternUtils = new LockPatternUtils(this);
-        mRequestedMode = getIntent().getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, mRequestedMode);
+        mRequestedQuality = getIntent().getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, mRequestedQuality);
         mPasswordMinLength = getIntent().getIntExtra(PASSWORD_MIN_KEY, mPasswordMinLength);
         mPasswordMaxLength = getIntent().getIntExtra(PASSWORD_MAX_KEY, mPasswordMaxLength);
-        int minMode = mLockPatternUtils.getRequestedPasswordMode();
-        if (mRequestedMode < minMode) {
-            mRequestedMode = minMode;
+        int minMode = mLockPatternUtils.getRequestedPasswordQuality();
+        if (mRequestedQuality < minMode) {
+            mRequestedQuality = minMode;
         }
         int minLength = mLockPatternUtils.getRequestedMinimumPasswordLength();
         if (mPasswordMinLength < minLength) {
@@ -143,7 +136,8 @@
         mPasswordEntry.setOnEditorActionListener(this);
         mPasswordEntry.addTextChangedListener(this);
 
-        mIsAlphaMode = LockPatternUtils.MODE_PASSWORD == mRequestedMode;
+        mIsAlphaMode = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == mRequestedQuality
+            || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == mRequestedQuality;
         mKeyboardHelper = new PasswordEntryKeyboardHelper(this, mKeyboardView, mPasswordEntry);
         mKeyboardHelper.setKeyboardMode(mIsAlphaMode ?
                 PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
@@ -199,16 +193,16 @@
 
     /**
      * Validates PIN and returns a message to display if PIN fails test.
-     * @param pin
-     * @return message id to display to user
+     * @param password the raw password the user typed in
+     * @return error message to show to user or null if password is OK
      */
-    private String validatePassword(String pin) {
-        if (pin.length() < mPasswordMinLength) {
+    private String validatePassword(String password) {
+        if (password.length() < mPasswordMinLength) {
             return getString(mIsAlphaMode ?
                     R.string.lockpassword_password_too_short
                     : R.string.lockpassword_pin_too_short, mPasswordMinLength);
         }
-        if (pin.length() > mPasswordMaxLength) {
+        if (password.length() > mPasswordMaxLength) {
             return getString(mIsAlphaMode ?
                     R.string.lockpassword_password_too_long
                     : R.string.lockpassword_pin_too_long, mPasswordMaxLength);
@@ -216,8 +210,8 @@
         boolean hasAlpha = false;
         boolean hasDigit = false;
         boolean hasSymbol = false;
-        for (int i = 0; i < pin.length(); i++) {
-            char c = pin.charAt(i);
+        for (int i = 0; i < password.length(); i++) {
+            char c = password.charAt(i);
             // allow non white space Latin-1 characters only
             if (c <= 32 || c > 127) {
                 return getString(R.string.lockpassword_illegal_character);
@@ -230,11 +224,25 @@
                 hasSymbol = true;
             }
         }
-        if (LockPatternUtils.MODE_PIN == mRequestedMode && (hasAlpha | hasSymbol)) {
-                return getString(R.string.lockpassword_pin_contains_non_digits);
-        } else if (LockPatternUtils.MODE_PASSWORD == mRequestedMode && !hasAlpha) {
-            // require at least 1 alpha character
-            return getString(R.string.lockpassword_password_requires_alpha);
+        if (DevicePolicyManager.PASSWORD_QUALITY_NUMERIC == mRequestedQuality
+                && (hasAlpha | hasSymbol)) {
+            // This shouldn't be possible unless user finds some way to bring up soft keyboard
+            return getString(R.string.lockpassword_pin_contains_non_digits);
+        } else {
+            final boolean alphabetic = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
+                    == mRequestedQuality;
+            final boolean alphanumeric = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
+                    == mRequestedQuality;
+            final boolean symbolic = false; // not yet
+            if ((alphabetic || alphanumeric) && !hasAlpha) {
+                return getString(R.string.lockpassword_password_requires_alpha);
+            }
+            if (alphanumeric && !hasDigit) {
+                return getString(R.string.lockpassword_password_requires_digit);
+            }
+            if (symbolic && !hasSymbol) {
+                return getString(R.string.lockpassword_password_requires_symbol);
+            }
         }
         return null;
     }
@@ -255,7 +263,7 @@
         } else if (mUiStage == Stage.NeedToConfirm) {
             if (mFirstPin.equals(pin)) {
                 mLockPatternUtils.clearLock();
-                mLockPatternUtils.saveLockPassword(pin, mRequestedMode);
+                mLockPatternUtils.saveLockPassword(pin, mRequestedQuality);
                 finish();
             } else {
                 updateStage(Stage.ConfirmWrong);
@@ -304,7 +312,8 @@
      * Update the hint based on current Stage and length of password entry
      */
     private void updateUi() {
-        final int length = mPasswordEntry.getText().toString().length();
+        String password = mPasswordEntry.getText().toString();
+        final int length = password.length();
         if (mUiStage == Stage.Introduction && length > 0) {
             if (length < mPasswordMinLength) {
                 String msg = getString(mIsAlphaMode ? R.string.lockpassword_password_too_short
@@ -312,8 +321,14 @@
                 mHeaderText.setText(msg);
                 mNextButton.setEnabled(false);
             } else {
-                mHeaderText.setText(R.string.lockpassword_press_continue);
-                mNextButton.setEnabled(true);
+                String error = validatePassword(password);
+                if (error != null) {
+                    mHeaderText.setText(error);
+                    mNextButton.setEnabled(false);
+                } else {
+                    mHeaderText.setText(R.string.lockpassword_press_continue);
+                    mNextButton.setEnabled(true);
+                }
             }
         } else {
             mHeaderText.setText(mIsAlphaMode ? mUiStage.alphaHint : mUiStage.numericHint);
diff --git a/src/com/android/settings/ChooseLockSettingsHelper.java b/src/com/android/settings/ChooseLockSettingsHelper.java
index 3697b28e..5fe3118 100644
--- a/src/com/android/settings/ChooseLockSettingsHelper.java
+++ b/src/com/android/settings/ChooseLockSettingsHelper.java
@@ -17,6 +17,7 @@
 package com.android.settings;
 
 import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
 import android.content.Intent;
 
 import com.android.internal.widget.LockPatternUtils;
@@ -41,12 +42,12 @@
      */
     protected boolean launchConfirmationActivity(int request) {
         boolean launched = false;
-        switch (mLockPatternUtils.getPasswordMode()) {
-            case LockPatternUtils.MODE_PATTERN:
+        switch (mLockPatternUtils.getKeyguardStoredPasswordQuality()) {
+            case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
                 launched = confirmPattern(request);
                 break;
-            case LockPatternUtils.MODE_PIN:
-            case LockPatternUtils.MODE_PASSWORD:
+            case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
+            case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
                 launched = confirmPassword(request);
                 break;
         }
diff --git a/src/com/android/settings/ConfirmLockPassword.java b/src/com/android/settings/ConfirmLockPassword.java
index eedbc28..6bc135b 100644
--- a/src/com/android/settings/ConfirmLockPassword.java
+++ b/src/com/android/settings/ConfirmLockPassword.java
@@ -21,6 +21,7 @@
 import com.android.internal.widget.PasswordEntryKeyboardView;
 
 import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
 import android.os.Bundle;
 import android.os.Handler;
 import android.text.Editable;
@@ -51,7 +52,7 @@
     }
 
     private void initViews() {
-        int mode = mLockPatternUtils.getPasswordMode();
+        final int storedQuality = mLockPatternUtils.getKeyguardStoredPasswordQuality();
         setContentView(R.layout.confirm_lock_password);
         // Disable IME on our window since we provide our own keyboard
         getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
@@ -63,8 +64,8 @@
         mPasswordEntry.setOnEditorActionListener(this);
         mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
         mHeaderText = (TextView) findViewById(R.id.headerText);
-        final boolean isAlpha =
-                LockPatternUtils.MODE_PASSWORD == mLockPatternUtils.getPasswordMode();
+        final boolean isAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == storedQuality
+                || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == storedQuality;
         mHeaderText.setText(isAlpha ? R.string.lockpassword_confirm_your_password_header
                 : R.string.lockpassword_confirm_your_pin_header);
         mKeyboardHelper = new PasswordEntryKeyboardHelper(this, mKeyboardView, mPasswordEntry);
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index c36ef38..0848af9 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -162,13 +162,17 @@
         if (!mLockPatternUtils.isSecure()) {
             addPreferencesFromResource(R.xml.security_settings_chooser);
         } else {
-            final int currentMode = mLockPatternUtils.getPasswordMode();
-            if (currentMode == LockPatternUtils.MODE_PATTERN) {
-                addPreferencesFromResource(R.xml.security_settings_pattern);
-            } else if (currentMode == LockPatternUtils.MODE_PIN) {
-                addPreferencesFromResource(R.xml.security_settings_pin);
-            } else if (currentMode == LockPatternUtils.MODE_PASSWORD) {
-                addPreferencesFromResource(R.xml.security_settings_password);
+            switch (mLockPatternUtils.getKeyguardStoredPasswordQuality()) {
+                case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
+                    addPreferencesFromResource(R.xml.security_settings_pattern);
+                    break;
+                case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
+                    addPreferencesFromResource(R.xml.security_settings_pin);
+                    break;
+                case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
+                case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
+                    addPreferencesFromResource(R.xml.security_settings_password);
+                    break;
             }
         }
 
@@ -243,12 +247,13 @@
     protected void handleUpdateUnlockMethod(String value) {
         // NULL means update the current password/pattern/pin
         if (value == null) {
-            int mode = mLockPatternUtils.getPasswordMode();
-            if (LockPatternUtils.MODE_PATTERN == mode) {
+            int mode = mLockPatternUtils.getKeyguardStoredPasswordQuality();
+            if (DevicePolicyManager.PASSWORD_QUALITY_SOMETHING == mode) {
                 value = "pattern";
-            } else if (LockPatternUtils.MODE_PASSWORD == mode) {
+            } else if (DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == mode
+                    || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == mode) {
                 value = "password";
-            } else if (LockPatternUtils.MODE_PIN == mode) {
+            } else if (DevicePolicyManager.PASSWORD_QUALITY_NUMERIC == mode) {
                 value = "pin";
             } else {
                 throw new IllegalStateException("Unknown password mode: " + value);
@@ -262,11 +267,11 @@
         } else {
             int reqMode;
             if ("password".equals(value)) {
-                reqMode = LockPatternUtils.MODE_PASSWORD;
+                reqMode = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
             } else if ( "pin".equals(value)) {
-                reqMode = LockPatternUtils.MODE_PIN;
+                reqMode = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
             } else {
-                reqMode = LockPatternUtils.MODE_PATTERN;
+                reqMode = DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
             }
             int minMode = mDPM.getPasswordQuality(null);
             if (reqMode < minMode) {