Repo Created

This commit is contained in:
Fr4nz D13trich 2025-11-15 17:44:12 +01:00
parent eb305e2886
commit a8c22c65db
4784 changed files with 329907 additions and 2 deletions

View file

@ -0,0 +1,43 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
apply plugin: 'com.android.library'
apply plugin: 'maven-publish'
apply plugin: 'signing'
android {
namespace "com.google.mlkit.vision.face"
compileSdkVersion androidCompileSdk
buildToolsVersion "$androidBuildVersionTools"
buildFeatures {
aidl = true
}
defaultConfig {
versionName version
minSdkVersion androidMinSdk
targetSdkVersion androidTargetSdk
}
compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
}
apply from: '../../gradle/publish-android.gradle'
description = 'microG implementation of play-services-mlkit-face-detection'
dependencies {
// Dependencies from play-services-mlkit-face-detection:17.1.0
api project(':play-services-base')
api project(':play-services-basement')
api project(':play-services-tasks')
annotationProcessor project(":safe-parcel-processor")
}

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2023 microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application />
</manifest>

View file

@ -0,0 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.mlkit.vision.face;
parcelable FaceDetectionOptions;

View file

@ -0,0 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.mlkit.vision.face;
parcelable FrameMetadataParcel;

View file

@ -0,0 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.mlkit.vision.face.aidls;
parcelable FaceParcel;

View file

@ -0,0 +1,17 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.mlkit.vision.face.aidls;
import com.google.android.gms.dynamic.IObjectWrapper;
import java.util.List;
import com.google.mlkit.vision.face.FrameMetadataParcel;
import com.google.mlkit.vision.face.aidls.FaceParcel;
interface IFaceDetector {
void initDetector() = 0;
void close() = 1;
List<FaceParcel> detectFaces(IObjectWrapper wrapper, in FrameMetadataParcel metadata) = 2;
}

View file

@ -0,0 +1,14 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.mlkit.vision.face.aidls;
import com.google.mlkit.vision.face.aidls.IFaceDetector;
import com.google.android.gms.dynamic.IObjectWrapper;
import com.google.mlkit.vision.face.FaceDetectionOptions;
interface IFaceDetectorCreator {
IFaceDetector newFaceDetector(IObjectWrapper context, in FaceDetectionOptions faceDetectionOptions) = 0;
}

View file

