summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonstantin Lopyrev <klopyrev@google.com>2010-05-24 17:10:56 -0700
committerKonstantin Lopyrev <klopyrev@google.com>2010-05-27 15:27:06 -0700
commita15dcfaf2bc7cbd13b30db6766afe3bbaa01db97 (patch)
treef58aeeaf40b2c9eec459fca00ee4fa2126629652
parentafd52a0b40e7986d0993217b3fe0cf44fea21274 (diff)
downloadframeworks_base-a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97.zip
frameworks_base-a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97.tar.gz
frameworks_base-a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97.tar.bz2
Fix 2677197: Adding minimum complex character support.
Change-Id: I520bc5f9aa924bf9b5585b2235a91cc96cb99c25
-rw-r--r--api/current.xml151
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java269
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl19
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java74
-rw-r--r--policy/com/android/internal/policy/impl/LockPatternKeyguardView.java1
-rw-r--r--policy/com/android/internal/policy/impl/PasswordUnlockScreen.java6
-rw-r--r--services/java/com/android/server/DevicePolicyManagerService.java356
7 files changed, 846 insertions, 30 deletions
diff --git a/api/current.xml b/api/current.xml
index f416a18..f98a369 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -31769,6 +31769,71 @@
<parameter name="admin" type="android.content.ComponentName">
</parameter>
</method>
+<method name="getPasswordMinimumLetters"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+</method>
+<method name="getPasswordMinimumLowerCase"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+</method>
+<method name="getPasswordMinimumNumeric"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+</method>
+<method name="getPasswordMinimumSymbols"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+</method>
+<method name="getPasswordMinimumUpperCase"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+</method>
<method name="getPasswordQuality"
return="int"
abstract="false"
@@ -31905,6 +31970,81 @@
<parameter name="length" type="int">
</parameter>
</method>
+<method name="setPasswordMinimumLetters"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+<parameter name="length" type="int">
+</parameter>
+</method>
+<method name="setPasswordMinimumLowerCase"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+<parameter name="length" type="int">
+</parameter>
+</method>
+<method name="setPasswordMinimumNumeric"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+<parameter name="length" type="int">
+</parameter>
+</method>
+<method name="setPasswordMinimumSymbols"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+<parameter name="length" type="int">
+</parameter>
+</method>
+<method name="setPasswordMinimumUpperCase"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+<parameter name="length" type="int">
+</parameter>
+</method>
<method name="setPasswordQuality"
return="void"
abstract="false"
@@ -31999,6 +32139,17 @@
visibility="public"
>
</field>
+<field name="PASSWORD_QUALITY_COMPLEX"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="393216"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="PASSWORD_QUALITY_NUMERIC"
type="int"
transient="false"
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 67992a4..634adb0 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -205,6 +205,14 @@ public class DevicePolicyManager {
public static final int PASSWORD_QUALITY_ALPHANUMERIC = 0x50000;
/**
+ * Constant for {@link #setPasswordQuality}: the user must have entered a
+ * password containing numeric <em>and</em> alphabetic characters,
+ * <em>and</em> special symbols. Note that quality constants are ordered so
+ * that higher values are more restrictive.
+ */
+ public static final int PASSWORD_QUALITY_COMPLEX = 0x60000;
+
+ /**
* Called by an application that is administering the device to set the
* password restrictions it is imposing. After setting this, the user
* will not be able to enter a new password that is not at least as
@@ -226,7 +234,7 @@ public class DevicePolicyManager {
* @param quality The new desired quality. One of
* {@link #PASSWORD_QUALITY_UNSPECIFIED}, {@link #PASSWORD_QUALITY_SOMETHING},
* {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_ALPHABETIC},
- * or {@link #PASSWORD_QUALITY_ALPHANUMERIC}.
+ * {@link #PASSWORD_QUALITY_ALPHANUMERIC} or {@link #PASSWORD_QUALITY_COMPLEX}.
*/
public void setPasswordQuality(ComponentName admin, int quality) {
if (mService != null) {
@@ -264,8 +272,8 @@ public class DevicePolicyManager {
* take place immediately. To prompt the user for a new password, use
* {@link #ACTION_SET_NEW_PASSWORD} after setting this value. This
* constraint is only imposed if the administrator has also requested either
- * {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_ALPHABETIC},
- * or {@link #PASSWORD_QUALITY_ALPHANUMERIC}
+ * {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_ALPHABETIC}
+ * {@link #PASSWORD_QUALITY_ALPHANUMERIC}, or {@link #PASSWORD_QUALITY_COMPLEX}
* with {@link #setPasswordQuality}.
*
* <p>The calling device admin must have requested
@@ -303,6 +311,255 @@ public class DevicePolicyManager {
return 0;
}
+ /**
+ * Called by an application that is administering the device to set the
+ * minimum number of upper case letters required in the password. After
+ * setting this, the user will not be able to enter a new password that is
+ * not at least as restrictive as what has been set. Note that the current
+ * password will remain until the user has set a new one, so the change does
+ * not take place immediately. To prompt the user for a new password, use
+ * {@link #ACTION_SET_NEW_PASSWORD} after setting this value. This
+ * constraint is only imposed if the administrator has also requested
+ * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}.
+ * <p>
+ * The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
+ * this method; if it has not, a security exception will be thrown.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated
+ * with.
+ * @param length The new desired minimum number of upper case letters
+ * required in the password. A value of 0 means there is no
+ * restriction.
+ */
+ public void setPasswordMinimumUpperCase(ComponentName admin, int length) {
+ if (mService != null) {
+ try {
+ mService.setPasswordMinimumUpperCase(admin, length);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+
+ /**
+ * Retrieve the current number of upper case letters required in the
+ * password for all admins or a particular one.
+ *
+ * @param admin The name of the admin component to check, or null to
+ * aggregate all admins.
+ * @return The minimum number of upper case letters required in the
+ * password.
+ */
+ public int getPasswordMinimumUpperCase(ComponentName admin) {
+ if (mService != null) {
+ try {
+ return mService.getPasswordMinimumUpperCase(admin);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Called by an application that is administering the device to set the
+ * minimum number of lower case letters required in the password. After
+ * setting this, the user will not be able to enter a new password that is
+ * not at least as restrictive as what has been set. Note that the current
+ * password will remain until the user has set a new one, so the change does
+ * not take place immediately. To prompt the user for a new password, use
+ * {@link #ACTION_SET_NEW_PASSWORD} after setting this value. This
+ * constraint is only imposed if the administrator has also requested
+ * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}.
+ * <p>
+ * The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
+ * this method; if it has not, a security exception will be thrown.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated
+ * with.
+ * @param length The new desired minimum number of lower case letters
+ * required in the password. A value of 0 means there is no
+ * restriction.
+ */
+ public void setPasswordMinimumLowerCase(ComponentName admin, int length) {
+ if (mService != null) {
+ try {
+ mService.setPasswordMinimumLowerCase(admin, length);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+
+ /**
+ * Retrieve the current number of lower case letters required in the
+ * password for all admins or a particular one.
+ *
+ * @param admin The name of the admin component to check, or null to
+ * aggregate all admins.
+ * @return The minimum number of lower case letters required in the
+ * password.
+ */
+ public int getPasswordMinimumLowerCase(ComponentName admin) {
+ if (mService != null) {
+ try {
+ return mService.getPasswordMinimumLowerCase(admin);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Called by an application that is administering the device to set the
+ * minimum number of letters required in the password. After setting this,
+ * the user will not be able to enter a new password that is not at least as
+ * restrictive as what has been set. Note that the current password will
+ * remain until the user has set a new one, so the change does not take
+ * place immediately. To prompt the user for a new password, use
+ * {@link #ACTION_SET_NEW_PASSWORD} after setting this value. This
+ * constraint is only imposed if the administrator has also requested
+ * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}.
+ * <p>
+ * The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
+ * this method; if it has not, a security exception will be thrown.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated
+ * with.
+ * @param length The new desired minimum number of letters required in the
+ * password. A value of 0 means there is no restriction.
+ */
+ public void setPasswordMinimumLetters(ComponentName admin, int length) {
+ if (mService != null) {
+ try {
+ mService.setPasswordMinimumLetters(admin, length);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+
+ /**
+ * Retrieve the current number of letters required in the password for all
+ * admins or a particular one.
+ *
+ * @param admin The name of the admin component to check, or null to
+ * aggregate all admins.
+ * @return The minimum number of letters required in the password.
+ */
+ public int getPasswordMinimumLetters(ComponentName admin) {
+ if (mService != null) {
+ try {
+ return mService.getPasswordMinimumLetters(admin);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Called by an application that is administering the device to set the
+ * minimum number of numerical digits required in the password. After
+ * setting this, the user will not be able to enter a new password that is
+ * not at least as restrictive as what has been set. Note that the current
+ * password will remain until the user has set a new one, so the change does
+ * not take place immediately. To prompt the user for a new password, use
+ * {@link #ACTION_SET_NEW_PASSWORD} after setting this value. This
+ * constraint is only imposed if the administrator has also requested
+ * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}.
+ * <p>
+ * The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
+ * this method; if it has not, a security exception will be thrown.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated
+ * with.
+ * @param length The new desired minimum number of numerical digits required
+ * in the password. A value of 0 means there is no restriction.
+ */
+ public void setPasswordMinimumNumeric(ComponentName admin, int length) {
+ if (mService != null) {
+ try {
+ mService.setPasswordMinimumNumeric(admin, length);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+
+ /**
+ * Retrieve the current number of numerical digits required in the password
+ * for all admins or a particular one.
+ *
+ * @param admin The name of the admin component to check, or null to
+ * aggregate all admins.
+ * @return The minimum number of numerical digits required in the password.
+ */
+ public int getPasswordMinimumNumeric(ComponentName admin) {
+ if (mService != null) {
+ try {
+ return mService.getPasswordMinimumNumeric(admin);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Called by an application that is administering the device to set the
+ * minimum number of symbols required in the password. After setting this,
+ * the user will not be able to enter a new password that is not at least as
+ * restrictive as what has been set. Note that the current password will
+ * remain until the user has set a new one, so the change does not take
+ * place immediately. To prompt the user for a new password, use
+ * {@link #ACTION_SET_NEW_PASSWORD} after setting this value. This
+ * constraint is only imposed if the administrator has also requested
+ * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}.
+ * <p>
+ * The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
+ * this method; if it has not, a security exception will be thrown.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated
+ * with.
+ * @param length The new desired minimum number of symbols required in the
+ * password. A value of 0 means there is no restriction.
+ */
+ public void setPasswordMinimumSymbols(ComponentName admin, int length) {
+ if (mService != null) {
+ try {
+ mService.setPasswordMinimumSymbols(admin, length);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+
+ /**
+ * Retrieve the current number of symbols required in the password for all
+ * admins or a particular one.
+ *
+ * @param admin The name of the admin component to check, or null to
+ * aggregate all admins.
+ * @return The minimum number of symbols required in the password.
+ */
+ public int getPasswordMinimumSymbols(ComponentName admin) {
+ if (mService != null) {
+ try {
+ return mService.getPasswordMinimumSymbols(admin);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return 0;
+ }
+
/**
* Called by an application that is administering the device to set the length
* of the password history. After setting this, the user will not be able to
@@ -627,10 +884,12 @@ public class DevicePolicyManager {
/**
* @hide
*/
- public void setActivePasswordState(int quality, int length) {
+ public void setActivePasswordState(int quality, int length, int letters, int uppercase,
+ int lowercase, int numbers, int symbols) {
if (mService != null) {
try {
- mService.setActivePasswordState(quality, length);
+ mService.setActivePasswordState(quality, length, letters, uppercase, lowercase,
+ numbers, symbols);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 98fc162..fa31a37 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -27,9 +27,24 @@ import android.os.RemoteCallback;
interface IDevicePolicyManager {
void setPasswordQuality(in ComponentName who, int quality);
int getPasswordQuality(in ComponentName who);
-
+
void setPasswordMinimumLength(in ComponentName who, int length);
int getPasswordMinimumLength(in ComponentName who);
+
+ void setPasswordMinimumUpperCase(in ComponentName who, int length);
+ int getPasswordMinimumUpperCase(in ComponentName who);
+
+ void setPasswordMinimumLowerCase(in ComponentName who, int length);
+ int getPasswordMinimumLowerCase(in ComponentName who);
+
+ void setPasswordMinimumLetters(in ComponentName who, int length);
+ int getPasswordMinimumLetters(in ComponentName who);
+
+ void setPasswordMinimumNumeric(in ComponentName who, int length);
+ int getPasswordMinimumNumeric(in ComponentName who);
+
+ void setPasswordMinimumSymbols(in ComponentName who, int length);
+ int getPasswordMinimumSymbols(in ComponentName who);
void setPasswordHistoryLength(in ComponentName who, int length);
int getPasswordHistoryLength(in ComponentName who);
@@ -56,7 +71,7 @@ interface IDevicePolicyManager {
void getRemoveWarning(in ComponentName policyReceiver, in RemoteCallback result);
void removeActiveAdmin(in ComponentName policyReceiver);
- void setActivePasswordState(int quality, int length);
+ void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase, int numbers, int symbols);
void reportFailedPasswordAttempt();
void reportSuccessfulPasswordAttempt();
}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 28684a4..9983c02 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -144,6 +144,26 @@ public class LockPatternUtils {
return getDevicePolicyManager().getPasswordHistoryLength(null);
}
+ public int getRequestedPasswordMinimumLetters() {
+ return getDevicePolicyManager().getPasswordMinimumLetters(null);
+ }
+
+ public int getRequestedPasswordMinimumUpperCase() {
+ return getDevicePolicyManager().getPasswordMinimumUpperCase(null);
+ }
+
+ public int getRequestedPasswordMinimumLowerCase() {
+ return getDevicePolicyManager().getPasswordMinimumLowerCase(null);
+ }
+
+ public int getRequestedPasswordMinimumNumeric() {
+ return getDevicePolicyManager().getPasswordMinimumNumeric(null);
+ }
+
+ public int getRequestedPasswordMinimumSymbols() {
+ return getDevicePolicyManager().getPasswordMinimumSymbols(null);
+ }
+
/**
* Returns the actual password mode, as set by keyguard after updating the password.
*
@@ -308,6 +328,11 @@ public class LockPatternUtils {
activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
}
break;
+ case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
+ if (isLockPasswordEnabled()) {
+ activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
+ }
+ break;
}
return activePasswordQuality;
}
@@ -316,8 +341,6 @@ public class LockPatternUtils {
* Clear any lock pattern or password.
*/
public void clearLock() {
- getDevicePolicyManager().setActivePasswordState(
- DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0);
saveLockPassword(null, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
setLockPatternEnabled(false);
saveLockPattern(null);
@@ -330,7 +353,7 @@ public class LockPatternUtils {
*/
public void saveLockPattern(List<LockPatternView.Cell> pattern) {
// Compute the hash
- final byte[] hash = LockPatternUtils.patternToHash(pattern);
+ final byte[] hash = LockPatternUtils.patternToHash(pattern);
try {
// Write the hash to file
RandomAccessFile raf = new RandomAccessFile(sLockPatternFilename, "rw");
@@ -345,14 +368,15 @@ public class LockPatternUtils {
if (pattern != null) {
setBoolean(PATTERN_EVER_CHOSEN_KEY, true);
setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
- dpm.setActivePasswordState(
- DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, pattern.size());
+ dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, pattern
+ .size(), 0, 0, 0, 0, 0);
} else {
- dpm.setActivePasswordState(
- DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0);
+ dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0,
+ 0, 0, 0, 0);
}
} catch (FileNotFoundException fnfe) {
- // Cant do much, unless we want to fail over to using the settings provider
+ // Cant do much, unless we want to fail over to using the settings
+ // provider
Log.e(TAG, "Unable to save lock pattern to " + sLockPatternFilename);
} catch (IOException ioe) {
// Cant do much
@@ -410,13 +434,33 @@ public class LockPatternUtils {
DevicePolicyManager dpm = getDevicePolicyManager();
if (password != null) {
int computedQuality = computePasswordQuality(password);
- setLong(PASSWORD_TYPE_KEY, computedQuality);
+ setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality));
if (computedQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
- dpm.setActivePasswordState(computedQuality, password.length());
+ int letters = 0;
+ int uppercase = 0;
+ int lowercase = 0;
+ int numbers = 0;
+ int symbols = 0;
+ for (int i = 0; i < password.length(); i++) {
+ char c = password.charAt(i);
+ if (c >= 'A' && c <= 'Z') {
+ letters++;
+ uppercase++;
+ } else if (c >= 'a' && c <= 'z') {
+ letters++;
+ lowercase++;
+ } else if (c >= '0' && c <= '9') {
+ numbers++;
+ } else {
+ symbols++;
+ }
+ }
+ dpm.setActivePasswordState(Math.max(quality, computedQuality), password
+ .length(), letters, uppercase, lowercase, numbers, symbols);
} else {
// The password is not anything.
dpm.setActivePasswordState(
- DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0);
+ DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0);
}
// Add the password to the password history. We assume all
// password
@@ -439,7 +483,7 @@ public class LockPatternUtils {
setString(PASSWORD_HISTORY_KEY, passwordHistory);
} else {
dpm.setActivePasswordState(
- DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0);
+ DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0);
}
} catch (FileNotFoundException fnfe) {
// Cant do much, unless we want to fail over to using the settings provider
@@ -579,7 +623,8 @@ public class LockPatternUtils {
return savedPasswordExists() &&
(mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
|| mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
- || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC);
+ || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
+ || mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX);
}
/**
@@ -716,7 +761,8 @@ public class LockPatternUtils {
final boolean isPattern = mode == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
final boolean isPassword = mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
|| mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
- || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
+ || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
+ || mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
final boolean secure = isPattern && isLockPatternEnabled() && savedPatternExists()
|| isPassword && savedPasswordExists();
return secure;
diff --git a/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 587f9c1..8693294 100644
--- a/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -667,6 +667,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
currentMode = UnlockMode.Password;
break;
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
diff --git a/policy/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/com/android/internal/policy/impl/PasswordUnlockScreen.java
index c519d82..8fdff92 100644
--- a/policy/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ b/policy/com/android/internal/policy/impl/PasswordUnlockScreen.java
@@ -88,7 +88,8 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen
final int quality = lockPatternUtils.getKeyguardStoredPasswordQuality();
final boolean isAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == quality
- || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == quality;
+ || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == quality
+ || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == quality;
mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
mPasswordEntry = (EditText) findViewById(R.id.passwordEntry);
@@ -200,7 +201,8 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen
mPasswordEntry.setEnabled(true);
final int quality = mLockPatternUtils.getKeyguardStoredPasswordQuality();
final boolean isAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == quality
- || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == quality;
+ || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == quality
+ || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == quality;
if(isAlpha) {
mTitle.setText(R.string.keyguard_password_enter_password_code);
} else {
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index 7de510e..d2add10 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -75,6 +75,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
int mActivePasswordLength = 0;
+ int mActivePasswordUpperCase = 0;
+ int mActivePasswordLowerCase = 0;
+ int mActivePasswordLetters = 0;
+ int mActivePasswordNumeric = 0;
+ int mActivePasswordSymbols = 0;
int mFailedPasswordAttempts = 0;
int mPasswordOwner = -1;
@@ -90,6 +95,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
int passwordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
int minimumPasswordLength = 0;
int passwordHistoryLength = 0;
+ int minimumPasswordUpperCase = 0;
+ int minimumPasswordLowerCase = 0;
+ int minimumPasswordLetters = 1;
+ int minimumPasswordNumeric = 1;
+ int minimumPasswordSymbols = 1;
long maximumTimeToUnlock = 0;
int maximumFailedPasswordsForWipe = 0;
@@ -118,6 +128,31 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
out.attribute(null, "value", Integer.toString(passwordHistoryLength));
out.endTag(null, "password-history-length");
}
+ if (minimumPasswordUpperCase > 0) {
+ out.startTag(null, "min-password-uppercase");
+ out.attribute(null, "value", Integer.toString(minimumPasswordUpperCase));
+ out.endTag(null, "min-password-uppercase");
+ }
+ if (minimumPasswordLowerCase > 0) {
+ out.startTag(null, "min-password-lowercase");
+ out.attribute(null, "value", Integer.toString(minimumPasswordLowerCase));
+ out.endTag(null, "min-password-lowercase");
+ }
+ if (minimumPasswordLetters > 0) {
+ out.startTag(null, "min-password-letters");
+ out.attribute(null, "value", Integer.toString(minimumPasswordLetters));
+ out.endTag(null, "min-password-letters");
+ }
+ if (minimumPasswordNumeric > 0) {
+ out.startTag(null, "min-password-numeric");
+ out.attribute(null, "value", Integer.toString(minimumPasswordNumeric));
+ out.endTag(null, "min-password-numeric");
+ }
+ if (minimumPasswordSymbols > 0) {
+ out.startTag(null, "min-password-symbols");
+ out.attribute(null, "value", Integer.toString(minimumPasswordSymbols));
+ out.endTag(null, "min-password-symbols");
+ }
}
if (maximumTimeToUnlock != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
out.startTag(null, "max-time-to-unlock");
@@ -152,6 +187,21 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} else if ("password-history-length".equals(tag)) {
passwordHistoryLength = Integer.parseInt(
parser.getAttributeValue(null, "value"));
+ } else if ("min-password-uppercase".equals(tag)) {
+ minimumPasswordUpperCase = Integer.parseInt(
+ parser.getAttributeValue(null, "value"));
+ } else if ("min-password-lowercase".equals(tag)) {
+ minimumPasswordLowerCase = Integer.parseInt(
+ parser.getAttributeValue(null, "value"));
+ } else if ("min-password-letters".equals(tag)) {
+ minimumPasswordLetters = Integer.parseInt(
+ parser.getAttributeValue(null, "value"));
+ } else if ("min-password-numeric".equals(tag)) {
+ minimumPasswordNumeric = Integer.parseInt(
+ parser.getAttributeValue(null, "value"));
+ } else if ("min-password-symbols".equals(tag)) {
+ minimumPasswordSymbols = Integer.parseInt(
+ parser.getAttributeValue(null, "value"));
} else if ("max-time-to-unlock".equals(tag)) {
maximumTimeToUnlock = Long.parseLong(
parser.getAttributeValue(null, "value"));
@@ -180,6 +230,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
pw.println(minimumPasswordLength);
pw.print(prefix); pw.print("passwordHistoryLength=");
pw.println(passwordHistoryLength);
+ pw.print(prefix); pw.print("minimumPasswordUpperCase=");
+ pw.println(minimumPasswordUpperCase);
+ pw.print(prefix); pw.print("minimumPasswordLowerCase=");
+ pw.println(minimumPasswordLowerCase);
+ pw.print(prefix); pw.print("minimumPasswordLetters=");
+ pw.println(minimumPasswordLetters);
+ pw.print(prefix); pw.print("minimumPasswordNumeric=");
+ pw.println(minimumPasswordNumeric);
+ pw.print(prefix); pw.print("minimumPasswordSymbols=");
+ pw.println(minimumPasswordSymbols);
pw.print(prefix); pw.print("maximumTimeToUnlock=");
pw.println(maximumTimeToUnlock);
pw.print(prefix); pw.print("maximumFailedPasswordsForWipe=");
@@ -366,10 +426,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
out.endTag(null, "failed-password-attempts");
}
- if (mActivePasswordQuality != 0 || mActivePasswordLength != 0) {
+ if (mActivePasswordQuality != 0 || mActivePasswordLength != 0
+ || mActivePasswordUpperCase != 0 || mActivePasswordLowerCase != 0
+ || mActivePasswordLetters != 0 || mActivePasswordNumeric != 0
+ || mActivePasswordSymbols != 0) {
out.startTag(null, "active-password");
out.attribute(null, "quality", Integer.toString(mActivePasswordQuality));
out.attribute(null, "length", Integer.toString(mActivePasswordLength));
+ out.attribute(null, "uppercase", Integer.toString(mActivePasswordUpperCase));
+ out.attribute(null, "lowercase", Integer.toString(mActivePasswordLowerCase));
+ out.attribute(null, "letters", Integer.toString(mActivePasswordLetters));
+ out.attribute(null, "numeric", Integer
+ .toString(mActivePasswordNumeric));
+ out.attribute(null, "symbols", Integer.toString(mActivePasswordSymbols));
out.endTag(null, "active-password");
}
@@ -443,6 +512,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
parser.getAttributeValue(null, "quality"));
mActivePasswordLength = Integer.parseInt(
parser.getAttributeValue(null, "length"));
+ mActivePasswordUpperCase = Integer.parseInt(
+ parser.getAttributeValue(null, "uppercase"));
+ mActivePasswordLowerCase = Integer.parseInt(
+ parser.getAttributeValue(null, "lowercase"));
+ mActivePasswordLetters = Integer.parseInt(
+ parser.getAttributeValue(null, "letters"));
+ mActivePasswordNumeric = Integer.parseInt(
+ parser.getAttributeValue(null, "numeric"));
+ mActivePasswordSymbols = Integer.parseInt(
+ parser.getAttributeValue(null, "symbols"));
XmlUtils.skipCurrentTag(parser);
} else {
Slog.w(TAG, "Unknown tag: " + tag);
@@ -480,6 +559,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
+ Integer.toHexString(utils.getActivePasswordQuality()));
mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
mActivePasswordLength = 0;
+ mActivePasswordUpperCase = 0;
+ mActivePasswordLowerCase = 0;
+ mActivePasswordLetters = 0;
+ mActivePasswordNumeric = 0;
+ mActivePasswordSymbols = 0;
}
validatePasswordOwnerLocked();
@@ -502,6 +586,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
return;
}
throw new IllegalArgumentException("Invalid quality constant: 0x"
@@ -712,14 +797,194 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
+ public void setPasswordMinimumUpperCase(ComponentName who, int length) {
+ synchronized (this) {
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ ActiveAdmin ap = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
+ if (ap.minimumPasswordUpperCase != length) {
+ ap.minimumPasswordUpperCase = length;
+ saveSettingsLocked();
+ }
+ }
+ }
+
+ public int getPasswordMinimumUpperCase(ComponentName who) {
+ synchronized (this) {
+ int length = 0;
+
+ if (who != null) {
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ return admin != null ? admin.minimumPasswordUpperCase : length;
+ }
+
+ final int N = mAdminList.size();
+ for (int i=0; i<N; i++) {
+ ActiveAdmin admin = mAdminList.get(i);
+ if (length < admin.minimumPasswordUpperCase) {
+ length = admin.minimumPasswordUpperCase;
+ }
+ }
+ return length;
+ }
+ }
+
+ public void setPasswordMinimumLowerCase(ComponentName who, int length) {
+ synchronized (this) {
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ ActiveAdmin ap = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
+ if (ap.minimumPasswordLowerCase != length) {
+ ap.minimumPasswordLowerCase = length;
+ saveSettingsLocked();
+ }
+ }
+ }
+
+ public int getPasswordMinimumLowerCase(ComponentName who) {
+ synchronized (this) {
+ int length = 0;
+
+ if (who != null) {
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ return admin != null ? admin.minimumPasswordLowerCase : length;
+ }
+
+ final int N = mAdminList.size();
+ for (int i=0; i<N; i++) {
+ ActiveAdmin admin = mAdminList.get(i);
+ if (length < admin.minimumPasswordLowerCase) {
+ length = admin.minimumPasswordLowerCase;
+ }
+ }
+ return length;
+ }
+ }
+
+ public void setPasswordMinimumLetters(ComponentName who, int length) {
+ synchronized (this) {
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ ActiveAdmin ap = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
+ if (ap.minimumPasswordLetters != length) {
+ ap.minimumPasswordLetters = length;
+ saveSettingsLocked();
+ }
+ }
+ }
+
+ public int getPasswordMinimumLetters(ComponentName who) {
+ synchronized (this) {
+ int length = 0;
+
+ if (who != null) {
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ return admin != null ? admin.minimumPasswordLetters : length;
+ }
+
+ final int N = mAdminList.size();
+ for (int i=0; i<N; i++) {
+ ActiveAdmin admin = mAdminList.get(i);
+ if (length < admin.minimumPasswordLetters) {
+ length = admin.minimumPasswordLetters;
+ }
+ }
+ return length;
+ }
+ }
+
+ public void setPasswordMinimumNumeric(ComponentName who, int length) {
+ synchronized (this) {
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ ActiveAdmin ap = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
+ if (ap.minimumPasswordNumeric != length) {
+ ap.minimumPasswordNumeric = length;
+ saveSettingsLocked();
+ }
+ }
+ }
+
+ public int getPasswordMinimumNumeric(ComponentName who) {
+ synchronized (this) {
+ int length = 0;
+
+ if (who != null) {
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ return admin != null ? admin.minimumPasswordNumeric : length;
+ }
+
+ final int N = mAdminList.size();
+ for (int i = 0; i < N; i++) {
+ ActiveAdmin admin = mAdminList.get(i);
+ if (length < admin.minimumPasswordNumeric) {
+ length = admin.minimumPasswordNumeric;
+ }
+ }
+ return length;
+ }
+ }
+
+ public void setPasswordMinimumSymbols(ComponentName who, int length) {
+ synchronized (this) {
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ ActiveAdmin ap = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
+ if (ap.minimumPasswordSymbols != length) {
+ ap.minimumPasswordSymbols = length;
+ saveSettingsLocked();
+ }
+ }
+ }
+
+ public int getPasswordMinimumSymbols(ComponentName who) {
+ synchronized (this) {
+ int length = 0;
+
+ if (who != null) {
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ return admin != null ? admin.minimumPasswordSymbols : length;
+ }
+
+ final int N = mAdminList.size();
+ for (int i=0; i<N; i++) {
+ ActiveAdmin admin = mAdminList.get(i);
+ if (length < admin.minimumPasswordSymbols) {
+ length = admin.minimumPasswordSymbols;
+ }
+ }
+ return length;
+ }
+ }
+
public boolean isActivePasswordSufficient() {
synchronized (this) {
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
getActiveAdminForCallerLocked(null,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
- return mActivePasswordQuality >= getPasswordQuality(null)
- && mActivePasswordLength >= getPasswordMinimumLength(null);
+ if (mActivePasswordQuality < getPasswordQuality(null)
+ || mActivePasswordLength < getPasswordMinimumLength(null)) {
+ return false;
+ }
+ if(mActivePasswordQuality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
+ return true;
+ }
+ return mActivePasswordUpperCase >= getPasswordMinimumUpperCase(null)
+ && mActivePasswordLowerCase >= getPasswordMinimumLowerCase(null)
+ && mActivePasswordLetters >= getPasswordMinimumLetters(null)
+ && mActivePasswordNumeric >= getPasswordMinimumNumeric(null)
+ && mActivePasswordSymbols >= getPasswordMinimumSymbols(null);
}
}
@@ -781,14 +1046,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
quality = getPasswordQuality(null);
if (quality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
int realQuality = LockPatternUtils.computePasswordQuality(password);
- if (realQuality < quality) {
+ if (realQuality < quality
+ && quality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
Slog.w(TAG, "resetPassword: password quality 0x"
+ Integer.toHexString(quality)
+ " does not meet required quality 0x"
+ Integer.toHexString(quality));
return false;
}
- quality = realQuality;
+ quality = Math.max(realQuality, quality);
}
int length = getPasswordMinimumLength(null);
if (password.length() < length) {
@@ -796,6 +1062,68 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
+ " does not meet required length " + length);
return false;
}
+ if (quality == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
+ int letters = 0;
+ int uppercase = 0;
+ int lowercase = 0;
+ int numbers = 0;
+ int symbols = 0;
+ for (int i = 0; i < password.length(); i++) {
+ char c = password.charAt(i);
+ if (c >= 'A' && c <= 'Z') {
+ letters++;
+ uppercase++;
+ } else if (c >= 'a' && c <= 'z') {
+ letters++;
+ lowercase++;
+ } else if (c >= '0' && c <= '9') {
+ numbers++;
+ } else {
+ symbols++;
+ }
+ }
+ int neededLetters = getPasswordMinimumLetters(null);
+ if(letters < neededLetters) {
+ Slog.w(TAG, "resetPassword: number of letters " + letters
+ + " does not meet required number of letters " + neededLetters);
+ return false;
+ }
+ int neededNumbers = getPasswordMinimumNumeric(null);
+ if (numbers < neededNumbers) {
+ Slog
+ .w(TAG, "resetPassword: number of numerical digits " + numbers
+ + " does not meet required number of numerical digits "
+ + neededNumbers);
+ return false;
+ }
+ int neededLowerCase = getPasswordMinimumLowerCase(null);
+ if (lowercase < neededLowerCase) {
+ Slog.w(TAG, "resetPassword: number of lowercase letters " + lowercase
+ + " does not meet required number of lowercase letters "
+ + neededLowerCase);
+ return false;
+ }
+ int neededUpperCase = getPasswordMinimumUpperCase(null);
+ if (uppercase < neededUpperCase) {
+ Slog.w(TAG, "resetPassword: number of uppercase letters " + uppercase
+ + " does not meet required number of uppercase letters "
+ + neededUpperCase);
+ return false;
+ }
+ int neededSymbols = getPasswordMinimumSymbols(null);
+ if (symbols < neededSymbols) {
+ Slog.w(TAG, "resetPassword: number of special symbols " + symbols
+ + " does not meet required number of special symbols " + neededSymbols);
+ return false;
+ }
+ }
+
+ LockPatternUtils utils = new LockPatternUtils(mContext);
+ if(utils.checkPasswordHistory(password)) {
+ Slog.w(TAG, "resetPassword: password is the same as one of the last "
+ + getPasswordHistoryLength(null) + " passwords");
+ return false;
+ }
}
int callingUid = Binder.getCallingUid();
@@ -946,7 +1274,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- public void setActivePasswordState(int quality, int length) {
+ public void setActivePasswordState(int quality, int length, int letters, int uppercase,
+ int lowercase, int numbers, int symbols) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
@@ -954,11 +1283,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
if (mActivePasswordQuality != quality || mActivePasswordLength != length
- || mFailedPasswordAttempts != 0) {
+ || mFailedPasswordAttempts != 0 || mActivePasswordLetters != letters
+ || mActivePasswordUpperCase != uppercase
+ || mActivePasswordLowerCase != lowercase || mActivePasswordNumeric != numbers
+ || mActivePasswordSymbols != symbols) {
long ident = Binder.clearCallingIdentity();
try {
mActivePasswordQuality = quality;
mActivePasswordLength = length;
+ mActivePasswordLetters = letters;
+ mActivePasswordLowerCase = lowercase;
+ mActivePasswordUpperCase = uppercase;
+ mActivePasswordNumeric = numbers;
+ mActivePasswordSymbols = symbols;
mFailedPasswordAttempts = 0;
saveSettingsLocked();
sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
@@ -1042,6 +1379,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
pw.print(" mActivePasswordQuality=0x");
pw.println(Integer.toHexString(mActivePasswordQuality));
pw.print(" mActivePasswordLength="); pw.println(mActivePasswordLength);
+ pw.print(" mActivePasswordUpperCase="); pw.println(mActivePasswordUpperCase);
+ pw.print(" mActivePasswordLowerCase="); pw.println(mActivePasswordLowerCase);
+ pw.print(" mActivePasswordLetters="); pw.println(mActivePasswordLetters);
+ pw.print(" mActivePasswordNumeric="); pw.println(mActivePasswordNumeric);
+ pw.print(" mActivePasswordSymbols="); pw.println(mActivePasswordSymbols);
pw.print(" mFailedPasswordAttempts="); pw.println(mFailedPasswordAttempts);
pw.print(" mPasswordOwner="); pw.println(mPasswordOwner);
}