Merge changes from topic "IFace.aidl"

* changes:
  Default implementation skeleton for IFace
  Add VTS tests skeleton for IFace
  Define IFace
This commit is contained in:
Ilya Matyukhin
2020-10-14 22:11:59 +00:00
committed by Android (Google) Code Review
28 changed files with 1831 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
aidl_interface {
name: "android.hardware.biometrics.face",
vendor_available: true,
srcs: [
"android/hardware/biometrics/face/**/*.aidl",
],
imports: [
"android.hardware.biometrics.common",
"android.hardware.common",
"android.hardware.keymaster",
],
stability: "vintf",
backend: {
java: {
enabled: false,
platform_apis: false,
},
cpp: {
enabled: false,
},
},
}

View File

@@ -0,0 +1,44 @@
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
// edit this file. It looks like you are doing that because you have modified
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
// from an interface or a field from a parcelable and it broke the build. That
// breakage is intended.
//
// You must not make a backward incompatible changes to the AIDL files built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.face;
@Backing(type="byte") @VintfStability
enum AcquiredInfo {
GOOD = 0,
INSUFFICIENT = 1,
TOO_BRIGHT = 2,
TOO_DARK = 3,
TOO_CLOSE = 4,
TOO_FAR = 5,
FACE_TOO_HIGH = 6,
FACE_TOO_LOW = 7,
FACE_TOO_RIGHT = 8,
FACE_TOO_LEFT = 9,
POOR_GAZE = 10,
NOT_DETECTED = 11,
TOO_MUCH_MOTION = 12,
RECALIBRATE = 13,
TOO_DIFFERENT = 14,
TOO_SIMILAR = 15,
PAN_TOO_EXTREME = 16,
TILT_TOO_EXTREME = 17,
ROLL_TOO_EXTREME = 18,
FACE_OBSCURED = 19,
START = 20,
SENSOR_DIRTY = 21,
VENDOR = 22,
}

View File

@@ -0,0 +1,28 @@
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
// edit this file. It looks like you are doing that because you have modified
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
// from an interface or a field from a parcelable and it broke the build. That
// breakage is intended.
//
// You must not make a backward incompatible changes to the AIDL files built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.face;
@Backing(type="byte") @VintfStability
enum Error {
HW_UNAVAILABLE = 1,
UNABLE_TO_PROCESS = 2,
TIMEOUT = 3,
NO_SPACE = 4,
CANCELED = 5,
UNABLE_TO_REMOVE = 6,
VENDOR = 8,
}

View File

@@ -0,0 +1,23 @@
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
// edit this file. It looks like you are doing that because you have modified
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
// from an interface or a field from a parcelable and it broke the build. That
// breakage is intended.
//
// You must not make a backward incompatible changes to the AIDL files built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.face;
@Backing(type="byte") @VintfStability
enum FaceSensorType {
RGB = 0,
IR = 1,
}

View File

@@ -0,0 +1,23 @@
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
// edit this file. It looks like you are doing that because you have modified
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
// from an interface or a field from a parcelable and it broke the build. That
// breakage is intended.
//
// You must not make a backward incompatible changes to the AIDL files built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.face;
@VintfStability
interface IFace {
android.hardware.biometrics.face.SensorProps[] getSensorProps();
android.hardware.biometrics.face.ISession createSession(in int sensorId, in int userId, in android.hardware.biometrics.face.ISessionCallback cb);
}

View File

@@ -0,0 +1,31 @@
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
// edit this file. It looks like you are doing that because you have modified
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
// from an interface or a field from a parcelable and it broke the build. That
// breakage is intended.
//
// You must not make a backward incompatible changes to the AIDL files built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.face;
@VintfStability
interface ISession {
void generateChallenge(in int cookie, in int sensorId, in int userId, in int timeoutSec);
void revokeChallenge(in int cookie, in int sensorId, in int userId, in long challenge);
android.hardware.biometrics.common.ICancellationSignal enroll(in int cookie, in android.hardware.keymaster.HardwareAuthToken hat, in android.hardware.common.NativeHandle previewSurface);
android.hardware.biometrics.common.ICancellationSignal authenticate(in int cookie, in long operationId);
android.hardware.biometrics.common.ICancellationSignal detectInteraction(in int cookie);
void enumerateEnrollments(in int cookie);
void removeEnrollments(in int cookie, in int[] enrollmentIds);
void getAuthenticatorId(in int cookie);
void invalidateAuthenticatorId(in int cookie);
void resetLockout(in int cookie, in android.hardware.keymaster.HardwareAuthToken hat);
}

View File

@@ -0,0 +1,37 @@
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
// edit this file. It looks like you are doing that because you have modified
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
// from an interface or a field from a parcelable and it broke the build. That
// breakage is intended.
//
// You must not make a backward incompatible changes to the AIDL files built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.face;
@VintfStability
interface ISessionCallback {
void onStateChanged(in int cookie, in android.hardware.biometrics.face.SessionState state);
void onChallengeGenerated(in int sensorId, in int userId, in long challenge);
void onChallengeRevoked(in int sensorId, in int userId, in long challenge);
void onAcquired(in android.hardware.biometrics.face.AcquiredInfo info, in int vendorCode);
void onError(in android.hardware.biometrics.face.Error error, in int vendorCode);
void onEnrollmentProgress(in int enrollmentId, int remaining);
void onAuthenticationSucceeded(in int enrollmentId, in android.hardware.keymaster.HardwareAuthToken hat);
void onAuthenticationFailed();
void onLockoutTimed(in long durationMillis);
void onLockoutPermanent();
void onLockoutCleared();
void onInteractionDetected();
void onEnrollmentsEnumerated(in int[] enrollmentIds);
void onEnrollmentsRemoved(in int[] enrollmentIds);
void onAuthenticatorIdRetrieved(in long authenticatorId);
void onAuthenticatorIdInvalidated();
}

View File

@@ -0,0 +1,24 @@
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
// edit this file. It looks like you are doing that because you have modified
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
// from an interface or a field from a parcelable and it broke the build. That
// breakage is intended.
//
// You must not make a backward incompatible changes to the AIDL files built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.face;
@VintfStability
parcelable SensorProps {
android.hardware.biometrics.common.CommonProps commonProps;
android.hardware.biometrics.face.FaceSensorType sensorType;
boolean halControlsPreview;
}

View File

