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

Commit 4c349b67 authored by Andrew Scull's avatar Andrew Scull Committed by android-build-merger
Browse files

resolve merge conflicts of ad4aa1ce to nyc-mr1-dev am: eb35ad99 am: 3aac3ebe

am: 9af145dc

Change-Id: I15cb7dbf619355f22f27e81aa1465683bac7e619
parents 7dfd0b98 9af145dc
Loading
Loading
Loading
Loading
+16 −1
Original line number Original line Diff line number Diff line
@@ -2026,7 +2026,8 @@ public class DevicePolicyManager {
     * Determine whether the current password the user has set is sufficient to meet the policy
     * Determine whether the current password the user has set is sufficient to meet the policy
     * requirements (e.g. quality, minimum length) that have been requested by the admins of this
     * requirements (e.g. quality, minimum length) that have been requested by the admins of this
     * user and its participating profiles. Restrictions on profiles that have a separate challenge
     * user and its participating profiles. Restrictions on profiles that have a separate challenge
     * are not taken into account.
     * are not taken into account. If the user has a password, it must have been entered in order to
     * perform this check.
     * <p>
     * <p>
     * The calling device admin must have requested
     * The calling device admin must have requested
     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
@@ -2039,6 +2040,7 @@ public class DevicePolicyManager {
     * @return Returns true if the password meets the current requirements, else false.
     * @return Returns true if the password meets the current requirements, else false.
     * @throws SecurityException if the calling application does not own an active administrator
     * @throws SecurityException if the calling application does not own an active administrator
     *             that uses {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
     *             that uses {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
     * @throws IllegalStateException if the user has a password but has not entered it yet.
     */
     */
    public boolean isActivePasswordSufficient() {
    public boolean isActivePasswordSufficient() {
        if (mService != null) {
        if (mService != null) {
@@ -3548,6 +3550,19 @@ public class DevicePolicyManager {
        }
        }
    }
    }


    /**
     * @hide
     */
    public void reportPasswordChanged(int userId) {
        if (mService != null) {
            try {
                mService.reportPasswordChanged(userId);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }

    /**
    /**
     * @hide
     * @hide
     */
     */
+1 −0
Original line number Original line Diff line number Diff line
@@ -120,6 +120,7 @@ interface IDevicePolicyManager {


    void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase,
    void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase,
        int numbers, int symbols, int nonletter, int userHandle);
        int numbers, int symbols, int nonletter, int userHandle);
    void reportPasswordChanged(int userId);
    void reportFailedPasswordAttempt(int userHandle);
    void reportFailedPasswordAttempt(int userHandle);
    void reportSuccessfulPasswordAttempt(int userHandle);
    void reportSuccessfulPasswordAttempt(int userHandle);
    void reportFailedFingerprintAttempt(int userHandle);
    void reportFailedFingerprintAttempt(int userHandle);
+3 −42
Original line number Original line Diff line number Diff line
@@ -593,9 +593,6 @@ public class LockPatternUtils {
            setCredentialRequiredToDecrypt(false);
            setCredentialRequiredToDecrypt(false);
        }
        }


        getDevicePolicyManager().setActivePasswordState(
                DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0, userHandle);

        onAfterChangingPassword(userHandle);
        onAfterChangingPassword(userHandle);
    }
    }


@@ -642,6 +639,7 @@ public class LockPatternUtils {
                        + MIN_LOCK_PATTERN_SIZE + " dots long.");
                        + MIN_LOCK_PATTERN_SIZE + " dots long.");
            }
            }


            setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, userId);
            getLockSettings().setLockPattern(patternToString(pattern), savedPattern, userId);
            getLockSettings().setLockPattern(patternToString(pattern), savedPattern, userId);
            DevicePolicyManager dpm = getDevicePolicyManager();
            DevicePolicyManager dpm = getDevicePolicyManager();


