Refactor LockSettingsService to unify the handling of pattern and password
Also fix LockSettingsStorageTests. More unit tests on LockSettingsService
to be added in the next CL.
Bug: 33126408
Test: runtest frameworks-services -c com.android.server.LockSettingsStorageTests
Change-Id: I0f143b26fed1d5ae122fba3b57bd39c7793ad8d9
diff --git a/services/core/java/com/android/server/LockSettingsStorage.java b/services/core/java/com/android/server/LockSettingsStorage.java
index ab91a73..3d973a0 100644
--- a/services/core/java/com/android/server/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/LockSettingsStorage.java
@@ -16,7 +16,7 @@
package com.android.server;
-import com.android.internal.annotations.VisibleForTesting;
+import static android.content.Context.USER_SERVICE;
import android.content.ContentValues;
import android.content.Context;
@@ -29,14 +29,15 @@
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
-import android.util.SparseArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.widget.LockPatternUtils;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
-import static android.content.Context.USER_SERVICE;
-
/**
* Storage for the lock settings service.
*/
@@ -72,29 +73,48 @@
private final Cache mCache = new Cache();
private final Object mFileWriteLock = new Object();
- private SparseArray<Integer> mStoredCredentialType;
-
- static class CredentialHash {
- static final int TYPE_NONE = -1;
- static final int TYPE_PATTERN = 1;
- static final int TYPE_PASSWORD = 2;
-
+ @VisibleForTesting
+ public static class CredentialHash {
static final int VERSION_LEGACY = 0;
static final int VERSION_GATEKEEPER = 1;
- CredentialHash(byte[] hash, int version) {
+ private CredentialHash(byte[] hash, int type, int version) {
+ if (type != LockPatternUtils.CREDENTIAL_TYPE_NONE) {
+ if (hash == null) {
+ throw new RuntimeException("Empty hash for CredentialHash");
+ }
+ } else /* type == LockPatternUtils.CREDENTIAL_TYPE_NONE */ {
+ if (hash != null) {
+ throw new RuntimeException("None type CredentialHash should not have hash");
+ }
+ }
this.hash = hash;
+ this.type = type;
this.version = version;
this.isBaseZeroPattern = false;
}
- CredentialHash(byte[] hash, boolean isBaseZeroPattern) {
+ private CredentialHash(byte[] hash, boolean isBaseZeroPattern) {
this.hash = hash;
+ this.type = LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
this.version = VERSION_GATEKEEPER;
this.isBaseZeroPattern = isBaseZeroPattern;
}
+ static CredentialHash create(byte[] hash, int type) {
+ if (type == LockPatternUtils.CREDENTIAL_TYPE_NONE) {
+ throw new RuntimeException("Bad type for CredentialHash");
+ }
+ return new CredentialHash(hash, type, VERSION_GATEKEEPER);
+ }
+
+ static CredentialHash createEmptyHash() {
+ return new CredentialHash(null, LockPatternUtils.CREDENTIAL_TYPE_NONE,
+ VERSION_GATEKEEPER);
+ }
+
byte[] hash;
+ int type;
int version;
boolean isBaseZeroPattern;
}
@@ -102,7 +122,6 @@
public LockSettingsStorage(Context context, Callback callback) {
mContext = context;
mOpenHelper = new DatabaseHelper(context, callback);
- mStoredCredentialType = new SparseArray<Integer>();
}
public void writeKeyValue(String key, String value, int userId) {
@@ -178,75 +197,62 @@
}
// Populate cache by reading the password and pattern files.
- readPasswordHash(userId);
- readPatternHash(userId);
+ readCredentialHash(userId);
}
- public int getStoredCredentialType(int userId) {
- final Integer cachedStoredCredentialType = mStoredCredentialType.get(userId);
- if (cachedStoredCredentialType != null) {
- return cachedStoredCredentialType.intValue();
- }
-
- int storedCredentialType;
- CredentialHash pattern = readPatternHash(userId);
- if (pattern == null) {
- if (readPasswordHash(userId) != null) {
- storedCredentialType = CredentialHash.TYPE_PASSWORD;
- } else {
- storedCredentialType = CredentialHash.TYPE_NONE;
- }
- } else {
- CredentialHash password = readPasswordHash(userId);
- if (password != null) {
- // Both will never be GateKeeper
- if (password.version == CredentialHash.VERSION_GATEKEEPER) {
- storedCredentialType = CredentialHash.TYPE_PASSWORD;
- } else {
- storedCredentialType = CredentialHash.TYPE_PATTERN;
- }
- } else {
- storedCredentialType = CredentialHash.TYPE_PATTERN;
- }
- }
- mStoredCredentialType.put(userId, storedCredentialType);
- return storedCredentialType;
- }
-
-
- public CredentialHash readPasswordHash(int userId) {
+ private CredentialHash readPasswordHashIfExists(int userId) {
byte[] stored = readFile(getLockPasswordFilename(userId));
- if (stored != null && stored.length > 0) {
- return new CredentialHash(stored, CredentialHash.VERSION_GATEKEEPER);
+ if (!ArrayUtils.isEmpty(stored)) {
+ return new CredentialHash(stored, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
+ CredentialHash.VERSION_GATEKEEPER);
}
stored = readFile(getLegacyLockPasswordFilename(userId));
- if (stored != null && stored.length > 0) {
- return new CredentialHash(stored, CredentialHash.VERSION_LEGACY);
+ if (!ArrayUtils.isEmpty(stored)) {
+ return new CredentialHash(stored, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
+ CredentialHash.VERSION_LEGACY);
}
-
return null;
}
- public CredentialHash readPatternHash(int userId) {
+ private CredentialHash readPatternHashIfExists(int userId) {
byte[] stored = readFile(getLockPatternFilename(userId));
- if (stored != null && stored.length > 0) {
- return new CredentialHash(stored, CredentialHash.VERSION_GATEKEEPER);
+ if (!ArrayUtils.isEmpty(stored)) {
+ return new CredentialHash(stored, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
+ CredentialHash.VERSION_GATEKEEPER);
}
stored = readFile(getBaseZeroLockPatternFilename(userId));
- if (stored != null && stored.length > 0) {
+ if (!ArrayUtils.isEmpty(stored)) {
return new CredentialHash(stored, true);
}
stored = readFile(getLegacyLockPatternFilename(userId));
- if (stored != null && stored.length > 0) {
- return new CredentialHash(stored, CredentialHash.VERSION_LEGACY);
+ if (!ArrayUtils.isEmpty(stored)) {
+ return new CredentialHash(stored, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
+ CredentialHash.VERSION_LEGACY);
}
-
return null;
}
+ public CredentialHash readCredentialHash(int userId) {
+ CredentialHash passwordHash = readPasswordHashIfExists(userId);
+ CredentialHash patternHash = readPatternHashIfExists(userId);
+ if (passwordHash != null && patternHash != null) {
+ if (passwordHash.version == CredentialHash.VERSION_GATEKEEPER) {
+ return passwordHash;
+ } else {
+ return patternHash;
+ }
+ } else if (passwordHash != null) {
+ return passwordHash;
+ } else if (patternHash != null) {
+ return patternHash;
+ } else {
+ return CredentialHash.createEmptyHash();
+ }
+ }
+
public void removeChildProfileLock(int userId) {
if (DEBUG)
Slog.e(TAG, "Remove child profile lock for user: " + userId);
@@ -355,26 +361,17 @@
}
}
- public void writePatternHash(byte[] hash, int userId) {
- mStoredCredentialType.put(userId, hash == null ? CredentialHash.TYPE_NONE
- : CredentialHash.TYPE_PATTERN);
- writeFile(getLockPatternFilename(userId), hash);
- clearPasswordHash(userId);
- }
+ public void writeCredentialHash(CredentialHash hash, int userId) {
+ byte[] patternHash = null;
+ byte[] passwordHash = null;
- private void clearPatternHash(int userId) {
- writeFile(getLockPatternFilename(userId), null);
- }
-
- public void writePasswordHash(byte[] hash, int userId) {
- mStoredCredentialType.put(userId, hash == null ? CredentialHash.TYPE_NONE
- : CredentialHash.TYPE_PASSWORD);
- writeFile(getLockPasswordFilename(userId), hash);
- clearPatternHash(userId);
- }
-
- private void clearPasswordHash(int userId) {
- writeFile(getLockPasswordFilename(userId), null);
+ if (hash.type == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD) {
+ passwordHash = hash.hash;
+ } else if (hash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN) {
+ patternHash = hash.hash;
+ }
+ writeFile(getLockPasswordFilename(userId), passwordHash);
+ writeFile(getLockPatternFilename(userId), patternHash);
}
@VisibleForTesting