@@ -0,0 +1,33 @@
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
// edit this file. It looks like you are doing that because you have modified
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
// from an interface or a field from a parcelable and it broke the build. That
// breakage is intended.
//
// You must not make a backward incompatible changes to the AIDL files built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.face;
@Backing(type="byte") @VintfStability
enum SessionState {
IDLING = 0,
TERMINATED = 1,
GENERATING_CHALLENGE = 2,
REVOKING_CHALLENGE = 3,
ENROLLING = 4,
AUTHENTICATING = 5,
DETECTING_INTERACTION = 6,
ENUMERATING_ENROLLMENTS = 7,
REMOVING_ENROLLMENTS = 8,
GETTING_AUTHENTICATOR_ID = 9,
INVALIDATING_AUTHENTICATOR_ID = 10,
RESETTING_LOCKOUT = 11,
}

View File

@@ -0,0 +1,219 @@
/*
* 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.face;
@VintfStability
@Backing(type="byte")
enum AcquiredInfo {
/**
* The acquired face data was good, no further user interaction is necessary.
*/
GOOD = 0,
/**
* The acquired face data was too noisy or did not have sufficient detail.
* This is a catch-all for all acquisition errors not captured by the other
* constants.
*/
INSUFFICIENT = 1,
/**
* Because there was too much ambient light, the captured face data was too
* bright. It's reasonable to return this after multiple
* AcquiredInfo.INSUFFICIENT.
*
* The user is expected to take action to retry the operation in better
* lighting conditions when this is returned.
*/
TOO_BRIGHT = 2,
/**
* Because there was not enough illumination, the captured face data was too
* dark. It's reasonable to return this after multiple
* AcquiredInfo.INSUFFICIENT.
*
* The user is expected to take action to retry the operation in better
* lighting conditions when this is returned.
*/
TOO_DARK = 3,
/**
* The detected face is too close to the sensor, and the image cannot be
* processed.
*
* The user is expected to be informed to move further from the sensor when
* this is returned.
*/
TOO_CLOSE = 4,
/**
* The detected face is too small, as the user might be too far away from
* the sensor.
*
* The user is expected to be informed to move closer to the sensor when
* this is returned.
*/
TOO_FAR = 5,
/**
* Only the upper part of the face was detected. The sensor's field of view
* is too high.
*
* The user should be informed to move up with respect to the sensor when
* this is returned.
*/
FACE_TOO_HIGH = 6,
/**
* Only the lower part of the face was detected. The sensor's field of view
* is too low.
*
* The user should be informed to move down with respect to the sensor when
* this is returned.
*/
FACE_TOO_LOW = 7,
/**
* Only the right part of the face was detected. The sensor's field of view
* is too far right.
*
* The user should be informed to move to the right with respect to the
* sensor when this is returned.
*/
FACE_TOO_RIGHT = 8,
/**
* Only the left part of the face was detected. The sensor's field of view
* is too far left.
*
* The user should be informed to move to the left with respect to the
* sensor when this is returned.
*/
FACE_TOO_LEFT = 9,
/**
* The user's eyes have strayed away from the sensor. If this message is
* sent, the user should be informed to look at the device. If the user
* can't be found in the frame, one of the other acquisition messages
* must be sent, e.g. NOT_DETECTED.
*/
POOR_GAZE = 10,
/**
* No face was detected within the sensor's field of view.
*
* The user should be informed to point the sensor to a face when this is
* returned.
*/
NOT_DETECTED = 11,
/**
* Too much motion was detected.
*
* The user should be informed to keep their face steady relative to the
* sensor.
*/
TOO_MUCH_MOTION = 12,
/**
* The sensor needs to be re-calibrated. This is an unexpected condition,
* and must only be sent if a serious, uncorrectable, and unrecoverable
* calibration issue is detected which requires user intervention, e.g.
* re-enrolling. The expected response to this message is to direct the
* user to re-enroll.
*/
RECALIBRATE = 13,
/**
* The face is too different from a previous acquisition. This condition
* only applies to enrollment. This can happen if the user passes the
* device to someone else in the middle of enrollment.
*/
TOO_DIFFERENT = 14,
/**
* The face is too similar to a previous acquisition. This condition only
* applies to enrollment. The user should change their pose.
*/
TOO_SIMILAR = 15,
/**
* The magnitude of the pan angle of the users face with respect to the sensors
* capture plane is too high.
*
* The pan angle is defined as the angle swept out by the users face turning
* their neck left and right. The pan angle would be zero if the user faced the
* camera directly.
*
* The user should be informed to look more directly at the camera.
*/
PAN_TOO_EXTREME = 16,
/**
* The magnitude of the tilt angle of the users face with respect to the sensors
* capture plane is too high.
*
* The tilt angle is defined as the angle swept out by the users face looking up
* and down. The tilt angle would be zero if the user faced the camera directly.
*
* The user should be informed to look more directly at the camera.
*/
TILT_TOO_EXTREME = 17,
/**
* The magnitude of the roll angle of the users face with respect to the sensors
* capture plane is too high.
*
* The roll angle is defined as the angle swept out by the users face tilting their head
* towards their shoulders to the left and right. The roll angle would be zero if the user's
* head is vertically aligned with the camera.
*
* The user should be informed to look more directly at the camera.
*/
ROLL_TOO_EXTREME = 18,
/**
* The users face has been obscured by some object.
*
* The user should be informed to remove any objects from the line of sight from
* the sensor to the users face.
*/
FACE_OBSCURED = 19,
/**
* This message represents the earliest message sent at the beginning of the authentication
* pipeline. It is expected to be used to measure latency. For example, in a camera-based
* authentication system it's expected to be sent prior to camera initialization. Note this
* should be sent whenever authentication is restarted (see IBiometricsFace#userActivity).
* The framework will measure latency based on the time between the last START message and the
* onAuthenticated callback.
*/
START = 20,
/**
* The sensor is dirty. The user should be informed to clean the sensor.
*/
SENSOR_DIRTY = 21,
/**
* Vendor-specific acquisition message. See ISessionCallback#onAcquired vendorCode
* documentation.
*/
VENDOR = 22
}

View File

