Mode constants are ordered so that higher values are more restrictive; - * thus the highest requested mode constant (between the policy set here, + *
Quality constants are ordered so that higher values are more restrictive; + * thus the highest requested quality constant (between the policy set here, * the user's preference, and any other considerations) is the one that * is in effect. * @@ -195,14 +196,14 @@ public class DevicePolicyManager { * this method; if it has not, a security exception will be thrown. * * @param admin Which {@link DeviceAdmin} this request is associated with. - * @param mode The new desired mode. One of - * {@link #PASSWORD_MODE_UNSPECIFIED}, {@link #PASSWORD_MODE_SOMETHING}, - * {@link #PASSWORD_MODE_NUMERIC}, or {@link #PASSWORD_MODE_ALPHANUMERIC}. + * @param quality The new desired quality. One of + * {@link #PASSWORD_QUALITY_UNSPECIFIED}, {@link #PASSWORD_QUALITY_SOMETHING}, + * {@link #PASSWORD_QUALITY_NUMERIC}, or {@link #PASSWORD_QUALITY_ALPHANUMERIC}. */ - public void setPasswordMode(ComponentName admin, int mode) { + public void setPasswordQuality(ComponentName admin, int quality) { if (mService != null) { try { - mService.setPasswordMode(admin, mode); + mService.setPasswordQuality(admin, quality); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -210,20 +211,20 @@ public class DevicePolicyManager { } /** - * Retrieve the current minimum password mode for all admins + * Retrieve the current minimum password quality for all admins * or a particular one. * @param admin The name of the admin component to check, or null to aggregate * all admins. */ - public int getPasswordMode(ComponentName admin) { + public int getPasswordQuality(ComponentName admin) { if (mService != null) { try { - return mService.getPasswordMode(admin); + return mService.getPasswordQuality(admin); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } } - return PASSWORD_MODE_UNSPECIFIED; + return PASSWORD_QUALITY_UNSPECIFIED; } /** @@ -235,8 +236,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_MODE_NUMERIC} or {@link #PASSWORD_MODE_ALPHANUMERIC} - * with {@link #setPasswordMode}. + * {@link #PASSWORD_QUALITY_NUMERIC} or {@link #PASSWORD_QUALITY_ALPHANUMERIC} + * with {@link #setPasswordQuality}. * *
The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call @@ -275,18 +276,18 @@ public class DevicePolicyManager { /** * Return the maximum password length that the device supports for a - * particular password mode. + * particular password quality. * @param mode The mode being interrogated. * @return Returns the maximum length that the user can enter. */ - public int getPasswordMaximumLength(int mode) { + public int getPasswordMaximumLength(int quality) { // Kind-of arbitrary. return 16; } /** * Determine whether the current password the user has set is sufficient - * to meet the policy requirements (mode, minimum length) that have been + * to meet the policy requirements (quality, minimum length) that have been * requested. * *
The calling device admin must have requested @@ -368,14 +369,15 @@ public class DevicePolicyManager { } /** - * Force a new password on the user. This takes effect immediately. The - * given password must meet the current password minimum length constraint - * or it will be rejected. The given password will be accepted regardless - * of the current password mode, automatically adjusting the password mode - * higher if needed to meet the requirements of all active administrators. - * (The string you give here is acceptable for any mode; - * if it contains only digits, that is still an acceptable alphanumeric - * password.) + * Force a new password on the user. This takes effect immediately. + * The given password must be sufficient for the + * current password quality and length constraints as returned by + * {@link #getPasswordQuality(ComponentName)} and + * {@link #getPasswordMinimumLength(ComponentName)}; if it does not meet + * these constraints, then it will be rejected and false returned. Note + * that the password may be a stronger quality (containing alphanumeric + * characters when the requested quality is only numeric), in which case + * the currently active quality will be increased to match. * *
The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} to be able to call
@@ -531,10 +533,10 @@ public class DevicePolicyManager {
/**
* @hide
*/
- public void setActivePasswordState(int mode, int length) {
+ public void setActivePasswordState(int quality, int length) {
if (mService != null) {
try {
- mService.setActivePasswordState(mode, length);
+ mService.setActivePasswordState(quality, length);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 016d465cea120..86f28bfa6cb32 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -288,6 +288,8 @@ public interface IActivityManager extends IInterface {
public void overridePendingTransition(IBinder token, String packageName,
int enterAnim, int exitAnim) throws RemoteException;
+ public boolean isUserAMonkey() throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -450,4 +452,5 @@ public interface IActivityManager extends IInterface {
int OVERRIDE_PENDING_TRANSITION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+100;
int HANDLE_APPLICATION_WTF_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+101;
int KILL_BACKGROUND_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+102;
+ int IS_USER_A_MONKEY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+103;
}
diff --git a/core/java/android/app/IDevicePolicyManager.aidl b/core/java/android/app/IDevicePolicyManager.aidl
index 8d804f98026a7..ae5c4bf6fbf9a 100644
--- a/core/java/android/app/IDevicePolicyManager.aidl
+++ b/core/java/android/app/IDevicePolicyManager.aidl
@@ -25,8 +25,8 @@ import android.os.RemoteCallback;
* {@hide}
*/
interface IDevicePolicyManager {
- void setPasswordMode(in ComponentName who, int mode);
- int getPasswordMode(in ComponentName who);
+ void setPasswordQuality(in ComponentName who, int quality);
+ int getPasswordQuality(in ComponentName who);
void setPasswordMinimumLength(in ComponentName who, int length);
int getPasswordMinimumLength(in ComponentName who);
@@ -52,7 +52,7 @@ interface IDevicePolicyManager {
void getRemoveWarning(in ComponentName policyReceiver, in RemoteCallback result);
void removeActiveAdmin(in ComponentName policyReceiver);
- void setActivePasswordState(int mode, int length);
+ void setActivePasswordState(int quality, int length);
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 6347146267bdf..f074b80cc8a28 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -80,9 +80,10 @@ public class LockPatternUtils {
* pin = digit-only password
* password = alphanumeric password
*/
- public static final int MODE_PATTERN = DevicePolicyManager.PASSWORD_MODE_SOMETHING;
- public static final int MODE_PIN = DevicePolicyManager.PASSWORD_MODE_NUMERIC;
- public static final int MODE_PASSWORD = DevicePolicyManager.PASSWORD_MODE_ALPHANUMERIC;
+ public static final int MODE_UNSPECIFIED = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+ public static final int MODE_PATTERN = DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
+ public static final int MODE_PIN = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
+ public static final int MODE_PASSWORD = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
/**
* The minimum number of dots the user must include in a wrong pattern
@@ -132,13 +133,13 @@ public class LockPatternUtils {
* @return
*/
public int getRequestedPasswordMode() {
- int policyMode = mDevicePolicyManager.getPasswordMode(null);
+ int policyMode = mDevicePolicyManager.getPasswordQuality(null);
switch (policyMode) {
- case DevicePolicyManager.PASSWORD_MODE_ALPHANUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
return MODE_PASSWORD;
- case DevicePolicyManager.PASSWORD_MODE_NUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
return MODE_PIN;
- case DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED:
+ case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
return MODE_PATTERN;
}
return MODE_PATTERN;
@@ -158,16 +159,16 @@ public class LockPatternUtils {
}
public void setActivePasswordState(int mode, int length) {
- int policyMode = DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED;
+ int policyMode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
switch (mode) {
case MODE_PATTERN:
- policyMode = DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED;
+ policyMode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
break;
case MODE_PIN:
- policyMode = DevicePolicyManager.PASSWORD_MODE_NUMERIC;
+ policyMode = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
break;
case MODE_PASSWORD:
- policyMode = DevicePolicyManager.PASSWORD_MODE_ALPHANUMERIC;
+ policyMode = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
break;
}
mDevicePolicyManager.setActivePasswordState(policyMode, length);
@@ -302,7 +303,7 @@ public class LockPatternUtils {
DevicePolicyManager dpm = (DevicePolicyManager)mContext.getSystemService(
Context.DEVICE_POLICY_SERVICE);
dpm.setActivePasswordState(
- DevicePolicyManager.PASSWORD_MODE_SOMETHING, pattern.size());
+ DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, pattern.size());
}
} catch (FileNotFoundException fnfe) {
// Cant do much, unless we want to fail over to using the settings provider
@@ -314,7 +315,65 @@ public class LockPatternUtils {
}
/**
- * Save a lock password.
+ * Compare the given password and mode, ensuring that the password meets
+ * the mode and returning the minimum mode needed for the given password.
+ * @param password The password to be used.
+ * @param reqMode The desired password mode.
+ * @return Returns {@link #MODE_UNSPECIFIED} if the password is not
+ * good enough for the given mode. Otherwise, returns either the original
+ * reqMode or something better if that is needed for the given password.
+ */
+ static public int adjustPasswordMode(String password, int reqMode) {
+ boolean hasDigit = false;
+ boolean hasNonDigit = false;
+ final int len = password.length();
+ for (int i = 0; i < len; i++) {
+ if (Character.isDigit(password.charAt(i))) {
+ hasDigit = true;
+ } else {
+ hasNonDigit = true;
+ }
+ }
+
+ // First check if it is sufficient.
+ switch (reqMode) {
+ case MODE_PASSWORD: {
+ if (!hasDigit || !hasNonDigit) {
+ return MODE_UNSPECIFIED;
+ }
+ } break;
+
+ case MODE_PIN:
+ case MODE_PATTERN: {
+ // Whatever we have is acceptable; we may need to promote the
+ // mode later.
+ } break;
+
+ default:
+ // If it isn't a mode we specifically know, then fail fast.
+ Log.w(TAG, "adjustPasswordMode: unknown mode " + reqMode);
+ return MODE_UNSPECIFIED;
+ }
+
+ // Do we need to promote?
+ if (hasNonDigit) {
+ if (reqMode < MODE_PASSWORD) {
+ reqMode = MODE_PASSWORD;
+ }
+ }
+ if (hasDigit) {
+ if (reqMode < MODE_PIN) {
+ reqMode = MODE_PIN;
+ }
+ }
+
+ return reqMode;
+ }
+
+ /**
+ * Save a lock password. Does not ensure that the pattern is as good
+ * as the requested mode, but will adjust the mode to be as good as the
+ * pattern.
* @param password The password to save
*/
public void saveLockPassword(String password, int mode) {
@@ -331,9 +390,9 @@ public class LockPatternUtils {
}
raf.close();
if (password != null) {
- int textMode = TextUtils.isDigitsOnly(password) ? MODE_PIN : MODE_PASSWORD;
- if (textMode > mode) {
- mode = textMode;
+ int finalMode = adjustPasswordMode(password, mode);
+ if (mode < finalMode) {
+ mode = finalMode;
}
setLong(PASSWORD_TYPE_KEY, mode);
DevicePolicyManager dpm = (DevicePolicyManager)mContext.getSystemService(
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 979955c2d941c..015b4877e4f38 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -71,7 +71,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
// database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
// is properly propagated through your change. Not doing so will result in a loss of user
// settings.
- private static final int DATABASE_VERSION = 47;
+ private static final int DATABASE_VERSION = 48;
private Context mContext;
@@ -595,8 +595,23 @@ public class DatabaseHelper extends SQLiteOpenHelper {
upgradeVersion = 47;
}
+
+ if (upgradeVersion == 47) {
+ /*
+ * The password mode constants have changed again; reset back to no
+ * password.
+ */
+ db.beginTransaction();
+ try {
+ db.execSQL("DELETE FROM system WHERE name='lockscreen.password_type';");
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ upgradeVersion = 48;
+ }
- if (upgradeVersion != currentVersion) {
+ if (upgradeVersion != currentVersion) {
Log.w(TAG, "Got stuck trying to upgrade from version " + upgradeVersion
+ ", must wipe the settings provider");
db.execSQL("DROP TABLE IF EXISTS system");
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index 17a3ab847f81a..e4ee4aee9f146 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -64,7 +64,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
IPowerManager mIPowerManager;
- int mActivePasswordMode = DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED;
+ int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
int mActivePasswordLength = 0;
int mFailedPasswordAttempts = 0;
@@ -76,7 +76,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
static class ActiveAdmin {
final DeviceAdminInfo info;
- int passwordMode = DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED;
+ int passwordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
int minimumPasswordLength = 0;
long maximumTimeToUnlock = 0;
int maximumFailedPasswordsForWipe = 0;
@@ -89,17 +89,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
void writeToXml(XmlSerializer out)
throws IllegalArgumentException, IllegalStateException, IOException {
- if (passwordMode != DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED) {
- out.startTag(null, "password-mode");
- out.attribute(null, "value", Integer.toString(passwordMode));
- out.endTag(null, "password-mode");
+ if (passwordQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
+ out.startTag(null, "password-quality");
+ out.attribute(null, "value", Integer.toString(passwordQuality));
+ out.endTag(null, "password-quality");
if (minimumPasswordLength > 0) {
out.startTag(null, "min-password-length");
out.attribute(null, "value", Integer.toString(minimumPasswordLength));
out.endTag(null, "mn-password-length");
}
}
- if (maximumTimeToUnlock != DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED) {
+ if (maximumTimeToUnlock != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
out.startTag(null, "max-time-to-unlock");
out.attribute(null, "value", Long.toString(maximumTimeToUnlock));
out.endTag(null, "max-time-to-unlock");
@@ -121,8 +121,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
continue;
}
String tag = parser.getName();
- if ("password-mode".equals(tag)) {
- passwordMode = Integer.parseInt(
+ if ("password-quality".equals(tag)) {
+ passwordQuality = Integer.parseInt(
parser.getAttributeValue(null, "value"));
} else if ("min-password-length".equals(tag)) {
minimumPasswordLength = Integer.parseInt(
@@ -435,34 +435,34 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- public void setPasswordMode(ComponentName who, int mode) {
+ public void setPasswordQuality(ComponentName who, int mode) {
synchronized (this) {
if (who == null) {
throw new NullPointerException("ComponentName is null");
}
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
- if (ap.passwordMode != mode) {
- ap.passwordMode = mode;
+ if (ap.passwordQuality != mode) {
+ ap.passwordQuality = mode;
saveSettingsLocked();
}
}
}
- public int getPasswordMode(ComponentName who) {
+ public int getPasswordQuality(ComponentName who) {
synchronized (this) {
- int mode = DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED;
+ int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
if (who != null) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
- return admin != null ? admin.passwordMode : mode;
+ return admin != null ? admin.passwordQuality : mode;
}
final int N = mAdminList.size();
for (int i=0; i