Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fc26e8a0 authored by Kevin Chyn's avatar Kevin Chyn
Browse files

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
parent 526abec2
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ package android {
    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.graphics.drawable {

}

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.display {

}

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 {
+14 −0
Original line number Diff line number Diff line
@@ -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;
@@ -195,6 +198,17 @@ public class BiometricManager {
        mService = service;
    }

    /**
     * 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,
+202 −0
Original line number Diff line number Diff line
/*
 * 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() {

    }
}
+57 −0
Original line number Diff line number Diff line
/*
 * 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);
}
+2 −5
Original line number Diff line number Diff line
@@ -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 @@ import java.lang.annotation.RetentionPolicy;
 * 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 @@ public class SensorProperties {
     * 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 @@ public class SensorProperties {

    /**
     * @return The sensor's unique identifier.
     * @hide
     */
    public int getSensorId() {
        return mSensorId;
@@ -78,7 +76,6 @@ public class SensorProperties {

    /**
     * @return The sensor's strength.
     * @hide
     */
    @Strength
    public int getSensorStrength() {
Loading