@@ -0,0 +1,92 @@
/*
* 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.face;
@VintfStability
@Backing(type="byte")
enum Error {
/**
* Reserved for testing and to keep subsequent numbering consistent with
* older interfaces.
*
* NO_ERROR = 0,
*/
/**
* A hardware error has occurred that cannot be resolved. Try again later.
*/
HW_UNAVAILABLE = 1,
/**
* The current enroll or authenticate operation could not be completed,
* e.g. the sensor was unable to process the current image or the HAT was
* invalid.
*/
UNABLE_TO_PROCESS = 2,
/**
* The current operation took too long to complete. This is intended to
* prevent programs from blocking the face HAL indefinitely. The timeout is
* framework and sensor-specific, but is generally on the order of 30
* seconds.
*
* The timeout is a device-specific time meant to optimize power. For
* example after 30 seconds of searching for a face it can be use to
* indicate that the implementation is no longer looking and the framework
* should restart the operation on the next user interaction.
*/
TIMEOUT = 3,
/**
* The current operation could not be completed because there is not enough
* storage space remaining to do so.
*/
NO_SPACE = 4,
/**
* The current operation has been cancelled. This may happen if a new
* request (authenticate, remove, enumerate, enroll) is initiated while
* an on-going operation is in progress, or if cancel() was called.
*/
CANCELED = 5,
/**
* The current remove operation could not be completed; the face template
* provided could not be removed.
*/
UNABLE_TO_REMOVE = 6,
/**
* Reserved to maintain backwards compatibility. See
* ISessionCallback#onLockoutTimed instead.
*
* LOCKOUT = 7,
*/
/**
* Used to enable a vendor-specific error message.
*/
VENDOR = 8,
/**
* Reserved to maintain backwards compatibility. See
* ISessionCallback#onLockoutPermanent instead.
*
* LOCKOUT_PERMANENT = 9
*/
}

View File

@@ -0,0 +1,24 @@
/*
* 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.face;
@VintfStability
@Backing(type="byte")
enum FaceSensorType {
RGB,
IR
}

View File

@@ -0,0 +1,50 @@
/*
* 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.face;
import android.hardware.biometrics.face.ISession;
import android.hardware.biometrics.face.ISessionCallback;
import android.hardware.biometrics.face.SensorProps;
@VintfStability
interface IFace {
/**
* getSensorProps:
*
* @return A list of properties for all face sensors available to the HAL.
*/
SensorProps[] getSensorProps();
/**
* createSession:
*
* Creates a session that can be used by the framework to perform operations such as
* enroll, authenticate, etc. for the given sensorId and userId.
*
* Implementations must store user-specific state or metadata in /data/vendor_de/<user>/facedata
* as specified by the SELinux policy. The directory /data/vendor_de is managed by vold (see
* vold_prepare_subdirs.cpp). Implementations may store additional user-specific data, such as
* embeddings or templates in StrongBox.
*
* @param sensorId The sensorId with which this session is being created.
* @param userId The userId with which this session is being created.
* @param cb A callback to notify the framework about the session's results and events.
* @return A new session.
*/
ISession createSession(in int sensorId, in int userId, in ISessionCallback cb);
}

View File

