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

Commit c05b6dbe authored by Curtis Belmonte's avatar Curtis Belmonte Committed by Android (Google) Code Review
Browse files

Merge "Send AIDL face enrollment frame info to clients" into sc-dev

parents 64143732 e39cc9a1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.hardware.face;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.hardware.face.FaceEnrollStages.FaceEnrollStage;
import android.os.Parcel;
import android.os.Parcelable;

+29 −19
Original line number Diff line number Diff line
@@ -21,54 +21,64 @@ import android.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * A collection of constants representing different stages of face enrollment.
 *
 * @hide
 */
public final class FaceEnrollStages {
    // Prevent instantiation.
    private FaceEnrollStages() {}

    /**
     * A stage that may occur during face enrollment.
     *
     * @hide
     */
@Retention(RetentionPolicy.SOURCE)
    @IntDef({
    FaceEnrollStage.UNKNOWN,
    FaceEnrollStage.FIRST_FRAME_RECEIVED,
    FaceEnrollStage.WAITING_FOR_CENTERING,
    FaceEnrollStage.HOLD_STILL_IN_CENTER,
    FaceEnrollStage.ENROLLING_MOVEMENT_1,
    FaceEnrollStage.ENROLLING_MOVEMENT_2,
    FaceEnrollStage.ENROLLMENT_FINISHED
        UNKNOWN,
        FIRST_FRAME_RECEIVED,
        WAITING_FOR_CENTERING,
        HOLD_STILL_IN_CENTER,
        ENROLLING_MOVEMENT_1,
        ENROLLING_MOVEMENT_2,
        ENROLLMENT_FINISHED
    })
public @interface FaceEnrollStage {
    @Retention(RetentionPolicy.SOURCE)
    public @interface FaceEnrollStage {}

    /**
     * The current enrollment stage is not known.
     */
    int UNKNOWN = -1;
    public static final int UNKNOWN = 0;

    /**
     * Enrollment has just begun. No action is needed from the user yet.
     */
    int FIRST_FRAME_RECEIVED = 0;
    public static final int FIRST_FRAME_RECEIVED = 1;

    /**
     * The user must center their face in the frame.
     */
    int WAITING_FOR_CENTERING = 1;
    public static final int WAITING_FOR_CENTERING = 2;

    /**
     * The user must keep their face centered in the frame.
     */
    int HOLD_STILL_IN_CENTER = 2;
    public static final int HOLD_STILL_IN_CENTER = 3;

    /**
     * The user must follow a first set of movement instructions.
     */
    int ENROLLING_MOVEMENT_1 = 3;
    public static final int ENROLLING_MOVEMENT_1 = 4;

    /**
     * The user must follow a second set of movement instructions.
     */
    int ENROLLING_MOVEMENT_2 = 4;
    public static final int ENROLLING_MOVEMENT_2 = 5;

    /**
     * Enrollment has completed. No more action is needed from the user.
     */
    int ENROLLMENT_FINISHED = 5;
    public static final int ENROLLMENT_FINISHED = 6;
}
+40 −5
Original line number Diff line number Diff line
@@ -1022,6 +1022,34 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
        public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
        }

        /**
         * Called each time a single frame is captured during enrollment.
         *
         * <p>For older, non-AIDL implementations, only {@code helpCode} and {@code helpMessage} are
         * supported. Sensible default values will be provided for all other arguments.
         *
         * @param helpCode    An integer identifying the capture status for this frame.
         * @param helpMessage A human-readable help string that can be shown in UI.
         * @param cell        The cell captured during this frame of enrollment, if any.
         * @param stage       An integer representing the current stage of enrollment.
         * @param pan         The horizontal pan of the detected face. Values in the range [-1, 1]
         *                    indicate a good capture.
         * @param tilt        The vertical tilt of the detected face. Values in the range [-1, 1]
         *                    indicate a good capture.
         * @param distance    The distance of the detected face from the device. Values in
         *                    the range [-1, 1] indicate a good capture.
         */
        public void onEnrollmentFrame(
                int helpCode,
                @Nullable CharSequence helpMessage,
                @Nullable FaceEnrollCell cell,
                @FaceEnrollStages.FaceEnrollStage int stage,
                float pan,
                float tilt,
                float distance) {
            onEnrollmentHelp(helpCode, helpMessage);
        }

        /**
         * Called as each enrollment step progresses. Enrollment is considered complete when
         * remaining reaches 0. This function will not be called if enrollment fails. See
@@ -1305,7 +1333,7 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
        } else if (mEnrollmentCallback != null) {
            final FaceEnrollFrame frame = new FaceEnrollFrame(
                    null /* cell */,
                    FaceEnrollStage.UNKNOWN,
                    FaceEnrollStages.UNKNOWN,
                    new FaceDataFrame(acquireInfo, vendorCode));
            sendEnrollmentFrame(frame);
        }