@@ -658,9 +656,6 @@ public class LockPatternUtils {


            setBoolean(PATTERN_EVER_CHOSEN_KEY, true, userId);
            setBoolean(PATTERN_EVER_CHOSEN_KEY, true, userId);


            setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, userId);
            dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
                    pattern.size(), 0, 0, 0, 0, 0, 0, userId);
            onAfterChangingPassword(userId);
            onAfterChangingPassword(userId);
        } catch (RemoteException re) {
        } catch (RemoteException re) {
            Log.e(TAG, "Couldn't save lock pattern " + re);
            Log.e(TAG, "Couldn't save lock pattern " + re);
@@ -863,9 +858,9 @@ public class LockPatternUtils {
                        + "of length " + MIN_LOCK_PASSWORD_SIZE);
                        + "of length " + MIN_LOCK_PASSWORD_SIZE);
            }
            }


            final int computedQuality = computePasswordQuality(password);
            setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality), userHandle);
            getLockSettings().setLockPassword(password, savedPassword, userHandle);
            getLockSettings().setLockPassword(password, savedPassword, userHandle);
            getLockSettings().setSeparateProfileChallengeEnabled(userHandle, true, null);
            int computedQuality = computePasswordQuality(password);


            // Update the device encryption password.
            // Update the device encryption password.
            if (userHandle == UserHandle.USER_SYSTEM
            if (userHandle == UserHandle.USER_SYSTEM
@@ -883,40 +878,6 @@ public class LockPatternUtils {
                }
                }
            }
            }


            setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality), userHandle);
            if (computedQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
                int letters = 0;
                int uppercase = 0;
                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') {
                        letters++;
                        uppercase++;
                    } else if (c >= 'a' && c <= 'z') {
                        letters++;
                        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, nonletter, userHandle);
            } else {
                // The password is not anything.
                dpm.setActivePasswordState(
                        DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
                        0, 0, 0, 0, 0, 0, 0, userHandle);
            }

            // Add the password to the password history. We assume all
            // Add the password to the password history. We assume all
            // password hashes have the same length for simplicity of implementation.
            // password hashes have the same length for simplicity of implementation.
            String passwordHistory = getString(PASSWORD_HISTORY_KEY, userHandle);
            String passwordHistory = getString(PASSWORD_HISTORY_KEY, userHandle);
+60 −0
Original line number Original line Diff line number Diff line
@@ -927,6 +927,7 @@ public class LockSettingsService extends ILockSettings.Stub {
        synchronized (mSeparateChallengeLock) {
        synchronized (mSeparateChallengeLock) {
            setLockPatternInternal(pattern, savedCredential, userId);
            setLockPatternInternal(pattern, savedCredential, userId);
            setSeparateProfileChallengeEnabled(userId, true, null);
            setSeparateProfileChallengeEnabled(userId, true, null);
            notifyPasswordChanged(userId);
        }
        }
    }
    }


@@ -941,6 +942,7 @@ public class LockSettingsService extends ILockSettings.Stub {
            setKeystorePassword(null, userId);
            setKeystorePassword(null, userId);
            fixateNewestUserKeyAuth(userId);
            fixateNewestUserKeyAuth(userId);
            onUserLockChanged(userId);
            onUserLockChanged(userId);
            notifyActivePasswordMetricsAvailable(null, userId);
            return;
            return;
        }
        }


@@ -990,6 +992,7 @@ public class LockSettingsService extends ILockSettings.Stub {
        synchronized (mSeparateChallengeLock) {
        synchronized (mSeparateChallengeLock) {
            setLockPasswordInternal(password, savedCredential, userId);
            setLockPasswordInternal(password, savedCredential, userId);
            setSeparateProfileChallengeEnabled(userId, true, null);
            setSeparateProfileChallengeEnabled(userId, true, null);
            notifyPasswordChanged(userId);
        }
        }
    }
    }


@@ -1003,6 +1006,7 @@ public class LockSettingsService extends ILockSettings.Stub {
            setKeystorePassword(null, userId);
            setKeystorePassword(null, userId);
            fixateNewestUserKeyAuth(userId);
            fixateNewestUserKeyAuth(userId);
            onUserLockChanged(userId);
            onUserLockChanged(userId);
            notifyActivePasswordMetricsAvailable(null, userId);
            return;
            return;
        }
        }