@@ -0,0 +1,369 @@
/*
* 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.face;
import android.hardware.biometrics.common.ICancellationSignal;
import android.hardware.keymaster.HardwareAuthToken;
import android.hardware.common.NativeHandle;
/**
* A session is a collection of immutable state (sensorId, userId), mutable state (SessionState),
* methods available for the framework to call, and a callback (ISessionCallback) to notify the
* framework about the events and results. A session is used to establish communication between
* the framework and the HAL.
*/
@VintfStability
interface ISession {
/**
* generateChallenge:
*
* Begins a secure transaction request. Note that the challenge by itself is not useful. It only
* becomes useful when wrapped in a verifiable message such as a HardwareAuthToken.
*
* Canonical example:
* 1) User requests an operation, such as face enrollment.
* 2) Face enrollment cannot happen until the user confirms their lockscreen credential
* (PIN/Pattern/Password).
* 3) However, the biometric subsystem does not want just "any" proof of credential
* confirmation. It needs proof that the user explicitly authenticated credential in order
* to allow addition of biometric enrollments.
* To secure this path, the following path is taken:
* 1) Upon user requesting face enroll, the framework requests
* IFace#generateChallenge
* 2) Framework sends the challenge to the credential subsystem, and upon credential
* confirmation, a HAT is created, containing the challenge in the "challenge" field.
* 3) Framework sends the HAT to the HAL, e.g. ISession#enroll.
* 4) Implementation verifies the authenticity and integrity of the HAT.
* 5) Implementation now has confidence that the user entered their credential to allow
* biometric enrollment.
*
* Note that the interface allows multiple in-flight challenges. For example, invoking
* generateChallenge(0, 0, timeoutSec) twice does not invalidate the first challenge. The
* challenge is invalidated only when:
* 1) The provided timeout expires, or
* 2) IFace#revokeChallenge is invoked
*
* For example, the following is a possible table of valid challenges:
* ----------------------------------------------
* | SensorId | UserId | ValidUntil | Challenge |
* |----------|--------|------------|-----------|
* | 0 | 0 | <Time1> | <Random1> |
* | 0 | 0 | <Time2> | <Random2> |
* | 1 | 0 | <Time3> | <Random3> |
* | 0 | 10 | <Time4> | <Random4> |
* ----------------------------------------------
*
* @param cookie A unique number identifying this operation
* @param sensorId Sensor to associate the challenge with
* @param userId User to associate the challenge with
* @param timeoutSec Duration for which the challenge is valid for
*/
void generateChallenge(in int cookie, in int sensorId, in int userId, in int timeoutSec);
/**
* revokeChallenge:
*
* Revokes a challenge that was previously generated. Note that if an invalid combination of
* parameters is requested, the implementation must still notify the framework using the
* provided callback.
*
* @param cookie A unique number identifying this operation
* @param sensorId Sensor that the revocation should apply to.
* @param userId User that the revocation should apply to.
* @param challenge Challenge that should be revoked.
*/
void revokeChallenge(in int cookie, in int sensorId, in int userId, in long challenge);
/**
* enroll:
*
* A request to add a face enrollment.
*
* Once the HAL is able to start processing the enrollment request, it must notify the framework
* via ISessionCallback#onStateChanged with SessionState::ENROLLING.
*
* At any point during enrollment, if a non-recoverable error occurs, the HAL must notify the
* framework via ISessionCallback#onError with the applicable enrollment-specific error, and
* then send ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no subsequent
* operation is in the queue.
*
* Before capturing face data, the implementation must first verify the authenticity and
* integrity of the provided HardwareAuthToken. In addition, it must check that the challenge
* within the provided HardwareAuthToken is valid. See IFace#generateChallenge. If any of
* the above checks fail, the framework must be notified via ISessionCallback#onError and the
* HAL must notify the framework when it returns to the idle state. See
* Error::UNABLE_TO_PROCESS.
*
* During enrollment, the implementation may notify the framework via
* ISessionCallback#onAcquired with messages that may be used to guide the user. This callback
* can be invoked multiple times if necessary. Similarly, the framework may be notified of
* enrollment progress changes via ISessionCallback#onEnrollmentProgress. Once the framework is
* notified that there are 0 "remaining" steps, the framework may cache the "enrollmentId". See
* ISessionCallback#onEnrollmentProgress for more info. The HAL must notify the framework once
* it returns to the idle state.
*
* When a finger is successfully added and before the framework is notified of remaining=0, the
* implementation MUST update and associate this (sensorId, userId) pair with a new new
* entropy-encoded random identifier. See ISession#getAuthenticatorId for more information.
*
* @param cookie An identifier used to track subsystem operations related to this call path. The
* client must guarantee that it is unique per ISession.
* @param previewSurface A surface provided by the framework if SensorProps#halControlsPreview is
* set to true. The HAL must send the preview frames to previewSurface if
* it's not null.
* @param hat See above documentation.
* @return ICancellationSignal An object that can be used by the framework to cancel this
* operation.
*/
ICancellationSignal enroll(in int cookie, in HardwareAuthToken hat, in NativeHandle previewSurface);
/**
* authenticate:
*
* A request to start looking for faces to authenticate.
*
* Once the HAL is able to start processing the authentication request, it must notify framework
* via ISessionCallback#onStateChanged with SessionState::AUTHENTICATING.
*
* At any point during authentication, if a non-recoverable error occurs, the HAL must notify
* the framework via ISessionCallback#onError with the applicable authentication-specific error,
* and then send ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no
* subsequent operation is in the queue.
*
* During authentication, the implementation may notify the framework via
* ISessionCallback#onAcquired with messages that may be used to guide the user. This callback
* can be invoked multiple times if necessary.
*
* The HAL must notify the framework of accepts/rejects via ISessionCallback#onAuthentication*.
*
* The authentication lifecycle ends when either
* 1) A face is accepted, and ISessionCallback#onAuthenticationSucceeded is invoked, or
* 2) Any non-recoverable error occurs (such as lockout). See the full list of
* authentication-specific errors in the Error enum.
*
* Note that upon successful authentication, the lockout counter for this (sensorId, userId)
* pair must be cleared.
*
* Note that upon successful authentication, ONLY sensors configured as SensorStrength::STRONG
* are allowed to create and send a HardwareAuthToken to the framework. See the Android CDD for
* more details. For SensorStrength::STRONG sensors, the HardwareAuthToken's "challenge" field
* must be set with the operationId passed in during #authenticate. If the sensor is NOT
* SensorStrength::STRONG, the HardwareAuthToken MUST be null.
*
* @param cookie An identifier used to track subsystem operations related to this call path. The
* client must guarantee that it is unique per ISession.
* @param operationId For sensors configured as SensorStrength::STRONG, this must be used ONLY
* upon successful authentication and wrapped in the HardwareAuthToken's
* "challenge" field and sent to the framework via
* ISessionCallback#onAuthenticated. The operationId is an opaque identifier
* created from a separate secure subsystem such as, but not limited to
* KeyStore/KeyMaster. The HardwareAuthToken can then be used as an
* attestation for the provided operation. For example, this is used
* to unlock biometric-bound auth-per-use keys (see
* setUserAuthenticationParameters in KeyGenParameterSpec.Builder and
* KeyProtection.Builder.
* @return ICancellationSignal An object that can be used by the framework to cancel this
* operation.
*/
ICancellationSignal authenticate(in int cookie, in long operationId);
/**
* detectInteraction:
*
* A request to start looking for faces without performing matching.
*
* Once the HAL is able to start processing this request, it must notify the framework via
* ISessionCallback#onStateChanged with SessionState::DETECTING_INTERACTION.
*
* The framework will use this method in cases where determing user presence is required, but
* identifying/authentication is not. For example, when the device is encrypted (first boot) or
* in lockdown mode.
*
* At any point during detectInteraction, if a non-recoverable error occurs, the HAL must notify
* the framework via ISessionCallback#onError with the applicable error, and then send
* ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no subsequent operation is
* in the queue.
*
* The implementation must only check for a face-like image was detected (e.g. to
* minimize interactions due to non-face objects), and the lockout counter must not
* be modified.
*
* Upon detecting any face, the implementation must invoke
* ISessionCallback#onInteractionDetected.
*
* The lifecycle of this operation ends when either
* 1) Any face is detected and the framework is notified via
* ISessionCallback#onInteractiondetected
* 2) The operation was cancelled by the framework (see ICancellationSignal)
* 3) The HAL ends the operation, for example when a subsequent operation pre-empts this one.
*
* Note that if the operation is canceled, the implementation must notify the framework via
* ISessionCallback#onError with Error::CANCELED.
*
* @param cookie An identifier used to track subsystem operations related to this call path.
* The framework will guarantee that it is unique per ISession.
* @return ICancellationSignal An object that can be used by the framework to cancel this
* operation.
*/
ICancellationSignal detectInteraction(in int cookie);
/*
* enumerateEnrollments:
*
* A request to enumerate (list) the enrollments for this (sensorId, userId) pair. The
* framework typically uses this to ensure that its cache is in sync with the HAL.
*
* Once the HAL is able to start processing this request, it must notify the framework via
* ISessionCallback#onStateChanged with SessionState::ENUMERATING_ENROLLMENTS.
*
* The implementation must then notify the framework with a list of enrollments applicable
* for the current session via ISessionCallback#onEnrollmentsEnumerated.
*
* @param cookie An identifier used to track subsystem operations related to this call path.
* The framework will guarantee that it is unique per ISession.
*/
void enumerateEnrollments(in int cookie);
/**
* removeEnrollments:
*
* A request to remove the enrollments for this (sensorId, userId) pair.
*
* Once the HAL is able to start processing this request, it must notify the framework via
* ISessionCallback#onStateChanged with SessionState::REMOVING_ENROLLMENTS.
*
* After removing the enrollmentIds from everywhere necessary (filesystem, secure subsystems,
* etc), the implementation must notify the framework via ISessionCallback#onEnrollmentsRemoved.
*
* @param cookie An identifier used to track subsystem operations related to this call path.
* The framework will guarantee that it is unique per ISession.
*/
void removeEnrollments(in int cookie, in int[] enrollmentIds);
/**
* getAuthenticatorId:
*
* MUST return 0 via ISessionCallback#onAuthenticatorIdRetrieved for sensors that are configured
* as SensorStrength::WEAK or SensorStrength::CONVENIENCE.
*
* The following only applies to sensors that are configured as SensorStrength::STRONG.
*
* The authenticatorId is a (sensorId, user)-specific identifier which can be used during key
* generation and key import to to associate a key (in KeyStore / KeyMaster) with the current
* set of enrolled faces. For example, the following public Android APIs allow for keys
* to be invalidated when the user adds a new enrollment after the key was created:
* KeyGenParameterSpec.Builder.setInvalidatedByBiometricEnrollment and
* KeyProtection.Builder.setInvalidatedByBiometricEnrollment.
*
* In addition, upon successful face authentication, the signed HAT that is returned to
* the framework via ISessionCallback#onAuthenticated must contain this identifier in the
* authenticatorId field.
*
* Returns an entropy-encoded random identifier associated with the current set of enrollments
* via ISessionCallback#onAuthenticatorIdRetrieved. The authenticatorId
* 1) MUST change whenever a new face is enrolled
* 2) MUST return 0 if no faces are enrolled
* 3) MUST not change if a face is deleted.
* 4) MUST be an entropy-encoded random number
*
* @param cookie An identifier used to track subsystem operations related to this call path. The
* client must guarantee that it is unique per ISession.
*/
void getAuthenticatorId(in int cookie);
/**
* invalidateAuthenticatorId:
*
* This method only applies to sensors that are configured as SensorStrength::STRONG. If invoked
* by the framework for sensor of other strengths, the HAL should immediately invoke
* ISessionCallback#onAuthenticatorIdInvalidated.
*
* The following only applies to sensors that are configured as SensorStrength::STRONG.
*
* When invoked by the framework, the implementation must perform the following sequence of
* events:
* 1) Verify the authenticity and integrity of the provided HAT. If this check fails, the HAL
* must invoke ISessionCallback#onError with Error::UNABLE_TO_PROCESS and return to
* SessionState::IDLING if no subsequent work is in the queue.
* 2) Verify that the timestamp provided within the HAT is relatively recent (e.g. on the
* order of minutes, not hours). If this check fails, the HAL must invoke
* ISessionCallback#onError with Error::UNABLE_TO_PROCESS and return to
* SessionState::IDLING if no subsequent work is in the queue.
* 3) Update the authenticatorId with a new entropy-encoded random number
* 4) Persist the new authenticatorId to non-ephemeral storage
* 5) Notify the framework that the above is completed, via
* ISessionCallback#onAuthenticatorInvalidated
*
* A practical use case of invalidation would be when the user adds a new enrollment to a sensor
* managed by a different HAL instance. The public android.security.keystore APIs bind keys to
* "all biometrics" rather than "face-only" or "face-only" (see #getAuthenticatorId
* for more details). As such, the framework would coordinate invalidation across multiple
* biometric HALs as necessary.
*
* @param cookie An identifier used to track subsystem operations related to this call path. The
* client must guarantee that it is unique per ISession.
*/
void invalidateAuthenticatorId(in int cookie);
/**
* resetLockout:
*
* Requests the implementation to clear the lockout counter. Upon receiving this request, the
* implementation must perform the following:
* 1) Verify the authenticity and integrity of the provided HAT
* 2) Verify that the timestamp provided within the HAT is relatively recent (e.g. on the
* order of minutes, not hours).
* If either of the checks fail, the HAL must invoke ISessionCallback#onError with
* Error::UNABLE_TO_PROCESS and return to SessionState::IDLING if no subsequent work is in the
* queue.
*
* Upon successful verification, the HAL must clear the lockout counter and notify the framework
* via ISessionCallback#onLockoutCleared.
*
* Note that lockout is user AND sensor specific. In other words, there is a separate lockout
* state for each (user, sensor) pair. For example, the following is a valid state on a
* multi-sensor device:
* ------------------------------------------------------------------
* | SensorId | UserId | FailedAttempts | LockedOut | LockedUntil |
* |----------|--------|----------------|-----------|---------------|
* | 0 | 0 | 1 | false | x |
* | 1 | 0 | 5 | true | <future_time> |
* | 0 | 10 | 0 | false | x |
* | 1 | 10 | 0 | false | x |
* ------------------------------------------------------------------
*
* Lockout may be cleared in the following ways:
* 1) ISession#resetLockout
* 2) After a period of time, according to a rate-limiter.
*
* Note that the "FailedAttempts" counter must be cleared upon successful face
* authentication. For example, if SensorId=0 UserId=0 FailedAttempts=1, and a successful
* face authentication occurs, the counter for that (SensorId, UserId) pair must be reset
* to 0.
*
* In addition, lockout states MUST persist after device reboots, HAL crashes, etc.
*
* See the Android CDD section 7.3.10 for the full set of lockout and rate-limiting
* requirements.
*
* @param cookie An identifier used to track subsystem operations related to this call path. The
* client must guarantee that it is unique per ISession.
* @param hat HardwareAuthToken See above documentation.
*/
void resetLockout(in int cookie, in HardwareAuthToken hat);
}

