Fix DPM.resetPassword("")
While we're at it, also fix some multi-user issues in
LockPatternUtils.
Bug: 17496766
Change-Id: I8e557ea640fa589817c8f8f818c91463585d5ea7
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 86f9060..d00cbb7 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1381,13 +1381,16 @@
* characters when the requested quality is only numeric), in which case
* the currently active quality will be increased to match.
*
+ * <p>Calling with a null or empty password will clear any existing PIN,
+ * pattern or password if the current password constraints allow it.
+ *
* <p>The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} to be able to call
* this method; if it has not, a security exception will be thrown.
*
* <p>Calling this from a managed profile will throw a security exception.
*
- * @param password The new password for the user.
+ * @param password The new password for the user. Null or empty clears the password.
* @param flags May be 0 or {@link #RESET_PASSWORD_REQUIRE_ENTRY}.
* @return Returns true if the password was applied, or false if it is
* not acceptable for the current constraints.
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 8d3db5b..f6c42af 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -191,9 +191,6 @@
return trust;
}
- /**
- * @param contentResolver Used to look up and save settings.
- */
public LockPatternUtils(Context context) {
mContext = context;
mContentResolver = context.getContentResolver();
@@ -490,17 +487,23 @@
return activePasswordQuality;
}
+ public void clearLock(boolean isFallback) {
+ clearLock(isFallback, getCurrentOrCallingUserId());
+ }
+
/**
* Clear any lock pattern or password.
*/
- public void clearLock(boolean isFallback) {
- if(!isFallback) deleteGallery();
- saveLockPassword(null, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
- setLockPatternEnabled(false);
- saveLockPattern(null);
- setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
- setLong(PASSWORD_TYPE_ALTERNATE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
- onAfterChangingPassword();
+ public void clearLock(boolean isFallback, int userHandle) {
+ if(!isFallback) deleteGallery(userHandle);
+ saveLockPassword(null, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, isFallback,
+ userHandle);
+ setLockPatternEnabled(false, userHandle);
+ saveLockPattern(null, isFallback, userHandle);
+ setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userHandle);
+ setLong(PASSWORD_TYPE_ALTERNATE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
+ userHandle);
+ onAfterChangingPassword(userHandle);
}
/**
@@ -547,11 +550,11 @@
/**
* Calls back SetupFaceLock to delete the gallery file when the lock type is changed
*/
- void deleteGallery() {
- if(usingBiometricWeak()) {
+ void deleteGallery(int userId) {
+ if(usingBiometricWeak(userId)) {
Intent intent = new Intent().setAction("com.android.facelock.DELETE_GALLERY");
intent.putExtra("deleteGallery", true);
- mContext.sendBroadcast(intent);
+ mContext.sendBroadcastAsUser(intent, new UserHandle(userId));
}
}
@@ -566,11 +569,20 @@
/**
* Save a lock pattern.
* @param pattern The new pattern to save.
- * @param isFallback Specifies if this is a fallback to biometric weak
*/
public void saveLockPattern(List<LockPatternView.Cell> pattern, boolean isFallback) {
+ this.saveLockPattern(pattern, isFallback, getCurrentOrCallingUserId());
+ }
+
+ /**
+ * Save a lock pattern.
+ * @param pattern The new pattern to save.
+ * @param isFallback Specifies if this is a fallback to biometric weak
+ * @param userId the user whose pattern is to be saved.
+ */
+ public void saveLockPattern(List<LockPatternView.Cell> pattern, boolean isFallback,
+ int userId) {
try {
- int userId = getCurrentOrCallingUserId();
getLockSettings().setLockPattern(patternToString(pattern), userId);
DevicePolicyManager dpm = getDevicePolicyManager();
if (pattern != null) {
@@ -586,17 +598,17 @@
}
}
- setBoolean(PATTERN_EVER_CHOSEN_KEY, true);
+ setBoolean(PATTERN_EVER_CHOSEN_KEY, true, userId);
if (!isFallback) {
- deleteGallery();
- setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+ deleteGallery(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);
} else {
- setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK);
+ setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK, userId);
setLong(PASSWORD_TYPE_ALTERNATE_KEY,
- DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
- finishBiometricWeak();
+ DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, userId);
+ finishBiometricWeak(userId);
dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK,
0, 0, 0, 0, 0, 0, 0, userId);
}
@@ -604,7 +616,7 @@
dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0,
0, 0, 0, 0, 0, userId);
}
- onAfterChangingPassword();
+ onAfterChangingPassword(userId);
} catch (RemoteException re) {
Log.e(TAG, "Couldn't save lock pattern " + re);
}
@@ -822,7 +834,7 @@
}
if (!isFallback) {
- deleteGallery();
+ deleteGallery(userHandle);
setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality), userHandle);
if (computedQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
int letters = 0;
@@ -862,7 +874,7 @@
userHandle);
setLong(PASSWORD_TYPE_ALTERNATE_KEY, Math.max(quality, computedQuality),
userHandle);
- finishBiometricWeak();
+ finishBiometricWeak(userHandle);
dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK,
0, 0, 0, 0, 0, 0, 0, userHandle);
}
@@ -870,7 +882,7 @@
// password hashes have the same length for simplicity of implementation.
String passwordHistory = getString(PASSWORD_HISTORY_KEY, userHandle);
if (passwordHistory == null) {
- passwordHistory = new String();
+ passwordHistory = "";
}
int passwordHistoryLength = getRequestedPasswordHistoryLength();
if (passwordHistoryLength == 0) {
@@ -897,7 +909,7 @@
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0,
userHandle);
}
- onAfterChangingPassword();
+ onAfterChangingPassword(userHandle);
} catch (RemoteException re) {
// Cant do much
Log.e(TAG, "Unable to save lock password " + re);
@@ -1190,7 +1202,14 @@
* Set whether the lock pattern is enabled.
*/
public void setLockPatternEnabled(boolean enabled) {
- setBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, enabled);
+ setLockPatternEnabled(enabled, getCurrentOrCallingUserId());
+ }
+
+ /**
+ * Set whether the lock pattern is enabled.
+ */
+ public void setLockPatternEnabled(boolean enabled, int userHandle) {
+ setBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, enabled, userHandle);
}
/**
@@ -1584,15 +1603,15 @@
return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
}
- private void finishBiometricWeak() {
- setBoolean(BIOMETRIC_WEAK_EVER_CHOSEN_KEY, true);
+ private void finishBiometricWeak(int userId) {
+ setBoolean(BIOMETRIC_WEAK_EVER_CHOSEN_KEY, true, userId);
// Launch intent to show final screen, this also
// moves the temporary gallery to the actual gallery
Intent intent = new Intent();
intent.setClassName("com.android.facelock",
"com.android.facelock.SetupEndScreen");
- mContext.startActivity(intent);
+ mContext.startActivityAsUser(intent, new UserHandle(userId));
}
public void setPowerButtonInstantlyLocks(boolean enabled) {
@@ -1686,8 +1705,8 @@
getTrustManager().reportRequireCredentialEntry(userId);
}
- private void onAfterChangingPassword() {
- getTrustManager().reportEnabledTrustAgentsChanged(getCurrentOrCallingUserId());
+ private void onAfterChangingPassword(int userHandle) {
+ getTrustManager().reportEnabledTrustAgentsChanged(userHandle);
}
public boolean isCredentialRequiredToDecrypt(boolean defaultValue) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index ac5fb18..6331dfe 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -77,6 +77,7 @@
import android.security.IKeyChainService;
import android.security.KeyChain;
import android.security.KeyChain.KeyChainConnection;
+import android.text.TextUtils;
import android.util.Log;
import android.util.PrintWriterPrinter;
import android.util.Printer;
@@ -2575,13 +2576,15 @@
return strictestAdmin;
}
- public boolean resetPassword(String password, int flags, int userHandle) {
+ public boolean resetPassword(String passwordOrNull, int flags, int userHandle) {
if (!mHasFeature) {
return false;
}
enforceCrossUserPermission(userHandle);
enforceNotManagedProfile(userHandle, "reset the password");
+ String password = passwordOrNull != null ? passwordOrNull : "";
+
int quality;
synchronized (this) {
// This api can only be called by an active device admin,
@@ -2685,7 +2688,11 @@
long ident = Binder.clearCallingIdentity();
try {
LockPatternUtils utils = new LockPatternUtils(mContext);
- utils.saveLockPassword(password, quality, false, userHandle);
+ if (!TextUtils.isEmpty(password)) {
+ utils.saveLockPassword(password, quality, false, userHandle);
+ } else {
+ utils.clearLock(false, userHandle);
+ }
boolean requireEntry = (flags & DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY) != 0;
if (requireEntry) {
utils.requireCredentialEntry(UserHandle.USER_ALL);