Remove InternalCleanupClient enrolled list cache

(mEnrolledList), retrieve the enrolled list from framework
when the client starts.

Bug: 268695802
Test: atest com.android.server.biometrics
      atest CtsBiometricsTestCases
      atest CtsBiometricsHostTestCases
Change-Id: Iab3663d0dde2f9a96cdcf5aced629451e874b674
This commit is contained in:
Jeff Pu
2023-02-10 20:58:12 +00:00
parent bdad038351
commit 86a2d7f476
11 changed files with 165 additions and 24 deletions

View File

@@ -64,7 +64,6 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide
private final ArrayList<UserTemplate> mUnknownHALTemplates = new ArrayList<>();
private final BiometricUtils<S> mBiometricUtils;
private final Map<Integer, Long> mAuthenticatorIds;
private final List<S> mEnrolledList;
private final boolean mHasEnrollmentsBeforeStarting;
private BaseClientMonitor mCurrentTask;
private boolean mFavorHalEnrollments = false;
@@ -135,13 +134,12 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide
protected InternalCleanupClient(@NonNull Context context, @NonNull Supplier<T> lazyDaemon,
int userId, @NonNull String owner, int sensorId,
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
@NonNull List<S> enrolledList, @NonNull BiometricUtils<S> utils,
@NonNull BiometricUtils<S> utils,
@NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, null /* token */, null /* ClientMonitorCallbackConverter */,
userId, owner, 0 /* cookie */, sensorId, logger, biometricContext);
mBiometricUtils = utils;
mAuthenticatorIds = authenticatorIds;
mEnrolledList = enrolledList;
mHasEnrollmentsBeforeStarting = !utils.getBiometricsForUser(context, userId).isEmpty();
}
@@ -169,12 +167,16 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide
public void start(@NonNull ClientMonitorCallback callback) {
super.start(callback);
final List<S> enrolledList =
mBiometricUtils.getBiometricsForUser(getContext(), getTargetUserId());
// Start enumeration. Removal will start if necessary, when enumeration is completed.
mCurrentTask = getEnumerateClient(getContext(), mLazyDaemon, getToken(), getTargetUserId(),
getOwnerString(), mEnrolledList, mBiometricUtils, getSensorId(), getLogger(),
getOwnerString(), enrolledList, mBiometricUtils, getSensorId(), getLogger(),
getBiometricContext());
Slog.d(TAG, "Starting enumerate: " + mCurrentTask);
Slog.d(TAG, "Starting enumerate: " + mCurrentTask + " enrolledList size:"
+ enrolledList.size());
mCurrentTask.start(mEnumerateCallback);
}

View File

@@ -43,10 +43,10 @@ class FaceInternalCleanupClient extends InternalCleanupClient<Face, AidlSession>
FaceInternalCleanupClient(@NonNull Context context,
@NonNull Supplier<AidlSession> lazyDaemon, int userId, @NonNull String owner,
int sensorId, @NonNull BiometricLogger logger,
@NonNull BiometricContext biometricContext, @NonNull List<Face> enrolledList,
@NonNull BiometricContext biometricContext,
@NonNull BiometricUtils<Face> utils, @NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, userId, owner, sensorId, logger, biometricContext,
enrolledList, utils, authenticatorIds);
utils, authenticatorIds);
}
@Override

View File

