Loading core/java/android/hardware/face/FaceManager.java +36 −6 Original line number Diff line number Diff line Loading @@ -244,17 +244,17 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan } /** * Requests a pre-enrollment auth token to tie enrollment to the confirmation of * Requests an auth token to tie sensitive operations to the confirmation of * existing device credentials (e.g. pin/pattern/password). * * @hide */ @RequiresPermission(MANAGE_BIOMETRIC) public long preEnroll() { public long generateChallenge() { long result = 0; if (mService != null) { try { result = mService.preEnroll(mToken); result = mService.generateChallenge(mToken); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading @@ -263,16 +263,46 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan } /** * Finishes enrollment and cancels the current auth token. * Invalidates the current auth token. * * @hide */ @RequiresPermission(MANAGE_BIOMETRIC) public int postEnroll() { public int revokeChallenge() { int result = 0; if (mService != null) { try { result = mService.postEnroll(mToken); result = mService.revokeChallenge(mToken); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } return result; } /** * @hide */ @RequiresPermission(MANAGE_BIOMETRIC) public void setRequireAttention(boolean requireAttention, byte[] token) { if (mService != null) { try { mService.setRequireAttention(requireAttention, token); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } /** * @hide */ @RequiresPermission(MANAGE_BIOMETRIC) public boolean getRequireAttention(byte[] token) { boolean result = true; if (mService != null) { try { mService.getRequireAttention(token); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading core/java/android/hardware/face/IFaceService.aidl +6 −2 Original line number Diff line number Diff line Loading @@ -66,10 +66,10 @@ interface IFaceService { boolean isHardwareDetected(long deviceId, String opPackageName); // Get a pre-enrollment authentication token long preEnroll(IBinder token); long generateChallenge(IBinder token); // Finish an enrollment sequence and invalidate the authentication token int postEnroll(IBinder token); int revokeChallenge(IBinder token); // Determine if a user has at least one enrolled face boolean hasEnrolledFaces(int userId, String opPackageName); Loading @@ -94,4 +94,8 @@ interface IFaceService { // Enumerate all faces void enumerate(IBinder token, int userId, IFaceServiceReceiver receiver); int setRequireAttention(boolean requireAttention, in byte [] token); boolean getRequireAttention(in byte [] token); } core/java/android/provider/Settings.java +11 −0 Original line number Diff line number Diff line Loading @@ -7688,6 +7688,15 @@ public final class Settings { private static final Validator FACE_UNLOCK_KEYGUARD_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; /** * Whether or not face unlock is allowed for apps (through BiometricPrompt). * @hide */ public static final String FACE_UNLOCK_APP_ENABLED = "face_unlock_app_enabled"; private static final Validator FACE_UNLOCK_APP_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; /** * Whether the assist gesture should be enabled. * Loading Loading @@ -8189,6 +8198,7 @@ public final class Settings { NFC_PAYMENT_DEFAULT_COMPONENT, AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN, FACE_UNLOCK_KEYGUARD_ENABLED, FACE_UNLOCK_APP_ENABLED, ASSIST_GESTURE_ENABLED, ASSIST_GESTURE_SILENCE_ALERTS_ENABLED, ASSIST_GESTURE_WAKE_ENABLED, Loading Loading @@ -8337,6 +8347,7 @@ public final class Settings { VALIDATORS.put(AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN, AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_VALIDATOR); VALIDATORS.put(FACE_UNLOCK_KEYGUARD_ENABLED, FACE_UNLOCK_KEYGUARD_ENABLED_VALIDATOR); VALIDATORS.put(FACE_UNLOCK_APP_ENABLED, FACE_UNLOCK_APP_ENABLED_VALIDATOR); VALIDATORS.put(ASSIST_GESTURE_ENABLED, ASSIST_GESTURE_ENABLED_VALIDATOR); VALIDATORS.put(ASSIST_GESTURE_SILENCE_ALERTS_ENABLED, ASSIST_GESTURE_SILENCE_ALERTS_ENABLED_VALIDATOR); Loading services/core/java/com/android/server/biometrics/BiometricService.java +22 −3 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.provider.Settings; import android.util.Slog; import com.android.internal.R; Loading Loading @@ -156,9 +157,18 @@ public class BiometricService extends SystemService { } else if (mCurrentModality == BIOMETRIC_IRIS) { Slog.w(TAG, "Unsupported modality"); } else if (mCurrentModality == BIOMETRIC_FACE) { mFaceService.authenticateFromService(true /* requireConfirmation */, token, sessionId, userId, receiver, flags, opPackageName, bundle, dialogReceiver, callingUid, callingPid, callingUserId); // If the user disabled face for apps, return ERROR_HW_UNAVAILABLE if (isFaceEnabledForApps()) { receiver.onError(0 /* deviceId */, BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE, FaceManager.getErrorString(getContext(), BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */)); } else { mFaceService.authenticateFromService(true /* requireConfirmation */, token, sessionId, userId, receiver, flags, opPackageName, bundle, dialogReceiver, callingUid, callingPid, callingUserId); } } else { Slog.w(TAG, "Unsupported modality"); } Loading @@ -168,6 +178,15 @@ public class BiometricService extends SystemService { }); } private boolean isFaceEnabledForApps() { // TODO: maybe cache this and eliminate duplicated code with KeyguardUpdateMonitor return Settings.Secure.getIntForUser( getContext().getContentResolver(), Settings.Secure.FACE_UNLOCK_APP_ENABLED, 1 /* default */, UserHandle.USER_CURRENT) == 0; } @Override // Binder call public void cancelAuthentication(IBinder token, String opPackageName) throws RemoteException { Loading services/core/java/com/android/server/biometrics/face/FaceService.java +51 −11 Original line number Diff line number Diff line Loading @@ -28,10 +28,11 @@ import android.content.pm.UserInfo; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.IBiometricPromptReceiver; import android.hardware.biometrics.IBiometricServiceReceiver; import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; import android.hardware.biometrics.IBiometricServiceReceiver; import android.hardware.biometrics.face.V1_0.IBiometricsFace; import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback; import android.hardware.biometrics.face.V1_0.Status; import android.hardware.face.Face; import android.hardware.face.FaceManager; import android.hardware.face.IFaceService; Loading Loading @@ -121,15 +122,15 @@ public class FaceService extends BiometricServiceBase { * The following methods contain common code which is shared in biometrics/common. */ @Override // Binder call public long preEnroll(IBinder token) { public long generateChallenge(IBinder token) { checkPermission(MANAGE_BIOMETRIC); return startPreEnroll(token); return startGenerateChallenge(token); } @Override // Binder call public int postEnroll(IBinder token) { public int revokeChallenge(IBinder token) { checkPermission(MANAGE_BIOMETRIC); return startPostEnroll(token); return startRevokeChallenge(token); } @Override // Binder call Loading Loading @@ -346,6 +347,45 @@ public class FaceService extends BiometricServiceBase { // TODO: confirm security token when we move timeout management into the HAL layer. mHandler.post(mResetFailedAttemptsForCurrentUserRunnable); } @Override public int setRequireAttention(boolean requireAttention, final byte[] token) { checkPermission(MANAGE_BIOMETRIC); final ArrayList<Byte> byteToken = new ArrayList<>(); for (int i = 0; i < token.length; i++) { byteToken.add(token[i]); } int result; try { result = mDaemon != null ? mDaemon.setRequireAttention(requireAttention, byteToken) : Status.INTERNAL_ERROR; } catch (RemoteException e) { Slog.e(getTag(), "Unable to setRequireAttention to " + requireAttention); result = Status.INTERNAL_ERROR; } return result; } @Override public boolean getRequireAttention(final byte[] token) { checkPermission(MANAGE_BIOMETRIC); final ArrayList<Byte> byteToken = new ArrayList<>(); for (int i = 0; i < token.length; i++) { byteToken.add(token[i]); } boolean result = true; try { result = mDaemon != null ? mDaemon.getRequireAttention(byteToken).value : true; } catch (RemoteException e) { Slog.e(getTag(), "Unable to getRequireAttention"); } return result; } } /** Loading Loading @@ -779,30 +819,30 @@ public class FaceService extends BiometricServiceBase { return mDaemon; } private long startPreEnroll(IBinder token) { private long startGenerateChallenge(IBinder token) { IBiometricsFace daemon = getFaceDaemon(); if (daemon == null) { Slog.w(TAG, "startPreEnroll: no face HAL!"); Slog.w(TAG, "startGenerateChallenge: no face HAL!"); return 0; } try { return daemon.generateChallenge(CHALLENGE_TIMEOUT_SEC).value; } catch (RemoteException e) { Slog.e(TAG, "startPreEnroll failed", e); Slog.e(TAG, "startGenerateChallenge failed", e); } return 0; } private int startPostEnroll(IBinder token) { private int startRevokeChallenge(IBinder token) { IBiometricsFace daemon = getFaceDaemon(); if (daemon == null) { Slog.w(TAG, "startPostEnroll: no face HAL!"); Slog.w(TAG, "startRevokeChallenge: no face HAL!"); return 0; } try { return daemon.revokeChallenge(); } catch (RemoteException e) { Slog.e(TAG, "startPostEnroll failed", e); Slog.e(TAG, "startRevokeChallenge failed", e); } return 0; } Loading Loading
core/java/android/hardware/face/FaceManager.java +36 −6 Original line number Diff line number Diff line Loading @@ -244,17 +244,17 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan } /** * Requests a pre-enrollment auth token to tie enrollment to the confirmation of * Requests an auth token to tie sensitive operations to the confirmation of * existing device credentials (e.g. pin/pattern/password). * * @hide */ @RequiresPermission(MANAGE_BIOMETRIC) public long preEnroll() { public long generateChallenge() { long result = 0; if (mService != null) { try { result = mService.preEnroll(mToken); result = mService.generateChallenge(mToken); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading @@ -263,16 +263,46 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan } /** * Finishes enrollment and cancels the current auth token. * Invalidates the current auth token. * * @hide */ @RequiresPermission(MANAGE_BIOMETRIC) public int postEnroll() { public int revokeChallenge() { int result = 0; if (mService != null) { try { result = mService.postEnroll(mToken); result = mService.revokeChallenge(mToken); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } return result; } /** * @hide */ @RequiresPermission(MANAGE_BIOMETRIC) public void setRequireAttention(boolean requireAttention, byte[] token) { if (mService != null) { try { mService.setRequireAttention(requireAttention, token); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } /** * @hide */ @RequiresPermission(MANAGE_BIOMETRIC) public boolean getRequireAttention(byte[] token) { boolean result = true; if (mService != null) { try { mService.getRequireAttention(token); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading
core/java/android/hardware/face/IFaceService.aidl +6 −2 Original line number Diff line number Diff line Loading @@ -66,10 +66,10 @@ interface IFaceService { boolean isHardwareDetected(long deviceId, String opPackageName); // Get a pre-enrollment authentication token long preEnroll(IBinder token); long generateChallenge(IBinder token); // Finish an enrollment sequence and invalidate the authentication token int postEnroll(IBinder token); int revokeChallenge(IBinder token); // Determine if a user has at least one enrolled face boolean hasEnrolledFaces(int userId, String opPackageName); Loading @@ -94,4 +94,8 @@ interface IFaceService { // Enumerate all faces void enumerate(IBinder token, int userId, IFaceServiceReceiver receiver); int setRequireAttention(boolean requireAttention, in byte [] token); boolean getRequireAttention(in byte [] token); }
core/java/android/provider/Settings.java +11 −0 Original line number Diff line number Diff line Loading @@ -7688,6 +7688,15 @@ public final class Settings { private static final Validator FACE_UNLOCK_KEYGUARD_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; /** * Whether or not face unlock is allowed for apps (through BiometricPrompt). * @hide */ public static final String FACE_UNLOCK_APP_ENABLED = "face_unlock_app_enabled"; private static final Validator FACE_UNLOCK_APP_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; /** * Whether the assist gesture should be enabled. * Loading Loading @@ -8189,6 +8198,7 @@ public final class Settings { NFC_PAYMENT_DEFAULT_COMPONENT, AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN, FACE_UNLOCK_KEYGUARD_ENABLED, FACE_UNLOCK_APP_ENABLED, ASSIST_GESTURE_ENABLED, ASSIST_GESTURE_SILENCE_ALERTS_ENABLED, ASSIST_GESTURE_WAKE_ENABLED, Loading Loading @@ -8337,6 +8347,7 @@ public final class Settings { VALIDATORS.put(AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN, AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_VALIDATOR); VALIDATORS.put(FACE_UNLOCK_KEYGUARD_ENABLED, FACE_UNLOCK_KEYGUARD_ENABLED_VALIDATOR); VALIDATORS.put(FACE_UNLOCK_APP_ENABLED, FACE_UNLOCK_APP_ENABLED_VALIDATOR); VALIDATORS.put(ASSIST_GESTURE_ENABLED, ASSIST_GESTURE_ENABLED_VALIDATOR); VALIDATORS.put(ASSIST_GESTURE_SILENCE_ALERTS_ENABLED, ASSIST_GESTURE_SILENCE_ALERTS_ENABLED_VALIDATOR); Loading
services/core/java/com/android/server/biometrics/BiometricService.java +22 −3 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.provider.Settings; import android.util.Slog; import com.android.internal.R; Loading Loading @@ -156,9 +157,18 @@ public class BiometricService extends SystemService { } else if (mCurrentModality == BIOMETRIC_IRIS) { Slog.w(TAG, "Unsupported modality"); } else if (mCurrentModality == BIOMETRIC_FACE) { mFaceService.authenticateFromService(true /* requireConfirmation */, token, sessionId, userId, receiver, flags, opPackageName, bundle, dialogReceiver, callingUid, callingPid, callingUserId); // If the user disabled face for apps, return ERROR_HW_UNAVAILABLE if (isFaceEnabledForApps()) { receiver.onError(0 /* deviceId */, BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE, FaceManager.getErrorString(getContext(), BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */)); } else { mFaceService.authenticateFromService(true /* requireConfirmation */, token, sessionId, userId, receiver, flags, opPackageName, bundle, dialogReceiver, callingUid, callingPid, callingUserId); } } else { Slog.w(TAG, "Unsupported modality"); } Loading @@ -168,6 +178,15 @@ public class BiometricService extends SystemService { }); } private boolean isFaceEnabledForApps() { // TODO: maybe cache this and eliminate duplicated code with KeyguardUpdateMonitor return Settings.Secure.getIntForUser( getContext().getContentResolver(), Settings.Secure.FACE_UNLOCK_APP_ENABLED, 1 /* default */, UserHandle.USER_CURRENT) == 0; } @Override // Binder call public void cancelAuthentication(IBinder token, String opPackageName) throws RemoteException { Loading
services/core/java/com/android/server/biometrics/face/FaceService.java +51 −11 Original line number Diff line number Diff line Loading @@ -28,10 +28,11 @@ import android.content.pm.UserInfo; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.IBiometricPromptReceiver; import android.hardware.biometrics.IBiometricServiceReceiver; import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; import android.hardware.biometrics.IBiometricServiceReceiver; import android.hardware.biometrics.face.V1_0.IBiometricsFace; import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback; import android.hardware.biometrics.face.V1_0.Status; import android.hardware.face.Face; import android.hardware.face.FaceManager; import android.hardware.face.IFaceService; Loading Loading @@ -121,15 +122,15 @@ public class FaceService extends BiometricServiceBase { * The following methods contain common code which is shared in biometrics/common. */ @Override // Binder call public long preEnroll(IBinder token) { public long generateChallenge(IBinder token) { checkPermission(MANAGE_BIOMETRIC); return startPreEnroll(token); return startGenerateChallenge(token); } @Override // Binder call public int postEnroll(IBinder token) { public int revokeChallenge(IBinder token) { checkPermission(MANAGE_BIOMETRIC); return startPostEnroll(token); return startRevokeChallenge(token); } @Override // Binder call Loading Loading @@ -346,6 +347,45 @@ public class FaceService extends BiometricServiceBase { // TODO: confirm security token when we move timeout management into the HAL layer. mHandler.post(mResetFailedAttemptsForCurrentUserRunnable); } @Override public int setRequireAttention(boolean requireAttention, final byte[] token) { checkPermission(MANAGE_BIOMETRIC); final ArrayList<Byte> byteToken = new ArrayList<>(); for (int i = 0; i < token.length; i++) { byteToken.add(token[i]); } int result; try { result = mDaemon != null ? mDaemon.setRequireAttention(requireAttention, byteToken) : Status.INTERNAL_ERROR; } catch (RemoteException e) { Slog.e(getTag(), "Unable to setRequireAttention to " + requireAttention); result = Status.INTERNAL_ERROR; } return result; } @Override public boolean getRequireAttention(final byte[] token) { checkPermission(MANAGE_BIOMETRIC); final ArrayList<Byte> byteToken = new ArrayList<>(); for (int i = 0; i < token.length; i++) { byteToken.add(token[i]); } boolean result = true; try { result = mDaemon != null ? mDaemon.getRequireAttention(byteToken).value : true; } catch (RemoteException e) { Slog.e(getTag(), "Unable to getRequireAttention"); } return result; } } /** Loading Loading @@ -779,30 +819,30 @@ public class FaceService extends BiometricServiceBase { return mDaemon; } private long startPreEnroll(IBinder token) { private long startGenerateChallenge(IBinder token) { IBiometricsFace daemon = getFaceDaemon(); if (daemon == null) { Slog.w(TAG, "startPreEnroll: no face HAL!"); Slog.w(TAG, "startGenerateChallenge: no face HAL!"); return 0; } try { return daemon.generateChallenge(CHALLENGE_TIMEOUT_SEC).value; } catch (RemoteException e) { Slog.e(TAG, "startPreEnroll failed", e); Slog.e(TAG, "startGenerateChallenge failed", e); } return 0; } private int startPostEnroll(IBinder token) { private int startRevokeChallenge(IBinder token) { IBiometricsFace daemon = getFaceDaemon(); if (daemon == null) { Slog.w(TAG, "startPostEnroll: no face HAL!"); Slog.w(TAG, "startRevokeChallenge: no face HAL!"); return 0; } try { return daemon.revokeChallenge(); } catch (RemoteException e) { Slog.e(TAG, "startPostEnroll failed", e); Slog.e(TAG, "startRevokeChallenge failed", e); } return 0; } Loading