View File

@@ -0,0 +1,200 @@
/*
* 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.face;
import android.hardware.biometrics.face.AcquiredInfo;
import android.hardware.biometrics.face.Error;
import android.hardware.biometrics.face.SessionState;
import android.hardware.keymaster.HardwareAuthToken;
@VintfStability
interface ISessionCallback {
/**
* Used to notify the framework of session state changes. See ISession for more information.
*/
void onStateChanged(in int cookie, in SessionState state);
/**
* Notifies the framework when a challenge is successfully generated.
*/
void onChallengeGenerated(in int sensorId, in int userId, in long challenge);
/**
* Notifies the framework when a challenge has been revoked.
*/
void onChallengeRevoked(in int sensorId, in int userId, in long challenge);
/**
* This method must only be used to notify the framework during the following states:
* 1) SessionState::ENROLLING
* 2) SessionState::AUTHENTICATING
* 3) SessionState::DETECTING_INTERACTION
*
* These messages may be used to provide user guidance multiple times if necessary per
* operation.
*
* @param info See the AcquiredInfo enum.
* @param vendorCode Only valid if info == AcquiredInfo::VENDOR. The vendorCode must be used to
* index into the configuration
* com.android.internal.R.array.face_acquired_vendor that's installed
* on the vendor partition.
*/
void onAcquired(in AcquiredInfo info, in int vendorCode);
/**
* This method must only be used to notify the framework during the following states:
* 1) SessionState::ENROLLING
* 2) SessionState::AUTHENTICATING
* 3) SessionState::DETECTING_INTERACTION
* 4) SessionState::INVALIDATING_AUTHENTICATOR_ID
* 5) SessionState::RESETTING_LOCKOUT
*
* These messages may be used to notify the framework or user that a non-recoverable error
* has occurred. The operation is finished, and the HAL must proceed with the next operation
* or return to SessionState::IDLING if the queue is empty.
*
* Note that cancellation (see common::ICancellationSignal) and preemption most be followed with
* an Error::CANCELED message.
*
* @param error See the Error enum.
* @param vendorCode Only valid if error == Error::VENDOR. The vendorCode must be used to index
* into the configuration
* com.android.internal.R.face_error_vendor that's installed on the
* vendor partition.
*/
void onError(in Error error, in int vendorCode);
/**
* This method must only be used to notify the framework during the following state:
* 1) SessionState::ENROLLING
*
* @param enrollmentId Unique stable identifier for the enrollment that's being added by this
* ISession#enroll invocation.
* @param remaining Remaining number of steps before enrollment is complete.
*/
void onEnrollmentProgress(in int enrollmentId, int remaining);
/**
* This method must only be used to notify the framework during SessionState::AUTHENTICATING.
*
* Used to notify the framework upon successful authentication. Note that the authentication
* lifecycle ends when either 1) a face is accepted, or 2) an error occurred. The
* authentication lifecycle does NOT end when a face is rejected.
*
* @param enrollmentId Face that was accepted.
* @param hat If the sensor is configured as SensorStrength::STRONG, a non-null attestation that
* a face was accepted. The HardwareAuthToken's "challenge" field must be set
* with the operationId passed in during ISession#authenticate. If the sensor is NOT
* SensorStrength::STRONG, the HardwareAuthToken MUST be null.
*/
void onAuthenticationSucceeded(in int enrollmentId, in HardwareAuthToken hat);
/**
* This method must only be used to notify the framework during SessionState::AUTHENTICATING.
*
* Used to notify the framework upon rejected attempts. Note that the authentication
* lifecycle ends when either 1) a face is accepted, or 2) an occurred. The
* authentication lifecycle does NOT end when a face is rejected.
*/
void onAuthenticationFailed();
/**
* This method must only be used to notify the framework during SessionState::AUTHENTICATING.
*
* Authentication is locked out due to too many unsuccessful attempts. This is a rate-limiting
* lockout, and authentication can be restarted after a period of time. See
* ISession#resetLockout.
*
* @param sensorId Sensor for which the user is locked out.
* @param userId User for which the sensor is locked out.
* @param durationMillis Remaining duration of the lockout.
*/
void onLockoutTimed(in long durationMillis);
/**
* This method must only be used to notify the framework during SessionState::AUTHENTICATING.
*
* Authentication is disabled until the user unlocks with their device credential
* (PIN/Pattern/Password). See ISession#resetLockout.
*
* @param sensorId Sensor for which the user is locked out.
* @param userId User for which the sensor is locked out.
*/
void onLockoutPermanent();
/**
* Notifies the framework that lockout has been cleared for this (sensorId, userId) pair.
*
* Note that this method can be used to notify the framework during any state.
*
* Lockout can be cleared in the following scenarios:
* 1) A timed lockout has ended (e.g. durationMillis specified in previous #onLockoutTimed
* has expired.
* 2) See ISession#resetLockout.
*
* @param sensorId Sensor for which the user's lockout is cleared.
* @param userId User for the sensor's lockout is cleared.
*/
void onLockoutCleared();
/**
* This method must only be used to notify the framework during
* SessionState::DETECTING_INTERACTION
*
* Notifies the framework that user interaction occurred. See ISession#detectInteraction.
*/
void onInteractionDetected();
/**
* This method must only be used to notify the framework during
* SessionState::ENUMERATING_ENROLLMENTS.
*
* Notifies the framework of the current enrollments. See ISession#enumerateEnrollments.
*
* @param enrollmentIds A list of enrollments for the session's (userId, sensorId) pair.
*/
void onEnrollmentsEnumerated(in int[] enrollmentIds);
/**
* This method must only be used to notify the framework during
* SessionState::REMOVING_ENROLLMENTS.
*
* Notifies the framework that the specified enrollments are removed.
*
* @param enrollmentIds The enrollments that were removed.
*/
void onEnrollmentsRemoved(in int[] enrollmentIds);
/**
* This method must only be used to notify the framework during
* SessionState::GETTING_AUTHENTICATOR_ID.
*
* Notifies the framework with the authenticatorId corresponding to this session's
* (userId, sensorId) pair.
*
* @param authenticatorId See the above documentation.
*/
void onAuthenticatorIdRetrieved(in long authenticatorId);
/**
* This method must only be used to notify the framework during
* SessionState::INVALIDATING_AUTHENTICATOR_ID.
*
* See ISession#invalidateAuthenticatorId for more information.
*/
void onAuthenticatorIdInvalidated();
}

