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
This commit is contained in:
@@ -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.
|
||||
@@ -271,6 +281,18 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
|
||||
public void onAuthenticationAcquired(int acquireInfo) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -453,6 +475,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
|
||||
@@ -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();
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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));
|
||||
@@ -418,6 +420,43 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
||||
assertThat(mKeyguardUpdateMonitor.mTelephonyCapable).isTrue();
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -274,6 +321,17 @@ public class FingerprintService extends BiometricServiceBase {
|
||||
cancelAuthenticationInternal(token, opPackageName);
|
||||
}
|
||||
|
||||
@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) {
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user