Add a binder cache to ILockSettings#getCredentialType
Bug: 214623625 Put a binder cache in front of ILockSettings#getCredentialType(). The cache is in LockPatternUtils and the invalidation logic is in LogSettingsService. The cache is invalidated whenever the LockSettingsStorage changes. Three unit tests disable caches because they do not have permission to write to the system properties. Test: atest com.android.server.locksettings Change-Id: Iea4c50ba5cc39de9196d9a9873ae501a946bf9fd
This commit is contained in:
@@ -26,6 +26,7 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.PropertyInvalidatedCache;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.admin.PasswordMetrics;
|
||||
import android.app.trust.IStrongAuthTracker;
|
||||
@@ -915,18 +916,54 @@ public class LockPatternUtils {
|
||||
return Long.toHexString(salt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the credential type of a user.
|
||||
*/
|
||||
private final PropertyInvalidatedCache.QueryHandler<Integer, Integer> mCredentialTypeQuery =
|
||||
new PropertyInvalidatedCache.QueryHandler<>() {
|
||||
@Override
|
||||
public Integer apply(Integer userHandle) {
|
||||
try {
|
||||
return getLockSettings().getCredentialType(userHandle);
|
||||
} catch (RemoteException re) {
|
||||
Log.e(TAG, "failed to get credential type", re);
|
||||
return CREDENTIAL_TYPE_NONE;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public boolean shouldBypassCache(Integer userHandle) {
|
||||
return userHandle == USER_FRP;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The API that is cached.
|
||||
*/
|
||||
private final static String CREDENTIAL_TYPE_API = "getCredentialType";
|
||||
|
||||
/**
|
||||
* Cache the credential type of a user.
|
||||
*/
|
||||
private final PropertyInvalidatedCache<Integer, Integer> mCredentialTypeCache =
|
||||
new PropertyInvalidatedCache<>(4, PropertyInvalidatedCache.MODULE_SYSTEM,
|
||||
CREDENTIAL_TYPE_API, CREDENTIAL_TYPE_API, mCredentialTypeQuery);
|
||||
|
||||
/**
|
||||
* Invalidate the credential cache
|
||||
* @hide
|
||||
*/
|
||||
public final static void invalidateCredentialTypeCache() {
|
||||
PropertyInvalidatedCache.invalidateCache(PropertyInvalidatedCache.MODULE_SYSTEM,
|
||||
CREDENTIAL_TYPE_API);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the credential type of the user, can be one of {@link #CREDENTIAL_TYPE_NONE},
|
||||
* {@link #CREDENTIAL_TYPE_PATTERN}, {@link #CREDENTIAL_TYPE_PIN} and
|
||||
* {@link #CREDENTIAL_TYPE_PASSWORD}
|
||||
*/
|
||||
public @CredentialType int getCredentialTypeForUser(int userHandle) {
|
||||
try {
|
||||
return getLockSettings().getCredentialType(userHandle);
|
||||
} catch (RemoteException re) {
|
||||
Log.e(TAG, "failed to get credential type", re);
|
||||
return CREDENTIAL_TYPE_NONE;
|
||||
}
|
||||
return mCredentialTypeCache.query(userHandle);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -148,6 +148,8 @@ import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationTo
|
||||
import com.android.server.locksettings.SyntheticPasswordManager.TokenType;
|
||||
import com.android.server.locksettings.recoverablekeystore.RecoverableKeyStoreManager;
|
||||
import com.android.server.pm.UserManagerInternal;
|
||||
import com.android.server.utils.Watchable;
|
||||
import com.android.server.utils.Watcher;
|
||||
import com.android.server.wm.WindowManagerInternal;
|
||||
|
||||
import libcore.util.HexEncoding;
|
||||
@@ -229,6 +231,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
protected final Handler mHandler;
|
||||
@VisibleForTesting
|
||||
protected final LockSettingsStorage mStorage;
|
||||
private final Watcher mStorageWatcher;
|
||||
private final LockSettingsStrongAuth mStrongAuth;
|
||||
private final SynchronizedStrongAuthTracker mStrongAuthTracker;
|
||||
private final BiometricDeferredQueue mBiometricDeferredQueue;
|
||||
@@ -569,6 +572,12 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private class StorageWatcher extends Watcher {
|
||||
public void onChange(Watchable what) {
|
||||
LockSettingsService.this.onChange();
|
||||
}
|
||||
}
|
||||
|
||||
public LockSettingsService(Context context) {
|
||||
this(new Injector(context));
|
||||
}
|
||||
@@ -610,6 +619,16 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
mStorage);
|
||||
|
||||
LocalServices.addService(LockSettingsInternal.class, new LocalService());
|
||||
|
||||
mStorageWatcher = new StorageWatcher();
|
||||
mStorage.registerObserver(mStorageWatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate caches if the storage has changed.
|
||||
*/
|
||||
private void onChange() {
|
||||
LockPatternUtils.invalidateCredentialTypeCache();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1273,6 +1292,11 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* This API is cached; whenever the result would change,
|
||||
* {@link com.android.internal.widget.LockPatternUtils#invalidateCredentialTypeCache}
|
||||
* must be called.
|
||||
*/
|
||||
@Override
|
||||
public int getCredentialType(int userId) {
|
||||
checkPasswordHavePermission(userId);
|
||||
|
||||
@@ -47,6 +47,7 @@ import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.internal.widget.LockPatternUtils.CredentialType;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.PersistentDataBlockManagerInternal;
|
||||
import com.android.server.utils.WatchableImpl;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@@ -66,7 +67,7 @@ import java.util.Map;
|
||||
/**
|
||||
* Storage for the lock settings service.
|
||||
*/
|
||||
class LockSettingsStorage {
|
||||
class LockSettingsStorage extends WatchableImpl {
|
||||
|
||||
private static final String TAG = "LockSettingsStorage";
|
||||
private static final String TABLE = "locksettings";
|
||||
@@ -173,7 +174,7 @@ class LockSettingsStorage {
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
dispatchChange(this);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -221,7 +222,7 @@ class LockSettingsStorage {
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
dispatchChange(this);
|
||||
}
|
||||
|
||||
public void prefetchUser(int userId) {
|
||||
@@ -412,6 +413,7 @@ class LockSettingsStorage {
|
||||
}
|
||||
}
|
||||
mCache.putFile(name, hash);
|
||||
dispatchChange(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -423,6 +425,7 @@ class LockSettingsStorage {
|
||||
file.delete();
|
||||
mCache.putFile(name, null);
|
||||
}
|
||||
dispatchChange(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -500,6 +503,7 @@ class LockSettingsStorage {
|
||||
Slog.w(TAG, "Failed to zeroize " + path, e);
|
||||
} finally {
|
||||
file.delete();
|
||||
dispatchChange(this);
|
||||
}
|
||||
mCache.putFile(path, null);
|
||||
}
|
||||
@@ -587,6 +591,7 @@ class LockSettingsStorage {
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
dispatchChange(this);
|
||||
}
|
||||
|
||||
private void deleteFilesAndRemoveCache(String... names) {
|
||||
@@ -595,6 +600,7 @@ class LockSettingsStorage {
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
mCache.putFile(name, null);
|
||||
dispatchChange(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -675,6 +681,7 @@ class LockSettingsStorage {
|
||||
}
|
||||
persistentDataBlock.setFrpCredentialHandle(PersistentData.toBytes(
|
||||
persistentType, userId, qualityForUi, payload));
|
||||
dispatchChange(this);
|
||||
}
|
||||
|
||||
public PersistentData readPersistentDataBlock() {
|
||||
|
||||
@@ -34,6 +34,7 @@ import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.app.PropertyInvalidatedCache;
|
||||
import android.os.RemoteException;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.service.gatekeeper.GateKeeperResponse;
|
||||
@@ -47,6 +48,7 @@ import com.android.internal.widget.VerifyCredentialResponse;
|
||||
import com.android.server.locksettings.FakeGateKeeperService.VerifyHandle;
|
||||
import com.android.server.locksettings.LockSettingsStorage.CredentialHash;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@@ -57,6 +59,11 @@ import org.junit.runner.RunWith;
|
||||
@Presubmit
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
|
||||
@Before
|
||||
public void disableProcessCaches() {
|
||||
PropertyInvalidatedCache.disableForTestMode();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreatePasswordPrimaryUser() throws RemoteException {
|
||||
testCreateCredential(PRIMARY_USER_ID, newPassword("password"));
|
||||
|
||||
@@ -24,6 +24,7 @@ import static com.android.internal.widget.LockPatternUtils.USER_FRP;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import android.app.PropertyInvalidatedCache;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
@@ -46,6 +47,11 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
|
||||
mSettings.setDeviceProvisioned(false);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void disableProcessCaches() {
|
||||
PropertyInvalidatedCache.disableForTestMode();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFrpCredential_setPin() {
|
||||
mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID);
|
||||
|
||||
@@ -36,6 +36,7 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.admin.PasswordMetrics;
|
||||
import android.app.PropertyInvalidatedCache;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
@@ -49,6 +50,7 @@ import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationRe
|
||||
import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationToken;
|
||||
import com.android.server.locksettings.SyntheticPasswordManager.PasswordData;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
@@ -68,6 +70,11 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
|
||||
public static final byte[] PAYLOAD = new byte[] {1, 2, -1, -2, 55};
|
||||
public static final byte[] PAYLOAD2 = new byte[] {2, 3, -2, -3, 44, 1};
|
||||
|
||||
@Before
|
||||
public void disableProcessCaches() {
|
||||
PropertyInvalidatedCache.disableForTestMode();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPasswordBasedSyntheticPassword() throws RemoteException {
|
||||
final int USER_ID = 10;
|
||||
|
||||
Reference in New Issue
Block a user