View File

@@ -0,0 +1,43 @@
/*
* 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.face;
import android.hardware.biometrics.common.CommonProps;
import android.hardware.biometrics.face.FaceSensorType;
@VintfStability
parcelable SensorProps {
/**
* Statically configured properties that apply to this face sensor.
*/
CommonProps commonProps;
/**
* A statically configured sensor type representing this face sensor.
*/
FaceSensorType sensorType;
/**
* Whether or not the HAL is responsible for showing the face enrollment preview to the user.
* Devices with multiple front camera sensors can set this to false and rely on the framework to
* show the preview with one of the unused cameras. Devices with a single front sensor must set
* this to true and configure their send their camera stream to the preview surface provided by
* the framework.
*/
boolean halControlsPreview;
}

View File

@@ -0,0 +1,82 @@
/*
* 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.face;
@VintfStability
@Backing(type="byte")
enum SessionState {
/**
* The HAL is not processing any session requests.
*/
IDLING,
/**
* The session has been terminated by the HAL.
*/
TERMINATED,
/**
* The HAL is processing the ISession#generateChallenge request.
*/
GENERATING_CHALLENGE,
/**
* The HAL is processing the ISession#revokeChallenge request.
*/
REVOKING_CHALLENGE,
/**
* The HAL is processing the ISession#enroll request.
*/
ENROLLING,
/**
* The HAL is processing the ISession#authenticate request.
*/
AUTHENTICATING,
/**
* The HAL is processing the ISession#detectInteraction request.
*/
DETECTING_INTERACTION,
/**
* The HAL is processing the ISession#enumerateEnrollments request.
*/
ENUMERATING_ENROLLMENTS,
/**
* The HAL is processing the ISession#removeEnrollments request.
*/
REMOVING_ENROLLMENTS,
/**
* The HAL is processing the ISession#getAuthenticatorId request.
*/
GETTING_AUTHENTICATOR_ID,
/**
* The HAL is processing the ISession#invalidateAuthenticatorId request.
*/
INVALIDATING_AUTHENTICATOR_ID,
/**
* The HAL is processing the ISession#resetLockout request.
*/
RESETTING_LOCKOUT
}

View File

