From 5b0dd45ad880250c4b7aaf77f55db63563271db5 Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Wed, 7 Apr 2021 15:02:37 -0700 Subject: [PATCH] Update face detectInteraction 1) Sets the sensor property based on the HAL, instead of hard coding false 2) Schedules/cancels detection when requested 3) Updates biometric dumpsys to include internal properties Test: atest com.android.server.biometrics Test: adb shell dumpsys biometric Test: manual Bug: 184672091 Change-Id: I2fb1db0994f6d2ed235420967d78e70f1b13cdd0 --- .../face/FaceSensorPropertiesInternal.java | 3 +- .../keyguard/KeyguardUpdateMonitor.java | 10 +- .../server/biometrics/BiometricSensor.java | 18 +++- .../server/biometrics/BiometricService.java | 11 +- .../sensors/BiometricScheduler.java | 22 ++-- .../biometrics/sensors/DetectionConsumer.java | 24 +++++ .../biometrics/sensors/face/FaceService.java | 18 +++- .../sensors/face/ServiceProvider.java | 7 +- .../sensors/face/aidl/FaceDetectClient.java | 102 ++++++++++++++++++ .../sensors/face/aidl/FaceProvider.java | 26 ++++- .../biometrics/sensors/face/aidl/Sensor.java | 12 ++- .../biometrics/sensors/face/hidl/Face10.java | 16 ++- .../aidl/FingerprintDetectClient.java | 6 ++ .../fingerprint/aidl/FingerprintProvider.java | 5 +- .../fingerprint/hidl/Fingerprint21.java | 4 +- .../server/biometrics/AuthSessionTest.java | 4 +- .../biometrics/BiometricServiceTest.java | 4 +- .../biometrics/InvalidationTrackerTest.java | 25 +++-- .../sensors/BiometricSchedulerTest.java | 4 +- 19 files changed, 275 insertions(+), 46 deletions(-) create mode 100644 services/core/java/com/android/server/biometrics/sensors/DetectionConsumer.java create mode 100644 services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java diff --git a/core/java/android/hardware/face/FaceSensorPropertiesInternal.java b/core/java/android/hardware/face/FaceSensorPropertiesInternal.java index 44dffb2077313..9936b885707ef 100644 --- a/core/java/android/hardware/face/FaceSensorPropertiesInternal.java +++ b/core/java/android/hardware/face/FaceSensorPropertiesInternal.java @@ -96,6 +96,7 @@ public class FaceSensorPropertiesInternal extends SensorPropertiesInternal { @Override public String toString() { - return "ID: " + sensorId + ", Strength: " + sensorStrength + ", Type: " + sensorType; + return "ID: " + sensorId + ", Strength: " + sensorStrength + ", Type: " + sensorType + + ", SupportsFaceDetection: " + supportsFaceDetection; } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 2219cf4274983..94d925f010aae 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -2131,8 +2131,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab // Scan even when encrypted or timeout to show a preemptive bouncer when bypassing. // Lock-down mode shouldn't scan, since it is more explicit. - boolean strongAuthAllowsScanning = (!isEncryptedOrTimedOut || canBypass && !mBouncer) - && !isLockDown; + boolean strongAuthAllowsScanning = (!isEncryptedOrTimedOut || canBypass && !mBouncer); + + // If the device supports face detection (without authentication), allow it to happen + // if the device is in lockdown mode. Otherwise, prevent scanning. + boolean supportsDetectOnly = mFaceSensorProperties.get(0).supportsFaceDetection; + if (isLockDown && !supportsDetectOnly) { + strongAuthAllowsScanning = false; + } // Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an // instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware. diff --git a/services/core/java/com/android/server/biometrics/BiometricSensor.java b/services/core/java/com/android/server/biometrics/BiometricSensor.java index c9e148f9b6fff..8a842b53d8e8d 100644 --- a/services/core/java/com/android/server/biometrics/BiometricSensor.java +++ b/services/core/java/com/android/server/biometrics/BiometricSensor.java @@ -19,10 +19,13 @@ package com.android.server.biometrics; import static android.hardware.biometrics.BiometricManager.Authenticators; import android.annotation.IntDef; +import android.annotation.NonNull; +import android.content.Context; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.IBiometricAuthenticator; import android.hardware.biometrics.IBiometricSensorReceiver; +import android.hardware.biometrics.SensorPropertiesInternal; import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; @@ -62,6 +65,7 @@ public abstract class BiometricSensor { @Retention(RetentionPolicy.SOURCE) @interface SensorState {} + @NonNull private final Context mContext; public final int id; public final @Authenticators.Types int oemStrength; // strength as configured by the OEM public final int modality; @@ -84,8 +88,9 @@ public abstract class BiometricSensor { */ abstract boolean confirmationSupported(); - BiometricSensor(int id, int modality, @Authenticators.Types int strength, - IBiometricAuthenticator impl) { + BiometricSensor(@NonNull Context context, int id, int modality, + @Authenticators.Types int strength, IBiometricAuthenticator impl) { + this.mContext = context; this.id = id; this.modality = modality; this.oemStrength = strength; @@ -169,12 +174,19 @@ public abstract class BiometricSensor { @Override public String toString() { + SensorPropertiesInternal properties = null; + try { + properties = impl.getSensorProperties(mContext.getOpPackageName()); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception", e); + } + return "ID(" + id + ")" + ", oemStrength: " + oemStrength + ", updatedStrength: " + mUpdatedStrength + ", modality " + modality + ", state: " + mSensorState + ", cookie: " + mCookie - + ", authenticator: " + impl; + + ", props: " + properties; } } diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index 70f26aca3f631..cb7c568757e54 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -725,7 +725,7 @@ public class BiometricService extends SystemService { } } - mSensors.add(new BiometricSensor(id, modality, strength, authenticator) { + mSensors.add(new BiometricSensor(getContext(), id, modality, strength, authenticator) { @Override boolean confirmationAlwaysRequired(int userId) { return mSettingObserver.getConfirmationAlwaysRequired(modality, userId); @@ -1351,13 +1351,8 @@ public class BiometricService extends SystemService { for (BiometricSensor sensor : mSensors) { pw.println(" " + sensor); } + pw.println(); pw.println("CurrentSession: " + mCurrentAuthSession); - - final List fpProps = - mInjector.getFingerprintSensorProperties(getContext()); - pw.println("FingerprintSensorProperties: " + fpProps.size()); - for (FingerprintSensorPropertiesInternal prop : fpProps) { - pw.println(" " + prop); - } + pw.println(); } } diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java index 6c480f1342792..85d849f6ff9a9 100644 --- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java +++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java @@ -559,22 +559,21 @@ public class BiometricScheduler { } /** - * Requests to cancel authentication. + * Requests to cancel authentication or detection. * @param token from the caller, should match the token passed in when requesting authentication */ - public void cancelAuthentication(IBinder token) { + public void cancelAuthenticationOrDetection(IBinder token) { if (mCurrentOperation == null) { Slog.e(getTag(), "Unable to cancel authentication, null operation"); return; } - final boolean isAuthenticating = - mCurrentOperation.mClientMonitor instanceof AuthenticationConsumer; + final boolean isCorrectClient = isAuthenticationOrDetectionOperation(mCurrentOperation); final boolean tokenMatches = mCurrentOperation.mClientMonitor.getToken() == token; - if (isAuthenticating && tokenMatches) { - Slog.d(getTag(), "Cancelling authentication: " + mCurrentOperation); + if (isCorrectClient && tokenMatches) { + Slog.d(getTag(), "Cancelling: " + mCurrentOperation); cancelInternal(mCurrentOperation); - } else if (!isAuthenticating) { + } else if (!isCorrectClient) { // Look through the current queue for all authentication clients for the specified // token, and mark them as STATE_WAITING_IN_QUEUE_CANCELING. Note that we're marking // all of them, instead of just the first one, since the API surface currently doesn't @@ -582,7 +581,7 @@ public class BiometricScheduler { // process. However, this generally does not happen anyway, and would be a class of // bugs on its own. for (Operation operation : mPendingOperations) { - if (operation.mClientMonitor instanceof AuthenticationConsumer + if (isAuthenticationOrDetectionOperation(operation) && operation.mClientMonitor.getToken() == token) { Slog.d(getTag(), "Marking " + operation + " as STATE_WAITING_IN_QUEUE_CANCELING"); @@ -592,6 +591,13 @@ public class BiometricScheduler { } } + private boolean isAuthenticationOrDetectionOperation(@NonNull Operation operation) { + final boolean isAuthentication = operation.mClientMonitor + instanceof AuthenticationConsumer; + final boolean isDetection = operation.mClientMonitor instanceof DetectionConsumer; + return isAuthentication || isDetection; + } + /** * @return the current operation */ diff --git a/services/core/java/com/android/server/biometrics/sensors/DetectionConsumer.java b/services/core/java/com/android/server/biometrics/sensors/DetectionConsumer.java new file mode 100644 index 0000000000000..c71c954f0234a --- /dev/null +++ b/services/core/java/com/android/server/biometrics/sensors/DetectionConsumer.java @@ -0,0 +1,24 @@ +/* + * 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.sensors; + +/** + * Interface that clients interested/eligible for interaction detection events should implement. + */ +public interface DetectionConsumer { + void onInteractionDetected(); +} diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java index 34a86d3e63985..ada84769b9ef2 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java @@ -296,7 +296,15 @@ public class FaceService extends SystemService implements BiometricServiceCallba return; } - // TODO(b/152413782): Implement this once it's supported in the HAL + final Pair provider = getSingleProvider(); + if (provider == null) { + Slog.w(TAG, "Null provider for detectFace"); + return; + } + + provider.second.scheduleFaceDetect(provider.first, token, userId, + new ClientMonitorCallbackConverter(receiver), opPackageName, + BiometricsProtoEnums.CLIENT_KEYGUARD); } @Override // Binder call @@ -353,7 +361,13 @@ public class FaceService extends SystemService implements BiometricServiceCallba return; } - // TODO(b/152413782): Implement this once it's supported in the HAL + final Pair provider = getSingleProvider(); + if (provider == null) { + Slog.w(TAG, "Null provider for cancelFaceDetect"); + return; + } + + provider.second.cancelFaceDetect(provider.first, token); } @Override // Binder call diff --git a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java index 9b6fb0b75c579..6d6c2e9e975fa 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java @@ -101,12 +101,17 @@ public interface ServiceProvider { void cancelEnrollment(int sensorId, @NonNull IBinder token); + void scheduleFaceDetect(int sensorId, @NonNull IBinder token, int userId, + @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName, + int statsClient); + + void cancelFaceDetect(int sensorId, @NonNull IBinder token); + void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName, boolean restricted, int statsClient, boolean allowBackgroundAuthentication); - void cancelAuthentication(int sensorId, @NonNull IBinder token); void scheduleRemove(int sensorId, @NonNull IBinder token, int faceId, int userId, diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java new file mode 100644 index 0000000000000..0ba731ee8b4b0 --- /dev/null +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java @@ -0,0 +1,102 @@ +/* + * 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.sensors.face.aidl; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.hardware.biometrics.BiometricsProtoEnums; +import android.hardware.biometrics.common.ICancellationSignal; +import android.hardware.biometrics.face.ISession; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Slog; + +import com.android.server.biometrics.BiometricsProto; +import com.android.server.biometrics.sensors.AcquisitionClient; +import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; +import com.android.server.biometrics.sensors.DetectionConsumer; + +/** + * Performs face detection without exposing any matching information (e.g. accept/reject have the + * same haptic, lockout counter is not increased). + */ +public class FaceDetectClient extends AcquisitionClient implements DetectionConsumer { + + private static final String TAG = "FaceDetectClient"; + + private final boolean mIsStrongBiometric; + @Nullable private ICancellationSignal mCancellationSignal; + + public FaceDetectClient(@NonNull Context context, @NonNull LazyDaemon lazyDaemon, + @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId, + @NonNull String owner, int sensorId, boolean isStrongBiometric, int statsClient) { + super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId, + BiometricsProtoEnums.MODALITY_FACE, BiometricsProtoEnums.ACTION_AUTHENTICATE, + statsClient); + mIsStrongBiometric = isStrongBiometric; + } + + @Override + public void start(@NonNull Callback callback) { + super.start(callback); + startHalOperation(); + } + + @Override + protected void stopHalOperation() { + try { + mCancellationSignal.cancel(); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception", e); + mCallback.onClientFinished(this, false /* success */); + } + } + + @Override + protected void startHalOperation() { + try { + mCancellationSignal = getFreshDaemon().detectInteraction(); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception when requesting face detect", e); + mCallback.onClientFinished(this, false /* success */); + } + } + + @Override + public void onInteractionDetected() { + vibrateSuccess(); + + try { + getListener().onDetected(getSensorId(), getTargetUserId(), mIsStrongBiometric); + mCallback.onClientFinished(this, true /* success */); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception when sending onDetected", e); + mCallback.onClientFinished(this, false /* success */); + } + } + + @Override + public int getProtoEnum() { + return BiometricsProto.CM_DETECT_INTERACTION; + } + + @Override + public boolean interruptsPrecedingClients() { + return true; + } +} 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 4fb71ffdaab02..b8bac402f4301 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 @@ -110,7 +110,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { Slog.e(getTag(), "Stopping background authentication, top: " + topPackage + " currentClient: " + client); mSensors.valueAt(i).getScheduler() - .cancelAuthentication(client.getToken()); + .cancelAuthenticationOrDetection(client.getToken()); } } } @@ -145,7 +145,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { final FaceSensorPropertiesInternal internalProp = new FaceSensorPropertiesInternal( prop.commonProps.sensorId, prop.commonProps.sensorStrength, prop.commonProps.maxEnrollmentsPerUser, componentInfo, prop.sensorType, - false /* supportsFaceDetection */, prop.halControlsPreview, + prop.supportsDetectInteraction, prop.halControlsPreview, false /* resetLockoutRequiresChallenge */); final Sensor sensor = new Sensor(getTag() + "/" + sensorId, this, mContext, mHandler, internalProp); @@ -345,6 +345,25 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { mHandler.post(() -> mSensors.get(sensorId).getScheduler().cancelEnrollment(token)); } + @Override + public void scheduleFaceDetect(int sensorId, @NonNull IBinder token, + int userId, @NonNull ClientMonitorCallbackConverter callback, + @NonNull String opPackageName, int statsClient) { + mHandler.post(() -> { + final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId); + final FaceDetectClient client = new FaceDetectClient(mContext, + mSensors.get(sensorId).getLazySession(), token, callback, userId, opPackageName, + sensorId, isStrongBiometric, statsClient); + scheduleForSensor(sensorId, client); + }); + } + + @Override + public void cancelFaceDetect(int sensorId, @NonNull IBinder token) { + mHandler.post(() -> mSensors.get(sensorId).getScheduler() + .cancelAuthenticationOrDetection(token)); + } + @Override public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback, @@ -364,7 +383,8 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { @Override public void cancelAuthentication(int sensorId, @NonNull IBinder token) { - mHandler.post(() -> mSensors.get(sensorId).getScheduler().cancelAuthentication(token)); + mHandler.post(() -> mSensors.get(sensorId).getScheduler() + .cancelAuthenticationOrDetection(token)); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java index ee367756dc04d..a533c8f7ecc65 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java @@ -337,7 +337,17 @@ public class Sensor { @Override public void onInteractionDetected() { - // no-op + mHandler.post(() -> { + final BaseClientMonitor client = mScheduler.getCurrentClient(); + if (!(client instanceof FaceDetectClient)) { + Slog.e(mTag, "onInteractionDetected for wrong client: " + + Utils.getClientName(client)); + return; + } + + final FaceDetectClient detectClient = (FaceDetectClient) client; + detectClient.onInteractionDetected(); + }); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java index 4ffbe06c11bae..6bcc9e6f85d47 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java @@ -637,6 +637,20 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { }); } + @Override + public void scheduleFaceDetect(int sensorId, @NonNull IBinder token, + int userId, @NonNull ClientMonitorCallbackConverter callback, + @NonNull String opPackageName, int statsClient) { + throw new IllegalStateException("Face detect not supported by IBiometricsFace@1.0. Did you" + + "forget to check the supportsFaceDetection flag?"); + } + + @Override + public void cancelFaceDetect(int sensorId, @NonNull IBinder token) { + throw new IllegalStateException("Face detect not supported by IBiometricsFace@1.0. Did you" + + "forget to check the supportsFaceDetection flag?"); + } + @Override public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId, int cookie, @NonNull ClientMonitorCallbackConverter receiver, @@ -657,7 +671,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { @Override public void cancelAuthentication(int sensorId, @NonNull IBinder token) { mHandler.post(() -> { - mScheduler.cancelAuthentication(token); + mScheduler.cancelAuthenticationOrDetection(token); }); } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java index 9e9d0eec74abb..45e93a0965504 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java @@ -57,6 +57,12 @@ class FingerprintDetectClient extends AcquisitionClient { mUdfpsOverlayController = udfpsOverlayController; } + @Override + public void start(@NonNull Callback callback) { + super.start(callback); + startHalOperation(); + } + @Override protected void stopHalOperation() { UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController); 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 01fd6419aee0e..9851ae08ac3ad 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 @@ -115,7 +115,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi Slog.e(getTag(), "Stopping background authentication, top: " + topPackage + " currentClient: " + client); mSensors.valueAt(i).getScheduler() - .cancelAuthentication(client.getToken()); + .cancelAuthenticationOrDetection(client.getToken()); } } } @@ -383,7 +383,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @Override public void cancelAuthentication(int sensorId, @NonNull IBinder token) { - mHandler.post(() -> mSensors.get(sensorId).getScheduler().cancelAuthentication(token)); + mHandler.post(() -> mSensors.get(sensorId).getScheduler() + .cancelAuthenticationOrDetection(token)); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java index 243cc7cd9b002..07affb18270eb 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java @@ -143,7 +143,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider && !client.isAlreadyDone()) { Slog.e(TAG, "Stopping background authentication, top: " + topPackage + " currentClient: " + client); - mScheduler.cancelAuthentication(client.getToken()); + mScheduler.cancelAuthenticationOrDetection(client.getToken()); } } }); @@ -644,7 +644,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider @Override public void cancelAuthentication(int sensorId, @NonNull IBinder token) { - mHandler.post(() -> mScheduler.cancelAuthentication(token)); + mHandler.post(() -> mScheduler.cancelAuthenticationOrDetection(token)); } @Override diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java index 3cbc226542928..e322ce5513727 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java @@ -279,7 +279,7 @@ public class AuthSessionTest { IBiometricAuthenticator fingerprintAuthenticator = mock(IBiometricAuthenticator.class); when(fingerprintAuthenticator.isHardwareDetected(any())).thenReturn(true); when(fingerprintAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(true); - mSensors.add(new BiometricSensor(id, + mSensors.add(new BiometricSensor(mContext, id, TYPE_FINGERPRINT /* modality */, Authenticators.BIOMETRIC_STRONG /* strength */, fingerprintAuthenticator) { @@ -314,7 +314,7 @@ public class AuthSessionTest { IBiometricAuthenticator authenticator) throws RemoteException { when(authenticator.isHardwareDetected(any())).thenReturn(true); when(authenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(true); - mSensors.add(new BiometricSensor(id, + mSensors.add(new BiometricSensor(mContext, id, TYPE_FACE /* modality */, Authenticators.BIOMETRIC_STRONG /* strength */, authenticator) { diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java index abc873766de1a..a5fbab519aaa7 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java @@ -1278,10 +1278,10 @@ public class BiometricServiceTest { for (int i = 0; i < testCases.length; i++) { final BiometricSensor sensor = - new BiometricSensor(0 /* id */, + new BiometricSensor(mContext, 0 /* id */, BiometricAuthenticator.TYPE_FINGERPRINT, testCases[i][0], - null /* impl */) { + mock(IBiometricAuthenticator.class)) { @Override boolean confirmationAlwaysRequired(int userId) { return false; 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 bb2b1c2fb0db5..ee5ab92065ee8 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/InvalidationTrackerTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/InvalidationTrackerTest.java @@ -24,6 +24,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.annotation.NonNull; import android.content.Context; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricManager.Authenticators; @@ -35,7 +36,10 @@ import androidx.test.filters.SmallTest; import com.android.server.biometrics.BiometricService.InvalidationTracker; +import org.junit.Before; import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import java.util.ArrayList; @@ -43,29 +47,37 @@ import java.util.ArrayList; @SmallTest public class InvalidationTrackerTest { + @Mock + private Context mContext; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + @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 */, + final TestSensor sensor1 = new TestSensor(mContext, 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 */, + final TestSensor sensor2 = new TestSensor(mContext, 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 */, + final TestSensor sensor3 = new TestSensor(mContext, 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 */, + final TestSensor sensor4 = new TestSensor(mContext, 3 /* id */, BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_WEAK, authenticator4); @@ -101,8 +113,9 @@ public class InvalidationTrackerTest { private static class TestSensor extends BiometricSensor { - TestSensor(int id, int modality, int strength, IBiometricAuthenticator impl) { - super(id, modality, strength, impl); + TestSensor(@NonNull Context context, int id, int modality, int strength, + @NonNull IBiometricAuthenticator impl) { + super(context, id, modality, strength, impl); } @Override diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java index 7dd073499c73e..c5ed20afacecc 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java @@ -188,7 +188,7 @@ public class BiometricSchedulerTest { // Request it to be canceled. The operation can be canceled immediately, and the scheduler // should go back to idle, since in this case the framework has not even requested the HAL // to authenticate yet. - mScheduler.cancelAuthentication(mToken); + mScheduler.cancelAuthenticationOrDetection(mToken); assertNull(mScheduler.mCurrentOperation); } @@ -298,7 +298,7 @@ public class BiometricSchedulerTest { mScheduler.mPendingOperations.getFirst().mState); // Request cancel before the authentication client has started - mScheduler.cancelAuthentication(mToken); + mScheduler.cancelAuthenticationOrDetection(mToken); waitForIdle(); assertEquals(Operation.STATE_WAITING_IN_QUEUE_CANCELING, mScheduler.mPendingOperations.getFirst().mState);