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

Commit 9df80202 authored by Curtis Belmonte's avatar Curtis Belmonte
Browse files

Add onFrame methods to face auth/enroll client monitors

Updates the AIDL face sensor implementation to forward the
onAuthenticationFrame and onEnrollmentFrame events to appropriate
methods in the FaceAuthenticationClient and FaceEnrollClient monitors.

This implementation also converts the hardware AIDL models
AuthenticationFrame and EnrollmentFrame to equivalent framework classes
FaceAuthenticationFrame and FaceEnrollFrame, respectively. This will
allow the framework to define AIDL interface methods with these models.

Test: atest CtsBiometricsTestCases

Bug: 178414967

Change-Id: I093c4396dddab9cb9fb8fd8ec3426b4f3a81abeb
parent e0a71c14
Loading
Loading
Loading
Loading
+75 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.face;

import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;

/**
 * Data model for a frame captured during face authentication.
 *
 * @hide
 */
public final class FaceAuthenticationFrame implements Parcelable {
    @NonNull private final FaceDataFrame mData;

    /**
     * Data model for a frame captured during face authentication.
     *
     * @param data Information about the current frame.
     */
    public FaceAuthenticationFrame(@NonNull FaceDataFrame data) {
        mData = data;
    }

    /**
     * @return Information about the current frame.
     */
    @NonNull
    public FaceDataFrame getData() {
        return mData;
    }

    private FaceAuthenticationFrame(@NonNull Parcel source) {
        mData = source.readParcelable(FaceDataFrame.class.getClassLoader());
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeParcelable(mData, flags);
    }

    public static final Creator<FaceAuthenticationFrame> CREATOR =
            new Creator<FaceAuthenticationFrame>() {

        @Override
        public FaceAuthenticationFrame createFromParcel(Parcel source) {
            return new FaceAuthenticationFrame(source);
        }

        @Override
        public FaceAuthenticationFrame[] newArray(int size) {
            return new FaceAuthenticationFrame[size];
        }
    };
}
+151 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.face;

import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;

/**
 * A container for data common to {@link FaceAuthenticationFrame} and {@link FaceEnrollFrame}.
 *
 * @hide
 */
public final class FaceDataFrame implements Parcelable {
    private final int mAcquiredInfo;
    private final int mVendorCode;
    private final float mPan;
    private final float mTilt;
    private final float mDistance;
    private final boolean mIsCancellable;

    /**
     * A container for data common to {@link FaceAuthenticationFrame} and {@link FaceEnrollFrame}.
     *
     * @param acquiredInfo An integer corresponding to a known acquired message.
     * @param vendorCode An integer representing a custom vendor-specific message. Ignored unless
     *  {@code acquiredInfo} is {@code FACE_ACQUIRED_VENDOR}.
     * @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.
     * @param isCancellable Whether the ongoing face operation should be canceled.
     */
    public FaceDataFrame(
            int acquiredInfo,
            int vendorCode,
            float pan,
            float tilt,
            float distance,
            boolean isCancellable) {
        mAcquiredInfo = acquiredInfo;
        mVendorCode = vendorCode;
        mPan = pan;
        mTilt = tilt;
        mDistance = distance;
        mIsCancellable = isCancellable;
    }

    /**
     * @return An integer corresponding to a known acquired message.
     *
     * @see android.hardware.biometrics.BiometricFaceConstants
     */
    public int getAcquiredInfo() {
        return mAcquiredInfo;
    }

    /**
     * @return An integer representing a custom vendor-specific message. Ignored unless
     * {@code acquiredInfo} is {@link
     * android.hardware.biometrics.BiometricFaceConstants#FACE_ACQUIRED_VENDOR}.
     *
     * @see android.hardware.biometrics.BiometricFaceConstants
     */
    public int getVendorCode() {
        return mVendorCode;
    }

    /**
     * @return The horizontal pan of the detected face. Values in the range [-1, 1] indicate a good
     * capture.
     */
    public float getPan() {
        return mPan;
    }

    /**
     * @return The vertical tilt of the detected face. Values in the range [-1, 1] indicate a good
     * capture.
     */
    public float getTilt() {
        return mTilt;
    }

    /**
     * @return The distance of the detected face from the device. Values in the range [-1, 1]
     * indicate a good capture.
     */
    public float getDistance() {
        return mDistance;
    }

    /**
     * @return Whether the ongoing face operation should be canceled.
     */
    public boolean isCancellable() {
        return mIsCancellable;
    }

