Revert "Revert "Update face detectInteraction""

This reverts commit 2a4f86bea0b6317939a724297e21e06a0913b5d6.

Reason for revert: Re-merge with NPE fixed
Fixes: 184672091

Change-Id: I68315310d9c7226584564b3b1eb3861189c7d080
diff --git a/core/java/android/hardware/face/FaceSensorPropertiesInternal.java b/core/java/android/hardware/face/FaceSensorPropertiesInternal.java
index 44dffb2..9936b88 100644
--- a/core/java/android/hardware/face/FaceSensorPropertiesInternal.java
+++ b/core/java/android/hardware/face/FaceSensorPropertiesInternal.java
@@ -96,6 +96,7 @@
 
     @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 b4c6321..67ee1f4 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -2116,6 +2116,11 @@
      * If face auth is allows to scan on this exact moment.
      */
     public boolean shouldListenForFace() {
+        if (mFaceManager == null) {
+            // Device does not have face auth
+            return false;
+        }
+
         final boolean statusBarShadeLocked = mStatusBarState == StatusBarState.SHADE_LOCKED;
         final boolean awakeKeyguard = mKeyguardIsVisible && mDeviceInteractive && !mGoingToSleep
                 && !statusBarShadeLocked;
@@ -2137,8 +2142,15 @@
 
         // 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.isEmpty()
+                && 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 c9e148f..8a842b5 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 @@
 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 @@
     @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 @@
      */
     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 @@
 
     @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 70f26ac..cb7c568 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 @@
                 }
             }
 
-            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 @@
         for (BiometricSensor sensor : mSensors) {
             pw.println(" " + sensor);
         }
+        pw.println();
         pw.println("CurrentSession: " + mCurrentAuthSession);
-
-        final List<FingerprintSensorPropertiesInternal> 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 2fe2752..cc27127 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 @@
     }
 
     /**
-     * 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 @@
             // 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 @@
         }
     }
 
+    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 0000000..c71c954
--- /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 34a86d3..ada8476 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 @@
                 return;
             }
 
-            // TODO(b/152413782): Implement this once it's supported in the HAL
+            final Pair<Integer, ServiceProvider> 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 @@
                 return;
             }
 
-            // TODO(b/152413782): Implement this once it's supported in the HAL
+            final Pair<Integer, ServiceProvider> 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 9b6fb0b..6d6c2e9 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 @@
 
     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 0000000..0ba731e
--- /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<ISession> implements DetectionConsumer {
+
+    private static final String TAG = "FaceDetectClient";
+
+    private final boolean mIsStrongBiometric;
+    @Nullable private ICancellationSignal mCancellationSignal;
+
+    public FaceDetectClient(@NonNull Context context, @NonNull LazyDaemon<ISession> 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 4fb71ff..b8bac40 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 @@
                             Slog.e(getTag(), "Stopping background authentication, top: "
                                     + topPackage + " currentClient: " + client);
                             mSensors.valueAt(i).getScheduler()
-                                    .cancelAuthentication(client.getToken());
+                                    .cancelAuthenticationOrDetection(client.getToken());
                         }
                     }
                 }
@@ -145,7 +145,7 @@
             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);
@@ -346,6 +346,25 @@
     }
 
     @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,
             @NonNull String opPackageName, boolean restricted, int statsClient,
@@ -364,7 +383,8 @@
 
     @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 4627a9d..d56fd12 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
@@ -338,7 +338,17 @@
 
         @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 56fad946..2cb2939 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
@@ -639,6 +639,20 @@
     }
 
     @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,
             @NonNull String opPackageName, boolean restricted, int statsClient,
@@ -658,7 +672,7 @@
     @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 9e9d0ee..45e93a0 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
@@ -58,6 +58,12 @@
     }
 
     @Override
+    public void start(@NonNull Callback callback) {
+        super.start(callback);
+        startHalOperation();
+    }
+
+    @Override
     protected void stopHalOperation() {
         UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
         try {
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 01fd641..9851ae0 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 @@
                             Slog.e(getTag(), "Stopping background authentication, top: "
                                     + topPackage + " currentClient: " + client);
                             mSensors.valueAt(i).getScheduler()
-                                    .cancelAuthentication(client.getToken());
+                                    .cancelAuthenticationOrDetection(client.getToken());
                         }
                     }
                 }
@@ -383,7 +383,8 @@
 
     @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 7353cc7..eb78245 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
@@ -144,7 +144,7 @@
                             && !client.isAlreadyDone()) {
                         Slog.e(TAG, "Stopping background authentication, top: "
                                 + topPackage + " currentClient: " + client);
-                        mScheduler.cancelAuthentication(client.getToken());
+                        mScheduler.cancelAuthenticationOrDetection(client.getToken());
                     }
                 }
             });
@@ -645,7 +645,7 @@
 
     @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 3cbc226..e322ce5 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 @@
         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 @@
             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 abc87376..a5fbab5 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 @@
 
         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 bb2b1c2..ee5ab92 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.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 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 @@
 @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 @@
 
     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 7dd0734..c5ed20a 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 @@
         // 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 @@
                 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);