Loading api/current.xml +28 −0 Original line number Diff line number Diff line Loading @@ -31871,6 +31871,19 @@ <parameter name="admin" type="android.content.ComponentName"> </parameter> </method> <method name="getPasswordMinimumNonLetter" 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" Loading Loading @@ -32076,6 +32089,21 @@ <parameter name="length" type="int"> </parameter> </method> <method name="setPasswordMinimumNonLetter" 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" core/java/android/app/admin/DevicePolicyManager.java +92 −15 Original line number Diff line number Diff line Loading @@ -215,9 +215,13 @@ public class DevicePolicyManager { /** * 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. * password containing at least a letter, a numerical digit and a special * symbol, by default. With this password quality, passwords can be * restricted to contain various sets of characters, like at least an * uppercase letter, etc. These are specified using various methods, * like {@link #setPasswordMinimumLowerCase(ComponentName, int)}. Note * that quality constants are ordered so that higher values are more * restrictive. */ public static final int PASSWORD_QUALITY_COMPLEX = 0x60000; Loading Loading @@ -329,7 +333,8 @@ public class DevicePolicyManager { * 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}. * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The * default value is 0. * <p> * The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call Loading @@ -353,7 +358,10 @@ public class DevicePolicyManager { /** * Retrieve the current number of upper case letters required in the * password for all admins or a particular one. * password for all admins or a particular one. This is the same value as * set by {#link {@link #setPasswordMinimumUpperCase(ComponentName, int)} * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * * @param admin The name of the admin component to check, or null to * aggregate all admins. Loading @@ -380,7 +388,8 @@ public class DevicePolicyManager { * 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}. * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The * default value is 0. * <p> * The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call Loading @@ -404,7 +413,10 @@ public class DevicePolicyManager { /** * Retrieve the current number of lower case letters required in the * password for all admins or a particular one. * password for all admins or a particular one. This is the same value as * set by {#link {@link #setPasswordMinimumLowerCase(ComponentName, int)} * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * * @param admin The name of the admin component to check, or null to * aggregate all admins. Loading @@ -431,7 +443,8 @@ public class DevicePolicyManager { * 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}. * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The * default value is 1. * <p> * The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call Loading @@ -454,7 +467,10 @@ public class DevicePolicyManager { /** * Retrieve the current number of letters required in the password for all * admins or a particular one. * admins or a particular one. This is the same value as * set by {#link {@link #setPasswordMinimumLetters(ComponentName, int)} * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * * @param admin The name of the admin component to check, or null to * aggregate all admins. Loading @@ -480,7 +496,8 @@ public class DevicePolicyManager { * 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}. * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The * default value is 1. * <p> * The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call Loading @@ -503,7 +520,10 @@ public class DevicePolicyManager { /** * Retrieve the current number of numerical digits required in the password * for all admins or a particular one. * for all admins or a particular one. This is the same value as * set by {#link {@link #setPasswordMinimumNumeric(ComponentName, int)} * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * * @param admin The name of the admin component to check, or null to * aggregate all admins. Loading @@ -529,7 +549,8 @@ public class DevicePolicyManager { * 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}. * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The * default value is 1. * <p> * The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call Loading @@ -552,7 +573,10 @@ public class DevicePolicyManager { /** * Retrieve the current number of symbols required in the password for all * admins or a particular one. * admins or a particular one. This is the same value as * set by {#link {@link #setPasswordMinimumSymbols(ComponentName, int)} * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * * @param admin The name of the admin component to check, or null to * aggregate all admins. Loading @@ -569,6 +593,59 @@ public class DevicePolicyManager { return 0; } /** * Called by an application that is administering the device to set the * minimum number of non-letter characters (numerical digits or 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}. The default value is 0. * <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 setPasswordMinimumNonLetter(ComponentName admin, int length) { if (mService != null) { try { mService.setPasswordMinimumNonLetter(admin, length); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } } } /** * Retrieve the current number of non-letter characters required in the * password for all admins or a particular one. This is the same value as * set by {#link {@link #setPasswordMinimumNonLetter(ComponentName, int)} * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * * @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 getPasswordMinimumNonLetter(ComponentName admin) { if (mService != null) { try { return mService.getPasswordMinimumNonLetter(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 Loading Loading @@ -894,11 +971,11 @@ public class DevicePolicyManager { * @hide */ public void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase, int numbers, int symbols) { int lowercase, int numbers, int symbols, int nonletter) { if (mService != null) { try { mService.setActivePasswordState(quality, length, letters, uppercase, lowercase, numbers, symbols); numbers, symbols, nonletter); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } Loading core/java/android/app/admin/IDevicePolicyManager.aidl +5 −1 Original line number Diff line number Diff line Loading @@ -46,6 +46,9 @@ interface IDevicePolicyManager { void setPasswordMinimumSymbols(in ComponentName who, int length); int getPasswordMinimumSymbols(in ComponentName who); void setPasswordMinimumNonLetter(in ComponentName who, int length); int getPasswordMinimumNonLetter(in ComponentName who); void setPasswordHistoryLength(in ComponentName who, int length); int getPasswordHistoryLength(in ComponentName who); Loading @@ -71,7 +74,8 @@ interface IDevicePolicyManager { void getRemoveWarning(in ComponentName policyReceiver, in RemoteCallback result); void removeActiveAdmin(in ComponentName policyReceiver); void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase, int numbers, int symbols); void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase, int numbers, int symbols, int nonletter); void reportFailedPasswordAttempt(); void reportSuccessfulPasswordAttempt(); } core/java/com/android/internal/widget/LockPatternUtils.java +11 −5 Original line number Diff line number Diff line Loading @@ -164,6 +164,9 @@ public class LockPatternUtils { return getDevicePolicyManager().getPasswordMinimumSymbols(null); } public int getRequestedPasswordMinimumNonLetter() { return getDevicePolicyManager().getPasswordMinimumNonLetter(null); } /** * Returns the actual password mode, as set by keyguard after updating the password. * Loading Loading @@ -369,10 +372,10 @@ public class LockPatternUtils { setBoolean(PATTERN_EVER_CHOSEN_KEY, true); setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, pattern .size(), 0, 0, 0, 0, 0); .size(), 0, 0, 0, 0, 0, 0); } else { dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0); 0, 0, 0, 0, 0); } } catch (FileNotFoundException fnfe) { // Cant do much, unless we want to fail over to using the settings Loading Loading @@ -441,6 +444,7 @@ public class LockPatternUtils { int lowercase = 0; int numbers = 0; int symbols = 0; int nonletter = 0; for (int i = 0; i < password.length(); i++) { char c = password.charAt(i); if (c >= 'A' && c <= 'Z') { Loading @@ -451,16 +455,18 @@ public class LockPatternUtils { lowercase++; } else if (c >= '0' && c <= '9') { numbers++; nonletter++; } else { symbols++; nonletter++; } } dpm.setActivePasswordState(Math.max(quality, computedQuality), password .length(), letters, uppercase, lowercase, numbers, symbols); .length(), letters, uppercase, lowercase, numbers, symbols, nonletter); } else { // The password is not anything. dpm.setActivePasswordState( DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0); DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0); } // Add the password to the password history. We assume all // password Loading @@ -483,7 +489,7 @@ public class LockPatternUtils { setString(PASSWORD_HISTORY_KEY, passwordHistory); } else { dpm.setActivePasswordState( DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0); DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0); } } catch (FileNotFoundException fnfe) { // Cant do much, unless we want to fail over to using the settings provider Loading services/java/com/android/server/DevicePolicyManagerService.java +67 −4 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { int mActivePasswordLetters = 0; int mActivePasswordNumeric = 0; int mActivePasswordSymbols = 0; int mActivePasswordNonLetter = 0; int mFailedPasswordAttempts = 0; int mPasswordOwner = -1; Loading @@ -100,6 +101,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { int minimumPasswordLetters = 1; int minimumPasswordNumeric = 1; int minimumPasswordSymbols = 1; int minimumPasswordNonLetter = 0; long maximumTimeToUnlock = 0; int maximumFailedPasswordsForWipe = 0; Loading Loading @@ -153,6 +155,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { out.attribute(null, "value", Integer.toString(minimumPasswordSymbols)); out.endTag(null, "min-password-symbols"); } if (minimumPasswordNonLetter > 0) { out.startTag(null, "min-password-nonletter"); out.attribute(null, "value", Integer.toString(minimumPasswordNonLetter)); out.endTag(null, "min-password-nonletter"); } } if (maximumTimeToUnlock != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { out.startTag(null, "max-time-to-unlock"); Loading Loading @@ -202,6 +209,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } else if ("min-password-symbols".equals(tag)) { minimumPasswordSymbols = Integer.parseInt( parser.getAttributeValue(null, "value")); } else if ("min-password-nonletter".equals(tag)) { minimumPasswordNonLetter = Integer.parseInt( parser.getAttributeValue(null, "value")); } else if ("max-time-to-unlock".equals(tag)) { maximumTimeToUnlock = Long.parseLong( parser.getAttributeValue(null, "value")); Loading Loading @@ -240,6 +250,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { pw.println(minimumPasswordNumeric); pw.print(prefix); pw.print("minimumPasswordSymbols="); pw.println(minimumPasswordSymbols); pw.print(prefix); pw.print("minimumPasswordNonLetter="); pw.println(minimumPasswordNonLetter); pw.print(prefix); pw.print("maximumTimeToUnlock="); pw.println(maximumTimeToUnlock); pw.print(prefix); pw.print("maximumFailedPasswordsForWipe="); Loading Loading @@ -429,7 +441,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (mActivePasswordQuality != 0 || mActivePasswordLength != 0 || mActivePasswordUpperCase != 0 || mActivePasswordLowerCase != 0 || mActivePasswordLetters != 0 || mActivePasswordNumeric != 0 || mActivePasswordSymbols != 0) { || mActivePasswordSymbols != 0 || mActivePasswordNonLetter != 0) { out.startTag(null, "active-password"); out.attribute(null, "quality", Integer.toString(mActivePasswordQuality)); out.attribute(null, "length", Integer.toString(mActivePasswordLength)); Loading @@ -439,6 +451,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { out.attribute(null, "numeric", Integer .toString(mActivePasswordNumeric)); out.attribute(null, "symbols", Integer.toString(mActivePasswordSymbols)); out.attribute(null, "nonletter", Integer.toString(mActivePasswordNonLetter)); out.endTag(null, "active-password"); } Loading Loading @@ -529,6 +542,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { parser.getAttributeValue(null, "numeric")); mActivePasswordSymbols = Integer.parseInt( parser.getAttributeValue(null, "symbols")); mActivePasswordNonLetter = Integer.parseInt( parser.getAttributeValue(null, "nonletter")); XmlUtils.skipCurrentTag(parser); } else { Slog.w(TAG, "Unknown tag: " + tag); Loading Loading @@ -571,6 +586,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { mActivePasswordLetters = 0; mActivePasswordNumeric = 0; mActivePasswordSymbols = 0; mActivePasswordNonLetter = 0; } validatePasswordOwnerLocked(); Loading Loading @@ -974,6 +990,40 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } public void setPasswordMinimumNonLetter(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.minimumPasswordNonLetter != length) { ap.minimumPasswordNonLetter = length; saveSettingsLocked(); } } } public int getPasswordMinimumNonLetter(ComponentName who) { synchronized (this) { int length = 0; if (who != null) { ActiveAdmin admin = getActiveAdminUncheckedLocked(who); return admin != null ? admin.minimumPasswordNonLetter : length; } final int N = mAdminList.size(); for (int i=0; i<N; i++) { ActiveAdmin admin = mAdminList.get(i); if (length < admin.minimumPasswordNonLetter) { length = admin.minimumPasswordNonLetter; } } return length; } } public boolean isActivePasswordSufficient() { synchronized (this) { // This API can only be called by an active device admin, Loading @@ -991,7 +1041,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { && mActivePasswordLowerCase >= getPasswordMinimumLowerCase(null) && mActivePasswordLetters >= getPasswordMinimumLetters(null) && mActivePasswordNumeric >= getPasswordMinimumNumeric(null) && mActivePasswordSymbols >= getPasswordMinimumSymbols(null); && mActivePasswordSymbols >= getPasswordMinimumSymbols(null) && mActivePasswordNonLetter >= getPasswordMinimumNonLetter(null); } } Loading Loading @@ -1075,6 +1126,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { int lowercase = 0; int numbers = 0; int symbols = 0; int nonletter = 0; for (int i = 0; i < password.length(); i++) { char c = password.charAt(i); if (c >= 'A' && c <= 'Z') { Loading @@ -1085,8 +1137,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { lowercase++; } else if (c >= '0' && c <= '9') { numbers++; nonletter++; } else { symbols++; nonletter++; } } int neededLetters = getPasswordMinimumLetters(null); Loading Loading @@ -1123,6 +1177,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + " does not meet required number of special symbols " + neededSymbols); return false; } int neededNonLetter = getPasswordMinimumNonLetter(null); if (nonletter < neededNonLetter) { Slog.w(TAG, "resetPassword: number of non-letter characters " + nonletter + " does not meet required number of non-letter characters " + neededNonLetter); return false; } } LockPatternUtils utils = new LockPatternUtils(mContext); Loading Loading @@ -1282,7 +1343,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } public void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase, int numbers, int symbols) { int lowercase, int numbers, int symbols, int nonletter) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BIND_DEVICE_ADMIN, null); Loading @@ -1293,7 +1354,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { || mFailedPasswordAttempts != 0 || mActivePasswordLetters != letters || mActivePasswordUpperCase != uppercase || mActivePasswordLowerCase != lowercase || mActivePasswordNumeric != numbers || mActivePasswordSymbols != symbols) { || mActivePasswordSymbols != symbols || mActivePasswordNonLetter != nonletter) { long ident = Binder.clearCallingIdentity(); try { mActivePasswordQuality = quality; Loading @@ -1303,6 +1364,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { mActivePasswordUpperCase = uppercase; mActivePasswordNumeric = numbers; mActivePasswordSymbols = symbols; mActivePasswordNonLetter = nonletter; mFailedPasswordAttempts = 0; saveSettingsLocked(); sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED, Loading Loading @@ -1391,6 +1453,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { pw.print(" mActivePasswordLetters="); pw.println(mActivePasswordLetters); pw.print(" mActivePasswordNumeric="); pw.println(mActivePasswordNumeric); pw.print(" mActivePasswordSymbols="); pw.println(mActivePasswordSymbols); pw.print(" mActivePasswordNonLetter="); pw.println(mActivePasswordNonLetter); pw.print(" mFailedPasswordAttempts="); pw.println(mFailedPasswordAttempts); pw.print(" mPasswordOwner="); pw.println(mPasswordOwner); } Loading Loading
api/current.xml +28 −0 Original line number Diff line number Diff line Loading @@ -31871,6 +31871,19 @@ <parameter name="admin" type="android.content.ComponentName"> </parameter> </method> <method name="getPasswordMinimumNonLetter" 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" Loading Loading @@ -32076,6 +32089,21 @@ <parameter name="length" type="int"> </parameter> </method> <method name="setPasswordMinimumNonLetter" 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"
core/java/android/app/admin/DevicePolicyManager.java +92 −15 Original line number Diff line number Diff line Loading @@ -215,9 +215,13 @@ public class DevicePolicyManager { /** * 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. * password containing at least a letter, a numerical digit and a special * symbol, by default. With this password quality, passwords can be * restricted to contain various sets of characters, like at least an * uppercase letter, etc. These are specified using various methods, * like {@link #setPasswordMinimumLowerCase(ComponentName, int)}. Note * that quality constants are ordered so that higher values are more * restrictive. */ public static final int PASSWORD_QUALITY_COMPLEX = 0x60000; Loading Loading @@ -329,7 +333,8 @@ public class DevicePolicyManager { * 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}. * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The * default value is 0. * <p> * The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call Loading @@ -353,7 +358,10 @@ public class DevicePolicyManager { /** * Retrieve the current number of upper case letters required in the * password for all admins or a particular one. * password for all admins or a particular one. This is the same value as * set by {#link {@link #setPasswordMinimumUpperCase(ComponentName, int)} * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * * @param admin The name of the admin component to check, or null to * aggregate all admins. Loading @@ -380,7 +388,8 @@ public class DevicePolicyManager { * 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}. * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The * default value is 0. * <p> * The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call Loading @@ -404,7 +413,10 @@ public class DevicePolicyManager { /** * Retrieve the current number of lower case letters required in the * password for all admins or a particular one. * password for all admins or a particular one. This is the same value as * set by {#link {@link #setPasswordMinimumLowerCase(ComponentName, int)} * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * * @param admin The name of the admin component to check, or null to * aggregate all admins. Loading @@ -431,7 +443,8 @@ public class DevicePolicyManager { * 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}. * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The * default value is 1. * <p> * The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call Loading @@ -454,7 +467,10 @@ public class DevicePolicyManager { /** * Retrieve the current number of letters required in the password for all * admins or a particular one. * admins or a particular one. This is the same value as * set by {#link {@link #setPasswordMinimumLetters(ComponentName, int)} * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * * @param admin The name of the admin component to check, or null to * aggregate all admins. Loading @@ -480,7 +496,8 @@ public class DevicePolicyManager { * 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}. * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The * default value is 1. * <p> * The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call Loading @@ -503,7 +520,10 @@ public class DevicePolicyManager { /** * Retrieve the current number of numerical digits required in the password * for all admins or a particular one. * for all admins or a particular one. This is the same value as * set by {#link {@link #setPasswordMinimumNumeric(ComponentName, int)} * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * * @param admin The name of the admin component to check, or null to * aggregate all admins. Loading @@ -529,7 +549,8 @@ public class DevicePolicyManager { * 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}. * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The * default value is 1. * <p> * The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call Loading @@ -552,7 +573,10 @@ public class DevicePolicyManager { /** * Retrieve the current number of symbols required in the password for all * admins or a particular one. * admins or a particular one. This is the same value as * set by {#link {@link #setPasswordMinimumSymbols(ComponentName, int)} * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * * @param admin The name of the admin component to check, or null to * aggregate all admins. Loading @@ -569,6 +593,59 @@ public class DevicePolicyManager { return 0; } /** * Called by an application that is administering the device to set the * minimum number of non-letter characters (numerical digits or 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}. The default value is 0. * <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 setPasswordMinimumNonLetter(ComponentName admin, int length) { if (mService != null) { try { mService.setPasswordMinimumNonLetter(admin, length); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } } } /** * Retrieve the current number of non-letter characters required in the * password for all admins or a particular one. This is the same value as * set by {#link {@link #setPasswordMinimumNonLetter(ComponentName, int)} * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * * @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 getPasswordMinimumNonLetter(ComponentName admin) { if (mService != null) { try { return mService.getPasswordMinimumNonLetter(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 Loading Loading @@ -894,11 +971,11 @@ public class DevicePolicyManager { * @hide */ public void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase, int numbers, int symbols) { int lowercase, int numbers, int symbols, int nonletter) { if (mService != null) { try { mService.setActivePasswordState(quality, length, letters, uppercase, lowercase, numbers, symbols); numbers, symbols, nonletter); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } Loading
core/java/android/app/admin/IDevicePolicyManager.aidl +5 −1 Original line number Diff line number Diff line Loading @@ -46,6 +46,9 @@ interface IDevicePolicyManager { void setPasswordMinimumSymbols(in ComponentName who, int length); int getPasswordMinimumSymbols(in ComponentName who); void setPasswordMinimumNonLetter(in ComponentName who, int length); int getPasswordMinimumNonLetter(in ComponentName who); void setPasswordHistoryLength(in ComponentName who, int length); int getPasswordHistoryLength(in ComponentName who); Loading @@ -71,7 +74,8 @@ interface IDevicePolicyManager { void getRemoveWarning(in ComponentName policyReceiver, in RemoteCallback result); void removeActiveAdmin(in ComponentName policyReceiver); void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase, int numbers, int symbols); void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase, int numbers, int symbols, int nonletter); void reportFailedPasswordAttempt(); void reportSuccessfulPasswordAttempt(); }
core/java/com/android/internal/widget/LockPatternUtils.java +11 −5 Original line number Diff line number Diff line Loading @@ -164,6 +164,9 @@ public class LockPatternUtils { return getDevicePolicyManager().getPasswordMinimumSymbols(null); } public int getRequestedPasswordMinimumNonLetter() { return getDevicePolicyManager().getPasswordMinimumNonLetter(null); } /** * Returns the actual password mode, as set by keyguard after updating the password. * Loading Loading @@ -369,10 +372,10 @@ public class LockPatternUtils { setBoolean(PATTERN_EVER_CHOSEN_KEY, true); setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, pattern .size(), 0, 0, 0, 0, 0); .size(), 0, 0, 0, 0, 0, 0); } else { dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0); 0, 0, 0, 0, 0); } } catch (FileNotFoundException fnfe) { // Cant do much, unless we want to fail over to using the settings Loading Loading @@ -441,6 +444,7 @@ public class LockPatternUtils { int lowercase = 0; int numbers = 0; int symbols = 0; int nonletter = 0; for (int i = 0; i < password.length(); i++) { char c = password.charAt(i); if (c >= 'A' && c <= 'Z') { Loading @@ -451,16 +455,18 @@ public class LockPatternUtils { lowercase++; } else if (c >= '0' && c <= '9') { numbers++; nonletter++; } else { symbols++; nonletter++; } } dpm.setActivePasswordState(Math.max(quality, computedQuality), password .length(), letters, uppercase, lowercase, numbers, symbols); .length(), letters, uppercase, lowercase, numbers, symbols, nonletter); } else { // The password is not anything. dpm.setActivePasswordState( DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0); DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0); } // Add the password to the password history. We assume all // password Loading @@ -483,7 +489,7 @@ public class LockPatternUtils { setString(PASSWORD_HISTORY_KEY, passwordHistory); } else { dpm.setActivePasswordState( DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0); DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0); } } catch (FileNotFoundException fnfe) { // Cant do much, unless we want to fail over to using the settings provider Loading
services/java/com/android/server/DevicePolicyManagerService.java +67 −4 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { int mActivePasswordLetters = 0; int mActivePasswordNumeric = 0; int mActivePasswordSymbols = 0; int mActivePasswordNonLetter = 0; int mFailedPasswordAttempts = 0; int mPasswordOwner = -1; Loading @@ -100,6 +101,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { int minimumPasswordLetters = 1; int minimumPasswordNumeric = 1; int minimumPasswordSymbols = 1; int minimumPasswordNonLetter = 0; long maximumTimeToUnlock = 0; int maximumFailedPasswordsForWipe = 0; Loading Loading @@ -153,6 +155,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { out.attribute(null, "value", Integer.toString(minimumPasswordSymbols)); out.endTag(null, "min-password-symbols"); } if (minimumPasswordNonLetter > 0) { out.startTag(null, "min-password-nonletter"); out.attribute(null, "value", Integer.toString(minimumPasswordNonLetter)); out.endTag(null, "min-password-nonletter"); } } if (maximumTimeToUnlock != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { out.startTag(null, "max-time-to-unlock"); Loading Loading @@ -202,6 +209,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } else if ("min-password-symbols".equals(tag)) { minimumPasswordSymbols = Integer.parseInt( parser.getAttributeValue(null, "value")); } else if ("min-password-nonletter".equals(tag)) { minimumPasswordNonLetter = Integer.parseInt( parser.getAttributeValue(null, "value")); } else if ("max-time-to-unlock".equals(tag)) { maximumTimeToUnlock = Long.parseLong( parser.getAttributeValue(null, "value")); Loading Loading @@ -240,6 +250,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { pw.println(minimumPasswordNumeric); pw.print(prefix); pw.print("minimumPasswordSymbols="); pw.println(minimumPasswordSymbols); pw.print(prefix); pw.print("minimumPasswordNonLetter="); pw.println(minimumPasswordNonLetter); pw.print(prefix); pw.print("maximumTimeToUnlock="); pw.println(maximumTimeToUnlock); pw.print(prefix); pw.print("maximumFailedPasswordsForWipe="); Loading Loading @@ -429,7 +441,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (mActivePasswordQuality != 0 || mActivePasswordLength != 0 || mActivePasswordUpperCase != 0 || mActivePasswordLowerCase != 0 || mActivePasswordLetters != 0 || mActivePasswordNumeric != 0 || mActivePasswordSymbols != 0) { || mActivePasswordSymbols != 0 || mActivePasswordNonLetter != 0) { out.startTag(null, "active-password"); out.attribute(null, "quality", Integer.toString(mActivePasswordQuality)); out.attribute(null, "length", Integer.toString(mActivePasswordLength)); Loading @@ -439,6 +451,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { out.attribute(null, "numeric", Integer .toString(mActivePasswordNumeric)); out.attribute(null, "symbols", Integer.toString(mActivePasswordSymbols)); out.attribute(null, "nonletter", Integer.toString(mActivePasswordNonLetter)); out.endTag(null, "active-password"); } Loading Loading @@ -529,6 +542,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { parser.getAttributeValue(null, "numeric")); mActivePasswordSymbols = Integer.parseInt( parser.getAttributeValue(null, "symbols")); mActivePasswordNonLetter = Integer.parseInt( parser.getAttributeValue(null, "nonletter")); XmlUtils.skipCurrentTag(parser); } else { Slog.w(TAG, "Unknown tag: " + tag); Loading Loading @@ -571,6 +586,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { mActivePasswordLetters = 0; mActivePasswordNumeric = 0; mActivePasswordSymbols = 0; mActivePasswordNonLetter = 0; } validatePasswordOwnerLocked(); Loading Loading @@ -974,6 +990,40 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } public void setPasswordMinimumNonLetter(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.minimumPasswordNonLetter != length) { ap.minimumPasswordNonLetter = length; saveSettingsLocked(); } } } public int getPasswordMinimumNonLetter(ComponentName who) { synchronized (this) { int length = 0; if (who != null) { ActiveAdmin admin = getActiveAdminUncheckedLocked(who); return admin != null ? admin.minimumPasswordNonLetter : length; } final int N = mAdminList.size(); for (int i=0; i<N; i++) { ActiveAdmin admin = mAdminList.get(i); if (length < admin.minimumPasswordNonLetter) { length = admin.minimumPasswordNonLetter; } } return length; } } public boolean isActivePasswordSufficient() { synchronized (this) { // This API can only be called by an active device admin, Loading @@ -991,7 +1041,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { && mActivePasswordLowerCase >= getPasswordMinimumLowerCase(null) && mActivePasswordLetters >= getPasswordMinimumLetters(null) && mActivePasswordNumeric >= getPasswordMinimumNumeric(null) && mActivePasswordSymbols >= getPasswordMinimumSymbols(null); && mActivePasswordSymbols >= getPasswordMinimumSymbols(null) && mActivePasswordNonLetter >= getPasswordMinimumNonLetter(null); } } Loading Loading @@ -1075,6 +1126,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { int lowercase = 0; int numbers = 0; int symbols = 0; int nonletter = 0; for (int i = 0; i < password.length(); i++) { char c = password.charAt(i); if (c >= 'A' && c <= 'Z') { Loading @@ -1085,8 +1137,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { lowercase++; } else if (c >= '0' && c <= '9') { numbers++; nonletter++; } else { symbols++; nonletter++; } } int neededLetters = getPasswordMinimumLetters(null); Loading Loading @@ -1123,6 +1177,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + " does not meet required number of special symbols " + neededSymbols); return false; } int neededNonLetter = getPasswordMinimumNonLetter(null); if (nonletter < neededNonLetter) { Slog.w(TAG, "resetPassword: number of non-letter characters " + nonletter + " does not meet required number of non-letter characters " + neededNonLetter); return false; } } LockPatternUtils utils = new LockPatternUtils(mContext); Loading Loading @@ -1282,7 +1343,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } public void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase, int numbers, int symbols) { int lowercase, int numbers, int symbols, int nonletter) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BIND_DEVICE_ADMIN, null); Loading @@ -1293,7 +1354,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { || mFailedPasswordAttempts != 0 || mActivePasswordLetters != letters || mActivePasswordUpperCase != uppercase || mActivePasswordLowerCase != lowercase || mActivePasswordNumeric != numbers || mActivePasswordSymbols != symbols) { || mActivePasswordSymbols != symbols || mActivePasswordNonLetter != nonletter) { long ident = Binder.clearCallingIdentity(); try { mActivePasswordQuality = quality; Loading @@ -1303,6 +1364,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { mActivePasswordUpperCase = uppercase; mActivePasswordNumeric = numbers; mActivePasswordSymbols = symbols; mActivePasswordNonLetter = nonletter; mFailedPasswordAttempts = 0; saveSettingsLocked(); sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED, Loading Loading @@ -1391,6 +1453,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { pw.print(" mActivePasswordLetters="); pw.println(mActivePasswordLetters); pw.print(" mActivePasswordNumeric="); pw.println(mActivePasswordNumeric); pw.print(" mActivePasswordSymbols="); pw.println(mActivePasswordSymbols); pw.print(" mActivePasswordNonLetter="); pw.println(mActivePasswordNonLetter); pw.print(" mFailedPasswordAttempts="); pw.println(mFailedPasswordAttempts); pw.print(" mPasswordOwner="); pw.println(mPasswordOwner); } Loading