    private FaceDataFrame(@NonNull Parcel source) {
        mAcquiredInfo = source.readInt();
        mVendorCode = source.readInt();
        mPan = source.readFloat();
        mTilt = source.readFloat();
        mDistance = source.readFloat();
        mIsCancellable = source.readBoolean();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mAcquiredInfo);
        dest.writeInt(mVendorCode);
        dest.writeFloat(mPan);
        dest.writeFloat(mTilt);
        dest.writeFloat(mDistance);
        dest.writeBoolean(mIsCancellable);
    }

    public static final Creator<FaceDataFrame> CREATOR = new Creator<FaceDataFrame>() {
        @Override
        public FaceDataFrame createFromParcel(Parcel source) {
            return new FaceDataFrame(source);
        }

        @Override
        public FaceDataFrame[] newArray(int size) {
            return new FaceDataFrame[size];
        }
    };
}
+96 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.face;

import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;

/**
 * A matrix cell, corresponding to a desired face image, that may be captured during enrollment.
 *
 * @hide
 */
public final class FaceEnrollCell implements Parcelable {
    private final int mX;
    private final int mY;
    private final int mZ;

    /**
     * A matrix cell, corresponding to a desired face image, that may be captured during enrollment.
     *
     * @param x The horizontal coordinate of this cell.
     * @param y The vertical coordinate of this cell.
     * @param z The depth coordinate of this cell.
     */
    public FaceEnrollCell(int x, int y, int z) {
        mX = x;
        mY = y;
        mZ = z;
    }

    /**
     * @return The horizontal coordinate of this cell.
     */
    public int getX() {
        return mX;
    }

    /**
     * @return The vertical coordinate of this cell.
     */
    public int getY() {
        return mY;
    }

    /**
     * @return The depth coordinate of this cell.
     */
    public int getZ() {
        return mZ;
    }

    private FaceEnrollCell(@NonNull Parcel source) {
        mX = source.readInt();
        mY = source.readInt();
        mZ = source.readInt();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mX);
        dest.writeInt(mY);
        dest.writeInt(mZ);
    }

    public static final Creator<FaceEnrollCell> CREATOR = new Creator<FaceEnrollCell>() {
        @Override
        public FaceEnrollCell createFromParcel(Parcel source) {
            return new FaceEnrollCell(source);
        }

        @Override
        public FaceEnrollCell[] newArray(int size) {
            return new FaceEnrollCell[size];
        }
    };
}
+103 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.face;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;

/**
 * Data model for a frame captured during face enrollment.
 *
 * @hide
 */
public final class FaceEnrollFrame implements Parcelable {
    @Nullable private final FaceEnrollCell mCell;
    @FaceEnrollStage private final int mStage;
    @NonNull private final FaceDataFrame mData;

    /**
     * Data model for a frame captured during face enrollment.
     *
     * @param cell The cell captured during this frame of enrollment, if any.
     * @param stage An integer representing the current stage of enrollment.
     * @param data Information about the current frame.
     */
    public FaceEnrollFrame(
            @Nullable FaceEnrollCell cell,
            @FaceEnrollStage int stage,
            @NonNull FaceDataFrame data) {
        mCell = cell;
        mStage = stage;
        mData = data;
    }

    /**
     * @return The cell captured during this frame of enrollment, if any.
     */
    @Nullable
    public FaceEnrollCell getCell() {
        return mCell;
    }

    /**
     * @return An integer representing the current stage of enrollment.
     */
    @FaceEnrollStage
    public int getStage() {
        return mStage;
    }

    /**
     * @return Information about the current frame.
     */
    @NonNull
    public FaceDataFrame getData() {
        return mData;
    }

    private FaceEnrollFrame(@NonNull Parcel source) {
        mCell = source.readParcelable(FaceEnrollCell.class.getClassLoader());
        mStage = source.readInt();
        mData = source.readParcelable(FaceDataFrame.class.getClassLoader());
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeParcelable(mCell, flags);
        dest.writeInt(mStage);
        dest.writeParcelable(mData, flags);
    }

    public static final Creator<FaceEnrollFrame> CREATOR = new Creator<FaceEnrollFrame>() {
        @Override
        public FaceEnrollFrame createFromParcel(Parcel source) {
            return new FaceEnrollFrame(source);
        }

        @Override
        public FaceEnrollFrame[] newArray(int size) {
            return new FaceEnrollFrame[size];
        }
    };
}
+68 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.face;

import android.annotation.IntDef;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * A stage that may occur during face enrollment.
 *
 * @hide
 */
@Retention(RetentionPolicy.SOURCE)
@IntDef({
    FaceEnrollStage.FIRST_FRAME_RECEIVED,
    FaceEnrollStage.WAITING_FOR_CENTERING,
    FaceEnrollStage.HOLD_STILL_IN_CENTER,
    FaceEnrollStage.ENROLLING_MOVEMENT_1,
    FaceEnrollStage.ENROLLING_MOVEMENT_2,
    FaceEnrollStage.ENROLLMENT_FINISHED
})
public @interface FaceEnrollStage {
    /**
     * Enrollment has just begun. No action is needed from the user yet.
     */
    int FIRST_FRAME_RECEIVED = 0;

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

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

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

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

    /**
     * Enrollment has completed. No more action is needed from the user.
     */
    int ENROLLMENT_FINISHED = 5;
}
Loading