Add wireframe for biometric TestApis

1) Adds BiometricTestSession and empty implementations
2) Adds TEST_BIOMETRIC permission
3) Grants Shell USE_BIOMETRIC and TEST_BIOMETRIC permission

Bug: 169459906
Test: make -j update-api && make -j

Change-Id: Iea9fd37d7234eb7e5e34a7a2698cbf0ca7a33a77
diff --git a/api/test-current.txt b/api/test-current.txt
index 4e79dc2..b8c0c80 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -23,6 +23,7 @@
     field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
     field public static final String RESET_APP_ERRORS = "android.permission.RESET_APP_ERRORS";
     field public static final String SUSPEND_APPS = "android.permission.SUSPEND_APPS";
+    field public static final String TEST_BIOMETRIC = "android.permission.TEST_BIOMETRIC";
     field public static final String TEST_MANAGE_ROLLBACKS = "android.permission.TEST_MANAGE_ROLLBACKS";
     field public static final String UPGRADE_RUNTIME_PERMISSIONS = "android.permission.UPGRADE_RUNTIME_PERMISSIONS";
     field public static final String WRITE_DEVICE_CONFIG = "android.permission.WRITE_DEVICE_CONFIG";
@@ -1223,6 +1224,35 @@
 
 }
 
+package android.hardware.biometrics {
+
+  public class BiometricManager {
+    method @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public android.hardware.biometrics.BiometricTestSession getTestSession();
+  }
+
+  public class BiometricTestSession implements java.lang.AutoCloseable {
+    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void authenticateReject(int, int);
+    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void authenticateSuccess(int, int);
+    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void close();
+    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void enableTestHal(int, boolean);
+    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void enrollFinish(int, int);
+    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void enrollStart(int, int);
+    method @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public java.util.List<android.hardware.biometrics.SensorProperties> getSensorProperties();
+    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void internalCleanup(int, int);
+    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void notifyAcquired(int, int);
+    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void notifyError(int, int);
+  }
+
+  public class SensorProperties {
+    method public int getSensorId();
+    method public int getSensorStrength();
+    field public static final int STRENGTH_CONVENIENCE = 0; // 0x0
+    field public static final int STRENGTH_STRONG = 2; // 0x2
+    field public static final int STRENGTH_WEAK = 1; // 0x1
+  }
+
+}
+
 package android.hardware.camera2 {
 
   public abstract class CameraDevice implements java.lang.AutoCloseable {
@@ -1328,6 +1358,14 @@
 
 }
 
+package android.hardware.fingerprint {
+
+  @Deprecated public class FingerprintManager {
+    method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public android.hardware.biometrics.BiometricTestSession getTestSession();
+  }
+
+}
+
 package android.hardware.hdmi {
 
   public final class HdmiControlManager {
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index 8d0cc68..35ef53b 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -16,14 +16,17 @@
 
 package android.hardware.biometrics;
 
+import static android.Manifest.permission.TEST_BIOMETRIC;
 import static android.Manifest.permission.USE_BIOMETRIC;
 import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
 import static android.Manifest.permission.WRITE_DEVICE_CONFIG;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.TestApi;
 import android.content.Context;
 import android.os.RemoteException;
 import android.security.keystore.KeyGenParameterSpec;
@@ -196,6 +199,17 @@
     }
 
     /**
+     * Retrieves a test session for BiometricManager/BiometricPrompt.
+     * @hide
+     */
+    @TestApi
+    @NonNull
+    @RequiresPermission(TEST_BIOMETRIC)
+    public BiometricTestSession getTestSession() {
+        return null; // TODO(169459906)
+    }
+
+    /**
      * Determine if biometrics can be used. In other words, determine if
      * {@link BiometricPrompt} can be expected to be shown (hardware available, templates enrolled,
      * user-enabled). This is the equivalent of {@link #canAuthenticate(int)} with
diff --git a/core/java/android/hardware/biometrics/BiometricTestSession.java b/core/java/android/hardware/biometrics/BiometricTestSession.java
new file mode 100644
index 0000000..719efa8
--- /dev/null
+++ b/core/java/android/hardware/biometrics/BiometricTestSession.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2020 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;
+
+import static android.Manifest.permission.TEST_BIOMETRIC;
+
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.TestApi;
+import android.content.Context;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Common set of interfaces to test biometric-related APIs, including {@link BiometricPrompt} and
+ * {@link android.hardware.fingerprint.FingerprintManager}.
+ * @hide
+ */
+@TestApi
+public class BiometricTestSession implements AutoCloseable {
+
+    private static final String TAG = "TestManager";
+
+    private final Context mContext;
+    private final ITestService mTestService;
+
+    /**
+     * @hide
+     */
+    public BiometricTestSession(@NonNull Context context, @NonNull ITestService testService) {
+        mContext = context;
+        mTestService = testService;
+    }
+
+    /**
+     * @return A list of {@link SensorProperties}
+     */
+    @NonNull
+    @RequiresPermission(TEST_BIOMETRIC)
+    public List<SensorProperties> getSensorProperties() {
+        try {
+            final List<SensorPropertiesInternal> internalProps =
+                    mTestService.getSensorPropertiesInternal(mContext.getOpPackageName());
+            final List<SensorProperties> props = new ArrayList<>();
+            for (SensorPropertiesInternal internalProp : internalProps) {
+                props.add(new SensorProperties(internalProp.sensorId, internalProp.sensorStrength));
+            }
+            return props;
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Switches the specified sensor to use a test HAL. In this mode, the framework will not invoke
+     * any methods on the real HAL implementation. This allows the framework to test a substantial
+     * portion of the framework code that would otherwise require human interaction. Note that
+     * secure pathways such as HAT/Keystore are not testable, since they depend on the TEE or its
+     * equivalent for the secret key.
+     *
+     * @param sensorId Sensor that this command applies to.
+     * @param enableTestHal If true, enable testing with a fake HAL instead of the real HAL.
+     */
+    @RequiresPermission(TEST_BIOMETRIC)
+    public void enableTestHal(int sensorId, boolean enableTestHal) {
+        try {
+            mTestService.enableTestHal(sensorId, enableTestHal);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Remote exception", e);
+        }
+    }
+
+    /**
+     * Starts the enrollment process. This should generally be used when the test HAL is enabled.
+     *
+     * @param sensorId Sensor that this command applies to.
+     * @param userId User that this command applies to.
+     */
+    @RequiresPermission(TEST_BIOMETRIC)
+    public void enrollStart(int sensorId, int userId) {
+        try {
+            mTestService.enrollStart(sensorId, userId);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Remote exception", e);
+        }
+    }
+
+    /**
+     * Finishes the enrollment process. Simulates the HAL's callback.
+     *
+     * @param sensorId Sensor that this command applies to.
+     * @param userId User that this command applies to.
+     */
+    @RequiresPermission(TEST_BIOMETRIC)
+    public void enrollFinish(int sensorId, int userId) {
+        try {
+            mTestService.enrollFinish(sensorId, userId);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Remote exception", e);
+        }
+    }
+
+    /**
+     * Simulates a successful authentication, but does not provide a valid HAT.
+     *
+     * @param sensorId Sensor that this command applies to.
+     * @param userId User that this command applies to.
+     */
+    @RequiresPermission(TEST_BIOMETRIC)
+    public void authenticateSuccess(int sensorId, int userId) {
+        try {
+            mTestService.authenticateSuccess(sensorId, userId);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Remote exception", e);
+        }
+    }
+
+    /**
+     * Simulates a rejected attempt.
+     *
+     * @param sensorId Sensor that this command applies to.
+     * @param userId User that this command applies to.
+     */
+    @RequiresPermission(TEST_BIOMETRIC)
+    public void authenticateReject(int sensorId, int userId) {
+        try {
+            mTestService.authenticateReject(sensorId, userId);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Remote exception", e);
+        }
+    }
+
+    /**
+     * Simulates an acquired message from the HAL.
+     *
+     * @param sensorId Sensor that this command applies to.
+     * @param userId User that this command applies to.
+     */
+    @RequiresPermission(TEST_BIOMETRIC)
+    public void notifyAcquired(int sensorId, int userId) {
+        try {
+            mTestService.notifyAcquired(sensorId, userId);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Remote exception", e);
+        }
+    }
+
+    /**
+     * Simulates an error message from the HAL.
+     *
+     * @param sensorId Sensor that this command applies to.
+     * @param userId User that this command applies to.
+     */
+    @RequiresPermission(TEST_BIOMETRIC)
+    public void notifyError(int sensorId, int userId) {
+        try {
+            mTestService.notifyError(sensorId, userId);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Remote exception", e);
+        }
+    }
+
+    /**
+     * Matches the framework's cached enrollments against the HAL's enrollments. Any enrollment
+     * that isn't known by both sides are deleted. This should generally be used when the test
+     * HAL is disabled (e.g. to clean up after a test).
+     *
+     * @param sensorId Sensor that this command applies to.
+     * @param userId User that this command applies to.
+     */
+    @RequiresPermission(TEST_BIOMETRIC)
+    public void internalCleanup(int sensorId, int userId) {
+        try {
+            mTestService.internalCleanup(sensorId, userId);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Remote exception", e);
+        }
+    }
+
+    @Override
+    @RequiresPermission(TEST_BIOMETRIC)
+    public void close() {
+
+    }
+}
diff --git a/core/java/android/hardware/biometrics/ITestService.aidl b/core/java/android/hardware/biometrics/ITestService.aidl
new file mode 100644
index 0000000..6373132
--- /dev/null
+++ b/core/java/android/hardware/biometrics/ITestService.aidl
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2020 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;
+
+import android.hardware.biometrics.SensorPropertiesInternal;
+
+/**
+ * A test service for FingerprintManager and BiometricPrompt.
+ * @hide
+ */
+interface ITestService {
+    // Returns a list of sensor properties supported by the interface.
+    List<SensorPropertiesInternal> getSensorPropertiesInternal(String opPackageName);
+
+    // Switches the specified sensor to use a test HAL. In this mode, the framework will not invoke
+    // any methods on the real HAL implementation. This allows the framework to test a substantial
+    // portion of the framework code that would otherwise require human interaction. Note that
+    // secure pathways such as HAT/Keystore are not testable, since they depend on the TEE or its
+    // equivalent for the secret key.
+    void enableTestHal(int sensorId, boolean enableTestHal);
+
+    // Starts the enrollment process. This should generally be used when the test HAL is enabled.
+    void enrollStart(int sensorId, int userId);
+
+    // Finishes the enrollment process. Simulates the HAL's callback.
+    void enrollFinish(int sensorId, int userId);
+
+    // Simulates a successful authentication, but does not provide a valid HAT.
+    void authenticateSuccess(int sensorId, int userId);
+
+    // Simulates a rejected attempt.
+    void authenticateReject(int sensorId, int userId);
+
+    // Simulates an acquired message from the HAL.
+    void notifyAcquired(int sensorId, int userId);
+
+    // Simulates an error message from the HAL.
+    void notifyError(int sensorId, int userId);
+
+    // Matches the framework's cached enrollments against the HAL's enrollments. Any enrollment
+    // that isn't known by both sides are deleted. This should generally be used when the test
+    // HAL is disabled (e.g. to clean up after a test).
+    void internalCleanup(int sensorId, int userId);
+}
diff --git a/core/java/android/hardware/biometrics/SensorProperties.java b/core/java/android/hardware/biometrics/SensorProperties.java
index b3dcb8f..5b1b5e6 100644
--- a/core/java/android/hardware/biometrics/SensorProperties.java
+++ b/core/java/android/hardware/biometrics/SensorProperties.java
@@ -17,6 +17,7 @@
 package android.hardware.biometrics;
 
 import android.annotation.IntDef;
+import android.annotation.TestApi;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -25,19 +26,18 @@
  * The base class containing all modality-agnostic information.
  * @hide
  */
+@TestApi
 public class SensorProperties {
     /**
      * A sensor that meets the requirements for Class 1 biometrics as defined in the CDD. This does
      * not correspond to a public BiometricManager.Authenticators constant. Sensors of this strength
      * are not available to applications via the public API surface.
-     * @hide
      */
     public static final int STRENGTH_CONVENIENCE = 0;
 
     /**
      * A sensor that meets the requirements for Class 2 biometrics as defined in the CDD.
      * Corresponds to BiometricManager.Authenticators.BIOMETRIC_WEAK.
-     * @hide
      */
     public static final int STRENGTH_WEAK = 1;
 
@@ -46,7 +46,6 @@
      * Corresponds to BiometricManager.Authenticators.BIOMETRIC_STRONG.
      *
      * Notably, this is the only strength that allows generation of HardwareAuthToken(s).
-     * @hide
      */
     public static final int STRENGTH_STRONG = 2;
 
@@ -70,7 +69,6 @@
 
     /**
      * @return The sensor's unique identifier.
-     * @hide
      */
     public int getSensorId() {
         return mSensorId;
@@ -78,7 +76,6 @@
 
     /**
      * @return The sensor's strength.
-     * @hide
      */
     @Strength
     public int getSensorStrength() {
diff --git a/core/java/android/hardware/biometrics/SensorPropertiesInternal.aidl b/core/java/android/hardware/biometrics/SensorPropertiesInternal.aidl
new file mode 100644
index 0000000..d85c788
--- /dev/null
+++ b/core/java/android/hardware/biometrics/SensorPropertiesInternal.aidl
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2020 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;
+
+parcelable SensorPropertiesInternal;
\ No newline at end of file
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index b76b877..84c5ea5 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -19,6 +19,7 @@
 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
 import static android.Manifest.permission.MANAGE_FINGERPRINT;
 import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT;
+import static android.Manifest.permission.TEST_BIOMETRIC;
 import static android.Manifest.permission.USE_BIOMETRIC;
 import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
 import static android.Manifest.permission.USE_FINGERPRINT;
@@ -28,6 +29,7 @@
 import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemService;
+import android.annotation.TestApi;
 import android.app.ActivityManager;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
@@ -35,6 +37,7 @@
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricFingerprintConstants;
 import android.hardware.biometrics.BiometricPrompt;
+import android.hardware.biometrics.BiometricTestSession;
 import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
 import android.os.Binder;
 import android.os.CancellationSignal;
@@ -94,6 +97,22 @@
     private Fingerprint mRemovalFingerprint;
     private Handler mHandler;
 
+    /**
+     * Retrieves a test session for FingerprintManager.
+     * @hide
+     */
+    @TestApi
+    @NonNull
+    @RequiresPermission(TEST_BIOMETRIC)
+    public BiometricTestSession getTestSession() {
+        try {
+            return new BiometricTestSession(mContext,
+                    mService.getTestService(mContext.getOpPackageName()));
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     private class OnEnrollCancelListener implements OnCancelListener {
         @Override
         public void onCancel() {
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index f467b1d..518e3ca 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -17,6 +17,7 @@
 
 import android.hardware.biometrics.IBiometricSensorReceiver;
 import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
+import android.hardware.biometrics.ITestService;
 import android.hardware.fingerprint.IFingerprintClientActiveCallback;
 import android.hardware.fingerprint.IFingerprintServiceReceiver;
 import android.hardware.fingerprint.IUdfpsOverlayController;
@@ -30,6 +31,10 @@
  * @hide
  */
 interface IFingerprintService {
+
+    // Retrieves a test service
+    ITestService getTestService(String opPackageName);
+
     // Retrieve static sensor properties for all fingerprint sensors
     List<FingerprintSensorPropertiesInternal> getSensorPropertiesInternal(String opPackageName);
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 2ac2a1f..e2f4f2f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4541,6 +4541,12 @@
     <permission android:name="android.permission.RESET_FINGERPRINT_LOCKOUT"
         android:protectionLevel="signature" />
 
+    <!-- Allows access to TestApis for various components in the biometric stack, including
+         FingerprintService, FaceService, BiometricService. Used by com.android.server.biometrics
+         CTS tests. @hide @TestApi -->
+    <permission android:name="android.permission.TEST_BIOMETRIC"
+        android:protectionLevel="signature" />
+
     <!-- Allows direct access to the <Biometric>Service interfaces. Reserved for the system. @hide -->
     <permission android:name="android.permission.MANAGE_BIOMETRIC"
         android:protectionLevel="signature" />
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 81da5c8..4c3b36f 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -437,6 +437,9 @@
         <permission name="android.permission.MANAGE_DEBUGGING" />
         <!-- Permissions required for CTS test - TimeManagerTest -->
         <permission name="android.permission.MANAGE_TIME_AND_ZONE_DETECTION" />
+        <!-- Permissions required for CTS test - android.server.biometrics -->
+        <permission name="android.permission.USE_BIOMETRIC" />
+        <permission name="android.permission.TEST_BIOMETRIC" />
     </privapp-permissions>
 
     <privapp-permissions package="com.android.statementservice">
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index a927997..bba29db 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -329,6 +329,12 @@
     <!-- Permission needed for CTS test - TimeManagerTest -->
     <uses-permission android:name="android.permission.MANAGE_TIME_AND_ZONE_DETECTION" />
 
+    <!-- Permission required for CTS test - android.server.biometrics -->
+    <uses-permission android:name="android.permission.USE_BIOMETRIC" />
+
+    <!-- Permission required for CTS test - android.server.biometrics -->
+    <uses-permission android:name="android.permission.TEST_BIOMETRIC" />
+
     <application android:label="@string/app_label"
                 android:theme="@android:style/Theme.DeviceDefault.DayNight"
                 android:defaultToDeviceProtectedStorage="true"
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index 165755a..105fcec 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -20,6 +20,7 @@
 import static android.Manifest.permission.MANAGE_BIOMETRIC;
 import static android.Manifest.permission.MANAGE_FINGERPRINT;
 import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT;
+import static android.Manifest.permission.TEST_BIOMETRIC;
 import static android.Manifest.permission.USE_BIOMETRIC;
 import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
 import static android.Manifest.permission.USE_FINGERPRINT;
@@ -34,6 +35,8 @@
 import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
 import android.hardware.biometrics.fingerprint.IFingerprint;
 import android.hardware.biometrics.fingerprint.SensorProps;
+import android.hardware.biometrics.ITestService;
+import android.hardware.biometrics.SensorPropertiesInternal;
 import android.hardware.fingerprint.Fingerprint;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
 import android.hardware.fingerprint.IFingerprintClientActiveCallback;
@@ -88,11 +91,74 @@
     private final GestureAvailabilityDispatcher mGestureAvailabilityDispatcher;
     private final LockPatternUtils mLockPatternUtils;
     @NonNull private List<ServiceProvider> mServiceProviders;
+    @Nullable private TestService mTestService;
+
+    private final class TestService extends ITestService.Stub {
+
+        @Override
+        public List<SensorPropertiesInternal> getSensorPropertiesInternal(
+                String opPackageName) {
+            Utils.checkPermission(getContext(), TEST_BIOMETRIC);
+            return null;
+        }
+
+        @Override
+        public void enableTestHal(int sensorId, boolean enableTestHal) {
+            Utils.checkPermission(getContext(), TEST_BIOMETRIC);
+        }
+
+        @Override
+        public void enrollStart(int sensorId, int userId) {
+            Utils.checkPermission(getContext(), TEST_BIOMETRIC);
+        }
+
+        @Override
+        public void enrollFinish(int sensorId, int userId) {
+            Utils.checkPermission(getContext(), TEST_BIOMETRIC);
+        }
+
+        @Override
+        public void authenticateSuccess(int sensorId, int userId)  {
+            Utils.checkPermission(getContext(), TEST_BIOMETRIC);
+        }
+
+        @Override
+        public void authenticateReject(int sensorId, int userId)  {
+            Utils.checkPermission(getContext(), TEST_BIOMETRIC);
+        }
+
+        @Override
+        public void notifyAcquired(int sensorId, int userId)  {
+            Utils.checkPermission(getContext(), TEST_BIOMETRIC);
+        }
+
+        @Override
+        public void notifyError(int sensorId, int userId)  {
+            Utils.checkPermission(getContext(), TEST_BIOMETRIC);
+        }
+
+        @Override
+        public void internalCleanup(int sensorId, int userId)  {
+            Utils.checkPermission(getContext(), TEST_BIOMETRIC);
+        }
+    }
 
     /**
      * Receives the incoming binder calls from FingerprintManager.
      */
     private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
+        @Override
+        public ITestService getTestService(String opPackageName) {
+            Utils.checkPermission(getContext(), TEST_BIOMETRIC);
+
+            synchronized (this) {
+                if (mTestService == null) {
+                    mTestService = new TestService();
+                }
+            }
+            return mTestService;
+        }
+
         @Override // Binder call
         public List<FingerprintSensorPropertiesInternal> getSensorPropertiesInternal(
                 String opPackageName) {