@ -0,0 +1,204 @@
/**
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.mlkit.vision.face;
import android.graphics.Rect;
import android.util.SparseArray;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.mlkit.vision.face.aidls.ContourParcel;
import com.google.mlkit.vision.face.aidls.FaceParcel;
import com.google.mlkit.vision.face.aidls.LandmarkParcel;
import org.microg.gms.common.Hide;
import org.microg.gms.utils.ToStringHelper;
import java.util.ArrayList;
import java.util.List;
public class Face {
@NonNull
private final Rect boundingBox;
private final int trackingId;
private final float rightEyeOpenProbability;
private final float leftEyeOpenProbability;
private final float smileProbability;
private final float eulerX;
private final float eulerY;
private final float eulerZ;
@NonNull
private final SparseArray<FaceLandmark> landmarks = new SparseArray<>();
@NonNull
private final SparseArray<FaceContour> contours = new SparseArray<>();
private static boolean isValidLandmarkType(int landmarkType) {
return landmarkType == 0 || landmarkType == 1 || (landmarkType >= 3 && landmarkType <= 7) || (landmarkType >= 9 && landmarkType <= 11);
}
private static boolean isValidContourType(int contourType) {
return contourType >= 1 && contourType <= 15;
}
@Hide
public Face(FaceParcel faceParcel) {
boundingBox = faceParcel.boundingBox;
trackingId = faceParcel.id;
for (LandmarkParcel landmarkParcel : faceParcel.landmarkParcelList) {
if (isValidLandmarkType(landmarkParcel.type)) {
landmarks.put(landmarkParcel.type, new FaceLandmark(landmarkParcel.type, landmarkParcel.position));
}
}
for (ContourParcel contourParcel : faceParcel.contourParcelList) {
if (isValidContourType(contourParcel.type)) {
contours.put(contourParcel.type, new FaceContour(contourParcel.type, contourParcel.pointsList));
}
}
eulerX = faceParcel.tiltAngle;
eulerY = faceParcel.panAngle;
eulerZ = faceParcel.rollAngle;
smileProbability = faceParcel.smileProbability;
leftEyeOpenProbability = faceParcel.leftEyeOpenProbability;
rightEyeOpenProbability = faceParcel.rightEyeOpenProbability;
}
/**
* Gets a list of all available {@link FaceContour}s. All {@link FaceContour}s are defined in {@link FaceContour.ContourType}. If no contours are available, an
* empty list is returned.
*/
@NonNull
public List<FaceContour> getAllContours() {
List<FaceContour> list = new ArrayList<>();
for (int i = 0; i < contours.size(); i++) {
list.add(contours.valueAt(i));
}
return list;
}
/**
* Gets a list of all available {@link FaceLandmark}s. All possible {@link FaceLandmark}s are defined in {@link FaceLandmark.LandmarkType}. If no landmarks are
* available, an empty list is returned.
*/
@NonNull
public List<FaceLandmark> getAllLandmarks() {
List<FaceLandmark> list = new ArrayList<>();
for (int i = 0; i < landmarks.size(); i++) {
list.add(landmarks.valueAt(i));
}
return list;
}
/**
* Returns the {@code NonNull} axis-aligned bounding rectangle of the detected face.
*/
@NonNull
public Rect getBoundingBox() {
return boundingBox;
}
/**
* Gets contour based on the provided {@link FaceContour.ContourType}. It returns {@code null} if the contour is not available.
*/
@Nullable
public FaceContour getContour(@FaceContour.ContourType int contourType) {
return contours.get(contourType);
}
/**
* Returns the rotation of the face about the horizontal axis of the image, in degrees. Positive euler X is the face is looking up.
*
* @return the rotation of the face about the horizontal axis of the image
*/
public Float getHeadEulerAngleX() {
return eulerX;
}
/**
* Returns the rotation of the face about the vertical axis of the image, in degrees. Positive euler y is when the face turns toward the right side
* of the image that is being processed.
*
* @return the rotation of the face about the vertical axis of the image
*/
public Float getHeadEulerAngleY() {
return eulerY;
}
/**
* Returns the rotation of the face about the axis pointing out of the image, in degrees. Positive euler z is a counter-clockwise rotation within the image plane.
*/
public Float getHeadEulerAngleZ() {
return eulerZ;
}
/**
* Gets a {@link FaceLandmark} based on the provided {@link FaceLandmark.LandmarkType}. It returns {@code null} if the landmark type is not available.
*/
public FaceLandmark getLandmark(@FaceLandmark.LandmarkType int landmarkType) {
return landmarks.get(landmarkType);
}
/**
* Returns a value between 0.0 and 1.0 giving a probability that the face's left eye is open. This returns {@code null} if the probability was not
* computed. The probability is not computed if classification is not enabled via
* {@link FaceDetectorOptions.Builder#setClassificationMode(int)} or the feature is not available.
*/
public Float getLeftEyeOpenProbability() {
if (leftEyeOpenProbability < 0.0f || leftEyeOpenProbability > 1.0f) {
return null;
}
return leftEyeOpenProbability;
}
/**
* Returns a value between 0.0 and 1.0 giving a probability that the face's right eye is open. This returns {@code null} if the probability was not
* computed. The probability is not computed if classification is not enabled via
* {@link FaceDetectorOptions.Builder#setClassificationMode(int)} or the feature is not available.
*/
public Float getRightEyeOpenProbability() {
if (rightEyeOpenProbability < 0.0f || rightEyeOpenProbability > 1.0f) {
return null;
}
return rightEyeOpenProbability;
}
/**
* Returns a value between 0.0 and 1.0 giving a probability that the face is smiling. This returns {@code null} if the probability was not computed.
* The probability is not computed if classification is not enabled via {@link FaceDetectorOptions.Builder#setClassificationMode(int)} or the
* required landmarks are not found.
*/
public Float getSmilingProbability() {
if (smileProbability < 0.0f || smileProbability > 1.0f) {
return null;
}
return smileProbability;
}
/**
* Returns the tracking ID if the tracking is enabled. Otherwise, returns {@code null}.
*/
public Integer getTrackingId() {
if (trackingId == -1) {
return null;
}
return trackingId;
}
@Override
public String toString() {
return ToStringHelper.name("Face")
.field("boundingBox", boundingBox)
.field("trackingId", trackingId)
.field("rightEyeOpenProbability", rightEyeOpenProbability)
.field("leftEyeOpenProbability", leftEyeOpenProbability)
.field("smileProbability", smileProbability)
.field("eulerX", eulerX)
.field("eulerY", eulerY)
.field("eulerZ", eulerZ)
.field("landmarks", landmarks)
.field("contours", contours)
.toString();
}
}