@@ -1333,12 +1361,19 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
        if (frame == null) {
            Slog.w(TAG, "Received null enrollment frame");
        } else if (mEnrollmentCallback != null) {
            // TODO(b/178414967): Send additional frame data to callback
            final int acquireInfo = frame.getData().getAcquiredInfo();
            final int vendorCode = frame.getData().getVendorCode();
            final FaceDataFrame data = frame.getData();
            final int acquireInfo = data.getAcquiredInfo();
            final int vendorCode = data.getVendorCode();
            final int helpCode = getHelpCode(acquireInfo, vendorCode);
            final String helpMessage = getEnrollHelpMessage(mContext, acquireInfo, vendorCode);
            mEnrollmentCallback.onEnrollmentHelp(helpCode, helpMessage);
            mEnrollmentCallback.onEnrollmentFrame(
                    helpCode,
                    helpMessage,
                    frame.getCell(),
                    frame.getStage(),
                    data.getPan(),
                    data.getTilt(),
                    data.getDistance());
        }
    }

+104 −84
Original line number Diff line number Diff line
@@ -24,11 +24,14 @@ import android.hardware.biometrics.face.AuthenticationFrame;
import android.hardware.biometrics.face.BaseFrame;
import android.hardware.biometrics.face.Cell;
import android.hardware.biometrics.face.EnrollmentFrame;
import android.hardware.biometrics.face.EnrollmentStage;
import android.hardware.biometrics.face.Error;
import android.hardware.face.FaceAuthenticationFrame;
import android.hardware.face.FaceDataFrame;
import android.hardware.face.FaceEnrollCell;
import android.hardware.face.FaceEnrollFrame;
import android.hardware.face.FaceEnrollStages;
import android.hardware.face.FaceEnrollStages.FaceEnrollStage;

