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

Commit 0bedc3c3 authored by Hao Dong's avatar Hao Dong Committed by Android (Google) Code Review
Browse files

Merge "Revert^2 "Add some new modality-specific APIs in BiometricManager."" into main

parents 5883e0ab ad67639f
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -4933,6 +4933,16 @@ package android.hardware {
package android.hardware.biometrics {
  @FlaggedApi("android.hardware.biometrics.move_fm_api_to_bm") public final class BiometricEnrollmentStatus {
    method @IntRange(from=0) public int getEnrollmentCount();
  }
  public class BiometricManager {
    method @FlaggedApi("android.hardware.biometrics.move_fm_api_to_bm") @NonNull @RequiresPermission(android.Manifest.permission.SET_BIOMETRIC_DIALOG_ADVANCED) public java.util.Map<java.lang.Integer,android.hardware.biometrics.BiometricEnrollmentStatus> getEnrollmentStatus();
    field @FlaggedApi("android.hardware.biometrics.move_fm_api_to_bm") public static final int TYPE_FACE = 8; // 0x8
    field @FlaggedApi("android.hardware.biometrics.move_fm_api_to_bm") public static final int TYPE_FINGERPRINT = 2; // 0x2
  }
  public static interface BiometricManager.Authenticators {
    field @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static final int BIOMETRIC_CONVENIENCE = 4095; // 0xfff
    field @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static final int EMPTY_SET = 0; // 0x0
+64 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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;

import android.annotation.FlaggedApi;
import android.annotation.IntRange;
import android.annotation.SystemApi;

import java.util.Objects;

/**
 * This class contains enrollment information of one biometric modality.
 *
 * @hide
 */
@SystemApi
@FlaggedApi(Flags.FLAG_MOVE_FM_API_TO_BM)
public final class BiometricEnrollmentStatus {
    private final int mEnrollmentCount;

    /**
     * @hide
     */
    public BiometricEnrollmentStatus(int enrollmentCount) {
        mEnrollmentCount = enrollmentCount;
    }

    /**
     * Returns the number of enrolled biometric for the associated modality.
     *
     * @return The number of enrolled biometric.
     */
    @IntRange(from = 0)
    public int getEnrollmentCount() {
        return mEnrollmentCount;
    }

    @Override
    public int hashCode() {
        return Objects.hash(mEnrollmentCount);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        BiometricEnrollmentStatus other = (BiometricEnrollmentStatus) obj;
        return mEnrollmentCount == other.mEnrollmentCount;
    }
}
+19 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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;

// @hide
parcelable BiometricEnrollmentStatusInternal;
+116 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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;

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

import java.util.Objects;

/**
 * This class contains enrollment information. It keeps track of the modality type (e.g.
 * fingerprint, face) and corresponding {@link BiometricEnrollmentStatus}. This is for
 * internal use in {@link com.android.server.biometrics.AuthService}, so it has to be parcelable.
 *
 * @hide
 */
@FlaggedApi(Flags.FLAG_MOVE_FM_API_TO_BM)
public final class BiometricEnrollmentStatusInternal implements Parcelable {
    @BiometricManager.BiometricModality
    private final int mModality;
    private final BiometricEnrollmentStatus mStatus;

    public BiometricEnrollmentStatusInternal(
            @BiometricManager.BiometricModality int modality, BiometricEnrollmentStatus status) {
        mModality = modality;
        mStatus = status;
    }

    /**
     * Returns the modality associated with this enrollment status.
     *
     * @return The int value representing the biometric sensor type, e.g.
     * {@link BiometricManager#TYPE_FACE} or
     * {@link BiometricManager#TYPE_FINGERPRINT}.
     */
    @BiometricManager.BiometricModality
    public int getModality() {
        return mModality;
    }

    /**
     * Returns the {@link BiometricEnrollmentStatus} for the associated modality.
     */
    public BiometricEnrollmentStatus getStatus() {
        return mStatus;
    }

    private BiometricEnrollmentStatusInternal(Parcel in) {
        this(in.readInt(), new BiometricEnrollmentStatus(in.readInt()));
    }

    @NonNull
    public static final Creator<BiometricEnrollmentStatusInternal> CREATOR = new Creator<>() {
        @Override
        public BiometricEnrollmentStatusInternal createFromParcel(Parcel in) {
            return new BiometricEnrollmentStatusInternal(in);
        }

        @Override
        public BiometricEnrollmentStatusInternal[] newArray(int size) {
            return new BiometricEnrollmentStatusInternal[size];
        }
    };

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeInt(mModality);
        dest.writeInt(mStatus.getEnrollmentCount());
    }

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

    @Override
    public String toString() {
        String modality = "";
        if (mModality == BiometricManager.TYPE_FINGERPRINT) {
            modality = "Fingerprint";
        } else if (mModality == BiometricManager.TYPE_FACE) {
            modality = "Face";
        }
        return "Modality: " + modality + ", Enrolled Count: " + mStatus.getEnrollmentCount();
    }

    @Override
    public int hashCode() {
        return Objects.hash(mModality, mStatus.getEnrollmentCount());
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        BiometricEnrollmentStatusInternal other = (BiometricEnrollmentStatusInternal) obj;
        return mModality == other.mModality
                && mStatus.getEnrollmentCount() == other.mStatus.getEnrollmentCount();
    }
}
+75 −2
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.hardware.biometrics;

import static android.Manifest.permission.SET_BIOMETRIC_DIALOG_ADVANCED;
import static android.Manifest.permission.TEST_BIOMETRIC;
import static android.Manifest.permission.USE_BIOMETRIC;
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
@@ -42,10 +43,14 @@ import android.util.Slog;

import com.android.internal.util.FrameworkStatsLog;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * A class that contains biometric utilities. For authentication, see {@link BiometricPrompt}.
@@ -142,6 +147,36 @@ public class BiometricManager {
    @Retention(RetentionPolicy.SOURCE)
    public @interface BiometricError {}

    /**
     * Constant representing fingerprint.
     * @hide
     */
    @SystemApi
    @FlaggedApi(Flags.FLAG_MOVE_FM_API_TO_BM)
    public static final int TYPE_FINGERPRINT = BiometricAuthenticator.TYPE_FINGERPRINT;

    /**
     * Constant representing face.
     * @hide
     */
    @SystemApi
    @FlaggedApi(Flags.FLAG_MOVE_FM_API_TO_BM)
    public static final int TYPE_FACE = BiometricAuthenticator.TYPE_FACE;

    /**
     * An {@link IntDef} representing the biometric modalities.
     * @hide
     */
    @IntDef(flag = true, value = {
            TYPE_FINGERPRINT,
            TYPE_FACE
    })
    @Retention(RetentionPolicy.SOURCE)
    @Target(ElementType.TYPE_USE)
    @interface BiometricModality {
    }


    /**
     * Types of authenticators, defined at a level of granularity supported by
     * {@link BiometricManager} and {@link BiometricPrompt}.
@@ -406,8 +441,6 @@ public class BiometricManager {

    /**
     * @hide
     * @param context
     * @param service
     */
    public BiometricManager(@NonNull Context context, @NonNull IAuthService service) {
        mContext = context;
@@ -566,6 +599,34 @@ public class BiometricManager {
        return new Strings(mContext, mService, authenticators);
    }

    /**
     * Return the current biometrics enrollment status map (modality -> BiometricEnrollmentStatus).
     *
     * <p>This method is intended for system apps, such as settings or device setup, which require
     * detailed enrollment information to show or hide features or to encourage users to enroll
     * in a specific modality. Applications should instead use
     * {@link BiometricManager#canAuthenticate(int)} to check the enrollment status and use the
     * enroll intent, when needed to allow users to enroll. That ensures that users are presented
     * with a consistent set of options across all of their apps and can be redirected to a
     * single system-managed settings surface.</p>
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(SET_BIOMETRIC_DIALOG_ADVANCED)
    @FlaggedApi(Flags.FLAG_MOVE_FM_API_TO_BM)
    @NonNull
    public Map<@BiometricManager.BiometricModality Integer, BiometricEnrollmentStatus>
            getEnrollmentStatus() {
        try {
            final List<BiometricEnrollmentStatusInternal> statusInternalList =
                    mService.getEnrollmentStatusList(mContext.getOpPackageName());
            return convertBiometricEnrollmentStatusInternalToMap(statusInternalList);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * @hide
     * @param userId
@@ -794,5 +855,17 @@ public class BiometricManager {
            return BIOMETRIC_NO_AUTHENTICATION;
        }
    }

    private static Map<Integer, BiometricEnrollmentStatus>
            convertBiometricEnrollmentStatusInternalToMap(
            List<BiometricEnrollmentStatusInternal> list) {
        Map<Integer, BiometricEnrollmentStatus> map = new HashMap<>();

        for (BiometricEnrollmentStatusInternal item : list) {
            map.put(item.getModality(), item.getStatus());
        }
        return map;
    }

}
Loading