/* * Copyright (C) 2018 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 static android.Manifest.permission.TEST_BIOMETRIC; import static android.Manifest.permission.USE_BIOMETRIC; import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; import static android.Manifest.permission.WRITE_DEVICE_CONFIG; import static com.android.internal.util.FrameworkStatsLog.AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_BIOMETRIC_MANAGER_CAN_AUTHENTICATE; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.content.Context; import android.os.IBinder; import android.os.RemoteException; import android.os.UserHandle; import android.security.keystore.KeyProperties; import android.util.Slog; import com.android.internal.util.FrameworkStatsLog; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; /** * A class that contains biometric utilities. For authentication, see {@link BiometricPrompt}. */ @SystemService(Context.BIOMETRIC_SERVICE) public class BiometricManager { private static final String TAG = "BiometricManager"; /** * No error detected. */ public static final int BIOMETRIC_SUCCESS = BiometricConstants.BIOMETRIC_SUCCESS; /** * The hardware is unavailable. Try again later. */ public static final int BIOMETRIC_ERROR_HW_UNAVAILABLE = BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE; /** * The user does not have any biometrics enrolled. */ public static final int BIOMETRIC_ERROR_NONE_ENROLLED = BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS; /** * There is no biometric hardware. */ public static final int BIOMETRIC_ERROR_NO_HARDWARE = BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT; /** * A security vulnerability has been discovered and the sensor is unavailable until a * security update has addressed this issue. This error can be received if for example, * authentication was requested with {@link Authenticators#BIOMETRIC_STRONG}, but the * sensor's strength can currently only meet {@link Authenticators#BIOMETRIC_WEAK}. */ public static final int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = BiometricConstants.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED; /** * @hide */ @IntDef({BIOMETRIC_SUCCESS, BIOMETRIC_ERROR_HW_UNAVAILABLE, BIOMETRIC_ERROR_NONE_ENROLLED, BIOMETRIC_ERROR_NO_HARDWARE, BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED}) @Retention(RetentionPolicy.SOURCE) public @interface BiometricError {} /** * Types of authenticators, defined at a level of granularity supported by * {@link BiometricManager} and {@link BiometricPrompt}. * *
Types may combined via bitwise OR into a single integer representing multiple
* authenticators (e.g. DEVICE_CREDENTIAL | BIOMETRIC_WEAK
).
*
* @see #canAuthenticate(int)
* @see BiometricPrompt.Builder#setAllowedAuthenticators(int)
*/
public interface Authenticators {
/**
* An {@link IntDef} representing valid combinations of authenticator types.
* @hide
*/
@IntDef(flag = true, value = {
BIOMETRIC_STRONG,
BIOMETRIC_WEAK,
BIOMETRIC_CONVENIENCE,
DEVICE_CREDENTIAL,
})
@interface Types {}
/**
* Empty set with no authenticators specified.
*
*
This constant is intended for use by {@link android.provider.DeviceConfig} to adjust * the reported strength of a biometric sensor. It is not a valid parameter for any of the * public {@link android.hardware.biometrics} APIs. * * @hide */ @SystemApi @RequiresPermission(WRITE_DEVICE_CONFIG) int EMPTY_SET = 0x0000; /** * Placeholder for the theoretical strongest biometric security tier. * @hide */ int BIOMETRIC_MAX_STRENGTH = 0x0001; /** * Any biometric (e.g. fingerprint, iris, or face) on the device that meets or exceeds the * requirements for Class 3 (formerly Strong), as defined * by the Android CDD. * *
This corresponds to {@link KeyProperties#AUTH_BIOMETRIC_STRONG} during key generation. * * @see android.security.keystore.KeyGenParameterSpec.Builder */ int BIOMETRIC_STRONG = 0x000F; /** * Any biometric (e.g. fingerprint, iris, or face) on the device that meets or exceeds the * requirements for Class 2 (formerly Weak), as defined by * the Android CDD. * *
Note that this is a superset of {@link #BIOMETRIC_STRONG} and is defined such that * {@code BIOMETRIC_STRONG | BIOMETRIC_WEAK == BIOMETRIC_WEAK}. */ int BIOMETRIC_WEAK = 0x00FF; /** * Any biometric (e.g. fingerprint, iris, or face) on the device that meets or exceeds the * requirements for Class 1 (formerly Convenience), as * defined by the Android CDD. * *
This constant is intended for use by {@link android.provider.DeviceConfig} to adjust * the reported strength of a biometric sensor. It is not a valid parameter for any of the * public {@link android.hardware.biometrics} APIs. * * @hide */ @SystemApi @RequiresPermission(WRITE_DEVICE_CONFIG) int BIOMETRIC_CONVENIENCE = 0x0FFF; /** * Placeholder for the theoretical weakest biometric security tier. * @hide */ int BIOMETRIC_MIN_STRENGTH = 0x7FFF; /** * The non-biometric credential used to secure the device (i.e., PIN, pattern, or password). * This should typically only be used in combination with a biometric auth type, such as * {@link #BIOMETRIC_WEAK}. * *
This corresponds to {@link KeyProperties#AUTH_DEVICE_CREDENTIAL} during key * generation. * * @see android.security.keystore.KeyGenParameterSpec.Builder */ int DEVICE_CREDENTIAL = 1 << 15; } /** * @hide * returns a string representation of an authenticator type. */ @NonNull public static String authenticatorToStr(@Authenticators.Types int authenticatorType) { switch(authenticatorType) { case Authenticators.BIOMETRIC_STRONG: return "BIOMETRIC_STRONG"; case Authenticators.BIOMETRIC_WEAK: return "BIOMETRIC_WEAK"; case Authenticators.BIOMETRIC_CONVENIENCE: return "BIOMETRIC_CONVENIENCE"; case Authenticators.DEVICE_CREDENTIAL: return "DEVICE_CREDENTIAL"; default: return "Unknown authenticator type: " + authenticatorType; } } /** * Provides localized strings for an application that uses {@link BiometricPrompt} to * authenticate the user. */ public static class Strings { @NonNull private final Context mContext; @NonNull private final IAuthService mService; @Authenticators.Types int mAuthenticators; private Strings(@NonNull Context context, @NonNull IAuthService service, @Authenticators.Types int authenticators) { mContext = context; mService = service; mAuthenticators = authenticators; } /** * Provides a localized string that can be used as the label for a button that invokes * {@link BiometricPrompt}. * *
When possible, this method should use the given authenticator requirements to more * precisely specify the authentication type that will be used. For example, if * Class 3 biometric authentication is requested on a device with a * Class 3 fingerprint sensor and a Class 2 face sensor, * the returned string should indicate that fingerprint authentication will be used. * *
This method should also try to specify which authentication method(s) will be used in * practice when multiple authenticators meet the given requirements. For example, if * biometric authentication is requested on a device with both face and fingerprint sensors * but the user has selected face as their preferred method, the returned string should * indicate that face authentication will be used. * *
This method may return {@code null} if none of the requested authenticator types are * available, but this should not be relied upon for checking the status of * authenticators. Instead, use {@link #canAuthenticate(int)}. * * @return The label for a button that invokes {@link BiometricPrompt} for authentication. */ @RequiresPermission(USE_BIOMETRIC) @Nullable public CharSequence getButtonLabel() { final int userId = mContext.getUserId(); final String opPackageName = mContext.getOpPackageName(); try { return mService.getButtonLabel(userId, opPackageName, mAuthenticators); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Provides a localized string that can be shown while the user is authenticating with * {@link BiometricPrompt}. * *
When possible, this method should use the given authenticator requirements to more * precisely specify the authentication type that will be used. For example, if * Class 3 biometric authentication is requested on a device with a * Class 3 fingerprint sensor and a Class 2 face sensor, * the returned string should indicate that fingerprint authentication will be used. * *
This method should also try to specify which authentication method(s) will be used in * practice when multiple authenticators meet the given requirements. For example, if * biometric authentication is requested on a device with both face and fingerprint sensors * but the user has selected face as their preferred method, the returned string should * indicate that face authentication will be used. * *
This method may return {@code null} if none of the requested authenticator types are * available, but this should not be relied upon for checking the status of * authenticators. Instead, use {@link #canAuthenticate(int)}. * * @return The label for a button that invokes {@link BiometricPrompt} for authentication. */ @RequiresPermission(USE_BIOMETRIC) @Nullable public CharSequence getPromptMessage() { final int userId = mContext.getUserId(); final String opPackageName = mContext.getOpPackageName(); try { return mService.getPromptMessage(userId, opPackageName, mAuthenticators); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Provides a localized string that can be shown as the title for an app setting that * enables authentication with {@link BiometricPrompt}. * *
When possible, this method should use the given authenticator requirements to more * precisely specify the authentication type that will be used. For example, if * Class 3 biometric authentication is requested on a device with a * Class 3 fingerprint sensor and a Class 2 face sensor, * the returned string should indicate that fingerprint authentication will be used. * *
This method should not try to specify which authentication method(s) will be * used in practice when multiple authenticators meet the given requirements. For example, * if biometric authentication is requested on a device with both face and fingerprint * sensors, the returned string should indicate that either face or fingerprint * authentication may be used, regardless of whether the user has enrolled or selected * either as their preferred method. * *
This method may return {@code null} if none of the requested authenticator types are
* supported by the system, but this should not be relied upon for checking the
* status of authenticators. Instead, use {@link #canAuthenticate(int)} or
* {@link android.content.pm.PackageManager#hasSystemFeature(String)}.
*
* @return The label for a button that invokes {@link BiometricPrompt} for authentication.
*/
@RequiresPermission(USE_BIOMETRIC)
@Nullable
public CharSequence getSettingName() {
final int userId = mContext.getUserId();
final String opPackageName = mContext.getOpPackageName();
try {
return mService.getSettingName(userId, opPackageName, mAuthenticators);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
@NonNull private final Context mContext;
@NonNull private final IAuthService mService;
/**
* @hide
* @param context
* @param service
*/
public BiometricManager(@NonNull Context context, @NonNull IAuthService service) {
mContext = context;
mService = service;
}
/**
* @return A list of {@link SensorProperties}
* @hide
*/
@TestApi
@NonNull
@RequiresPermission(TEST_BIOMETRIC)
public List