Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c857740f authored by Konstantin Lopyrev's avatar Konstantin Lopyrev
Browse files

Adding support for minimum number of non letter characters.

Change-Id: If54cb7209d65eef826d474d7e0dbbef63d2f2b47
parent db479c9a
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -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"
@@ -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"
+92 −15
Original line number Diff line number Diff line
@@ -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;

@@ -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
@@ -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.
@@ -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
@@ -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.
@@ -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
@@ -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.
@@ -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
@@ -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.
@@ -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
@@ -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.
@@ -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
@@ -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);
            }
+5 −1
Original line number Diff line number Diff line
@@ -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);

@@ -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();
}
+11 −5
Original line number Diff line number Diff line
@@ -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.
     *
@@ -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
@@ -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') {
@@ -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
@@ -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
+67 −4
Original line number Diff line number Diff line
@@ -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;
@@ -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;

@@ -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");
@@ -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"));
@@ -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=");
@@ -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));
@@ -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");
            }

@@ -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);
@@ -571,6 +586,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            mActivePasswordLetters = 0;
            mActivePasswordNumeric = 0;
            mActivePasswordSymbols = 0;
            mActivePasswordNonLetter = 0;
        }

        validatePasswordOwnerLocked();
@@ -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,
@@ -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);
        }
    }

@@ -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') {
@@ -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);
@@ -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);
@@ -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);

@@ -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;
@@ -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,
@@ -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);
        }