@@ -1412,6 +1416,7 @@ public class LockSettingsService extends ILockSettings.Stub {
                // migrate credential to GateKeeper
                // migrate credential to GateKeeper
                credentialUtil.setCredential(credential, null, userId);
                credentialUtil.setCredential(credential, null, userId);
                if (!hasChallenge) {
                if (!hasChallenge) {
                    notifyActivePasswordMetricsAvailable(credential, userId);
                    return VerifyCredentialResponse.OK;
                    return VerifyCredentialResponse.OK;
                }
                }
                // Fall through to get the auth token. Technically this should never happen,
                // Fall through to get the auth token. Technically this should never happen,
@@ -1451,6 +1456,7 @@ public class LockSettingsService extends ILockSettings.Stub {
            if (progressCallback != null) {
            if (progressCallback != null) {
                progressCallback.onCredentialVerified();
                progressCallback.onCredentialVerified();
            }
            }
            notifyActivePasswordMetricsAvailable(credential, userId);
            unlockKeystore(credential, userId);
            unlockKeystore(credential, userId);


            Slog.i(TAG, "Unlocking user " + userId +
            Slog.i(TAG, "Unlocking user " + userId +
@@ -1474,6 +1480,60 @@ public class LockSettingsService extends ILockSettings.Stub {
        return response;
        return response;
    }
    }


    private void notifyActivePasswordMetricsAvailable(final String password, int userId) {
        final int quality = mLockPatternUtils.getKeyguardStoredPasswordQuality(userId);

        // Asynchronous to avoid dead lock
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                int length = 0;
                int letters = 0;
                int uppercase = 0;
                int lowercase = 0;
                int numbers = 0;
                int symbols = 0;
                int nonletter = 0;
                if (password != null) {
                    length = password.length();
                    for (int i = 0; i < length; i++) {
                        char c = password.charAt(i);
                        if (c >= 'A' && c <= 'Z') {
                            letters++;
                            uppercase++;
                        } else if (c >= 'a' && c <= 'z') {
                            letters++;
                            lowercase++;
                        } else if (c >= '0' && c <= '9') {
                            numbers++;
                            nonletter++;
                        } else {
                            symbols++;
                            nonletter++;
                        }
                    }
                }
                DevicePolicyManager dpm = (DevicePolicyManager)
                        mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
                dpm.setActivePasswordState(quality, length, letters, uppercase, lowercase, numbers,
                        symbols, nonletter, userId);
            }
        });
    }

    /**
     * Call after {@link #notifyActivePasswordMetricsAvailable} so metrics are updated before
     * reporting the password changed.
     */
    private void notifyPasswordChanged(int userId) {
        // Same handler as notifyActivePasswordMetricsAvailable to ensure correct ordering
        mHandler.post(() -> {
            DevicePolicyManager dpm = (DevicePolicyManager)
                    mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
            dpm.reportPasswordChanged(userId);
        });
    }

    @Override
    @Override
    public boolean checkVoldPassword(int userId) throws RemoteException {
    public boolean checkVoldPassword(int userId) throws RemoteException {
        if (!mFirstCallToVold) {
        if (!mFirstCallToVold) {
+86 −61
Original line number Original line Diff line number Diff line
@@ -2324,10 +2324,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                out.endTag(null, "failed-password-attempts");
                out.endTag(null, "failed-password-attempts");
            }
            }


            if (policy.mActivePasswordQuality != 0 || policy.mActivePasswordLength != 0
            // Don't save metrics for FBE devices
            if (!mInjector.storageManagerIsFileBasedEncryptionEnabled()
                    && (policy.mActivePasswordQuality != 0 || policy.mActivePasswordLength != 0
                    || policy.mActivePasswordUpperCase != 0 || policy.mActivePasswordLowerCase != 0
                    || policy.mActivePasswordUpperCase != 0 || policy.mActivePasswordLowerCase != 0
                    || policy.mActivePasswordLetters != 0 || policy.mActivePasswordNumeric != 0
                    || policy.mActivePasswordLetters != 0 || policy.mActivePasswordNumeric != 0
                    || policy.mActivePasswordSymbols != 0 || policy.mActivePasswordNonLetter != 0) {
                    || policy.mActivePasswordSymbols != 0
                    || policy.mActivePasswordNonLetter != 0)) {
                out.startTag(null, "active-password");
                out.startTag(null, "active-password");
                out.attribute(null, "quality", Integer.toString(policy.mActivePasswordQuality));
                out.attribute(null, "quality", Integer.toString(policy.mActivePasswordQuality));
                out.attribute(null, "length", Integer.toString(policy.mActivePasswordLength));
                out.attribute(null, "length", Integer.toString(policy.mActivePasswordLength));
@@ -2420,6 +2423,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        JournaledFile journal = makeJournaledFile(userHandle);
        JournaledFile journal = makeJournaledFile(userHandle);
        FileInputStream stream = null;
        FileInputStream stream = null;
        File file = journal.chooseForRead();
        File file = journal.chooseForRead();
        boolean needsRewrite = false;
        try {
        try {
            stream = new FileInputStream(file);
            stream = new FileInputStream(file);
            XmlPullParser parser = Xml.newPullParser();
            XmlPullParser parser = Xml.newPullParser();
@@ -2506,7 +2510,27 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                } else if ("password-owner".equals(tag)) {
                } else if ("password-owner".equals(tag)) {
                    policy.mPasswordOwner = Integer.parseInt(
                    policy.mPasswordOwner = Integer.parseInt(
                            parser.getAttributeValue(null, "value"));
                            parser.getAttributeValue(null, "value"));
                } else if (TAG_ACCEPTED_CA_CERTIFICATES.equals(tag)) {
                    policy.mAcceptedCaCertificates.add(parser.getAttributeValue(null, ATTR_NAME));
                } else if (TAG_LOCK_TASK_COMPONENTS.equals(tag)) {
                    policy.mLockTaskPackages.add(parser.getAttributeValue(null, "name"));
                } else if (TAG_STATUS_BAR.equals(tag)) {
                    policy.mStatusBarDisabled = Boolean.parseBoolean(
                            parser.getAttributeValue(null, ATTR_DISABLED));
                } else if (DO_NOT_ASK_CREDENTIALS_ON_BOOT_XML.equals(tag)) {
                    policy.doNotAskCredentialsOnBoot = true;
                } else if (TAG_AFFILIATION_ID.equals(tag)) {
                    policy.mAffiliationIds.add(parser.getAttributeValue(null, "id"));
                } else if (TAG_ADMIN_BROADCAST_PENDING.equals(tag)) {
                    String pending = parser.getAttributeValue(null, ATTR_VALUE);
                    policy.mAdminBroadcastPending = Boolean.toString(true).equals(pending);
                } else if (TAG_INITIALIZATION_BUNDLE.equals(tag)) {
                    policy.mInitBundle = PersistableBundle.restoreFromXml(parser);
                } else if ("active-password".equals(tag)) {
                } else if ("active-password".equals(tag)) {
                    if (mInjector.storageManagerIsFileBasedEncryptionEnabled()) {
                        // Remove this from FBE devices
                        needsRewrite = true;
                    } else {
                        policy.mActivePasswordQuality = Integer.parseInt(
                        policy.mActivePasswordQuality = Integer.parseInt(
                            parser.getAttributeValue(null, "quality"));
                            parser.getAttributeValue(null, "quality"));
                        policy.mActivePasswordLength = Integer.parseInt(
                        policy.mActivePasswordLength = Integer.parseInt(
@@ -2523,22 +2547,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                                parser.getAttributeValue(null, "symbols"));
                                parser.getAttributeValue(null, "symbols"));
                        policy.mActivePasswordNonLetter = Integer.parseInt(
                        policy.mActivePasswordNonLetter = Integer.parseInt(
                                parser.getAttributeValue(null, "nonletter"));
                                parser.getAttributeValue(null, "nonletter"));
                } else if (TAG_ACCEPTED_CA_CERTIFICATES.equals(tag)) {
                    }
                    policy.mAcceptedCaCertificates.add(parser.getAttributeValue(null, ATTR_NAME));
                } else if (TAG_LOCK_TASK_COMPONENTS.equals(tag)) {
                    policy.mLockTaskPackages.add(parser.getAttributeValue(null, "name"));
                } else if (TAG_STATUS_BAR.equals(tag)) {
                    policy.mStatusBarDisabled = Boolean.parseBoolean(
                            parser.getAttributeValue(null, ATTR_DISABLED));
                } else if (DO_NOT_ASK_CREDENTIALS_ON_BOOT_XML.equals(tag)) {
                    policy.doNotAskCredentialsOnBoot = true;
                } else if (TAG_AFFILIATION_ID.equals(tag)) {
                    policy.mAffiliationIds.add(parser.getAttributeValue(null, "id"));
                } else if (TAG_ADMIN_BROADCAST_PENDING.equals(tag)) {
                    String pending = parser.getAttributeValue(null, ATTR_VALUE);
                    policy.mAdminBroadcastPending = Boolean.toString(true).equals(pending);
                } else if (TAG_INITIALIZATION_BUNDLE.equals(tag)) {
                    policy.mInitBundle = PersistableBundle.restoreFromXml(parser);
                } else {
                } else {
                    Slog.w(LOG_TAG, "Unknown tag: " + tag);
                    Slog.w(LOG_TAG, "Unknown tag: " + tag);
                    XmlUtils.skipCurrentTag(parser);
                    XmlUtils.skipCurrentTag(parser);
@@ -2558,34 +2567,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            // Ignore
            // Ignore
        }
        }


        // Might need to upgrade the file by rewriting it
        if (needsRewrite) {
            saveSettingsLocked(userHandle);
        }

        // Generate a list of admins from the admin map
        // Generate a list of admins from the admin map
        policy.mAdminList.addAll(policy.mAdminMap.values());
        policy.mAdminList.addAll(policy.mAdminMap.values());


        // Validate that what we stored for the password quality matches
        // sufficiently what is currently set.  Note that this is only
        // a sanity check in case the two get out of sync; this should
        // never normally happen.
        final long identity = mInjector.binderClearCallingIdentity();
        try {
            int actualPasswordQuality = mLockPatternUtils.getActivePasswordQuality(userHandle);
            if (actualPasswordQuality < policy.mActivePasswordQuality) {
                Slog.w(LOG_TAG, "Active password quality 0x"
                        + Integer.toHexString(policy.mActivePasswordQuality)
                        + " does not match actual quality 0x"
                        + Integer.toHexString(actualPasswordQuality));
                policy.mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
                policy.mActivePasswordLength = 0;
                policy.mActivePasswordUpperCase = 0;
                policy.mActivePasswordLowerCase = 0;
                policy.mActivePasswordLetters = 0;
                policy.mActivePasswordNumeric = 0;
                policy.mActivePasswordSymbols = 0;
                policy.mActivePasswordNonLetter = 0;
            }
        } finally {
            mInjector.binderRestoreCallingIdentity(identity);
        }

        validatePasswordOwnerLocked(policy);
        validatePasswordOwnerLocked(policy);
        updateMaximumTimeToLockLocked(userHandle);
        updateMaximumTimeToLockLocked(userHandle);
        updateLockTaskPackagesLocked(policy.mLockTaskPackages, userHandle);
        updateLockTaskPackagesLocked(policy.mLockTaskPackages, userHandle);
@@ -3809,6 +3798,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {


    private boolean isActivePasswordSufficientForUserLocked(
    private boolean isActivePasswordSufficientForUserLocked(
            DevicePolicyData policy, int userHandle, boolean parent) {
            DevicePolicyData policy, int userHandle, boolean parent) {
        enforceUserUnlocked(userHandle, parent);

        final int requiredPasswordQuality = getPasswordQuality(null, userHandle, parent);
        final int requiredPasswordQuality = getPasswordQuality(null, userHandle, parent);
        if (policy.mActivePasswordQuality < requiredPasswordQuality) {
        if (policy.mActivePasswordQuality < requiredPasswordQuality) {
            return false;
            return false;
@@ -4883,20 +4874,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            return;
            return;
        }
        }
        enforceFullCrossUsersPermission(userHandle);
        enforceFullCrossUsersPermission(userHandle);
        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.BIND_DEVICE_ADMIN, null);


        // Managed Profile password can only be changed when it has a separate challenge.
        // If the managed profile doesn't have a separate password, set the metrics to default
        if (!isSeparateProfileChallengeEnabled(userHandle)) {
        if (isManagedProfile(userHandle) && !isSeparateProfileChallengeEnabled(userHandle)) {
            enforceNotManagedProfile(userHandle, "set the active password");
            quality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
            length = 0;
            letters = 0;
            uppercase = 0;
            lowercase = 0;
            numbers = 0;
            symbols = 0;
            nonletter = 0;
        }
        }


        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.BIND_DEVICE_ADMIN, null);
        validateQualityConstant(quality);
        validateQualityConstant(quality);

        DevicePolicyData policy = getUserData(userHandle);
        DevicePolicyData policy = getUserData(userHandle);

        long ident = mInjector.binderClearCallingIdentity();
        try {
        synchronized (this) {
        synchronized (this) {
            policy.mActivePasswordQuality = quality;
            policy.mActivePasswordQuality = quality;
            policy.mActivePasswordLength = length;
            policy.mActivePasswordLength = length;
@@ -4906,17 +4900,40 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            policy.mActivePasswordNumeric = numbers;
            policy.mActivePasswordNumeric = numbers;
            policy.mActivePasswordSymbols = symbols;
            policy.mActivePasswordSymbols = symbols;
            policy.mActivePasswordNonLetter = nonletter;
            policy.mActivePasswordNonLetter = nonletter;
        }
    }

    @Override
    public void reportPasswordChanged(int userId) {
        if (!mHasFeature) {
            return;
        }
        enforceFullCrossUsersPermission(userId);

        // Managed Profile password can only be changed when it has a separate challenge.
        if (!isSeparateProfileChallengeEnabled(userId)) {
            enforceNotManagedProfile(userId, "set the active password");
        }

        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.BIND_DEVICE_ADMIN, null);

        DevicePolicyData policy = getUserData(userId);

        long ident = mInjector.binderClearCallingIdentity();
        try {
            synchronized (this) {
                policy.mFailedPasswordAttempts = 0;
                policy.mFailedPasswordAttempts = 0;
                saveSettingsLocked(userHandle);
                saveSettingsLocked(userId);
                updatePasswordExpirationsLocked(userHandle);
                updatePasswordExpirationsLocked(userId);
                setExpirationAlarmCheckLocked(mContext, userHandle, /* parent */ false);
                setExpirationAlarmCheckLocked(mContext, userId, /* parent */ false);


                // Send a broadcast to each profile using this password as its primary unlock.
                // Send a broadcast to each profile using this password as its primary unlock.
                sendAdminCommandForLockscreenPoliciesLocked(
                sendAdminCommandForLockscreenPoliciesLocked(
                        DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
                        DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
                        DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, userHandle);
                        DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, userId);
            }
            }
            removeCaApprovalsIfNeeded(userHandle);
            removeCaApprovalsIfNeeded(userId);
        } finally {
        } finally {
            mInjector.binderRestoreCallingIdentity(ident);
            mInjector.binderRestoreCallingIdentity(ident);
        }
        }
@@ -6512,6 +6529,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                "User must be running and unlocked");
                "User must be running and unlocked");
    }
    }


    private void enforceUserUnlocked(int userId, boolean parent) {
        if (parent) {
            enforceUserUnlocked(getProfileParentId(userId));
        } else {
            enforceUserUnlocked(userId);
        }
    }

    private void enforceManageUsers() {
    private void enforceManageUsers() {
        final int callingUid = mInjector.binderGetCallingUid();
        final int callingUid = mInjector.binderGetCallingUid();
        if (!(isCallerWithSystemUid() || callingUid == Process.ROOT_UID)) {
        if (!(isCallerWithSystemUid() || callingUid == Process.ROOT_UID)) {