Loading api/current.xml +28 −0 Original line number Diff line number Diff line Loading @@ -31730,6 +31730,19 @@ <parameter name="admin" type="android.content.ComponentName"> </parameter> </method> <method name="getPasswordHistoryLength" 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="getPasswordMaximumLength" return="int" abstract="false" Loading Loading @@ -31862,6 +31875,21 @@ <parameter name="timeMs" type="long"> </parameter> </method> <method name="setPasswordHistoryLength" 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="setPasswordMinimumLength" return="void" abstract="false" core/java/android/app/admin/DevicePolicyManager.java +112 −63 Original line number Diff line number Diff line Loading @@ -93,15 +93,14 @@ public class DevicePolicyManager { public static final String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION"; /** * Activity action: have the user enter a new password. This activity * should be launched after using {@link #setPasswordQuality(ComponentName, int)} * or {@link #setPasswordMinimumLength(ComponentName, int)} to have the * user enter a new password that meets the current requirements. You can * use {@link #isActivePasswordSufficient()} to determine whether you need * to have the user select a new password in order to meet the current * constraints. Upon being resumed from this activity, * you can check the new password characteristics to see if they are * sufficient. * Activity action: have the user enter a new password. This activity should * be launched after using {@link #setPasswordQuality(ComponentName, int)}, * or {@link #setPasswordMinimumLength(ComponentName, int)} to have the user * enter a new password that meets the current requirements. You can use * {@link #isActivePasswordSufficient()} to determine whether you need to * have the user select a new password in order to meet the current * constraints. Upon being resumed from this activity, you can check the new * password characteristics to see if they are sufficient. */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_SET_NEW_PASSWORD Loading Loading @@ -304,6 +303,56 @@ public class DevicePolicyManager { 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 * enter a new password that is the same as any password in the history. 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 * either {@link #PASSWORD_QUALITY_NUMERIC}, * {@link #PASSWORD_QUALITY_ALPHABETIC}, or * {@link #PASSWORD_QUALITY_ALPHANUMERIC} 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 length of password history. A value of 0 * means there is no restriction. */ public void setPasswordHistoryLength(ComponentName admin, int length) { if (mService != null) { try { mService.setPasswordHistoryLength(admin, length); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } } } /** * Retrieve the current password history length 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 length of the password history */ public int getPasswordHistoryLength(ComponentName admin) { if (mService != null) { try { return mService.getPasswordHistoryLength(admin); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } } return 0; } /** * Return the maximum password length that the device supports for a * particular password quality. Loading core/java/android/app/admin/IDevicePolicyManager.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,9 @@ interface IDevicePolicyManager { void setPasswordMinimumLength(in ComponentName who, int length); int getPasswordMinimumLength(in ComponentName who); void setPasswordHistoryLength(in ComponentName who, int length); int getPasswordHistoryLength(in ComponentName who); boolean isActivePasswordSufficient(); int getCurrentFailedPasswordAttempts(); Loading core/java/com/android/internal/widget/LockPatternUtils.java +30 −13 Original line number Diff line number Diff line Loading @@ -86,12 +86,6 @@ public class LockPatternUtils { */ public static final int MIN_PATTERN_REGISTER_FAIL = 3; /** * The number of previous password hashes to store. This is used to prevent * the user from setting the same password as any of the stored ones. */ public static final int MAX_PASSWORD_HISTORY_LENGTH = 5; private final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently"; private final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline"; private final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen"; Loading Loading @@ -146,6 +140,10 @@ public class LockPatternUtils { return getDevicePolicyManager().getPasswordQuality(null); } public int getRequestedPasswordHistoryLength() { return getDevicePolicyManager().getPasswordHistoryLength(null); } /** * Returns the actual password mode, as set by keyguard after updating the password. * Loading Loading @@ -219,7 +217,21 @@ public class LockPatternUtils { public boolean checkPasswordHistory(String password) { String passwordHashString = new String(passwordToHash(password)); String passwordHistory = getString(PASSWORD_HISTORY_KEY); return passwordHistory != null && passwordHistory.contains(passwordHashString); if (passwordHistory == null) { return false; } // Password History may be too long... int passwordHashLength = passwordHashString.length(); int passwordHistoryLength = getRequestedPasswordHistoryLength(); if(passwordHistoryLength == 0) { return false; } int neededPasswordHistoryLength = passwordHashLength * passwordHistoryLength + passwordHistoryLength - 1; if (passwordHistory.length() > neededPasswordHistoryLength) { passwordHistory = passwordHistory.substring(0, neededPasswordHistoryLength); } return passwordHistory.contains(passwordHashString); } /** Loading Loading @@ -413,12 +425,17 @@ public class LockPatternUtils { if (passwordHistory == null) { passwordHistory = new String(); } int passwordHistoryLength = getRequestedPasswordHistoryLength(); if (passwordHistoryLength == 0) { passwordHistory = ""; } else { passwordHistory = new String(hash) + "," + passwordHistory; // Cut it to contain MAX_PASSWORD_HISTORY_LENGTH hashes // and MAX_PASSWORD_HISTORY_LENGTH -1 commas. // Cut it to contain passwordHistoryLength hashes // and passwordHistoryLength -1 commas. passwordHistory = passwordHistory.substring(0, Math.min(hash.length * MAX_PASSWORD_HISTORY_LENGTH + MAX_PASSWORD_HISTORY_LENGTH - 1, passwordHistory.length())); * passwordHistoryLength + passwordHistoryLength - 1, passwordHistory .length())); } setString(PASSWORD_HISTORY_KEY, passwordHistory); } else { dpm.setActivePasswordState( Loading services/java/com/android/server/DevicePolicyManagerService.java +128 −83 Original line number Diff line number Diff line Loading @@ -89,6 +89,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { int passwordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; int minimumPasswordLength = 0; int passwordHistoryLength = 0; long maximumTimeToUnlock = 0; int maximumFailedPasswordsForWipe = 0; Loading @@ -110,7 +111,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (minimumPasswordLength > 0) { out.startTag(null, "min-password-length"); out.attribute(null, "value", Integer.toString(minimumPasswordLength)); out.endTag(null, "mn-password-length"); out.endTag(null, "min-password-length"); } if(passwordHistoryLength > 0) { out.startTag(null, "password-history-length"); out.attribute(null, "value", Integer.toString(passwordHistoryLength)); out.endTag(null, "password-history-length"); } } if (maximumTimeToUnlock != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { Loading Loading @@ -143,6 +149,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } else if ("min-password-length".equals(tag)) { minimumPasswordLength = Integer.parseInt( parser.getAttributeValue(null, "value")); } else if ("password-history-length".equals(tag)) { passwordHistoryLength = Integer.parseInt( parser.getAttributeValue(null, "value")); } else if ("max-time-to-unlock".equals(tag)) { maximumTimeToUnlock = Long.parseLong( parser.getAttributeValue(null, "value")); Loading @@ -166,9 +175,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } pw.print(prefix); pw.print("passwordQuality=0x"); pw.print(Integer.toHexString(passwordQuality)); pw.print(" minimumPasswordLength="); pw.println(Integer.toHexString(passwordQuality)); pw.print(prefix); pw.print("minimumPasswordLength="); pw.println(minimumPasswordLength); pw.print(prefix); pw.print("passwordHistoryLength="); pw.println(passwordHistoryLength); pw.print(prefix); pw.print("maximumTimeToUnlock="); pw.println(maximumTimeToUnlock); pw.print(prefix); pw.print("maximumFailedPasswordsForWipe="); Loading Loading @@ -667,6 +678,40 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } public void setPasswordHistoryLength(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.passwordHistoryLength != length) { ap.passwordHistoryLength = length; saveSettingsLocked(); } } } public int getPasswordHistoryLength(ComponentName who) { synchronized (this) { int length = 0; if (who != null) { ActiveAdmin admin = getActiveAdminUncheckedLocked(who); return admin != null ? admin.passwordHistoryLength : length; } final int N = mAdminList.size(); for (int i = 0; i < N; i++) { ActiveAdmin admin = mAdminList.get(i); if (length < admin.passwordHistoryLength) { length = admin.passwordHistoryLength; } } return length; } } public boolean isActivePasswordSufficient() { synchronized (this) { // This API can only be called by an active device admin, Loading Loading
api/current.xml +28 −0 Original line number Diff line number Diff line Loading @@ -31730,6 +31730,19 @@ <parameter name="admin" type="android.content.ComponentName"> </parameter> </method> <method name="getPasswordHistoryLength" 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="getPasswordMaximumLength" return="int" abstract="false" Loading Loading @@ -31862,6 +31875,21 @@ <parameter name="timeMs" type="long"> </parameter> </method> <method name="setPasswordHistoryLength" 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="setPasswordMinimumLength" return="void" abstract="false"
core/java/android/app/admin/DevicePolicyManager.java +112 −63 Original line number Diff line number Diff line Loading @@ -93,15 +93,14 @@ public class DevicePolicyManager { public static final String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION"; /** * Activity action: have the user enter a new password. This activity * should be launched after using {@link #setPasswordQuality(ComponentName, int)} * or {@link #setPasswordMinimumLength(ComponentName, int)} to have the * user enter a new password that meets the current requirements. You can * use {@link #isActivePasswordSufficient()} to determine whether you need * to have the user select a new password in order to meet the current * constraints. Upon being resumed from this activity, * you can check the new password characteristics to see if they are * sufficient. * Activity action: have the user enter a new password. This activity should * be launched after using {@link #setPasswordQuality(ComponentName, int)}, * or {@link #setPasswordMinimumLength(ComponentName, int)} to have the user * enter a new password that meets the current requirements. You can use * {@link #isActivePasswordSufficient()} to determine whether you need to * have the user select a new password in order to meet the current * constraints. Upon being resumed from this activity, you can check the new * password characteristics to see if they are sufficient. */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_SET_NEW_PASSWORD Loading Loading @@ -304,6 +303,56 @@ public class DevicePolicyManager { 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 * enter a new password that is the same as any password in the history. 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 * either {@link #PASSWORD_QUALITY_NUMERIC}, * {@link #PASSWORD_QUALITY_ALPHABETIC}, or * {@link #PASSWORD_QUALITY_ALPHANUMERIC} 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 length of password history. A value of 0 * means there is no restriction. */ public void setPasswordHistoryLength(ComponentName admin, int length) { if (mService != null) { try { mService.setPasswordHistoryLength(admin, length); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } } } /** * Retrieve the current password history length 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 length of the password history */ public int getPasswordHistoryLength(ComponentName admin) { if (mService != null) { try { return mService.getPasswordHistoryLength(admin); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } } return 0; } /** * Return the maximum password length that the device supports for a * particular password quality. Loading
core/java/android/app/admin/IDevicePolicyManager.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,9 @@ interface IDevicePolicyManager { void setPasswordMinimumLength(in ComponentName who, int length); int getPasswordMinimumLength(in ComponentName who); void setPasswordHistoryLength(in ComponentName who, int length); int getPasswordHistoryLength(in ComponentName who); boolean isActivePasswordSufficient(); int getCurrentFailedPasswordAttempts(); Loading
core/java/com/android/internal/widget/LockPatternUtils.java +30 −13 Original line number Diff line number Diff line Loading @@ -86,12 +86,6 @@ public class LockPatternUtils { */ public static final int MIN_PATTERN_REGISTER_FAIL = 3; /** * The number of previous password hashes to store. This is used to prevent * the user from setting the same password as any of the stored ones. */ public static final int MAX_PASSWORD_HISTORY_LENGTH = 5; private final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently"; private final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline"; private final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen"; Loading Loading @@ -146,6 +140,10 @@ public class LockPatternUtils { return getDevicePolicyManager().getPasswordQuality(null); } public int getRequestedPasswordHistoryLength() { return getDevicePolicyManager().getPasswordHistoryLength(null); } /** * Returns the actual password mode, as set by keyguard after updating the password. * Loading Loading @@ -219,7 +217,21 @@ public class LockPatternUtils { public boolean checkPasswordHistory(String password) { String passwordHashString = new String(passwordToHash(password)); String passwordHistory = getString(PASSWORD_HISTORY_KEY); return passwordHistory != null && passwordHistory.contains(passwordHashString); if (passwordHistory == null) { return false; } // Password History may be too long... int passwordHashLength = passwordHashString.length(); int passwordHistoryLength = getRequestedPasswordHistoryLength(); if(passwordHistoryLength == 0) { return false; } int neededPasswordHistoryLength = passwordHashLength * passwordHistoryLength + passwordHistoryLength - 1; if (passwordHistory.length() > neededPasswordHistoryLength) { passwordHistory = passwordHistory.substring(0, neededPasswordHistoryLength); } return passwordHistory.contains(passwordHashString); } /** Loading Loading @@ -413,12 +425,17 @@ public class LockPatternUtils { if (passwordHistory == null) { passwordHistory = new String(); } int passwordHistoryLength = getRequestedPasswordHistoryLength(); if (passwordHistoryLength == 0) { passwordHistory = ""; } else { passwordHistory = new String(hash) + "," + passwordHistory; // Cut it to contain MAX_PASSWORD_HISTORY_LENGTH hashes // and MAX_PASSWORD_HISTORY_LENGTH -1 commas. // Cut it to contain passwordHistoryLength hashes // and passwordHistoryLength -1 commas. passwordHistory = passwordHistory.substring(0, Math.min(hash.length * MAX_PASSWORD_HISTORY_LENGTH + MAX_PASSWORD_HISTORY_LENGTH - 1, passwordHistory.length())); * passwordHistoryLength + passwordHistoryLength - 1, passwordHistory .length())); } setString(PASSWORD_HISTORY_KEY, passwordHistory); } else { dpm.setActivePasswordState( Loading
services/java/com/android/server/DevicePolicyManagerService.java +128 −83 Original line number Diff line number Diff line Loading @@ -89,6 +89,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { int passwordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; int minimumPasswordLength = 0; int passwordHistoryLength = 0; long maximumTimeToUnlock = 0; int maximumFailedPasswordsForWipe = 0; Loading @@ -110,7 +111,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (minimumPasswordLength > 0) { out.startTag(null, "min-password-length"); out.attribute(null, "value", Integer.toString(minimumPasswordLength)); out.endTag(null, "mn-password-length"); out.endTag(null, "min-password-length"); } if(passwordHistoryLength > 0) { out.startTag(null, "password-history-length"); out.attribute(null, "value", Integer.toString(passwordHistoryLength)); out.endTag(null, "password-history-length"); } } if (maximumTimeToUnlock != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { Loading Loading @@ -143,6 +149,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } else if ("min-password-length".equals(tag)) { minimumPasswordLength = Integer.parseInt( parser.getAttributeValue(null, "value")); } else if ("password-history-length".equals(tag)) { passwordHistoryLength = Integer.parseInt( parser.getAttributeValue(null, "value")); } else if ("max-time-to-unlock".equals(tag)) { maximumTimeToUnlock = Long.parseLong( parser.getAttributeValue(null, "value")); Loading @@ -166,9 +175,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } pw.print(prefix); pw.print("passwordQuality=0x"); pw.print(Integer.toHexString(passwordQuality)); pw.print(" minimumPasswordLength="); pw.println(Integer.toHexString(passwordQuality)); pw.print(prefix); pw.print("minimumPasswordLength="); pw.println(minimumPasswordLength); pw.print(prefix); pw.print("passwordHistoryLength="); pw.println(passwordHistoryLength); pw.print(prefix); pw.print("maximumTimeToUnlock="); pw.println(maximumTimeToUnlock); pw.print(prefix); pw.print("maximumFailedPasswordsForWipe="); Loading Loading @@ -667,6 +678,40 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } public void setPasswordHistoryLength(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.passwordHistoryLength != length) { ap.passwordHistoryLength = length; saveSettingsLocked(); } } } public int getPasswordHistoryLength(ComponentName who) { synchronized (this) { int length = 0; if (who != null) { ActiveAdmin admin = getActiveAdminUncheckedLocked(who); return admin != null ? admin.passwordHistoryLength : length; } final int N = mAdminList.size(); for (int i = 0; i < N; i++) { ActiveAdmin admin = mAdminList.get(i); if (length < admin.passwordHistoryLength) { length = admin.passwordHistoryLength; } } return length; } } public boolean isActivePasswordSufficient() { synchronized (this) { // This API can only be called by an active device admin, Loading