@@ -0,0 +1,18 @@
cc_binary {
name: "android.hardware.biometrics.face-service.example",
relative_install_path: "hw",
init_rc: ["face-default.rc"],
vintf_fragments: ["face-default.xml"],
vendor: true,
shared_libs: [
"libbase",
"libbinder_ndk",
"android.hardware.biometrics.face-ndk_platform",
"android.hardware.biometrics.common-unstable-ndk_platform",
],
srcs: [
"main.cpp",
"Face.cpp",
"Session.cpp",
],
}

View File

@@ -0,0 +1,61 @@
/*
* 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.
*/
#include "Face.h"
#include "Session.h"
namespace aidl::android::hardware::biometrics::face {
const int kSensorId = 0;
const common::SensorStrength kSensorStrength = common::SensorStrength::WEAK;
const int kMaxEnrollmentsPerUser = 5;
const FaceSensorType kSensorType = FaceSensorType::RGB;
const bool kHalControlsPreview = true;
const std::string kHwDeviceName = "faceSensor";
const std::string kHardwareVersion = "vendor/model/revision";
const std::string kFirmwareVersion = "1.01";
const std::string kSerialNumber = "00000001";
ndk::ScopedAStatus Face::getSensorProps(std::vector<SensorProps>* return_val) {
common::HardwareInfo hardware_info;
hardware_info.deviceName = kHwDeviceName;
hardware_info.hardwareVersion = kHardwareVersion;
hardware_info.firmwareVersion = kFirmwareVersion;
hardware_info.serialNumber = kSerialNumber;
common::CommonProps commonProps;
commonProps.sensorId = kSensorId;
commonProps.sensorStrength = kSensorStrength;
commonProps.maxEnrollmentsPerUser = kMaxEnrollmentsPerUser;
commonProps.hardwareInfo = {std::move(hardware_info)};
SensorProps props;
props.commonProps = std::move(commonProps);
props.sensorType = kSensorType;
props.halControlsPreview = kHalControlsPreview;
*return_val = {std::move(props)};
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Face::createSession(int32_t /*sensorId*/, int32_t /*userId*/,
const std::shared_ptr<ISessionCallback>& cb,
std::shared_ptr<ISession>* return_val) {
*return_val = SharedRefBase::make<Session>(cb);
return ndk::ScopedAStatus::ok();
}
} // namespace aidl::android::hardware::biometrics::face

View File

@@ -0,0 +1,32 @@
/*
* 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.
*/
#pragma once
#include <aidl/android/hardware/biometrics/face/BnFace.h>
namespace aidl::android::hardware::biometrics::face {
class Face : public BnFace {
public:
ndk::ScopedAStatus getSensorProps(std::vector<SensorProps>* _aidl_return) override;
ndk::ScopedAStatus createSession(int32_t sensorId, int32_t userId,
const std::shared_ptr<ISessionCallback>& cb,
std::shared_ptr<ISession>* _aidl_return) override;
};
} // namespace aidl::android::hardware::biometrics::face

View File

@@ -0,0 +1,82 @@
/*
* 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.
*/
#include <aidl/android/hardware/biometrics/common/BnCancellationSignal.h>
#include "Session.h"
namespace aidl::android::hardware::biometrics::face {
class CancellationSignal : public common::BnCancellationSignal {
public:
ndk::ScopedAStatus cancel() override { return ndk::ScopedAStatus::ok(); }
};
Session::Session(std::shared_ptr<ISessionCallback> cb) : cb_(std::move(cb)) {}
ndk::ScopedAStatus Session::generateChallenge(int32_t /*cookie*/, int32_t /*sensorId*/,
int32_t /*userId*/, int32_t /*timeoutSec*/) {
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Session::revokeChallenge(int32_t /*cookie*/, int32_t /*sensorId*/,
int32_t /*userId*/, int64_t /*challenge*/) {
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Session::enroll(int32_t /*cookie*/, const keymaster::HardwareAuthToken& /*hat*/,
const NativeHandle& /*previewSurface*/,
std::shared_ptr<biometrics::common::ICancellationSignal>*
/*returnVal*/) {
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Session::authenticate(int32_t /*cookie*/, int64_t /*keystoreOperationId*/,
std::shared_ptr<common::ICancellationSignal>* return_val) {
if (cb_) {
cb_->onStateChanged(0, SessionState::AUTHENTICATING);
}
*return_val = SharedRefBase::make<CancellationSignal>();
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Session::detectInteraction(
int32_t /*cookie*/, std::shared_ptr<common::ICancellationSignal>* /*return_val*/) {
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Session::enumerateEnrollments(int32_t /*cookie*/) {
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Session::removeEnrollments(int32_t /*cookie*/,
const std::vector<int32_t>& /*enrollmentIds*/) {
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Session::getAuthenticatorId(int32_t /*cookie*/) {
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Session::invalidateAuthenticatorId(int32_t /*cookie*/) {
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Session::resetLockout(int32_t /*cookie*/,
const keymaster::HardwareAuthToken& /*hat*/) {
return ndk::ScopedAStatus::ok();
}
} // namespace aidl::android::hardware::biometrics::face

View File

@@ -0,0 +1,67 @@
/*
* 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.
*/
#pragma once
#include <aidl/android/hardware/biometrics/face/BnSession.h>
#include <aidl/android/hardware/biometrics/face/ISessionCallback.h>
namespace aidl::android::hardware::biometrics::face {
namespace common = aidl::android::hardware::biometrics::common;
namespace keymaster = aidl::android::hardware::keymaster;
using aidl::android::hardware::common::NativeHandle;
class Session : public BnSession {
public:
explicit Session(std::shared_ptr<ISessionCallback> cb);
ndk::ScopedAStatus generateChallenge(int32_t cookie, int32_t sensorId, int32_t userId,
int32_t timeoutSec) override;
ndk::ScopedAStatus revokeChallenge(int32_t cookie, int32_t sensorId, int32_t userId,
int64_t challenge) override;
ndk::ScopedAStatus enroll(
int32_t cookie, const keymaster::HardwareAuthToken& hat,
const NativeHandle& previewSurface,
std::shared_ptr<biometrics::common::ICancellationSignal>* returnVal) override;
ndk::ScopedAStatus authenticate(
int32_t cookie, int64_t keystoreOperationId,
std::shared_ptr<common::ICancellationSignal>* returnVal) override;
ndk::ScopedAStatus detectInteraction(
int32_t cookie, std::shared_ptr<common::ICancellationSignal>* returnVal) override;
ndk::ScopedAStatus enumerateEnrollments(int32_t cookie) override;
ndk::ScopedAStatus removeEnrollments(int32_t cookie,
const std::vector<int32_t>& enrollmentIds) override;
ndk::ScopedAStatus getAuthenticatorId(int32_t cookie) override;
ndk::ScopedAStatus invalidateAuthenticatorId(int32_t cookie) override;
ndk::ScopedAStatus resetLockout(int32_t cookie,
const keymaster::HardwareAuthToken& hat) override;
private:
std::shared_ptr<ISessionCallback> cb_;
};
} // namespace aidl::android::hardware::biometrics::face

View File

@@ -0,0 +1,5 @@
service vendor.face-default /vendor/bin/hw/android.hardware.biometrics.face-service.example
class hal
user nobody
group nobody

View File

@@ -0,0 +1,6 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.biometrics.face</name>
<fqname>IFace/default</fqname>
</hal>
</manifest>

View File

@@ -0,0 +1,36 @@
/*
* 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.
*/
#include "Face.h"
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
using aidl::android::hardware::biometrics::face::Face;
int main() {
LOG(INFO) << "Face HAL started";
ABinderProcess_setThreadPoolMaxThreadCount(0);
std::shared_ptr<Face> hal = ndk::SharedRefBase::make<Face>();
const std::string instance = std::string(Face::descriptor) + "/default";
binder_status_t status = AServiceManager_addService(hal->asBinder().get(), instance.c_str());
CHECK(status == STATUS_OK);
ABinderProcess_joinThreadPool();
return EXIT_FAILURE; // should not reach
}

View File

@@ -0,0 +1,16 @@
cc_test {
name: "VtsHalBiometricsFaceTargetTest",
defaults: [
"VtsHalTargetTestDefaults",
"use_libaidlvintf_gtest_helper_static",
],
srcs: ["VtsHalBiometricsFaceTargetTest.cpp"],
shared_libs: [
"libbinder_ndk",
"android.hardware.biometrics.face-ndk_platform",
],
test_suites: [
"general-tests",
"vts",
],
}

View File

@@ -0,0 +1,157 @@
/*
* 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.
*/
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
#include <aidl/android/hardware/biometrics/face/BnFace.h>
#include <aidl/android/hardware/biometrics/face/BnSessionCallback.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <future>
namespace aidl::android::hardware::biometrics::face {
namespace {
constexpr int kSensorId = 0;
constexpr int kUserId = 0;
constexpr auto kCallbackTimeout = std::chrono::seconds(1);
enum class SessionCallbackMethodName {
kOnStateChanged,
};
struct SessionCallbackInvocation {
SessionCallbackMethodName method_name;
SessionState state;
};
class SessionCallback : public BnSessionCallback {
public:
explicit SessionCallback(std::promise<SessionCallbackInvocation> invocation_promise)
: invocation_promise_(std::move(invocation_promise)) {}
ndk::ScopedAStatus onStateChanged(int32_t /*cookie*/, SessionState state) override {
SessionCallbackInvocation invocation = {};
invocation.method_name = SessionCallbackMethodName::kOnStateChanged;
invocation.state = state;
invocation_promise_.set_value(invocation);
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus onChallengeGenerated(int32_t /*sensorId*/, int32_t /*userId*/,
int64_t /*challenge*/) override {
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus onChallengeRevoked(int32_t /*sensorId*/, int32_t /*userId*/,
int64_t /*challenge*/) override {
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus onAcquired(AcquiredInfo /*info*/, int32_t /*vendorCode*/) override {
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus onError(Error /*error*/, int32_t /*vendorCode*/) override {
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus onEnrollmentProgress(int32_t /*enrollmentId*/,
int32_t /*remaining*/) override {
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus onAuthenticationSucceeded(
int32_t /*enrollmentId*/, const keymaster::HardwareAuthToken& /*hat*/) override {
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus onAuthenticationFailed() override { return ndk::ScopedAStatus::ok(); }
ndk::ScopedAStatus onLockoutTimed(int64_t /*durationMillis*/) override {
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus onLockoutPermanent() override { return ndk::ScopedAStatus::ok(); }
ndk::ScopedAStatus onLockoutCleared() override { return ndk::ScopedAStatus::ok(); }
ndk::ScopedAStatus onInteractionDetected() override { return ndk::ScopedAStatus::ok(); }
ndk::ScopedAStatus onEnrollmentsEnumerated(
const std::vector<int32_t>& /*enrollmentIds*/) override {
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus onEnrollmentsRemoved(
const std::vector<int32_t>& /*enrollmentIds*/) override {
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus onAuthenticatorIdRetrieved(int64_t /*authenticatorId*/) override {
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus onAuthenticatorIdInvalidated() override { return ndk::ScopedAStatus::ok(); }
private:
std::promise<SessionCallbackInvocation> invocation_promise_;
};
class Face : public testing::TestWithParam<std::string> {
protected:
void SetUp() override {
AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
ASSERT_NE(binder, nullptr);
hal_ = IFace::fromBinder(ndk::SpAIBinder(binder));
}
std::shared_ptr<IFace> hal_;
};
TEST_P(Face, AuthenticateTest) {
std::promise<SessionCallbackInvocation> invocation_promise;
std::future<SessionCallbackInvocation> invocation_future = invocation_promise.get_future();
std::shared_ptr<SessionCallback> session_cb =
ndk::SharedRefBase::make<SessionCallback>(std::move(invocation_promise));
std::shared_ptr<ISession> session;
ASSERT_TRUE(hal_->createSession(kSensorId, kUserId, session_cb, &session).isOk());
std::shared_ptr<common::ICancellationSignal> cancel_cb;
ASSERT_TRUE(session->authenticate(0, 0, &cancel_cb).isOk());
ASSERT_EQ(invocation_future.wait_for(kCallbackTimeout), std::future_status::ready);
SessionCallbackInvocation invocation = invocation_future.get();
EXPECT_EQ(invocation.method_name, SessionCallbackMethodName::kOnStateChanged);
EXPECT_EQ(invocation.state, SessionState::AUTHENTICATING);
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Face);
INSTANTIATE_TEST_SUITE_P(IFace, Face,
testing::ValuesIn(::android::getAidlHalInstanceNames(IFace::descriptor)),
::android::PrintInstanceNameToString);
} // namespace
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
ABinderProcess_setThreadPoolMaxThreadCount(1);
ABinderProcess_startThreadPool();
return RUN_ALL_TESTS();
}
} // namespace aidl::android::hardware::biometrics::face

View File

@@ -96,6 +96,13 @@
<instance>default</instance>
</interface>
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.biometrics.face</name>
<interface>
<name>IFace</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.biometrics.fingerprint</name>
<version>2.1-3</version>