/**
 * Utilities for converting from hardware to framework-defined AIDL models.
@@ -38,95 +41,110 @@ final class AidlConversionUtils {
    private AidlConversionUtils() {
    }

    public static @BiometricFaceConstants.FaceError int toFrameworkError(byte aidlError) {
        if (aidlError == Error.UNKNOWN) {
            // No framework constant available
            return BiometricFaceConstants.FACE_ERROR_UNKNOWN;
        } else if (aidlError == Error.HW_UNAVAILABLE) {
    @BiometricFaceConstants.FaceError
    public static int toFrameworkError(byte aidlError) {
        switch (aidlError) {
            case Error.HW_UNAVAILABLE:
                return BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE;
        } else if (aidlError == Error.UNABLE_TO_PROCESS) {
            case Error.UNABLE_TO_PROCESS:
                return BiometricFaceConstants.FACE_ERROR_UNABLE_TO_PROCESS;
        } else if (aidlError == Error.TIMEOUT) {
            case Error.TIMEOUT:
                return BiometricFaceConstants.FACE_ERROR_TIMEOUT;
        } else if (aidlError == Error.NO_SPACE) {
            case Error.NO_SPACE:
                return BiometricFaceConstants.FACE_ERROR_NO_SPACE;
        } else if (aidlError == Error.CANCELED) {
            case Error.CANCELED:
                return BiometricFaceConstants.FACE_ERROR_CANCELED;
        } else if (aidlError == Error.UNABLE_TO_REMOVE) {
            case Error.UNABLE_TO_REMOVE:
                return BiometricFaceConstants.FACE_ERROR_UNABLE_TO_REMOVE;
        } else if (aidlError == Error.VENDOR) {
            case Error.VENDOR:
                return BiometricFaceConstants.FACE_ERROR_VENDOR;
        } else if (aidlError == Error.REENROLL_REQUIRED) {
            case Error.REENROLL_REQUIRED:
                return BiometricFaceConstants.BIOMETRIC_ERROR_RE_ENROLL;
        } else {
            case Error.UNKNOWN:
            default:
                return BiometricFaceConstants.FACE_ERROR_UNKNOWN;
        }
    }

    public static @BiometricFaceConstants.FaceAcquired int toFrameworkAcquiredInfo(
            byte aidlAcquired) {
        if (aidlAcquired == AcquiredInfo.UNKNOWN) {
            return BiometricFaceConstants.FACE_ACQUIRED_UNKNOWN;
        } else if (aidlAcquired == AcquiredInfo.GOOD) {
    @BiometricFaceConstants.FaceAcquired
    public static int toFrameworkAcquiredInfo(byte aidlAcquiredInfo) {
        switch (aidlAcquiredInfo) {
            case AcquiredInfo.GOOD:
                return BiometricFaceConstants.FACE_ACQUIRED_GOOD;
        } else if (aidlAcquired == AcquiredInfo.INSUFFICIENT) {
            case AcquiredInfo.INSUFFICIENT:
                return BiometricFaceConstants.FACE_ACQUIRED_INSUFFICIENT;
        } else if (aidlAcquired == AcquiredInfo.TOO_BRIGHT) {
            case AcquiredInfo.TOO_BRIGHT:
                return BiometricFaceConstants.FACE_ACQUIRED_TOO_BRIGHT;
        } else if (aidlAcquired == AcquiredInfo.TOO_DARK) {
            case AcquiredInfo.TOO_DARK:
                return BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK;
        } else if (aidlAcquired == AcquiredInfo.TOO_CLOSE) {
            case AcquiredInfo.TOO_CLOSE:
                return BiometricFaceConstants.FACE_ACQUIRED_TOO_CLOSE;
        } else if (aidlAcquired == AcquiredInfo.TOO_FAR) {
            case AcquiredInfo.TOO_FAR:
                return BiometricFaceConstants.FACE_ACQUIRED_TOO_FAR;
        } else if (aidlAcquired == AcquiredInfo.FACE_TOO_HIGH) {
            case AcquiredInfo.FACE_TOO_HIGH:
                return BiometricFaceConstants.FACE_ACQUIRED_TOO_HIGH;
        } else if (aidlAcquired == AcquiredInfo.FACE_TOO_LOW) {
            case AcquiredInfo.FACE_TOO_LOW:
                return BiometricFaceConstants.FACE_ACQUIRED_TOO_LOW;
        } else if (aidlAcquired == AcquiredInfo.FACE_TOO_RIGHT) {
            case AcquiredInfo.FACE_TOO_RIGHT:
                return BiometricFaceConstants.FACE_ACQUIRED_TOO_RIGHT;
        } else if (aidlAcquired == AcquiredInfo.FACE_TOO_LEFT) {
            case AcquiredInfo.FACE_TOO_LEFT:
                return BiometricFaceConstants.FACE_ACQUIRED_TOO_LEFT;
        } else if (aidlAcquired == AcquiredInfo.POOR_GAZE) {
            case AcquiredInfo.POOR_GAZE:
                return BiometricFaceConstants.FACE_ACQUIRED_POOR_GAZE;
        } else if (aidlAcquired == AcquiredInfo.NOT_DETECTED) {
            case AcquiredInfo.NOT_DETECTED:
                return BiometricFaceConstants.FACE_ACQUIRED_NOT_DETECTED;
        } else if (aidlAcquired == AcquiredInfo.TOO_MUCH_MOTION) {
            case AcquiredInfo.TOO_MUCH_MOTION:
                return BiometricFaceConstants.FACE_ACQUIRED_TOO_MUCH_MOTION;
        } else if (aidlAcquired == AcquiredInfo.RECALIBRATE) {
            case AcquiredInfo.RECALIBRATE:
                return BiometricFaceConstants.FACE_ACQUIRED_RECALIBRATE;
        } else if (aidlAcquired == AcquiredInfo.TOO_DIFFERENT) {
            case AcquiredInfo.TOO_DIFFERENT:
                return BiometricFaceConstants.FACE_ACQUIRED_TOO_DIFFERENT;
        } else if (aidlAcquired == AcquiredInfo.TOO_SIMILAR) {
            case AcquiredInfo.TOO_SIMILAR:
                return BiometricFaceConstants.FACE_ACQUIRED_TOO_SIMILAR;
        } else if (aidlAcquired == AcquiredInfo.PAN_TOO_EXTREME) {
            case AcquiredInfo.PAN_TOO_EXTREME:
                return BiometricFaceConstants.FACE_ACQUIRED_PAN_TOO_EXTREME;
        } else if (aidlAcquired == AcquiredInfo.TILT_TOO_EXTREME) {
            case AcquiredInfo.TILT_TOO_EXTREME:
                return BiometricFaceConstants.FACE_ACQUIRED_TILT_TOO_EXTREME;
        } else if (aidlAcquired == AcquiredInfo.ROLL_TOO_EXTREME) {
            case AcquiredInfo.ROLL_TOO_EXTREME:
                return BiometricFaceConstants.FACE_ACQUIRED_ROLL_TOO_EXTREME;
        } else if (aidlAcquired == AcquiredInfo.FACE_OBSCURED) {
            case AcquiredInfo.FACE_OBSCURED:
                return BiometricFaceConstants.FACE_ACQUIRED_FACE_OBSCURED;
        } else if (aidlAcquired == AcquiredInfo.START) {
            case AcquiredInfo.START:
                return BiometricFaceConstants.FACE_ACQUIRED_START;
        } else if (aidlAcquired == AcquiredInfo.SENSOR_DIRTY) {
            case AcquiredInfo.SENSOR_DIRTY:
                return BiometricFaceConstants.FACE_ACQUIRED_SENSOR_DIRTY;
        } else if (aidlAcquired == AcquiredInfo.VENDOR) {
            case AcquiredInfo.VENDOR:
                return BiometricFaceConstants.FACE_ACQUIRED_VENDOR;
        } else if (aidlAcquired == AcquiredInfo.FIRST_FRAME_RECEIVED) {
            // No framework constant available
            return BiometricFaceConstants.FACE_ACQUIRED_UNKNOWN;
        } else if (aidlAcquired == AcquiredInfo.DARK_GLASSES_DETECTED) {
            // No framework constant available
            return BiometricFaceConstants.FACE_ACQUIRED_UNKNOWN;
        } else if (aidlAcquired == AcquiredInfo.MOUTH_COVERING_DETECTED) {
            // No framework constant available
            return BiometricFaceConstants.FACE_ACQUIRED_UNKNOWN;
        } else {
            case AcquiredInfo.UNKNOWN:
            case AcquiredInfo.FIRST_FRAME_RECEIVED:
            case AcquiredInfo.DARK_GLASSES_DETECTED:
            case AcquiredInfo.MOUTH_COVERING_DETECTED:
            default:
                return BiometricFaceConstants.FACE_ACQUIRED_UNKNOWN;
        }
    }

    @FaceEnrollStage
    public static int toFrameworkEnrollmentStage(int aidlEnrollmentStage) {
        switch (aidlEnrollmentStage) {
            case EnrollmentStage.FIRST_FRAME_RECEIVED:
                return FaceEnrollStages.FIRST_FRAME_RECEIVED;
            case EnrollmentStage.WAITING_FOR_CENTERING:
                return FaceEnrollStages.WAITING_FOR_CENTERING;
            case EnrollmentStage.HOLD_STILL_IN_CENTER:
                return FaceEnrollStages.HOLD_STILL_IN_CENTER;
            case EnrollmentStage.ENROLLING_MOVEMENT_1:
                return FaceEnrollStages.ENROLLING_MOVEMENT_1;
            case EnrollmentStage.ENROLLING_MOVEMENT_2:
                return FaceEnrollStages.ENROLLING_MOVEMENT_2;
            case EnrollmentStage.ENROLLMENT_FINISHED:
                return FaceEnrollStages.ENROLLMENT_FINISHED;
            case EnrollmentStage.UNKNOWN:
            default:
                return FaceEnrollStages.UNKNOWN;
        }
    }

    @NonNull
    public static FaceAuthenticationFrame toFrameworkAuthenticationFrame(
            @NonNull AuthenticationFrame frame) {
@@ -135,7 +153,9 @@ final class AidlConversionUtils {

    @NonNull
    public static FaceEnrollFrame toFrameworkEnrollmentFrame(@NonNull EnrollmentFrame frame) {
        return new FaceEnrollFrame(toFrameworkCell(frame.cell), frame.stage,
        return new FaceEnrollFrame(
                toFrameworkCell(frame.cell),
                toFrameworkEnrollmentStage(frame.stage),
                toFrameworkBaseFrame(frame.data));
    }