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
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index d57a7e4b..6900105 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -19,6 +19,7 @@
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 @@
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 @@
}
}
+ 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 @@
};
/**
+ * 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 @@
}
/**
+ * 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 @@
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 @@
}
}
+ 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 @@
}
}
+ private void cancelFingerprintDetect() {
+ if (mService == null) {
+ return;
+ }
+
+ try {
+ mService.cancelFingerprintDetect(mToken, mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/**
* @hide
*/
@@ -1032,6 +1107,12 @@
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 c5c3755..8aa36d7 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -33,6 +33,11 @@
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 @@
// 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 4412cee..a84b81e1 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl
@@ -26,6 +26,7 @@
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 3acbfb8..c07c982 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -1072,6 +1072,15 @@
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 @@
}
};
+ // 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 @@
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 @@
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 9e056cf..6362812 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 @@
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 @@
}
@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 88469a2..20c004d 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 @@
}
}
- 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 543ce57..c661f45 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.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 @@
}
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 72e1bbb..e5a1898 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 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 6b7ba6a..a53fe47 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.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 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.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 @@
}
private final class FingerprintAuthClient extends AuthenticationClientImpl {
+ private final boolean mDetectOnly;
+
@Override
protected boolean isFingerprint() {
return true;
@@ -133,9 +138,10 @@
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 @@
return super.handleFailedAttempt();
}
+
+ boolean isDetectOnly() {
+ return mDetectOnly;
+ }
}
/**
@@ -234,18 +244,55 @@
}
@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 @@
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 @@
}
@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 @@
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 @@
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 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 @@
mAlarmManager = context.getSystemService(AlarmManager.class);
context.registerReceiver(mLockoutReceiver, new IntentFilter(getLockoutResetIntent()),
getLockoutBroadcastPermission(), null /* handler */);
+ mLockPatternUtils = new LockPatternUtils(context);
}
@Override