Loading core/api/system-current.txt +10 −0 Original line number Diff line number Diff line Loading @@ -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 core/java/android/hardware/biometrics/BiometricEnrollmentStatus.java 0 → 100644 +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; } } core/java/android/hardware/biometrics/BiometricEnrollmentStatusInternal.aidl 0 → 100644 +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; core/java/android/hardware/biometrics/BiometricEnrollmentStatusInternal.java 0 → 100644 +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(); } } core/java/android/hardware/biometrics/BiometricManager.java +75 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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}. Loading Loading @@ -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}. Loading Loading @@ -406,8 +441,6 @@ public class BiometricManager { /** * @hide * @param context * @param service */ public BiometricManager(@NonNull Context context, @NonNull IAuthService service) { mContext = context; Loading Loading @@ -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 Loading Loading @@ -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
core/api/system-current.txt +10 −0 Original line number Diff line number Diff line Loading @@ -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
core/java/android/hardware/biometrics/BiometricEnrollmentStatus.java 0 → 100644 +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; } }
core/java/android/hardware/biometrics/BiometricEnrollmentStatusInternal.aidl 0 → 100644 +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;
core/java/android/hardware/biometrics/BiometricEnrollmentStatusInternal.java 0 → 100644 +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(); } }
core/java/android/hardware/biometrics/BiometricManager.java +75 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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}. Loading Loading @@ -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}. Loading Loading @@ -406,8 +441,6 @@ public class BiometricManager { /** * @hide * @param context * @param service */ public BiometricManager(@NonNull Context context, @NonNull IAuthService service) { mContext = context; Loading Loading @@ -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 Loading Loading @@ -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; } }