Merge "3/n: Add most remaining plumbing for authenticatorId invalidation"
This commit is contained in:
@@ -357,6 +357,27 @@ public class BiometricManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests all {@link Authenticators.Types#BIOMETRIC_STRONG} sensors to have their
|
||||
* authenticatorId invalidated for the specified user. This happens when enrollments have been
|
||||
* added on devices with multiple biometric sensors.
|
||||
*
|
||||
* @param userId userId that the authenticatorId should be invalidated for
|
||||
* @param fromSensorId sensor that triggered the invalidation request
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
|
||||
public void invalidateAuthenticatorIds(int userId, int fromSensorId,
|
||||
@NonNull IInvalidationCallback callback) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
mService.invalidateAuthenticatorIds(userId, fromSensorId, callback);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of AuthenticatorIDs for biometric authenticators which have 1) enrolled templates,
|
||||
* and 2) meet the requirements for integrating with Keystore. The AuthenticatorIDs are known
|
||||
|
||||
@@ -18,6 +18,7 @@ package android.hardware.biometrics;
|
||||
|
||||
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
|
||||
import android.hardware.biometrics.IBiometricServiceReceiver;
|
||||
import android.hardware.biometrics.IInvalidationCallback;
|
||||
import android.hardware.biometrics.ITestSession;
|
||||
import android.hardware.biometrics.PromptInfo;
|
||||
import android.hardware.biometrics.SensorPropertiesInternal;
|
||||
@@ -57,6 +58,11 @@ interface IAuthService {
|
||||
// Register callback for when keyguard biometric eligibility changes.
|
||||
void registerEnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback);
|
||||
|
||||
// Requests all BIOMETRIC_STRONG sensors to have their authenticatorId invalidated for the
|
||||
// specified user. This happens when enrollments have been added on devices with multiple
|
||||
// biometric sensors.
|
||||
void invalidateAuthenticatorIds(int userId, int fromSensorId, IInvalidationCallback callback);
|
||||
|
||||
// Get a list of AuthenticatorIDs for authenticators which have enrolled templates and meet
|
||||
// the requirements for integrating with Keystore. The AuthenticatorID are known in Keystore
|
||||
// land as SIDs, and are used during key generation.
|
||||
|
||||
@@ -18,6 +18,7 @@ package android.hardware.biometrics;
|
||||
|
||||
import android.hardware.biometrics.IBiometricSensorReceiver;
|
||||
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
|
||||
import android.hardware.biometrics.IInvalidationCallback;
|
||||
import android.hardware.biometrics.ITestSession;
|
||||
import android.hardware.biometrics.SensorPropertiesInternal;
|
||||
import android.hardware.face.IFaceServiceReceiver;
|
||||
@@ -63,6 +64,9 @@ interface IBiometricAuthenticator {
|
||||
// Return the LockoutTracker status for the specified user
|
||||
int getLockoutModeForUser(int userId);
|
||||
|
||||
// Request the authenticatorId to be invalidated for the specified user
|
||||
void invalidateAuthenticatorId(int userId, IInvalidationCallback callback);
|
||||
|
||||
// Gets the authenticator ID representing the current set of enrolled templates
|
||||
long getAuthenticatorId(int callingUserId);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package android.hardware.biometrics;
|
||||
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
|
||||
import android.hardware.biometrics.IBiometricServiceReceiver;
|
||||
import android.hardware.biometrics.IBiometricAuthenticator;
|
||||
import android.hardware.biometrics.IInvalidationCallback;
|
||||
import android.hardware.biometrics.ITestSession;
|
||||
import android.hardware.biometrics.PromptInfo;
|
||||
import android.hardware.biometrics.SensorPropertiesInternal;
|
||||
@@ -62,6 +63,11 @@ interface IBiometricService {
|
||||
// Client lifecycle is still managed in <Biometric>Service.
|
||||
void onReadyForAuthentication(int cookie);
|
||||
|
||||
// Requests all BIOMETRIC_STRONG sensors to have their authenticatorId invalidated for the
|
||||
// specified user. This happens when enrollments have been added on devices with multiple
|
||||
// biometric sensors.
|
||||
void invalidateAuthenticatorIds(int userId, int fromSensorId, IInvalidationCallback callback);
|
||||
|
||||
// Get a list of AuthenticatorIDs for authenticators which have enrolled templates and meet
|
||||
// the requirements for integrating with Keystore. The AuthenticatorID are known in Keystore
|
||||
// land as SIDs, and are used during key generation.
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.hardware.biometrics;
|
||||
|
||||
/**
|
||||
* Notifies the caller for BiometricManager#invalidateAuthenticatorIds status updates. See
|
||||
* InvalidationRequesterClient for more info.
|
||||
* @hide
|
||||
*/
|
||||
interface IInvalidationCallback {
|
||||
// Notifies the caller when all authenticatorId(s) have been invalidated.
|
||||
void onCompleted();
|
||||
}
|
||||
@@ -17,6 +17,7 @@ package android.hardware.face;
|
||||
|
||||
import android.hardware.biometrics.IBiometricSensorReceiver;
|
||||
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
|
||||
import android.hardware.biometrics.IInvalidationCallback;
|
||||
import android.hardware.biometrics.ITestSession;
|
||||
import android.hardware.face.IFaceServiceReceiver;
|
||||
import android.hardware.face.Face;
|
||||
@@ -104,6 +105,9 @@ interface IFaceService {
|
||||
// Return the LockoutTracker status for the specified user
|
||||
int getLockoutModeForUser(int sensorId, int userId);
|
||||
|
||||
// Requests for the specified sensor+userId's authenticatorId to be invalidated
|
||||
void invalidateAuthenticatorId(int sensorId, int userId, IInvalidationCallback callback);
|
||||
|
||||
// Gets the authenticator ID for face
|
||||
long getAuthenticatorId(int sensorId, int callingUserId);
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ package android.hardware.fingerprint;
|
||||
|
||||
import android.hardware.biometrics.IBiometricSensorReceiver;
|
||||
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
|
||||
import android.hardware.biometrics.IInvalidationCallback;
|
||||
import android.hardware.biometrics.ITestSession;
|
||||
import android.hardware.fingerprint.IFingerprintClientActiveCallback;
|
||||
import android.hardware.fingerprint.IFingerprintServiceReceiver;
|
||||
@@ -116,6 +117,9 @@ interface IFingerprintService {
|
||||
// Return the LockoutTracker status for the specified user
|
||||
int getLockoutModeForUser(int sensorId, int userId);
|
||||
|
||||
// Requests for the specified sensor+userId's authenticatorId to be invalidated
|
||||
void invalidateAuthenticatorId(int sensorId, int userId, IInvalidationCallback callback);
|
||||
|
||||
// Gets the authenticator ID for fingerprint
|
||||
long getAuthenticatorId(int sensorId, int callingUserId);
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ import android.hardware.biometrics.IBiometricAuthenticator;
|
||||
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
|
||||
import android.hardware.biometrics.IBiometricService;
|
||||
import android.hardware.biometrics.IBiometricServiceReceiver;
|
||||
import android.hardware.biometrics.IInvalidationCallback;
|
||||
import android.hardware.biometrics.ITestSession;
|
||||
import android.hardware.biometrics.PromptInfo;
|
||||
import android.hardware.biometrics.SensorPropertiesInternal;
|
||||
@@ -295,6 +296,19 @@ public class AuthService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateAuthenticatorIds(int userId, int fromSensorId,
|
||||
IInvalidationCallback callback) throws RemoteException {
|
||||
checkInternalPermission();
|
||||
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mBiometricService.invalidateAuthenticatorIds(userId, fromSensorId, callback);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] getAuthenticatorIds() throws RemoteException {
|
||||
// In this method, we're not checking whether the caller is permitted to use face
|
||||
|
||||
@@ -42,6 +42,7 @@ import android.hardware.biometrics.IBiometricSensorReceiver;
|
||||
import android.hardware.biometrics.IBiometricService;
|
||||
import android.hardware.biometrics.IBiometricServiceReceiver;
|
||||
import android.hardware.biometrics.IBiometricSysuiReceiver;
|
||||
import android.hardware.biometrics.IInvalidationCallback;
|
||||
import android.hardware.biometrics.ITestSession;
|
||||
import android.hardware.biometrics.PromptInfo;
|
||||
import android.hardware.biometrics.SensorPropertiesInternal;
|
||||
@@ -60,6 +61,7 @@ import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.security.KeyStore;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
@@ -78,6 +80,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* System service that arbitrates the modality for BiometricPrompt to use.
|
||||
@@ -240,6 +243,72 @@ public class BiometricService extends SystemService {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tracks authenticatorId invalidation. For more details, see
|
||||
* {@link com.android.server.biometrics.sensors.InvalidationRequesterClient}.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static class InvalidationTracker {
|
||||
@NonNull private final IInvalidationCallback mClientCallback;
|
||||
@NonNull private final Set<Integer> mSensorsPendingInvalidation;
|
||||
|
||||
public static InvalidationTracker start(@NonNull ArrayList<BiometricSensor> sensors,
|
||||
int userId, int fromSensorId, @NonNull IInvalidationCallback clientCallback) {
|
||||
return new InvalidationTracker(sensors, userId, fromSensorId, clientCallback);
|
||||
}
|
||||
|
||||
private InvalidationTracker(@NonNull ArrayList<BiometricSensor> sensors, int userId,
|
||||
int fromSensorId, @NonNull IInvalidationCallback clientCallback) {
|
||||
mClientCallback = clientCallback;
|
||||
mSensorsPendingInvalidation = new ArraySet<>();
|
||||
|
||||
for (BiometricSensor sensor : sensors) {
|
||||
if (sensor.id == fromSensorId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Utils.isAtLeastStrength(sensor.oemStrength, Authenticators.BIOMETRIC_STRONG)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Slog.d(TAG, "Requesting authenticatorId invalidation for sensor: " + sensor.id);
|
||||
|
||||
synchronized (this) {
|
||||
mSensorsPendingInvalidation.add(sensor.id);
|
||||
}
|
||||
|
||||
try {
|
||||
sensor.impl.invalidateAuthenticatorId(userId, new IInvalidationCallback.Stub() {
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
onInvalidated(sensor.id);
|
||||
}
|
||||
});
|
||||
} catch (RemoteException e) {
|
||||
Slog.d(TAG, "RemoteException", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void onInvalidated(int sensorId) {
|
||||
synchronized (this) {
|
||||
mSensorsPendingInvalidation.remove(sensorId);
|
||||
|
||||
Slog.d(TAG, "Sensor " + sensorId + " invalidated, remaining size: "
|
||||
+ mSensorsPendingInvalidation.size());
|
||||
|
||||
if (mSensorsPendingInvalidation.isEmpty()) {
|
||||
try {
|
||||
mClientCallback.onCompleted();
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote Exception", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public static class SettingObserver extends ContentObserver {
|
||||
|
||||
@@ -668,6 +737,14 @@ public class BiometricService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateAuthenticatorIds(int userId, int fromSensorId,
|
||||
IInvalidationCallback callback) {
|
||||
checkInternalPermission();
|
||||
|
||||
InvalidationTracker.start(mSensors, userId, fromSensorId, callback);
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public long[] getAuthenticatorIds(int callingUserId) {
|
||||
checkInternalPermission();
|
||||
|
||||
@@ -18,8 +18,10 @@ package com.android.server.biometrics.sensors;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.Context;
|
||||
import android.hardware.biometrics.BiometricAuthenticator;
|
||||
import android.hardware.biometrics.BiometricManager;
|
||||
import android.hardware.biometrics.BiometricsProtoEnums;
|
||||
import android.hardware.biometrics.IInvalidationCallback;
|
||||
|
||||
/**
|
||||
* ClientMonitor subclass responsible for coordination of authenticatorId invalidation of other
|
||||
@@ -53,25 +55,39 @@ import android.hardware.biometrics.BiometricsProtoEnums;
|
||||
* 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<T> extends ClientMonitor<T> {
|
||||
public abstract class InvalidationRequesterClient<S extends BiometricAuthenticator.Identifier, T>
|
||||
extends ClientMonitor<T> {
|
||||
|
||||
private final BiometricManager mBiometricManager;
|
||||
@NonNull private final BiometricUtils<S> mUtils;
|
||||
|
||||
@NonNull private final IInvalidationCallback mInvalidationCallback =
|
||||
new IInvalidationCallback.Stub() {
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
mUtils.setInvalidationInProgress(getContext(), getTargetUserId(),
|
||||
false /* inProgress */);
|
||||
mCallback.onClientFinished(InvalidationRequesterClient.this, true /* success */);
|
||||
}
|
||||
};
|
||||
|
||||
public InvalidationRequesterClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
|
||||
int userId, int sensorId) {
|
||||
int userId, int sensorId, @NonNull BiometricUtils<S> utils) {
|
||||
super(context, lazyDaemon, null /* token */, null /* listener */, userId,
|
||||
context.getOpPackageName(), 0 /* cookie */, sensorId,
|
||||
BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN,
|
||||
BiometricsProtoEnums.CLIENT_UNKNOWN);
|
||||
mBiometricManager = context.getSystemService(BiometricManager.class);
|
||||
mUtils = utils;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(@NonNull Callback callback) {
|
||||
super.start(callback);
|
||||
|
||||
// TODO(b/159667191): Request BiometricManager/BiometricService to invalidate
|
||||
// authenticatorIds. Be sure to invoke BiometricUtils#setInvalidationInProgress(true)
|
||||
mUtils.setInvalidationInProgress(getContext(), getTargetUserId(), true /* inProgress */);
|
||||
mBiometricManager.invalidateAuthenticatorIds(getTargetUserId(), getSensorId(),
|
||||
mInvalidationCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,13 +19,13 @@ package com.android.server.biometrics.sensors.face;
|
||||
import android.annotation.NonNull;
|
||||
import android.hardware.biometrics.IBiometricAuthenticator;
|
||||
import android.hardware.biometrics.IBiometricSensorReceiver;
|
||||
import android.hardware.biometrics.IInvalidationCallback;
|
||||
import android.hardware.biometrics.ITestSession;
|
||||
import android.hardware.biometrics.SensorPropertiesInternal;
|
||||
import android.hardware.face.IFaceService;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import com.android.server.biometrics.SensorConfig;
|
||||
import com.android.server.biometrics.sensors.LockoutTracker;
|
||||
|
||||
/**
|
||||
@@ -86,6 +86,12 @@ public final class FaceAuthenticator extends IBiometricAuthenticator.Stub {
|
||||
return mFaceService.hasEnrolledFaces(mSensorId, userId, opPackageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateAuthenticatorId(int userId, IInvalidationCallback callback)
|
||||
throws RemoteException {
|
||||
mFaceService.invalidateAuthenticatorId(mSensorId, userId, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @LockoutTracker.LockoutMode int getLockoutModeForUser(int userId)
|
||||
throws RemoteException {
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.hardware.biometrics.BiometricsProtoEnums;
|
||||
import android.hardware.biometrics.IBiometricSensorReceiver;
|
||||
import android.hardware.biometrics.IBiometricService;
|
||||
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
|
||||
import android.hardware.biometrics.IInvalidationCallback;
|
||||
import android.hardware.biometrics.ITestSession;
|
||||
import android.hardware.biometrics.face.IFace;
|
||||
import android.hardware.biometrics.face.SensorProps;
|
||||
@@ -54,10 +55,10 @@ import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.server.ServiceThread;
|
||||
import com.android.server.SystemService;
|
||||
import com.android.server.biometrics.Utils;
|
||||
import com.android.server.biometrics.sensors.BiometricServiceCallback;
|
||||
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
|
||||
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
|
||||
import com.android.server.biometrics.sensors.LockoutTracker;
|
||||
import com.android.server.biometrics.sensors.BiometricServiceCallback;
|
||||
import com.android.server.biometrics.sensors.face.aidl.FaceProvider;
|
||||
import com.android.server.biometrics.sensors.face.hidl.Face10;
|
||||
|
||||
@@ -503,6 +504,19 @@ public class FaceService extends SystemService implements BiometricServiceCallba
|
||||
return provider.getLockoutModeForUser(sensorId, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateAuthenticatorId(int sensorId, int userId,
|
||||
IInvalidationCallback callback) {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for invalidateAuthenticatorId");
|
||||
return;
|
||||
}
|
||||
provider.scheduleInvalidateAuthenticatorId(sensorId, userId, callback);
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public long getAuthenticatorId(int sensorId, int userId) {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.server.biometrics.sensors.face;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.hardware.biometrics.IInvalidationCallback;
|
||||
import android.hardware.biometrics.ITestSession;
|
||||
import android.hardware.face.Face;
|
||||
import android.hardware.face.FaceManager;
|
||||
@@ -71,6 +72,16 @@ public interface ServiceProvider {
|
||||
@LockoutTracker.LockoutMode
|
||||
int getLockoutModeForUser(int sensorId, int userId);
|
||||
|
||||
/**
|
||||
* Requests for the authenticatorId (whose source of truth is in the TEE or equivalent) to
|
||||
* be invalidated. See {@link com.android.server.biometrics.sensors.InvalidationRequesterClient}
|
||||
*/
|
||||
default void scheduleInvalidateAuthenticatorId(int sensorId, int userId,
|
||||
@NonNull IInvalidationCallback callback) {
|
||||
throw new IllegalStateException("Providers that support invalidation must override"
|
||||
+ " this method");
|
||||
}
|
||||
|
||||
long getAuthenticatorId(int sensorId, int userId);
|
||||
|
||||
boolean isHardwareDetected(int sensorId);
|
||||
|
||||
@@ -19,13 +19,13 @@ package com.android.server.biometrics.sensors.fingerprint;
|
||||
import android.annotation.NonNull;
|
||||
import android.hardware.biometrics.IBiometricAuthenticator;
|
||||
import android.hardware.biometrics.IBiometricSensorReceiver;
|
||||
import android.hardware.biometrics.IInvalidationCallback;
|
||||
import android.hardware.biometrics.ITestSession;
|
||||
import android.hardware.biometrics.SensorPropertiesInternal;
|
||||
import android.hardware.fingerprint.IFingerprintService;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import com.android.server.biometrics.SensorConfig;
|
||||
import com.android.server.biometrics.sensors.LockoutTracker;
|
||||
|
||||
/**
|
||||
@@ -93,6 +93,12 @@ public final class FingerprintAuthenticator extends IBiometricAuthenticator.Stub
|
||||
return mFingerprintService.getLockoutModeForUser(mSensorId, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateAuthenticatorId(int userId, IInvalidationCallback callback)
|
||||
throws RemoteException {
|
||||
mFingerprintService.invalidateAuthenticatorId(mSensorId, userId, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAuthenticatorId(int callingUserId) throws RemoteException {
|
||||
return mFingerprintService.getAuthenticatorId(mSensorId, callingUserId);
|
||||
|
||||
@@ -36,6 +36,7 @@ import android.hardware.biometrics.BiometricsProtoEnums;
|
||||
import android.hardware.biometrics.IBiometricSensorReceiver;
|
||||
import android.hardware.biometrics.IBiometricService;
|
||||
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
|
||||
import android.hardware.biometrics.IInvalidationCallback;
|
||||
import android.hardware.biometrics.ITestSession;
|
||||
import android.hardware.biometrics.fingerprint.IFingerprint;
|
||||
import android.hardware.biometrics.fingerprint.SensorProps;
|
||||
@@ -571,6 +572,19 @@ public class FingerprintService extends SystemService implements BiometricServic
|
||||
return provider.getLockoutModeForUser(sensorId, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateAuthenticatorId(int sensorId, int userId,
|
||||
IInvalidationCallback callback) {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for invalidateAuthenticatorId");
|
||||
return;
|
||||
}
|
||||
provider.scheduleInvalidateAuthenticatorId(sensorId, userId, callback);
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public long getAuthenticatorId(int sensorId, int userId) {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.server.biometrics.sensors.fingerprint;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.hardware.biometrics.IInvalidationCallback;
|
||||
import android.hardware.biometrics.ITestSession;
|
||||
import android.hardware.fingerprint.Fingerprint;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
@@ -109,6 +110,16 @@ public interface ServiceProvider {
|
||||
@LockoutTracker.LockoutMode
|
||||
int getLockoutModeForUser(int sensorId, int userId);
|
||||
|
||||
/**
|
||||
* Requests for the authenticatorId (whose source of truth is in the TEE or equivalent) to
|
||||
* be invalidated. See {@link com.android.server.biometrics.sensors.InvalidationRequesterClient}
|
||||
*/
|
||||
default void scheduleInvalidateAuthenticatorId(int sensorId, int userId,
|
||||
@NonNull IInvalidationCallback callback) {
|
||||
throw new IllegalStateException("Providers that support invalidation must override"
|
||||
+ " this method");
|
||||
}
|
||||
|
||||
long getAuthenticatorId(int sensorId, int userId);
|
||||
|
||||
void onPointerDown(int sensorId, int x, int y, float minor, float major);
|
||||
|
||||
@@ -19,13 +19,13 @@ package com.android.server.biometrics.sensors.iris;
|
||||
import android.annotation.NonNull;
|
||||
import android.hardware.biometrics.IBiometricAuthenticator;
|
||||
import android.hardware.biometrics.IBiometricSensorReceiver;
|
||||
import android.hardware.biometrics.IInvalidationCallback;
|
||||
import android.hardware.biometrics.ITestSession;
|
||||
import android.hardware.biometrics.SensorPropertiesInternal;
|
||||
import android.hardware.iris.IIrisService;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import com.android.server.biometrics.SensorConfig;
|
||||
import com.android.server.biometrics.sensors.LockoutTracker;
|
||||
|
||||
/**
|
||||
@@ -85,6 +85,10 @@ public final class IrisAuthenticator extends IBiometricAuthenticator.Stub {
|
||||
return LockoutTracker.LOCKOUT_NONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateAuthenticatorId(int userId, IInvalidationCallback callback) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAuthenticatorId(int callingUserId) throws RemoteException {
|
||||
return 0;
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.biometrics;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
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 android.hardware.biometrics.BiometricAuthenticator;
|
||||
import android.hardware.biometrics.BiometricManager.Authenticators;
|
||||
import android.hardware.biometrics.IBiometricAuthenticator;
|
||||
import android.hardware.biometrics.IInvalidationCallback;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.server.biometrics.BiometricService.InvalidationTracker;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@Presubmit
|
||||
@SmallTest
|
||||
public class InvalidationTrackerTest {
|
||||
|
||||
@Test
|
||||
public void testCallbackReceived_whenAllStrongSensorsInvalidated() throws Exception {
|
||||
final IBiometricAuthenticator authenticator1 = mock(IBiometricAuthenticator.class);
|
||||
final TestSensor sensor1 = new TestSensor(0 /* id */,
|
||||
BiometricAuthenticator.TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG,
|
||||
authenticator1);
|
||||
|
||||
final IBiometricAuthenticator authenticator2 = mock(IBiometricAuthenticator.class);
|
||||
final TestSensor sensor2 = new TestSensor(1 /* id */,
|
||||
BiometricAuthenticator.TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG,
|
||||
authenticator2);
|
||||
|
||||
final IBiometricAuthenticator authenticator3 = mock(IBiometricAuthenticator.class);
|
||||
final TestSensor sensor3 = new TestSensor(2 /* id */,
|
||||
BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG,
|
||||
authenticator3);
|
||||
|
||||
final IBiometricAuthenticator authenticator4 = mock(IBiometricAuthenticator.class);
|
||||
final TestSensor sensor4 = new TestSensor(3 /* id */,
|
||||
BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_WEAK,
|
||||
authenticator4);
|
||||
|
||||
final ArrayList<BiometricSensor> sensors = new ArrayList<>();
|
||||
sensors.add(sensor1);
|
||||
sensors.add(sensor2);
|
||||
sensors.add(sensor3);
|
||||
sensors.add(sensor4);
|
||||
|
||||
final IInvalidationCallback callback = mock(IInvalidationCallback.class);
|
||||
final InvalidationTracker tracker =
|
||||
InvalidationTracker.start(sensors, 0 /* userId */, 0 /* fromSensorId */, callback);
|
||||
|
||||
// The sensor which the request originated from should not be requested to invalidate
|
||||
// its authenticatorId.
|
||||
verify(authenticator1, never()).invalidateAuthenticatorId(anyInt(), any());
|
||||
|
||||
// All other strong sensors should be requested to invalidate authenticatorId
|
||||
verify(authenticator2).invalidateAuthenticatorId(eq(0) /* userId */, any());
|
||||
verify(authenticator3).invalidateAuthenticatorId(eq(0) /* userId */, any());
|
||||
|
||||
// Weak sensors are not requested to invalidate authenticatorId
|
||||
verify(authenticator4, never()).invalidateAuthenticatorId(anyInt(), any());
|
||||
|
||||
// Client is not notified until invalidation for all required sensors have completed
|
||||
verify(callback, never()).onCompleted();
|
||||
tracker.onInvalidated(1);
|
||||
verify(callback, never()).onCompleted();
|
||||
tracker.onInvalidated(2);
|
||||
verify(callback).onCompleted();
|
||||
}
|
||||
|
||||
private static class TestSensor extends BiometricSensor {
|
||||
|
||||
TestSensor(int id, int modality, int strength, IBiometricAuthenticator impl) {
|
||||
super(id, modality, strength, impl);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean confirmationAlwaysRequired(int userId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean confirmationSupported() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user