View file

@ -0,0 +1,124 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.mlkit.vision.face;
import android.graphics.PointF;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import org.microg.gms.utils.ToStringHelper;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
/**
* Represent a face contour. A contour is a list of points on a detected face, such as the mouth.
* <p>
* When 'left' and 'right' are used, they are relative to the subject in the image. For example, the {@link #LEFT_EYE} landmark is the subject's left eye,
* not the eye that is on the left when viewing the image.
*/
public class FaceContour {
/**
* The outline of the subject's face.
*/
public static final int FACE = 1;
/**
* The top outline of the subject's left eyebrow.
*/
public static final int LEFT_EYEBROW_TOP = 2;
/**
* The bottom outline of the subject's left eyebrow.
*/
public static final int LEFT_EYEBROW_BOTTOM = 3;
/**
* The top outline of the subject's right eyebrow.
*/
public static final int RIGHT_EYEBROW_TOP = 4;
/**
* The bottom outline of the subject's right eyebrow.
*/
public static final int RIGHT_EYEBROW_BOTTOM = 5;
/**
* The outline of the subject's left eye.
*/
public static final int LEFT_EYE = 6;
/**
* The outline of the subject's right eye.
*/
public static final int RIGHT_EYE = 7;
/**
* The top outline of the subject's upper lip.
*/
public static final int UPPER_LIP_TOP = 8;
/**
* The bottom outline of the subject's upper lip.
*/
public static final int UPPER_LIP_BOTTOM = 9;
/**
* The top outline of the subject's lower lip.
*/
public static final int LOWER_LIP_TOP = 10;
/**
* The bottom outline of the subject's lower lip.
*/
public static final int LOWER_LIP_BOTTOM = 11;
/**
* the outline of the subject's nose bridge.
*/
public static final int NOSE_BRIDGE = 12;
/**
* The outline of the subject's nose bridge.
*/
public static final int NOSE_BOTTOM = 13;
/**
* The center of the left cheek.
*/
public static final int LEFT_CHEEK = 14;
/**
* The center of the right cheek.
*/
public static final int RIGHT_CHEEK = 15;
@Retention(RetentionPolicy.CLASS)
@IntDef(value = {FACE, LEFT_EYEBROW_TOP, LEFT_EYEBROW_BOTTOM, RIGHT_EYEBROW_TOP, RIGHT_EYEBROW_BOTTOM, LEFT_EYE, RIGHT_EYE, UPPER_LIP_TOP, UPPER_LIP_BOTTOM, LOWER_LIP_TOP, LOWER_LIP_BOTTOM, NOSE_BRIDGE, NOSE_BOTTOM, LEFT_CHEEK, RIGHT_CHEEK})
public @interface ContourType {
}
private final @ContourType int type;
@NonNull
private final List<PointF> points;
FaceContour(@ContourType int type, @NonNull List<PointF> points) {
this.type = type;
this.points = points;
}
/**
* Gets the {@link FaceContour.ContourType} type.
*/
@FaceContour.ContourType
public int getFaceContourType() {
return type;
}
/**
* Gets a list of 2D points for this face contour, where (0, 0) is the upper-left corner of the image. The point is guaranteed to be within the
* bounds of the image.
*/
@NonNull
public List<PointF> getPoints() {
return points;
}
@NonNull
@Override
public String toString() {
return ToStringHelper.name("FaceContour").field("type", type).field("points", points.toArray()).toString();
}
}

View file

