Google is committed to advancing racial equity for Black communities. See how.

Face Authentication HIDL


Face authentication allows users to unlock their device simply by looking at the front of their device. Android 10 adds support for a new face authentication stack that can securely process camera frames, preserving security and privacy during face authentication on supported hardware. Android 10 also provides an easy way for security compliant implementations to enable application integration for transactions, such as online banking or other services.

The Android face authentication stack is a new implementation in Android 10. The new implementation introduces the IBiometricsFace.hal, IBiometricsFaceClientCallback.hal, and types.hal interfaces.


The BiometricPrompt API includes all biometric authentication including, face, finger, and iris. The Face HAL interacts with the following components.

Biometric stack
Figure 1. Biometric stack


FaceManager is a private interface that maintains a connection with FaceService. It's used by Keyguard to access face authentication with a custom UI. Apps don't have access to FaceManager and must use BiometricPrompt instead.


This is the framework implementation that manages access to the face authentication hardware. It contains basic enrollment and authentication state machines as well as various other helpers (for example, enumeration). Because of stability and security concerns, no vendor code is permitted to run in this process. All vendor code is accessed through the Face 1.0 HIDL interface.


This is a Linux executable that implements the Face 1.0 HIDL interface used by FaceService. It registers itself as IBiometricsFace@1.0 so that FaceService can find it.



To implement the Face HIDL, you must implement all the methods of IBiometricsFace.hal in a vendor-specific library.

Error messages

Error messages are sent by a callback and return the state machine to the idle state after they're sent. Most messages have a corresponding user-facing string to inform the user of the error, but not all errors have this user-facing string. For more information on error messages, see types.hal. All error messages represent a terminal state, meaning the framework assumes that the HAL returns to an idle state after sending an error message.

Acquisition messages

Acquisition messages are delivered during enrollment or authentication and are meant to guide the user toward a successful enrollment or authentication. Each ordinal has an associated message from the file. Vendor-specific messages can be added as long as the corresponding help strings are provided. Acquisition messages aren't terminal states in and of themselves; the HAL is expected to send as many of these as necessary to complete the current enrollment or authentication. If an acquisition message results in a terminal state where no progress can be made, then the HAL should follow the acquisition messages with an error message, for example, where the image is too dark and stays too dark for progress to be made. In this case, it's reasonable to send UNABLE_TO_PROCESS after several attempts have been made but no further progress can be made.


For devices to comply with the strong biometric requirements for Android 10, they must have secure hardware to ensure the integrity of face data and the ultimate authentication comparison. The Android Compatibility Definition Document (CDD) outlines the level of security required and the acceptable spoof acceptance rate (SAR) required. A trusted execution environment (TEE) is required for secure processing and recognition. Additionally, secure camera hardware is required to prevent injection attacks on face authentication. For example, the associated memory pages for image data could be privileged and marked read-only so only the camera hardware can update them. Ideally, no process should have access except TEE and the hardware.

Because face authentication hardware varies considerably, it's necessary to develop hardware-specific drivers to enable face authentication, depending on specific device architecture. As such, there is no reference implementation for faced.


The following methods are all asynchronous and must immediately return to the framework. Failing to do so results in a slow system and potential Watchdog resets. It's recommended to have a message queue with multiple threads to avoid blocking the caller. All GET requests should cache information where possible so the caller is blocked for a minimal amount of time.

Method Description
setCallback() Called by FaceService to plumb all messages back to itself.
setActiveUser() Sets the active user, which all subsequent HAL operations are applied. Authentication is always for this user until this method is called again.
revokeChallenge() Finishes the secure transaction by invalidating the challenge generated by generateChallenge().
enroll() Enrolls a user's face.
cancel() Cancels the current operation (for example, enroll, authenticate, remove, or enumerate) and returns faced to the idle state.
enumerate() Enumerates all face templates associated with the active user.
remove() Removes a face template or all face templates associated with the active user.
authenticate() Authenticates the active user.
userActivity() This method should only be used when the HAL is in the authenticating or standby state. Using this method when the HAL is not in one of these states returns OPERATION_NOT_SUPPORTED. Calling this method while the HAL is already authenticating may extend the amount of time the system looks for a face.
resetLockout() When too many faces are rejected, faced is required to enter a lockout state (LOCKOUT or LOCKOUT_PERMANENT). When it does, it's required to send the remaining time to the framework so it can display it for the user. As with setFeature(), this method requires an active hardware authentication token (HAT) to securely reset the internal state. Resets lockout only for the current user.

The three remaining methods are all synchronous and should block for the minimal amount of time to avoid stalling the framework.

Method Description
generateChallenge() Generates a unique and cryptographically secure random token used to indicate the start of a secure transaction.
setFeature() Enables or disables a feature for the current user. For security reasons, this requires a HAT from checking the user's pin/pattern/password against the above challenge
getFeature() Retrieves the current enablement state of the feature, as dictated by the default or a call to setFeature() above. If the face ID is invalid, the implementation must return ILLEGAL_ARGUMENT
getAuthenticatorId() Returns an identifier associated with the current face set. This identifier must change whenever a face is added

State Diagram

The framework expects faced to follow the state diagram below.

State Diagram
Figure 2. Face authentication state flow