diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 1b2322ff0c6c9..f53170a77220a 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -1826,9 +1826,23 @@ public class DevicePolicyManager { * this method; if it has not, a security exception will be thrown. */ public int getCurrentFailedPasswordAttempts() { + return getCurrentFailedPasswordAttempts(myUserId()); + } + + /** + * Retrieve the number of times the given user has failed at entering a + * password since that last successful password entry. + * + *
The calling device admin must have requested + * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to be able to call this method; if it has + * not and it is not the system uid, a security exception will be thrown. + * + * @hide + */ + public int getCurrentFailedPasswordAttempts(int userHandle) { if (mService != null) { try { - return mService.getCurrentFailedPasswordAttempts(myUserId(), mParentInstance); + return mService.getCurrentFailedPasswordAttempts(userHandle, mParentInstance); } catch (RemoteException e) { Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e); } diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index e239852673e88..cbc735fc065c2 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -283,6 +283,15 @@ public class LockPatternUtils { getTrustManager().reportUnlockAttempt(true /* authenticated */, userId); } + public int getCurrentFailedPasswordAttempts(int userId) { + return getDevicePolicyManager().getCurrentFailedPasswordAttempts(userId); + } + + public int getMaximumFailedPasswordsForWipe(int userId) { + return getDevicePolicyManager().getMaximumFailedPasswordsForWipe( + null /* componentName */, userId); + } + /** * Check to see if a pattern matches the saved pattern. * If pattern matches, return an opaque attestation that the challenge diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 22c0414e00d07..916b66d04a546 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -3524,11 +3524,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public int getCurrentFailedPasswordAttempts(int userHandle, boolean parent) { + enforceFullCrossUsersPermission(userHandle); synchronized (this) { - // This API can only be called by an active device admin, - // so try to retrieve it to check that the caller is one. - getActiveAdminForCallerLocked( - null, DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, parent); + if (!isCallerWithSystemUid()) { + // This API can only be called by an active device admin, + // so try to retrieve it to check that the caller is one. + getActiveAdminForCallerLocked( + null, DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, parent); + } DevicePolicyData policy = getUserDataUnchecked(getCredentialOwner(userHandle, parent));