@ -0,0 +1,145 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.mlkit.vision.face;
import android.os.Parcel;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.Executor;
@SafeParcelable.Class
public class FaceDetectionOptions extends AbstractSafeParcelable {
public static final int CLASSIFICATION_MODE_ALL = 2;
public static final int CLASSIFICATION_MODE_NONE = 1;
public static final int CONTOUR_MODE_ALL = 2;
public static final int CONTOUR_MODE_NONE = 1;
public static final int LANDMARK_MODE_ALL = 2;
public static final int LANDMARK_MODE_NONE = 1;
public static final int PERFORMANCE_MODE_ACCURATE = 2;
public static final int PERFORMANCE_MODE_FAST = 1;
@Retention(RetentionPolicy.CLASS)
@IntDef(value = {CLASSIFICATION_MODE_NONE, CLASSIFICATION_MODE_ALL})
public @interface ClassificationMode {
}
@Retention(RetentionPolicy.CLASS)
@IntDef(value = {CONTOUR_MODE_NONE, CONTOUR_MODE_ALL})
public @interface ContourMode {
}
@Retention(RetentionPolicy.CLASS)
@IntDef(value = {LANDMARK_MODE_NONE, LANDMARK_MODE_ALL})
public @interface LandmarkMode {
}
@Retention(RetentionPolicy.CLASS)
@IntDef(value = {PERFORMANCE_MODE_FAST, PERFORMANCE_MODE_ACCURATE})
public @interface PerformanceMode {
}
@Field(1)
private final int landmarkMode;
@Field(2)
private final int contourMode;
@Field(3)
private final int classificationMode;
@Field(4)
private final int performanceMode;
@Field(5)
private final boolean trackingEnabled;
@Field(6)
private final float minFaceSize;
private Executor executor;
@Constructor
FaceDetectionOptions(@Param(1) int landmarkMode, @Param(2) int contourMode, @Param(3) int classificationMode, @Param(4) int performanceMode, @Param(5) boolean trackingEnabled, @Param(6) float minFaceSize) {
this.landmarkMode = landmarkMode;
this.contourMode = contourMode;
this.classificationMode = classificationMode;
this.performanceMode = performanceMode;
this.trackingEnabled = trackingEnabled;
this.minFaceSize = minFaceSize;
}
public Executor getExecutor() {
return executor;
}
public void setExecutor(Executor executor) {
this.executor = executor;
}
public static class Builder {
private int landmarkMode;
private int contourMode;
private int classificationMode;
private int performanceMode;
private boolean trackingEnabled;
private float minFaceSize;
private Executor executor;
public Builder enableTracking(boolean enable) {
this.trackingEnabled = enable;
return this;
}
public Builder setClassificationMode(@ClassificationMode int mode) {
this.classificationMode = mode;
return this;
}
public Builder setContourMode(@ContourMode int mode) {
this.contourMode = mode;
return this;
}
public Builder setExecutor(Executor executor) {
this.executor = executor;
return this;
}
public Builder setLandmarkMode(@LandmarkMode int mode) {
this.landmarkMode = mode;
return this;
}
public Builder setMinFaceSize(float minFaceSize) {
this.minFaceSize = minFaceSize;
return this;
}
public Builder setPerformanceMode(@PerformanceMode int mode) {
this.performanceMode = mode;
return this;
}
public FaceDetectionOptions build() {
FaceDetectionOptions faceDetectionOptions = new FaceDetectionOptions(landmarkMode, contourMode, classificationMode, performanceMode, trackingEnabled, minFaceSize);
if (executor != null) {
faceDetectionOptions.setExecutor(executor);
}
return faceDetectionOptions;
}
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<FaceDetectionOptions> CREATOR = findCreator(FaceDetectionOptions.class);
}

View file

@ -0,0 +1,104 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.mlkit.vision.face;
import android.graphics.PointF;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import org.microg.gms.utils.ToStringHelper;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Represent a face landmark. A landmark is a point on a detected face, such as an eye, nose, or mouth.
* <p>
* When 'left' and 'right' are used, they are relative to the subject in the image. For example, the {@link #LEFT_EYE} landmark is the subject's left eye,
* not the eye that is on the left when viewing the image.
*/
public class FaceLandmark {
/**
* The center of the subject's bottom lip.
*/
public static final int MOUTH_BOTTOM = 0;
/**
* The midpoint between the subject's left mouth corner and the outer corner of the subject's left eye. For full profile faces, this becomes the
* centroid of the nose base, nose tip, left ear lobe and left ear tip.
*/
public static final int LEFT_CHEEK = 1;
/**
* The midpoint of the subject's left ear tip and left ear lobe.
*/
public static final int LEFT_EAR = 3;
/**
* The center of the subject's left eye cavity.
*/
public static final int LEFT_EYE = 4;
/**
* The subject's left mouth corner where the lips meet.
*/
public static final int MOUTH_LEFT = 5;
/**
* The midpoint between the subject's nostrils where the nose meets the face.
*/
public static final int NOSE_BASE = 6;
/**
* The midpoint between the subject's right mouth corner and the outer corner of the subject's right eye. For full profile faces, this becomes the
* centroid of the nose base, nose tip, right ear lobe and right ear tip.
*/
public static final int RIGHT_CHEEK = 7;
/**
* The midpoint of the subject's right ear tip and right ear lobe.
*/
public static final int RIGHT_EAR = 9;
/**
* The center of the subject's right eye cavity.
*/
public static final int RIGHT_EYE = 10;
/**
* The subject's right mouth corner where the lips meet.
*/
public static final int MOUTH_RIGHT = 11;
@Retention(RetentionPolicy.CLASS)
@IntDef(value = {MOUTH_BOTTOM, LEFT_CHEEK, LEFT_EAR, LEFT_EYE, MOUTH_LEFT, NOSE_BASE, RIGHT_CHEEK, RIGHT_EAR, RIGHT_EYE, MOUTH_RIGHT})
public @interface LandmarkType {
}
private final @LandmarkType int type;
@NonNull
private final PointF position;
FaceLandmark(@LandmarkType int type, @NonNull PointF position) {
this.type = type;
this.position = position;
}
/**
* Gets the {@link FaceLandmark.LandmarkType} type.
*/
@LandmarkType
public int getLandmarkType() {
return type;
}
/**
* Gets a 2D point for landmark position, where (0, 0) is the upper-left corner of the image. The point is guaranteed to be within the bounds of
* the image.
*/
@NonNull
public PointF getPosition() {
return position;
}
@NonNull
@Override
public String toString() {
return ToStringHelper.name("FaceLandmark").field("type", type).field("position", position).toString();
}
}

View file

@ -0,0 +1,37 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.mlkit.vision.face;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
@SafeParcelable.Class
public class FrameMetadataParcel extends AbstractSafeParcelable {
@Field(1)
public int format;
@Field(2)
public int width;
@Field(3)
public int height;
@Field(4)
public int rotation;
@Field(5)
public long timestampMillis;
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<FrameMetadataParcel> CREATOR = findCreator(FrameMetadataParcel.class);
}

View file

@ -0,0 +1,36 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.mlkit.vision.face.aidls;
import android.graphics.PointF;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import java.util.List;
@SafeParcelable.Class
public class ContourParcel extends AbstractSafeParcelable {
@Field(1)
public final int type;
@Field(2)
public final List<PointF> pointsList;
@Constructor
public ContourParcel(@Param(1) int type, @Param(2) List<PointF> pointsList) {
this.type = type;
this.pointsList = pointsList;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<ContourParcel> CREATOR = findCreator(ContourParcel.class);
}

View file

@ -0,0 +1,74 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.mlkit.vision.face.aidls;
import android.graphics.Rect;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import java.util.List;
@SafeParcelable.Class
public class FaceParcel extends AbstractSafeParcelable {
@Field(1)
public final int id;
@Field(2)
public final Rect boundingBox;
@Field(3)
public final float rollAngle;
@Field(4)
public final float panAngle;
@Field(5)
public final float tiltAngle;
@Field(6)
public final float leftEyeOpenProbability;
@Field(7)
public final float rightEyeOpenProbability;
@Field(8)
public final float smileProbability;
@Field(9)
public final float confidenceScore;
@Field(10)
public final List<LandmarkParcel> landmarkParcelList;
@Field(11)
public final List<ContourParcel> contourParcelList;
@Constructor
public FaceParcel(@Param(1) int id, @Param(2) Rect boundingBox, @Param(3) float rollAngle, @Param(4) float panAngle, @Param(5) float tiltAngle, @Param(6) float leftEyeOpenProbability, @Param(7) float rightEyeOpenProbability, @Param(8) float smileProbability, @Param(9) float confidenceScore, @Param(10) List<LandmarkParcel> landmarkParcelList, @Param(11) List<ContourParcel> contourParcelList) {
this.id = id;
this.boundingBox = boundingBox;
this.rollAngle = rollAngle;
this.panAngle = panAngle;
this.tiltAngle = tiltAngle;
this.leftEyeOpenProbability = leftEyeOpenProbability;
this.rightEyeOpenProbability = rightEyeOpenProbability;
this.smileProbability = smileProbability;
this.confidenceScore = confidenceScore;
this.landmarkParcelList = landmarkParcelList;
this.contourParcelList = contourParcelList;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<FaceParcel> CREATOR = findCreator(FaceParcel.class);
}

View file

@ -0,0 +1,34 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.mlkit.vision.face.aidls;
import android.graphics.PointF;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
@SafeParcelable.Class
public class LandmarkParcel extends AbstractSafeParcelable {
@Field(1)
public final int type;
@Field(2)
public final PointF position;
@Constructor
public LandmarkParcel(@Param(1) int type, @Param(2) PointF position) {
this.type = type;
this.position = position;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<LandmarkParcel> CREATOR = findCreator(LandmarkParcel.class);
}