@@ -595,14 +595,13 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
public void scheduleInternalCleanup(int sensorId, int userId,
@Nullable ClientMonitorCallback callback, boolean favorHalEnrollments) {
mHandler.post(() -> {
final List<Face> enrolledList = getEnrolledFaces(sensorId, userId);
final FaceInternalCleanupClient client =
new FaceInternalCleanupClient(mContext,
mSensors.get(sensorId).getLazySession(), userId,
mContext.getOpPackageName(), sensorId,
createLogger(BiometricsProtoEnums.ACTION_ENUMERATE,
BiometricsProtoEnums.CLIENT_UNKNOWN),
mBiometricContext, enrolledList,
mBiometricContext,
FaceUtils.getInstance(sensorId),
mSensors.get(sensorId).getAuthenticatorIds());
if (favorHalEnrollments) {

View File

@@ -818,12 +818,11 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
mHandler.post(() -> {
scheduleUpdateActiveUserWithoutHandler(userId);
final List<Face> enrolledList = getEnrolledFaces(mSensorId, userId);
final FaceInternalCleanupClient client = new FaceInternalCleanupClient(mContext,
mLazyDaemon, userId, mContext.getOpPackageName(), mSensorId,
createLogger(BiometricsProtoEnums.ACTION_ENUMERATE,
BiometricsProtoEnums.CLIENT_UNKNOWN),
mBiometricContext, enrolledList,
mBiometricContext,
FaceUtils.getLegacyInstance(mSensorId), mAuthenticatorIds);
mScheduler.scheduleClientMonitor(client, new ClientMonitorCompositeCallback(callback,
mBiometricStateCallback));

View File

@@ -42,10 +42,10 @@ class FaceInternalCleanupClient extends InternalCleanupClient<Face, IBiometricsF
FaceInternalCleanupClient(@NonNull Context context,
@NonNull Supplier<IBiometricsFace> lazyDaemon, int userId, @NonNull String owner,
int sensorId, @NonNull BiometricLogger logger,
@NonNull BiometricContext biometricContext, @NonNull List<Face> enrolledList,
@NonNull BiometricContext biometricContext,
@NonNull BiometricUtils<Face> utils, @NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, userId, owner, sensorId, logger, biometricContext,
enrolledList, utils, authenticatorIds);
utils, authenticatorIds);
}
@Override

View File

@@ -45,10 +45,9 @@ class FingerprintInternalCleanupClient extends InternalCleanupClient<Fingerprint
@NonNull Supplier<AidlSession> lazyDaemon,
int userId, @NonNull String owner, int sensorId,
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
@NonNull List<Fingerprint> enrolledList,
@NonNull FingerprintUtils utils, @NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, userId, owner, sensorId, logger, biometricContext,
enrolledList, utils, authenticatorIds);
utils, authenticatorIds);
}
@Override

View File

@@ -556,7 +556,6 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
public void scheduleInternalCleanup(int sensorId, int userId,
@Nullable ClientMonitorCallback callback, boolean favorHalEnrollments) {
mHandler.post(() -> {
final List<Fingerprint> enrolledList = getEnrolledFingerprints(sensorId, userId);
final FingerprintInternalCleanupClient client =
new FingerprintInternalCleanupClient(mContext,
mSensors.get(sensorId).getLazySession(), userId,
@@ -564,7 +563,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
createLogger(BiometricsProtoEnums.ACTION_ENUMERATE,
BiometricsProtoEnums.CLIENT_UNKNOWN),
mBiometricContext,
enrolledList, FingerprintUtils.getInstance(sensorId),
FingerprintUtils.getInstance(sensorId),
mSensors.get(sensorId).getAuthenticatorIds());
if (favorHalEnrollments) {
client.setFavorHalEnrollments();

View File

@@ -741,14 +741,12 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
mHandler.post(() -> {
scheduleUpdateActiveUserWithoutHandler(userId);
final List<Fingerprint> enrolledList = getEnrolledFingerprints(
mSensorProperties.sensorId, userId);
final FingerprintInternalCleanupClient client = new FingerprintInternalCleanupClient(
mContext, mLazyDaemon, userId, mContext.getOpPackageName(),
mSensorProperties.sensorId,
createLogger(BiometricsProtoEnums.ACTION_ENUMERATE,
BiometricsProtoEnums.CLIENT_UNKNOWN),
mBiometricContext, enrolledList,
mBiometricContext,
FingerprintUtils.getLegacyInstance(mSensorId), mAuthenticatorIds);
mScheduler.scheduleClientMonitor(client, callback);
});

View File

@@ -45,11 +45,10 @@ class FingerprintInternalCleanupClient
@NonNull Supplier<IBiometricsFingerprint> lazyDaemon, int userId,
@NonNull String owner, int sensorId,
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
@NonNull List<Fingerprint> enrolledList,
@NonNull BiometricUtils<Fingerprint> utils,
@NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, userId, owner, sensorId, logger, biometricContext,
enrolledList, utils, authenticatorIds);
utils, authenticatorIds);
}
@Override

View File

@@ -39,7 +39,9 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.IBiometricService;
import android.hardware.fingerprint.Fingerprint;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -48,6 +50,7 @@ import android.platform.test.annotations.Presubmit;
import android.testing.AndroidTestingRunner;
import android.testing.TestableContext;
import android.testing.TestableLooper;
import android.util.Slog;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -58,6 +61,8 @@ import com.android.server.biometrics.log.BiometricContext;
import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.nano.BiometricSchedulerProto;
import com.android.server.biometrics.nano.BiometricsProto;
import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
import com.android.server.biometrics.sensors.fingerprint.aidl.AidlSession;
import org.junit.Before;
import org.junit.Rule;
@@ -67,6 +72,9 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
@Presubmit
@@ -78,6 +86,9 @@ public class BiometricSchedulerTest {
private static final String TAG = "BiometricSchedulerTest";
private static final int TEST_SENSOR_ID = 1;
private static final int LOG_NUM_RECENT_OPERATIONS = 2;
private static final Fingerprint TEST_FINGERPRINT = new Fingerprint("" /* name */,
1 /* fingerId */, TEST_SENSOR_ID);
@Rule
public final TestableContext mContext = new TestableContext(
InstrumentationRegistry.getContext(), null);
@@ -673,6 +684,56 @@ public class BiometricSchedulerTest {
}
@Test
public void testTwoInternalCleanupOps_withFirstFavorHalEnrollment() throws Exception {
final String owner = "test.owner";
final int userId = 1;
final Supplier<Object> daemon = () -> mock(AidlSession.class);
final FingerprintUtils utils = mock(FingerprintUtils.class);
final Map<Integer, Long> authenticatorIds = new HashMap<>();
final ClientMonitorCallback callback0 = mock(ClientMonitorCallback.class);
final ClientMonitorCallback callback1 = mock(ClientMonitorCallback.class);
final ClientMonitorCallback callback2 = mock(ClientMonitorCallback.class);
final TestInternalCleanupClient client1 = new
TestInternalCleanupClient(mContext, daemon, userId,
owner, TEST_SENSOR_ID, mock(BiometricLogger.class),
mBiometricContext, utils, authenticatorIds);
final TestInternalCleanupClient client2 = new
TestInternalCleanupClient(mContext, daemon, userId,
owner, TEST_SENSOR_ID, mock(BiometricLogger.class),
mBiometricContext, utils, authenticatorIds);
//add initial start client to scheduler, so later clients will be on pending operation queue
final TestHalClientMonitor startClient = new TestHalClientMonitor(mContext, mToken,
daemon);
mScheduler.scheduleClientMonitor(startClient, callback0);
//add first cleanup client which favors enrollments from HAL
client1.setFavorHalEnrollments();
mScheduler.scheduleClientMonitor(client1, callback1);
assertEquals(1, mScheduler.mPendingOperations.size());
when(utils.getBiometricsForUser(mContext, userId)).thenAnswer(i ->
new ArrayList<>(client1.getFingerprints()));
//add second cleanup client
mScheduler.scheduleClientMonitor(client2, callback2);
//finish the start client, so other pending clients are processed
startClient.getCallback().onClientFinished(startClient, true);
waitForIdle();
assertTrue(client1.isAlreadyDone());
assertTrue(client2.isAlreadyDone());
assertNull(mScheduler.mCurrentOperation);
verify(utils, never()).removeBiometricForUser(mContext, userId,
TEST_FINGERPRINT.getBiometricId());
assertEquals(1, client1.getFingerprints().size());
}
private BiometricSchedulerProto getDump(boolean clearSchedulerBuffer) throws Exception {
return BiometricSchedulerProto.parseFrom(mScheduler.dumpProtoState(clearSchedulerBuffer));
}
@@ -835,4 +896,90 @@ public class BiometricSchedulerTest {
mDestroyed = true;
}
}
private static class TestInternalEnumerateClient extends InternalEnumerateClient<Object> {
private static final String TAG = "TestInternalEnumerateClient";
protected TestInternalEnumerateClient(@NonNull Context context,
@NonNull Supplier<Object> lazyDaemon, @NonNull IBinder token, int userId,
@NonNull String owner, @NonNull List<Fingerprint> enrolledList,
@NonNull BiometricUtils<Fingerprint> utils, int sensorId,
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
super(context, lazyDaemon, token, userId, owner, enrolledList, utils, sensorId,
logger, biometricContext);
}
@Override
protected void startHalOperation() {
Slog.d(TAG, "TestInternalEnumerateClient#startHalOperation");
onEnumerationResult(TEST_FINGERPRINT, 0 /* remaining */);
}
}
private static class TestRemovalClient extends RemovalClient<Fingerprint, Object> {
private static final String TAG = "TestRemovalClient";
TestRemovalClient(@NonNull Context context,
@NonNull Supplier<Object> lazyDaemon, @NonNull IBinder token,
@Nullable ClientMonitorCallbackConverter listener, int[] biometricIds, int userId,
@NonNull String owner, @NonNull BiometricUtils<Fingerprint> utils, int sensorId,
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
@NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, token, listener, userId, owner, utils, sensorId,
logger, biometricContext, authenticatorIds);
}
@Override
protected void startHalOperation() {
Slog.d(TAG, "Removing template from hw");
onRemoved(TEST_FINGERPRINT, 0);
}
}
private static class TestInternalCleanupClient extends
InternalCleanupClient<Fingerprint, Object> {
private List<Fingerprint> mFingerprints = new ArrayList<>();
TestInternalCleanupClient(@NonNull Context context,
@NonNull Supplier<Object> lazyDaemon,
int userId, @NonNull String owner, int sensorId,
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
@NonNull FingerprintUtils utils, @NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, userId, owner, sensorId, logger, biometricContext,
utils, authenticatorIds);
}
@Override
protected InternalEnumerateClient<Object> getEnumerateClient(Context context,
Supplier<Object> lazyDaemon, IBinder token, int userId, String owner,
List<Fingerprint> enrolledList, BiometricUtils<Fingerprint> utils, int sensorId,
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
return new TestInternalEnumerateClient(context, lazyDaemon, token, userId, owner,
enrolledList, utils, sensorId,
logger.swapAction(context, BiometricsProtoEnums.ACTION_ENUMERATE),
biometricContext);
}
@Override
protected RemovalClient<Fingerprint, Object> getRemovalClient(Context context,
Supplier<Object> lazyDaemon, IBinder token, int biometricId, int userId,
String owner, BiometricUtils<Fingerprint> utils, int sensorId,
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
Map<Integer, Long> authenticatorIds) {
return new TestRemovalClient(context, lazyDaemon, token, null,
new int[]{biometricId}, userId, owner, utils, sensorId, logger,
biometricContext, authenticatorIds);
}
@Override
protected void onAddUnknownTemplate(int userId,
@NonNull BiometricAuthenticator.Identifier identifier) {
mFingerprints.add((Fingerprint) identifier);
}
public List<Fingerprint> getFingerprints() {
return mFingerprints;
}
}
}

View File

@@ -164,10 +164,9 @@ public class FingerprintInternalCleanupClientTest {
}
protected FingerprintInternalCleanupClient createClient() {
final List<Fingerprint> enrollments = new ArrayList<>();
final Map<Integer, Long> authenticatorIds = new HashMap<>();
return new FingerprintInternalCleanupClient(mContext, () -> mAidlSession, 2 /* userId */,
"the.test.owner", SENSOR_ID, mLogger, mBiometricContext, enrollments,
"the.test.owner", SENSOR_ID, mLogger, mBiometricContext,
mFingerprintUtils, authenticatorIds) {
@Override
protected void onAddUnknownTemplate(int userId,