diff options
| author | 2020-07-15 19:17:38 -0700 | |
|---|---|---|
| committer | 2020-07-15 21:59:10 -0700 | |
| commit | d24084e95a9ff52a8c4a384dcce9bbf0d301bf6a (patch) | |
| tree | 70e9b1b8331ae63bf5499f72de5e2039f2ed3568 | |
| parent | 7b1c1db80aebc39f704360ad2ec636d912d470d2 (diff) | |
Update authentication when encrypted or lockout
Fingerprint authentication should not expose accept/reject/lockout
when the user is encrypted or locked out. This is possible with
IBiometricsFingerprint@2.1 since lockout is controlled by the framework.
IBiometricsFace@1.0 does not support this since lockout is controlled
in the HAL (or lower).
Bug: 79776455
Test: On fingerprint device, during encrypted or lockdown, any finger
works, lockout never occurs
Test: BiometricPromptDemo, normal path is run (e.g. incorrect fingers
are rejected)
Test: Test no effect on face device
Test: atest KeyguardUpdateMonitorTest
Change-Id: I9ded8efd80d4f8b92ce054262e721853703c6437
Merged-In: I6c9717d1f8ed3e844b3d92727396e2ce2e7fd94f
9 files changed, 275 insertions, 17 deletions
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index d57a7e4b97f0..6900105c4d4c 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -19,6 +19,7 @@ package android.hardware.fingerprint; import static android.Manifest.permission.INTERACT_ACROSS_USERS; import static android.Manifest.permission.MANAGE_FINGERPRINT; import static android.Manifest.permission.USE_BIOMETRIC; +import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; import static android.Manifest.permission.USE_FINGERPRINT; import android.annotation.NonNull; @@ -75,11 +76,13 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing private static final int MSG_ERROR = 104; private static final int MSG_REMOVED = 105; private static final int MSG_ENUMERATED = 106; + private static final int MSG_FINGERPRINT_DETECTED = 107; private IFingerprintService mService; private Context mContext; private IBinder mToken = new Binder(); private AuthenticationCallback mAuthenticationCallback; + private FingerprintDetectionCallback mFingerprintDetectionCallback; private EnrollmentCallback mEnrollmentCallback; private RemovalCallback mRemovalCallback; private EnumerateCallback mEnumerateCallback; @@ -107,6 +110,13 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing } } + private class OnFingerprintDetectionCancelListener implements OnCancelListener { + @Override + public void onCancel() { + cancelFingerprintDetect(); + } + } + /** * A wrapper class for the crypto objects supported by FingerprintManager. Currently the * framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects. @@ -272,6 +282,18 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing }; /** + * Callback structure provided for {@link #detectFingerprint(CancellationSignal, + * FingerprintDetectionCallback, int)}. + * @hide + */ + public interface FingerprintDetectionCallback { + /** + * Invoked when a fingerprint has been detected. + */ + void onFingerprintDetected(int userId, boolean isStrongBiometric); + } + + /** * Callback structure provided to {@link FingerprintManager#enroll(byte[], CancellationSignal, * int, int, EnrollmentCallback)} must provide an implementation of this for listening to * fingerprint events. @@ -454,6 +476,35 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing } /** + * Uses the fingerprint hardware to detect for the presence of a finger, without giving details + * about accept/reject/lockout. + * @hide + */ + @RequiresPermission(USE_BIOMETRIC_INTERNAL) + public void detectFingerprint(@NonNull CancellationSignal cancel, + @NonNull FingerprintDetectionCallback callback, int userId) { + if (mService == null) { + return; + } + + if (cancel.isCanceled()) { + Slog.w(TAG, "Detection already cancelled"); + return; + } else { + cancel.setOnCancelListener(new OnFingerprintDetectionCancelListener()); + } + + mFingerprintDetectionCallback = callback; + + try { + mService.detectFingerprint(mToken, userId, mServiceReceiver, + mContext.getOpPackageName()); + } catch (RemoteException e) { + Slog.w(TAG, "Remote exception when requesting finger detect", e); + } + } + + /** * Request fingerprint enrollment. This call warms up the fingerprint hardware * and starts scanning for fingerprints. Progress will be indicated by callbacks to the * {@link EnrollmentCallback} object. It terminates when @@ -797,6 +848,10 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing sendEnumeratedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */, msg.arg2 /* groupId */); break; + case MSG_FINGERPRINT_DETECTED: + sendFingerprintDetected(msg.arg1 /* userId */, + (boolean) msg.obj /* isStrongBiometric */); + break; } } }; @@ -891,6 +946,14 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing } } + private void sendFingerprintDetected(int userId, boolean isStrongBiometric) { + if (mFingerprintDetectionCallback == null) { + Slog.e(TAG, "sendFingerprintDetected, callback null"); + return; + } + mFingerprintDetectionCallback.onFingerprintDetected(userId, isStrongBiometric); + } + /** * @hide */ @@ -927,6 +990,18 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing } } + private void cancelFingerprintDetect() { + if (mService == null) { + return; + } + + try { + mService.cancelFingerprintDetect(mToken, mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * @hide */ @@ -1032,6 +1107,12 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing fp).sendToTarget(); } + @Override + public void onFingerprintDetected(long deviceId, int userId, boolean isStrongBiometric) { + mHandler.obtainMessage(MSG_FINGERPRINT_DETECTED, userId, 0, isStrongBiometric) + .sendToTarget(); + } + @Override // binder call public void onAuthenticationFailed(long deviceId) { mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget(); diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl index c5c375543adc..8aa36d7d5d76 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl @@ -33,6 +33,11 @@ interface IFingerprintService { void authenticate(IBinder token, long sessionId, int userId, IFingerprintServiceReceiver receiver, int flags, String opPackageName); + // Uses the fingerprint hardware to detect for the presence of a finger, without giving details + // about accept/reject/lockout. + void detectFingerprint(IBinder token, int userId, IFingerprintServiceReceiver receiver, + String opPackageName); + // This method prepares the service to start authenticating, but doesn't start authentication. // This is protected by the MANAGE_BIOMETRIC signatuer permission. This method should only be // called from BiometricService. The additional uid, pid, userId arguments should be determined @@ -48,6 +53,9 @@ interface IFingerprintService { // Cancel authentication for the given sessionId void cancelAuthentication(IBinder token, String opPackageName); + // Cancel finger detection + void cancelFingerprintDetect(IBinder token, String opPackageName); + // Same as above, except this is protected by the MANAGE_BIOMETRIC signature permission. Takes // an additional uid, pid, userid. void cancelAuthenticationFromService(IBinder token, String opPackageName, diff --git a/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl index 4412cee31bb0..a84b81e1eb81 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl @@ -26,6 +26,7 @@ oneway interface IFingerprintServiceReceiver { void onAcquired(long deviceId, int acquiredInfo, int vendorCode); void onAuthenticationSucceeded(long deviceId, in Fingerprint fp, int userId, boolean isStrongBiometric); + void onFingerprintDetected(long deviceId, int userId, boolean isStrongBiometric); void onAuthenticationFailed(long deviceId); void onError(long deviceId, int error, int vendorCode); void onRemoved(long deviceId, int fingerId, int groupId, int remaining); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 3acbfb87c3f4..c07c982b7451 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -1072,6 +1072,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN); } + private boolean isEncryptedOrLockdown(int userId) { + final int strongAuth = mStrongAuthTracker.getStrongAuthForUser(userId); + final boolean isLockDown = + containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW) + || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN); + final boolean isEncrypted = containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT); + return isEncrypted || isLockDown; + } + public boolean userNeedsStrongAuth() { return mStrongAuthTracker.getStrongAuthForUser(getCurrentUser()) != LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED; @@ -1248,6 +1257,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } }; + // Trigger the fingerprint success path so the bouncer can be shown + private final FingerprintManager.FingerprintDetectionCallback mFingerprintDetectionCallback + = this::handleFingerprintAuthenticated; + private FingerprintManager.AuthenticationCallback mFingerprintAuthenticationCallback = new AuthenticationCallback() { @@ -2050,8 +2063,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mFingerprintCancelSignal.cancel(); } mFingerprintCancelSignal = new CancellationSignal(); - mFpm.authenticate(null, mFingerprintCancelSignal, 0, mFingerprintAuthenticationCallback, - null, userId); + + if (isEncryptedOrLockdown(userId)) { + mFpm.detectFingerprint(mFingerprintCancelSignal, mFingerprintDetectionCallback, + userId); + } else { + mFpm.authenticate(null, mFingerprintCancelSignal, 0, + mFingerprintAuthenticationCallback, null, userId); + } + setFingerprintRunningState(BIOMETRIC_STATE_RUNNING); } } @@ -2087,7 +2107,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private boolean isUnlockWithFingerprintPossible(int userId) { return mFpm != null && mFpm.isHardwareDetected() && !isFingerprintDisabled(userId) - && mFpm.getEnrolledFingerprints(userId).size() > 0; + && mFpm.hasEnrolledTemplates(userId); } private boolean isUnlockWithFacePossible(int userId) { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 9e056cf16ec7..6362812d4fed 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -174,6 +174,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { when(mFaceManager.isHardwareDetected()).thenReturn(true); when(mFaceManager.hasEnrolledTemplates()).thenReturn(true); when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true); + when(mFingerprintManager.isHardwareDetected()).thenReturn(true); + when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true); when(mUserManager.isUserUnlocked(anyInt())).thenReturn(true); when(mUserManager.isPrimaryUser()).thenReturn(true); when(mStrongAuthTracker.getStub()).thenReturn(mock(IStrongAuthTracker.Stub.class)); @@ -419,6 +421,43 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { } @Test + public void testTriesToAuthenticateFingerprint_whenKeyguard() { + mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */); + mTestableLooper.processAllMessages(); + + verify(mFingerprintManager).authenticate(any(), any(), anyInt(), any(), any(), anyInt()); + verify(mFingerprintManager, never()).detectFingerprint(any(), any(), anyInt()); + } + + @Test + public void testFingerprintDoesNotAuth_whenEncrypted() { + testFingerprintWhenStrongAuth( + KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT); + } + + @Test + public void testFingerprintDoesNotAuth_whenDpmLocked() { + testFingerprintWhenStrongAuth( + KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW); + } + + @Test + public void testFingerprintDoesNotAuth_whenUserLockdown() { + testFingerprintWhenStrongAuth( + KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN); + } + + private void testFingerprintWhenStrongAuth(int strongAuth) { + when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(strongAuth); + mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */); + mTestableLooper.processAllMessages(); + + verify(mFingerprintManager, never()) + .authenticate(any(), any(), anyInt(), any(), any(), anyInt()); + verify(mFingerprintManager).detectFingerprint(any(), any(), anyInt()); + } + + @Test public void testTriesToAuthenticate_whenBouncer() { mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(true); mTestableLooper.processAllMessages(); diff --git a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java index 88469a2caee8..20c004db4c9f 100644 --- a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java +++ b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java @@ -722,10 +722,9 @@ public abstract class BiometricServiceBase extends SystemService } } - protected void handleAuthenticated(BiometricAuthenticator.Identifier identifier, - ArrayList<Byte> token) { + protected void handleAuthenticated(boolean authenticated, + BiometricAuthenticator.Identifier identifier, ArrayList<Byte> token) { ClientMonitor client = mCurrentClient; - final boolean authenticated = identifier.getBiometricId() != 0; if (client != null && client.onAuthenticated(identifier, authenticated, token)) { removeClient(client); diff --git a/services/core/java/com/android/server/biometrics/Utils.java b/services/core/java/com/android/server/biometrics/Utils.java index 543ce575b1fc..c661f452820d 100644 --- a/services/core/java/com/android/server/biometrics/Utils.java +++ b/services/core/java/com/android/server/biometrics/Utils.java @@ -16,11 +16,19 @@ package com.android.server.biometrics; +import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; import static android.hardware.biometrics.BiometricManager.Authenticators; +import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT; +import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW; +import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN; + +import android.annotation.NonNull; import android.app.ActivityManager; +import android.content.ComponentName; import android.content.Context; +import android.content.pm.PackageManager; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricPrompt; @@ -32,6 +40,9 @@ import android.os.UserHandle; import android.provider.Settings; import android.util.Slog; +import com.android.internal.R; +import com.android.internal.widget.LockPatternUtils; + import java.util.List; public class Utils { @@ -285,4 +296,28 @@ public class Utils { } return false; } + + public static boolean isKeyguard(Context context, String clientPackage) { + final boolean hasPermission = context.checkCallingOrSelfPermission(USE_BIOMETRIC_INTERNAL) + == PackageManager.PERMISSION_GRANTED; + + final ComponentName keyguardComponent = ComponentName.unflattenFromString( + context.getResources().getString(R.string.config_keyguardComponent)); + final String keyguardPackage = keyguardComponent != null + ? keyguardComponent.getPackageName() : null; + return hasPermission && keyguardPackage != null && keyguardPackage.equals(clientPackage); + } + + private static boolean containsFlag(int haystack, int needle) { + return (haystack & needle) != 0; + } + + public static boolean isUserEncryptedOrLockdown(@NonNull LockPatternUtils lpu, int user) { + final int strongAuth = lpu.getStrongAuthForUser(user); + final boolean isEncrypted = containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT); + final boolean isLockDown = containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW) + || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN); + Slog.d(TAG, "isEncrypted: " + isEncrypted + " isLockdown: " + isLockDown); + return isEncrypted || isLockDown; + } } diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java index 72e1bbbcba60..e5a1898459a2 100644 --- a/services/core/java/com/android/server/biometrics/face/FaceService.java +++ b/services/core/java/com/android/server/biometrics/face/FaceService.java @@ -896,8 +896,9 @@ public class FaceService extends BiometricServiceBase { public void onAuthenticated(final long deviceId, final int faceId, final int userId, ArrayList<Byte> token) { mHandler.post(() -> { - Face face = new Face("", faceId, deviceId); - FaceService.super.handleAuthenticated(face, token); + final Face face = new Face("", faceId, deviceId); + final boolean authenticated = faceId != 0; + FaceService.super.handleAuthenticated(authenticated, face, token); }); } diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java index 6b7ba6a56d82..a53fe47e4d3f 100644 --- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java @@ -56,6 +56,7 @@ import android.os.SELinux; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; +import android.util.EventLog; import android.util.Slog; import android.util.SparseBooleanArray; import android.util.SparseIntArray; @@ -64,6 +65,7 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; import com.android.internal.util.DumpUtils; +import com.android.internal.widget.LockPatternUtils; import com.android.server.SystemServerInitThreadPool; import com.android.server.biometrics.AuthenticationClient; import com.android.server.biometrics.BiometricServiceBase; @@ -72,6 +74,7 @@ import com.android.server.biometrics.ClientMonitor; import com.android.server.biometrics.Constants; import com.android.server.biometrics.EnumerateClient; import com.android.server.biometrics.RemovalClient; +import com.android.server.biometrics.Utils; import org.json.JSONArray; import org.json.JSONException; @@ -124,6 +127,8 @@ public class FingerprintService extends BiometricServiceBase { } private final class FingerprintAuthClient extends AuthenticationClientImpl { + private final boolean mDetectOnly; + @Override protected boolean isFingerprint() { return true; @@ -133,9 +138,10 @@ public class FingerprintService extends BiometricServiceBase { DaemonWrapper daemon, long halDeviceId, IBinder token, ServiceListener listener, int targetUserId, int groupId, long opId, boolean restricted, String owner, int cookie, - boolean requireConfirmation) { + boolean requireConfirmation, boolean detectOnly) { super(context, daemon, halDeviceId, token, listener, targetUserId, groupId, opId, restricted, owner, cookie, requireConfirmation); + mDetectOnly = detectOnly; } @Override @@ -177,6 +183,10 @@ public class FingerprintService extends BiometricServiceBase { return super.handleFailedAttempt(); } + + boolean isDetectOnly() { + return mDetectOnly; + } } /** @@ -234,18 +244,55 @@ public class FingerprintService extends BiometricServiceBase { } @Override // Binder call - public void authenticate(final IBinder token, final long opId, final int groupId, + public void authenticate(final IBinder token, final long opId, final int userId, final IFingerprintServiceReceiver receiver, final int flags, final String opPackageName) { - updateActiveGroup(groupId, opPackageName); + if (Utils.isUserEncryptedOrLockdown(mLockPatternUtils, userId) + && Utils.isKeyguard(getContext(), opPackageName)) { + // If this happens, something in KeyguardUpdateMonitor is wrong. + // SafetyNet for b/79776455 + EventLog.writeEvent(0x534e4554, "79776455"); + Slog.e(TAG, "Authenticate invoked when user is encrypted or lockdown"); + return; + } + + updateActiveGroup(userId, opPackageName); final boolean restricted = isRestricted(); final AuthenticationClientImpl client = new FingerprintAuthClient(getContext(), mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver), - mCurrentUserId, groupId, opId, restricted, opPackageName, - 0 /* cookie */, false /* requireConfirmation */); + mCurrentUserId, userId, opId, restricted, opPackageName, + 0 /* cookie */, false /* requireConfirmation */, false /* detectOnly */); authenticateInternal(client, opId, opPackageName); } + @Override + public void detectFingerprint(final IBinder token, final int userId, + final IFingerprintServiceReceiver receiver, final String opPackageName) { + checkPermission(USE_BIOMETRIC_INTERNAL); + if (!Utils.isKeyguard(getContext(), opPackageName)) { + Slog.w(TAG, "detectFingerprint called from non-sysui package: " + opPackageName); + return; + } + + if (!Utils.isUserEncryptedOrLockdown(mLockPatternUtils, userId)) { + // If this happens, something in KeyguardUpdateMonitor is wrong. This should only + // ever be invoked when the user is encrypted or lockdown. + Slog.e(TAG, "detectFingerprint invoked when user is not encrypted or lockdown"); + return; + } + + Slog.d(TAG, "detectFingerprint, owner: " + opPackageName + ", user: " + userId); + + updateActiveGroup(userId, opPackageName); + final boolean restricted = isRestricted(); + final int operationId = 0; + final AuthenticationClientImpl client = new FingerprintAuthClient(getContext(), + mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver), + mCurrentUserId, userId, operationId, restricted, opPackageName, + 0 /* cookie */, false /* requireConfirmation */, true /* detectOnly */); + authenticateInternal(client, operationId, opPackageName); + } + @Override // Binder call public void prepareForAuthentication(IBinder token, long opId, int groupId, IBiometricServiceReceiverInternal wrapperReceiver, String opPackageName, @@ -257,7 +304,7 @@ public class FingerprintService extends BiometricServiceBase { mDaemonWrapper, mHalDeviceId, token, new BiometricPromptServiceListenerImpl(wrapperReceiver), mCurrentUserId, groupId, opId, restricted, opPackageName, cookie, - false /* requireConfirmation */); + false /* requireConfirmation */, false /* detectOnly */); authenticateInternal(client, opId, opPackageName, callingUid, callingPid, callingUserId); } @@ -275,6 +322,17 @@ public class FingerprintService extends BiometricServiceBase { } @Override // Binder call + public void cancelFingerprintDetect(final IBinder token, final String opPackageName) { + checkPermission(USE_BIOMETRIC_INTERNAL); + if (!Utils.isKeyguard(getContext(), opPackageName)) { + Slog.w(TAG, "cancelFingerprintDetect called from non-sysui package: " + + opPackageName); + return; + } + cancelAuthenticationInternal(token, opPackageName); + } + + @Override // Binder call public void cancelAuthenticationFromService(final IBinder token, final String opPackageName, int callingUid, int callingPid, int callingUserId, boolean fromClient) { checkPermission(MANAGE_BIOMETRIC); @@ -518,7 +576,12 @@ public class FingerprintService extends BiometricServiceBase { BiometricAuthenticator.Identifier biometric, int userId) throws RemoteException { if (mFingerprintServiceReceiver != null) { - if (biometric == null || biometric instanceof Fingerprint) { + final ClientMonitor client = getCurrentClient(); + if (client instanceof FingerprintAuthClient + && ((FingerprintAuthClient) client).isDetectOnly()) { + mFingerprintServiceReceiver + .onFingerprintDetected(deviceId, userId, isStrongBiometric()); + } else if (biometric == null || biometric instanceof Fingerprint) { mFingerprintServiceReceiver.onAuthenticationSucceeded(deviceId, (Fingerprint) biometric, userId, isStrongBiometric()); } else { @@ -575,6 +638,7 @@ public class FingerprintService extends BiometricServiceBase { private final LockoutReceiver mLockoutReceiver = new LockoutReceiver(); protected final ResetFailedAttemptsForUserRunnable mResetFailedAttemptsForCurrentUserRunnable = new ResetFailedAttemptsForUserRunnable(); + private final LockPatternUtils mLockPatternUtils; /** * Receives callbacks from the HAL. @@ -608,8 +672,17 @@ public class FingerprintService extends BiometricServiceBase { public void onAuthenticated(final long deviceId, final int fingerId, final int groupId, ArrayList<Byte> token) { mHandler.post(() -> { - Fingerprint fp = new Fingerprint("", groupId, fingerId, deviceId); - FingerprintService.super.handleAuthenticated(fp, token); + boolean authenticated = fingerId != 0; + final ClientMonitor client = getCurrentClient(); + if (client instanceof FingerprintAuthClient) { + if (((FingerprintAuthClient) client).isDetectOnly()) { + Slog.w(TAG, "Detect-only. Device is encrypted or locked down"); + authenticated = true; + } + } + + final Fingerprint fp = new Fingerprint("", groupId, fingerId, deviceId); + FingerprintService.super.handleAuthenticated(authenticated, fp, token); }); } @@ -722,6 +795,7 @@ public class FingerprintService extends BiometricServiceBase { mAlarmManager = context.getSystemService(AlarmManager.class); context.registerReceiver(mLockoutReceiver, new IntentFilter(getLockoutResetIntent()), getLockoutBroadcastPermission(), null /* handler */); + mLockPatternUtils = new LockPatternUtils(context); } @Override |