diff options
| author | 2021-01-14 16:59:57 -0800 | |
|---|---|---|
| committer | 2021-01-15 11:24:13 -0800 | |
| commit | 6034d30ea27d4c40bda32a20642dc936f897514a (patch) | |
| tree | 58e32a5196d8bdf3e298a3aad51f6de4fc586254 | |
| parent | b9bb08eb83ea577c23fb9a53511d49e162fed42e (diff) | |
8/n: Schedule invalidation request
This should happen 1) Upon successful enrollment, and 2) After
session creation, if the framework detects a previous invalidation
has not completed for some reason.
Note that invalidation only needs to be requested if the (sensor, user)
pair has enrollments.
Also fixes the case where no sensors require invalidation.
Test: atest com.android.server.biometrics
Test: atest CtsBiometricsTestCases, existing tests pass. Additional
tests will be added in a subsequent CL.
Bug: 159667191
Change-Id: Id14391370904df004380428f1a064224489e2898
9 files changed, 87 insertions, 19 deletions
diff --git a/services/core/java/com/android/server/biometrics/AuthSession.java b/services/core/java/com/android/server/biometrics/AuthSession.java index e4d90525fc68..52152ab78992 100644 --- a/services/core/java/com/android/server/biometrics/AuthSession.java +++ b/services/core/java/com/android/server/biometrics/AuthSession.java @@ -805,7 +805,7 @@ public final class AuthSession implements IBinder.DeathRecipient { @Override public String toString() { return "State: " + mState - + "\nisCrypto: " + isCrypto() - + "\nPreAuthInfo: " + mPreAuthInfo; + + ", isCrypto: " + isCrypto() + + ", PreAuthInfo: " + mPreAuthInfo; } } diff --git a/services/core/java/com/android/server/biometrics/BiometricSensor.java b/services/core/java/com/android/server/biometrics/BiometricSensor.java index 17ec11233c4e..85de81bb3491 100644 --- a/services/core/java/com/android/server/biometrics/BiometricSensor.java +++ b/services/core/java/com/android/server/biometrics/BiometricSensor.java @@ -169,12 +169,11 @@ public abstract class BiometricSensor { @Override public String toString() { return "ID(" + id + ")" - + "\n oemStrength: " + oemStrength - + "\n updatedStrength: " + mUpdatedStrength - + "\n modality " + modality - + "\n state: " + mSensorState - + "\n cookie: " + mCookie - + "\n authenticator: " + impl - + "\n"; + + ", oemStrength: " + oemStrength + + ", updatedStrength: " + mUpdatedStrength + + ", modality " + modality + + ", state: " + mSensorState + + ", cookie: " + mCookie + + ", authenticator: " + impl; } } diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index fd5ada0ff9be..3387049d69f3 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -252,12 +252,14 @@ public class BiometricService extends SystemService { @NonNull private final IInvalidationCallback mClientCallback; @NonNull private final Set<Integer> mSensorsPendingInvalidation; - public static InvalidationTracker start(@NonNull ArrayList<BiometricSensor> sensors, + public static InvalidationTracker start(@NonNull Context context, + @NonNull ArrayList<BiometricSensor> sensors, int userId, int fromSensorId, @NonNull IInvalidationCallback clientCallback) { - return new InvalidationTracker(sensors, userId, fromSensorId, clientCallback); + return new InvalidationTracker(context, sensors, userId, fromSensorId, clientCallback); } - private InvalidationTracker(@NonNull ArrayList<BiometricSensor> sensors, int userId, + private InvalidationTracker(@NonNull Context context, + @NonNull ArrayList<BiometricSensor> sensors, int userId, int fromSensorId, @NonNull IInvalidationCallback clientCallback) { mClientCallback = clientCallback; mSensorsPendingInvalidation = new ArraySet<>(); @@ -271,6 +273,14 @@ public class BiometricService extends SystemService { continue; } + try { + if (!sensor.impl.hasEnrolledTemplates(userId, context.getOpPackageName())) { + continue; + } + } catch (RemoteException e) { + Slog.e(TAG, "Remote Exception", e); + } + Slog.d(TAG, "Requesting authenticatorId invalidation for sensor: " + sensor.id); synchronized (this) { @@ -288,6 +298,17 @@ public class BiometricService extends SystemService { Slog.d(TAG, "RemoteException", e); } } + + synchronized (this) { + if (mSensorsPendingInvalidation.isEmpty()) { + try { + Slog.d(TAG, "No sensors require invalidation"); + mClientCallback.onCompleted(); + } catch (RemoteException e) { + Slog.e(TAG, "Remote Exception", e); + } + } + } } @VisibleForTesting @@ -742,7 +763,7 @@ public class BiometricService extends SystemService { IInvalidationCallback callback) { checkInternalPermission(); - InvalidationTracker.start(mSensors, userId, fromSensorId, callback); + InvalidationTracker.start(getContext(), mSensors, userId, fromSensorId, callback); } @Override // Binder call diff --git a/services/core/java/com/android/server/biometrics/sensors/InvalidationRequesterClient.java b/services/core/java/com/android/server/biometrics/sensors/InvalidationRequesterClient.java index 3c8caf7b4a7f..c97003b875ed 100644 --- a/services/core/java/com/android/server/biometrics/sensors/InvalidationRequesterClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/InvalidationRequesterClient.java @@ -55,7 +55,7 @@ import android.hardware.biometrics.IInvalidationCallback; * switches, the framework can check if any sensor has the "invalidationInProgress" flag set. If so, * the framework should re-start the invalidation process described above. */ -public abstract class InvalidationRequesterClient<S extends BiometricAuthenticator.Identifier> +public class InvalidationRequesterClient<S extends BiometricAuthenticator.Identifier> extends BaseClientMonitor { private final BiometricManager mBiometricManager; diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java index eac2f0dc1641..810489b1c740 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java @@ -47,6 +47,7 @@ import com.android.server.biometrics.sensors.AuthenticationClient; import com.android.server.biometrics.sensors.BaseClientMonitor; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.HalClientMonitor; +import com.android.server.biometrics.sensors.InvalidationRequesterClient; import com.android.server.biometrics.sensors.LockoutResetDispatcher; import com.android.server.biometrics.sensors.PerformanceTracker; import com.android.server.biometrics.sensors.face.FaceUtils; @@ -206,6 +207,12 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { // this method "withoutHandler" means it should only ever be invoked from the worker thread, // so callers will never be blocked. mSensors.get(sensorId).createNewSession(daemon, sensorId, userId); + + if (FaceUtils.getInstance(sensorId).isInvalidationInProgress(mContext, userId)) { + Slog.w(getTag(), "Scheduling unfinished invalidation request for sensor: " + sensorId + + ", user: " + userId); + scheduleInvalidationRequest(sensorId, userId); + } } @@ -242,6 +249,15 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { }); } + private void scheduleInvalidationRequest(int sensorId, int userId) { + mHandler.post(() -> { + final InvalidationRequesterClient<Face> client = + new InvalidationRequesterClient<>(mContext, userId, sensorId, + FaceUtils.getInstance(sensorId)); + mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client); + }); + } + @Override public boolean containsSensor(int sensorId) { return mSensors.contains(sensorId); @@ -395,6 +411,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { boolean success) { if (success) { scheduleLoadAuthenticatorIdsForUser(sensorId, userId); + scheduleInvalidationRequest(sensorId, userId); } } }); diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java index fbc26c6498b3..50483d93f92b 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java @@ -24,12 +24,13 @@ import android.hardware.common.NativeHandle; import android.hardware.keymaster.HardwareAuthToken; import android.os.Binder; import android.os.IBinder; +import android.util.Slog; /** * Test session that provides mostly no-ops. */ public class TestSession extends ISession.Stub { - private static final String TAG = "TestSession"; + private static final String TAG = "FaceTestSession"; @NonNull private final Sensor.HalSessionCallback mHalSessionCallback; @@ -86,12 +87,16 @@ public class TestSession extends ISession.Stub { @Override public void getAuthenticatorId(int cookie) { + Slog.d(TAG, "getAuthenticatorId"); + // Immediately return a value so the framework can continue with subsequent requests. mHalSessionCallback.onAuthenticatorIdRetrieved(0); } @Override public void invalidateAuthenticatorId(int cookie) { - + Slog.d(TAG, "invalidateAuthenticatorId"); + // Immediately return a value so the framework can continue with subsequent requests. + mHalSessionCallback.onAuthenticatorIdInvalidated(0); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java index f1dfb52b6930..8a666f9acb7f 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java @@ -47,6 +47,7 @@ import com.android.server.biometrics.sensors.AuthenticationClient; import com.android.server.biometrics.sensors.BaseClientMonitor; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.HalClientMonitor; +import com.android.server.biometrics.sensors.InvalidationRequesterClient; import com.android.server.biometrics.sensors.LockoutResetDispatcher; import com.android.server.biometrics.sensors.PerformanceTracker; import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils; @@ -212,6 +213,12 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi // this method "withoutHandler" means it should only ever be invoked from the worker thread, // so callers will never be blocked. mSensors.get(sensorId).createNewSession(daemon, sensorId, userId); + + if (FingerprintUtils.getInstance(sensorId).isInvalidationInProgress(mContext, userId)) { + Slog.w(getTag(), "Scheduling unfinished invalidation request for sensor: " + sensorId + + ", user: " + userId); + scheduleInvalidationRequest(sensorId, userId); + } } @Override @@ -268,6 +275,15 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi }); } + private void scheduleInvalidationRequest(int sensorId, int userId) { + mHandler.post(() -> { + final InvalidationRequesterClient<Fingerprint> client = + new InvalidationRequesterClient<>(mContext, userId, sensorId, + FingerprintUtils.getInstance(sensorId)); + mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client); + }); + } + @Override public void scheduleResetLockout(int sensorId, int userId, @Nullable byte[] hardwareAuthToken) { mHandler.post(() -> { @@ -378,6 +394,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi boolean success) { if (success) { scheduleLoadAuthenticatorIdsForUser(sensorId, userId); + scheduleInvalidationRequest(sensorId, userId); } } }); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestSession.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestSession.java index ddae1107ff77..ac4f6651613d 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestSession.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestSession.java @@ -30,7 +30,7 @@ import android.util.Slog; */ class TestSession extends ISession.Stub { - private static final String TAG = "TestSession"; + private static final String TAG = "FingerprintTestSession"; @NonNull private final Sensor.HalSessionCallback mHalSessionCallback; @@ -92,7 +92,9 @@ class TestSession extends ISession.Stub { @Override public void invalidateAuthenticatorId(int cookie) { - + Slog.d(TAG, "invalidateAuthenticatorId"); + // Immediately return a value so the framework can continue with subsequent requests. + mHalSessionCallback.onAuthenticatorIdInvalidated(0); } @Override diff --git a/services/tests/servicestests/src/com/android/server/biometrics/InvalidationTrackerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/InvalidationTrackerTest.java index 340a1d9bdda0..bb2b1c2fb0db 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/InvalidationTrackerTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/InvalidationTrackerTest.java @@ -22,7 +22,9 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import android.content.Context; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricManager.Authenticators; import android.hardware.biometrics.IBiometricAuthenticator; @@ -44,21 +46,25 @@ public class InvalidationTrackerTest { @Test public void testCallbackReceived_whenAllStrongSensorsInvalidated() throws Exception { final IBiometricAuthenticator authenticator1 = mock(IBiometricAuthenticator.class); + when(authenticator1.hasEnrolledTemplates(anyInt(), any())).thenReturn(true); final TestSensor sensor1 = new TestSensor(0 /* id */, BiometricAuthenticator.TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG, authenticator1); final IBiometricAuthenticator authenticator2 = mock(IBiometricAuthenticator.class); + when(authenticator2.hasEnrolledTemplates(anyInt(), any())).thenReturn(true); final TestSensor sensor2 = new TestSensor(1 /* id */, BiometricAuthenticator.TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG, authenticator2); final IBiometricAuthenticator authenticator3 = mock(IBiometricAuthenticator.class); + when(authenticator3.hasEnrolledTemplates(anyInt(), any())).thenReturn(true); final TestSensor sensor3 = new TestSensor(2 /* id */, BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG, authenticator3); final IBiometricAuthenticator authenticator4 = mock(IBiometricAuthenticator.class); + when(authenticator4.hasEnrolledTemplates(anyInt(), any())).thenReturn(true); final TestSensor sensor4 = new TestSensor(3 /* id */, BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_WEAK, authenticator4); @@ -71,7 +77,8 @@ public class InvalidationTrackerTest { final IInvalidationCallback callback = mock(IInvalidationCallback.class); final InvalidationTracker tracker = - InvalidationTracker.start(sensors, 0 /* userId */, 0 /* fromSensorId */, callback); + InvalidationTracker.start(mock(Context.class), sensors, 0 /* userId */, + 0 /* fromSensorId */, callback); // The sensor which the request originated from should not be requested to invalidate // its authenticatorId. |