Merge "Add callback for when enrollment state changes" into sc-qpr1-dev
This commit is contained in:
@@ -849,26 +849,6 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
|
||||
return hasEnrolledFingerprints(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified user has enrollments in any of the specified sensors.
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
|
||||
public boolean hasEnrolledTemplatesForAnySensor(int userId,
|
||||
@NonNull List<FingerprintSensorPropertiesInternal> sensors) {
|
||||
if (mService == null) {
|
||||
Slog.w(TAG, "hasEnrolledTemplatesForAnySensor: no fingerprint service");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return mService.hasEnrolledTemplatesForAnySensor(userId, sensors,
|
||||
mContext.getOpPackageName());
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
|
||||
@@ -49,5 +49,10 @@ public abstract class FingerprintStateListener extends IFingerprintStateListener
|
||||
* Defines behavior in response to state update
|
||||
* @param newState new state of fingerprint sensor
|
||||
*/
|
||||
public abstract void onStateChanged(@FingerprintStateListener.State int newState);
|
||||
public void onStateChanged(@FingerprintStateListener.State int newState) {};
|
||||
|
||||
/**
|
||||
* Invoked when enrollment state changes for the specified user
|
||||
*/
|
||||
public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) {};
|
||||
}
|
||||
|
||||
@@ -120,9 +120,6 @@ interface IFingerprintService {
|
||||
// Determine if a user has at least one enrolled fingerprint.
|
||||
boolean hasEnrolledFingerprints(int sensorId, int userId, String opPackageName);
|
||||
|
||||
// Determine if a user has at least one enrolled fingerprint in any of the specified sensors
|
||||
boolean hasEnrolledTemplatesForAnySensor(int userId, in List<FingerprintSensorPropertiesInternal> sensors, String opPackageName);
|
||||
|
||||
// Return the LockoutTracker status for the specified user
|
||||
int getLockoutModeForUser(int sensorId, int userId);
|
||||
|
||||
|
||||
@@ -24,4 +24,5 @@ import android.hardware.fingerprint.Fingerprint;
|
||||
*/
|
||||
oneway interface IFingerprintStateListener {
|
||||
void onStateChanged(int newState);
|
||||
void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments);
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ import android.hardware.face.FaceManager;
|
||||
import android.hardware.face.FaceSensorPropertiesInternal;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.hardware.fingerprint.FingerprintStateListener;
|
||||
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
|
||||
import android.hardware.fingerprint.IUdfpsHbmListener;
|
||||
import android.os.Bundle;
|
||||
@@ -49,6 +50,7 @@ import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.WindowManager;
|
||||
|
||||
@@ -76,6 +78,9 @@ import kotlin.Unit;
|
||||
/**
|
||||
* Receives messages sent from {@link com.android.server.biometrics.BiometricService} and shows the
|
||||
* appropriate biometric UI (e.g. BiometricDialogView).
|
||||
*
|
||||
* Also coordinates biometric-related things, such as UDFPS, with
|
||||
* {@link com.android.keyguard.KeyguardUpdateMonitor}
|
||||
*/
|
||||
@SysUISingleton
|
||||
public class AuthController extends SystemUI implements CommandQueue.Callbacks,
|
||||
@@ -115,6 +120,8 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
|
||||
@Nullable private List<FingerprintSensorPropertiesInternal> mUdfpsProps;
|
||||
@Nullable private List<FingerprintSensorPropertiesInternal> mSidefpsProps;
|
||||
|
||||
@NonNull private final SparseBooleanArray mUdfpsEnrolledForUser;
|
||||
|
||||
private class BiometricTaskStackListener extends TaskStackListener {
|
||||
@Override
|
||||
public void onTaskStackChanged() {
|
||||
@@ -122,6 +129,21 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
|
||||
}
|
||||
}
|
||||
|
||||
private final FingerprintStateListener mFingerprintStateListener =
|
||||
new FingerprintStateListener() {
|
||||
@Override
|
||||
public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) {
|
||||
Log.d(TAG, "onEnrollmentsChanged, userId: " + userId
|
||||
+ ", sensorId: " + sensorId
|
||||
+ ", hasEnrollments: " + hasEnrollments);
|
||||
for (FingerprintSensorPropertiesInternal prop : mUdfpsProps) {
|
||||
if (prop.sensorId == sensorId) {
|
||||
mUdfpsEnrolledForUser.put(userId, hasEnrollments);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@NonNull
|
||||
private final IFingerprintAuthenticatorsRegisteredCallback
|
||||
mFingerprintAuthenticatorsRegisteredCallback =
|
||||
@@ -436,6 +458,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
|
||||
mUdfpsControllerFactory = udfpsControllerFactory;
|
||||
mSidefpsControllerFactory = sidefpsControllerFactory;
|
||||
mWindowManager = windowManager;
|
||||
mUdfpsEnrolledForUser = new SparseBooleanArray();
|
||||
mOrientationListener = new BiometricOrientationEventListener(context,
|
||||
() -> {
|
||||
onOrientationChanged();
|
||||
@@ -474,6 +497,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
|
||||
if (mFingerprintManager != null) {
|
||||
mFingerprintManager.addAuthenticatorsRegisteredCallback(
|
||||
mFingerprintAuthenticatorsRegisteredCallback);
|
||||
mFingerprintManager.registerFingerprintStateListener(mFingerprintStateListener);
|
||||
}
|
||||
|
||||
mTaskStackListener = new BiometricTaskStackListener();
|
||||
@@ -673,7 +697,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
|
||||
return false;
|
||||
}
|
||||
|
||||
return mFingerprintManager.hasEnrolledTemplatesForAnySensor(userId, mUdfpsProps);
|
||||
return mUdfpsEnrolledForUser.get(userId);
|
||||
}
|
||||
|
||||
private void showDialog(SomeArgs args, boolean skipAnimation, Bundle savedState) {
|
||||
|
||||
@@ -26,6 +26,8 @@ import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
@@ -70,26 +72,32 @@ public abstract class BaseClientMonitor extends LoggableMonitor
|
||||
}
|
||||
|
||||
/** Holder for wrapping multiple handlers into a single Callback. */
|
||||
protected static class CompositeCallback implements Callback {
|
||||
public static class CompositeCallback implements Callback {
|
||||
@NonNull
|
||||
private final Callback[] mCallbacks;
|
||||
private final List<Callback> mCallbacks;
|
||||
|
||||
public CompositeCallback(@NonNull Callback... callbacks) {
|
||||
mCallbacks = callbacks;
|
||||
mCallbacks = new ArrayList<>();
|
||||
|
||||
for (Callback callback : callbacks) {
|
||||
if (callback != null) {
|
||||
mCallbacks.add(callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
|
||||
for (int i = 0; i < mCallbacks.length; i++) {
|
||||
mCallbacks[i].onClientStarted(clientMonitor);
|
||||
for (int i = 0; i < mCallbacks.size(); i++) {
|
||||
mCallbacks.get(i).onClientStarted(clientMonitor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
|
||||
boolean success) {
|
||||
for (int i = mCallbacks.length - 1; i >= 0; i--) {
|
||||
mCallbacks[i].onClientFinished(clientMonitor, success);
|
||||
for (int i = mCallbacks.size() - 1; i >= 0; i--) {
|
||||
mCallbacks.get(i).onClientFinished(clientMonitor, success);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -256,7 +264,7 @@ public abstract class BaseClientMonitor extends LoggableMonitor
|
||||
return mToken;
|
||||
}
|
||||
|
||||
public final int getSensorId() {
|
||||
public int getSensorId() {
|
||||
return mSensorId;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ import java.util.Arrays;
|
||||
/**
|
||||
* A class to keep track of the enrollment state for a given client.
|
||||
*/
|
||||
public abstract class EnrollClient<T> extends AcquisitionClient<T> {
|
||||
public abstract class EnrollClient<T> extends AcquisitionClient<T> implements EnrollmentModifier {
|
||||
|
||||
private static final String TAG = "Biometrics/EnrollClient";
|
||||
|
||||
@@ -40,6 +40,7 @@ public abstract class EnrollClient<T> extends AcquisitionClient<T> {
|
||||
protected final BiometricUtils mBiometricUtils;
|
||||
|
||||
private long mEnrollmentStartTimeMs;
|
||||
private final boolean mHasEnrollmentsBeforeStarting;
|
||||
|
||||
/**
|
||||
* @return true if the user has already enrolled the maximum number of templates.
|
||||
@@ -56,6 +57,18 @@ public abstract class EnrollClient<T> extends AcquisitionClient<T> {
|
||||
mBiometricUtils = utils;
|
||||
mHardwareAuthToken = Arrays.copyOf(hardwareAuthToken, hardwareAuthToken.length);
|
||||
mTimeoutSec = timeoutSec;
|
||||
mHasEnrollmentsBeforeStarting = hasEnrollments();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasEnrollmentStateChanged() {
|
||||
final boolean hasEnrollmentsNow = hasEnrollments();
|
||||
return hasEnrollmentsNow != mHasEnrollmentsBeforeStarting;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasEnrollments() {
|
||||
return !mBiometricUtils.getBiometricsForUser(getContext(), getTargetUserId()).isEmpty();
|
||||
}
|
||||
|
||||
public void onEnrollResult(BiometricAuthenticator.Identifier identifier, int remaining) {
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.biometrics.sensors;
|
||||
|
||||
/**
|
||||
* Interface for {@link BaseClientMonitor} subclasses that affect the state of enrollment.
|
||||
*/
|
||||
public interface EnrollmentModifier {
|
||||
|
||||
/**
|
||||
* Callers should typically check this after
|
||||
* {@link BaseClientMonitor.Callback#onClientFinished(BaseClientMonitor, boolean)}
|
||||
*
|
||||
* @return true if the user has gone from:
|
||||
* 1) none-enrolled --> enrolled
|
||||
* 2) enrolled --> none-enrolled
|
||||
* but NOT any-enrolled --> more-enrolled
|
||||
*/
|
||||
boolean hasEnrollmentStateChanged();
|
||||
|
||||
/**
|
||||
* @return true if the user has any enrollments
|
||||
*/
|
||||
boolean hasEnrollments();
|
||||
}
|
||||
@@ -40,7 +40,8 @@ import java.util.Map;
|
||||
* {@link #onRemoved(BiometricAuthenticator.Identifier, int)} returns true/
|
||||
*/
|
||||
public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Identifier, T>
|
||||
extends HalClientMonitor<T> implements EnumerateConsumer, RemovalConsumer {
|
||||
extends HalClientMonitor<T> implements EnumerateConsumer, RemovalConsumer,
|
||||
EnrollmentModifier {
|
||||
|
||||
private static final String TAG = "Biometrics/InternalCleanupClient";
|
||||
|
||||
@@ -61,6 +62,7 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide
|
||||
private final BiometricUtils<S> mBiometricUtils;
|
||||
private final Map<Integer, Long> mAuthenticatorIds;
|
||||
private final List<S> mEnrolledList;
|
||||
private final boolean mHasEnrollmentsBeforeStarting;
|
||||
private BaseClientMonitor mCurrentTask;
|
||||
|
||||
private final Callback mEnumerateCallback = new Callback() {
|
||||
@@ -115,6 +117,7 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide
|
||||
mBiometricUtils = utils;
|
||||
mAuthenticatorIds = authenticatorIds;
|
||||
mEnrolledList = enrolledList;
|
||||
mHasEnrollmentsBeforeStarting = !utils.getBiometricsForUser(context, userId).isEmpty();
|
||||
}
|
||||
|
||||
private void startCleanupUnknownHalTemplates() {
|
||||
@@ -165,6 +168,18 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide
|
||||
((RemovalClient<S, T>) mCurrentTask).onRemoved(identifier, remaining);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasEnrollmentStateChanged() {
|
||||
final boolean hasEnrollmentsNow = !mBiometricUtils
|
||||
.getBiometricsForUser(getContext(), getTargetUserId()).isEmpty();
|
||||
return hasEnrollmentsNow != mHasEnrollmentsBeforeStarting;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasEnrollments() {
|
||||
return !mBiometricUtils.getBiometricsForUser(getContext(), getTargetUserId()).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnumerationResult(BiometricAuthenticator.Identifier identifier,
|
||||
int remaining) {
|
||||
|
||||
@@ -33,12 +33,13 @@ import java.util.Map;
|
||||
* A class to keep track of the remove state for a given client.
|
||||
*/
|
||||
public abstract class RemovalClient<S extends BiometricAuthenticator.Identifier, T>
|
||||
extends HalClientMonitor<T> implements RemovalConsumer {
|
||||
extends HalClientMonitor<T> implements RemovalConsumer, EnrollmentModifier {
|
||||
|
||||
private static final String TAG = "Biometrics/RemovalClient";
|
||||
|
||||
private final BiometricUtils<S> mBiometricUtils;
|
||||
private final Map<Integer, Long> mAuthenticatorIds;
|
||||
private final boolean mHasEnrollmentsBeforeStarting;
|
||||
|
||||
public RemovalClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
|
||||
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener,
|
||||
@@ -49,6 +50,7 @@ public abstract class RemovalClient<S extends BiometricAuthenticator.Identifier,
|
||||
BiometricsProtoEnums.CLIENT_UNKNOWN);
|
||||
mBiometricUtils = utils;
|
||||
mAuthenticatorIds = authenticatorIds;
|
||||
mHasEnrollmentsBeforeStarting = !utils.getBiometricsForUser(context, userId).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -90,6 +92,18 @@ public abstract class RemovalClient<S extends BiometricAuthenticator.Identifier,
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasEnrollmentStateChanged() {
|
||||
final boolean hasEnrollmentsNow = !mBiometricUtils
|
||||
.getBiometricsForUser(getContext(), getTargetUserId()).isEmpty();
|
||||
return hasEnrollmentsNow != mHasEnrollmentsBeforeStarting;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasEnrollments() {
|
||||
return !mBiometricUtils.getBiometricsForUser(getContext(), getTargetUserId()).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProtoEnum() {
|
||||
return BiometricsProto.CM_REMOVE;
|
||||
|
||||
@@ -35,6 +35,7 @@ import android.annotation.Nullable;
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.hardware.biometrics.BiometricManager;
|
||||
import android.hardware.biometrics.BiometricPrompt;
|
||||
import android.hardware.biometrics.BiometricsProtoEnums;
|
||||
@@ -62,11 +63,13 @@ import android.os.Build;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.util.EventLog;
|
||||
import android.util.Pair;
|
||||
@@ -111,6 +114,7 @@ public class FingerprintService extends SystemService {
|
||||
private final FingerprintServiceWrapper mServiceWrapper;
|
||||
@NonNull private final List<ServiceProvider> mServiceProviders;
|
||||
@NonNull private final FingerprintStateCallback mFingerprintStateCallback;
|
||||
@NonNull private final Handler mHandler;
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@NonNull private final RemoteCallbackList<IFingerprintAuthenticatorsRegisteredCallback>
|
||||
@@ -125,6 +129,37 @@ public class FingerprintService extends SystemService {
|
||||
*/
|
||||
public void registerFingerprintStateListener(@NonNull IFingerprintStateListener listener) {
|
||||
mFingerprintStateCallback.registerFingerprintStateListener(listener);
|
||||
broadcastCurrentEnrollmentState(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param listener if non-null, notifies only this listener. if null, notifies all listeners
|
||||
* in {@link FingerprintStateCallback}. This is slightly ugly, but reduces
|
||||
* redundant code.
|
||||
*/
|
||||
private void broadcastCurrentEnrollmentState(@Nullable IFingerprintStateListener listener) {
|
||||
final UserManager um = UserManager.get(getContext());
|
||||
synchronized (mLock) {
|
||||
// Update the new listener with current state of all sensors
|
||||
for (FingerprintSensorPropertiesInternal prop : mSensorProps) {
|
||||
final ServiceProvider provider = getProviderForSensor(prop.sensorId);
|
||||
for (UserInfo userInfo : um.getAliveUsers()) {
|
||||
final boolean enrolled = !provider
|
||||
.getEnrolledFingerprints(prop.sensorId, userInfo.id).isEmpty();
|
||||
|
||||
// Defer this work and allow the loop to release the lock sooner
|
||||
mHandler.post(() -> {
|
||||
if (listener != null) {
|
||||
mFingerprintStateCallback.notifyFingerprintEnrollmentStateChanged(
|
||||
listener, userInfo.id, prop.sensorId, enrolled);
|
||||
} else {
|
||||
mFingerprintStateCallback.notifyAllFingerprintEnrollmentStateChanged(
|
||||
userInfo.id, prop.sensorId, enrolled);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -143,8 +178,7 @@ public class FingerprintService extends SystemService {
|
||||
return null;
|
||||
}
|
||||
|
||||
return provider.createTestSession(sensorId, callback, mFingerprintStateCallback,
|
||||
opPackageName);
|
||||
return provider.createTestSession(sensorId, callback, opPackageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -227,7 +261,7 @@ public class FingerprintService extends SystemService {
|
||||
}
|
||||
|
||||
provider.second.scheduleEnroll(provider.first, token, hardwareAuthToken, userId,
|
||||
receiver, opPackageName, enrollReason, mFingerprintStateCallback);
|
||||
receiver, opPackageName, enrollReason);
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
@@ -306,7 +340,7 @@ public class FingerprintService extends SystemService {
|
||||
}
|
||||
return provider.second.scheduleAuthenticate(provider.first, token, operationId, userId,
|
||||
0 /* cookie */, new ClientMonitorCallbackConverter(receiver), opPackageName,
|
||||
restricted, statsClient, isKeyguard, mFingerprintStateCallback);
|
||||
restricted, statsClient, isKeyguard);
|
||||
}
|
||||
|
||||
private long authenticateWithPrompt(
|
||||
@@ -414,7 +448,7 @@ public class FingerprintService extends SystemService {
|
||||
|
||||
return provider.second.scheduleFingerDetect(provider.first, token, userId,
|
||||
new ClientMonitorCallbackConverter(receiver), opPackageName,
|
||||
BiometricsProtoEnums.CLIENT_KEYGUARD, mFingerprintStateCallback);
|
||||
BiometricsProtoEnums.CLIENT_KEYGUARD);
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
@@ -433,7 +467,7 @@ public class FingerprintService extends SystemService {
|
||||
provider.scheduleAuthenticate(sensorId, token, operationId, userId, cookie,
|
||||
new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, requestId,
|
||||
restricted, BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
|
||||
allowBackgroundAuthentication, mFingerprintStateCallback);
|
||||
allowBackgroundAuthentication);
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
@@ -687,27 +721,6 @@ public class FingerprintService extends SystemService {
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public boolean hasEnrolledTemplatesForAnySensor(int userId,
|
||||
@NonNull List<FingerprintSensorPropertiesInternal> sensors,
|
||||
@NonNull String opPackageName) {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
|
||||
for (FingerprintSensorPropertiesInternal prop : sensors) {
|
||||
final ServiceProvider provider = getProviderForSensor(prop.sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for sensorId: " + prop.sensorId
|
||||
+ ", caller: " + opPackageName);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!provider.getEnrolledFingerprints(prop.sensorId, userId).isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasEnrolledFingerprints(int sensorId, int userId, String opPackageName) {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
|
||||
@@ -797,10 +810,12 @@ public class FingerprintService extends SystemService {
|
||||
&& Settings.Secure.getIntForUser(getContext().getContentResolver(),
|
||||
Fingerprint21UdfpsMock.CONFIG_ENABLE_TEST_UDFPS, 0 /* default */,
|
||||
UserHandle.USER_CURRENT) != 0) {
|
||||
fingerprint21 = Fingerprint21UdfpsMock.newInstance(getContext(), hidlSensor,
|
||||
fingerprint21 = Fingerprint21UdfpsMock.newInstance(getContext(),
|
||||
mFingerprintStateCallback, hidlSensor,
|
||||
mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
|
||||
} else {
|
||||
fingerprint21 = Fingerprint21.newInstance(getContext(), hidlSensor,
|
||||
fingerprint21 = Fingerprint21.newInstance(getContext(),
|
||||
mFingerprintStateCallback, hidlSensor,
|
||||
mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
|
||||
}
|
||||
mServiceProviders.add(fingerprint21);
|
||||
@@ -823,8 +838,9 @@ public class FingerprintService extends SystemService {
|
||||
try {
|
||||
final SensorProps[] props = fp.getSensorProps();
|
||||
final FingerprintProvider provider =
|
||||
new FingerprintProvider(getContext(), props, instance,
|
||||
mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
|
||||
new FingerprintProvider(getContext(), mFingerprintStateCallback, props,
|
||||
instance, mLockoutResetDispatcher,
|
||||
mGestureAvailabilityDispatcher);
|
||||
mServiceProviders.add(provider);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception in getSensorProps: " + fqName);
|
||||
@@ -878,6 +894,7 @@ public class FingerprintService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
broadcastCurrentEnrollmentState(null); // broadcasts to all listeners
|
||||
broadcastAllAuthenticatorsRegistered();
|
||||
});
|
||||
}
|
||||
@@ -975,6 +992,7 @@ public class FingerprintService extends SystemService {
|
||||
mFingerprintStateCallback = new FingerprintStateCallback();
|
||||
mAuthenticatorsRegisteredCallbacks = new RemoteCallbackList<>();
|
||||
mSensorProps = new ArrayList<>();
|
||||
mHandler = new Handler(Looper.getMainLooper());
|
||||
}
|
||||
|
||||
// Notifies the callbacks that all of the authenticators have been registered and removes the
|
||||
|
||||
@@ -23,6 +23,7 @@ import static android.hardware.fingerprint.FingerprintStateListener.STATE_IDLE;
|
||||
import static android.hardware.fingerprint.FingerprintStateListener.STATE_KEYGUARD_AUTH;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.Context;
|
||||
import android.hardware.fingerprint.FingerprintStateListener;
|
||||
import android.hardware.fingerprint.IFingerprintStateListener;
|
||||
import android.os.RemoteException;
|
||||
@@ -31,6 +32,9 @@ import android.util.Slog;
|
||||
import com.android.server.biometrics.Utils;
|
||||
import com.android.server.biometrics.sensors.AuthenticationClient;
|
||||
import com.android.server.biometrics.sensors.BaseClientMonitor;
|
||||
import com.android.server.biometrics.sensors.EnrollClient;
|
||||
import com.android.server.biometrics.sensors.EnrollmentModifier;
|
||||
import com.android.server.biometrics.sensors.RemovalConsumer;
|
||||
import com.android.server.biometrics.sensors.fingerprint.hidl.FingerprintEnrollClient;
|
||||
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
@@ -39,9 +43,11 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
* A callback for receiving notifications about changes in fingerprint state.
|
||||
*/
|
||||
public class FingerprintStateCallback implements BaseClientMonitor.Callback {
|
||||
private @FingerprintStateListener.State int mFingerprintState;
|
||||
|
||||
@NonNull private final CopyOnWriteArrayList<IFingerprintStateListener>
|
||||
mFingerprintStateListeners = new CopyOnWriteArrayList<>();
|
||||
mFingerprintStateListeners = new CopyOnWriteArrayList<>();
|
||||
|
||||
private @FingerprintStateListener.State int mFingerprintState;
|
||||
|
||||
public FingerprintStateCallback() {
|
||||
mFingerprintState = STATE_IDLE;
|
||||
@@ -54,8 +60,9 @@ public class FingerprintStateCallback implements BaseClientMonitor.Callback {
|
||||
@Override
|
||||
public void onClientStarted(@NonNull BaseClientMonitor client) {
|
||||
final int previousFingerprintState = mFingerprintState;
|
||||
|
||||
if (client instanceof AuthenticationClient) {
|
||||
AuthenticationClient authClient = (AuthenticationClient) client;
|
||||
final AuthenticationClient<?> authClient = (AuthenticationClient<?>) client;
|
||||
if (authClient.isKeyguard()) {
|
||||
mFingerprintState = STATE_KEYGUARD_AUTH;
|
||||
} else if (authClient.isBiometricPrompt()) {
|
||||
@@ -70,6 +77,7 @@ public class FingerprintStateCallback implements BaseClientMonitor.Callback {
|
||||
"Other authentication client: " + Utils.getClientName(client));
|
||||
mFingerprintState = STATE_IDLE;
|
||||
}
|
||||
|
||||
Slog.d(FingerprintService.TAG, "Fps state updated from " + previousFingerprintState
|
||||
+ " to " + mFingerprintState + ", client " + client);
|
||||
notifyFingerprintStateListeners(mFingerprintState);
|
||||
@@ -81,6 +89,18 @@ public class FingerprintStateCallback implements BaseClientMonitor.Callback {
|
||||
Slog.d(FingerprintService.TAG,
|
||||
"Client finished, fps state updated to " + mFingerprintState + ", client "
|
||||
+ client);
|
||||
|
||||
if (client instanceof EnrollmentModifier) {
|
||||
EnrollmentModifier enrollmentModifier = (EnrollmentModifier) client;
|
||||
final boolean enrollmentStateChanged = enrollmentModifier.hasEnrollmentStateChanged();
|
||||
Slog.d(FingerprintService.TAG, "Enrollment state changed: " + enrollmentStateChanged);
|
||||
if (enrollmentStateChanged) {
|
||||
notifyAllFingerprintEnrollmentStateChanged(client.getTargetUserId(),
|
||||
client.getSensorId(),
|
||||
enrollmentModifier.hasEnrollments());
|
||||
}
|
||||
}
|
||||
|
||||
notifyFingerprintStateListeners(mFingerprintState);
|
||||
}
|
||||
|
||||
@@ -94,6 +114,32 @@ public class FingerprintStateCallback implements BaseClientMonitor.Callback {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be invoked when:
|
||||
* 1) Enrolled --> None-enrolled
|
||||
* 2) None-enrolled --> enrolled
|
||||
* 3) HAL becomes ready
|
||||
* 4) Listener is registered
|
||||
*/
|
||||
void notifyAllFingerprintEnrollmentStateChanged(int userId, int sensorId,
|
||||
boolean hasEnrollments) {
|
||||
for (IFingerprintStateListener listener : mFingerprintStateListeners) {
|
||||
notifyFingerprintEnrollmentStateChanged(listener, userId, sensorId, hasEnrollments);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the listener of enrollment state changes.
|
||||
*/
|
||||
void notifyFingerprintEnrollmentStateChanged(@NonNull IFingerprintStateListener listener,
|
||||
int userId, int sensorId, boolean hasEnrollments) {
|
||||
try {
|
||||
listener.onEnrollmentsChanged(userId, sensorId, hasEnrollments);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(FingerprintService.TAG, "Remote exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables clients to register a FingerprintStateListener. Used by FingerprintService to forward
|
||||
* updates in fingerprint sensor state to the SideFpNsEventHandler
|
||||
|
||||
@@ -90,27 +90,23 @@ public interface ServiceProvider {
|
||||
*/
|
||||
void scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken,
|
||||
int userId, @NonNull IFingerprintServiceReceiver receiver,
|
||||
@NonNull String opPackageName, @FingerprintManager.EnrollReason int enrollReason,
|
||||
@NonNull FingerprintStateCallback fingerprintStateCallback);
|
||||
@NonNull String opPackageName, @FingerprintManager.EnrollReason int enrollReason);
|
||||
|
||||
void cancelEnrollment(int sensorId, @NonNull IBinder token);
|
||||
|
||||
long scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId,
|
||||
@NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName,
|
||||
int statsClient,
|
||||
@NonNull FingerprintStateCallback fingerprintStateCallback);
|
||||
int statsClient);
|
||||
|
||||
void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
|
||||
int cookie, @NonNull ClientMonitorCallbackConverter callback,
|
||||
@NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
|
||||
boolean allowBackgroundAuthentication,
|
||||
@NonNull FingerprintStateCallback fingerprintStateCallback);
|
||||
boolean allowBackgroundAuthentication);
|
||||
|
||||
long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
|
||||
int cookie, @NonNull ClientMonitorCallbackConverter callback,
|
||||
@NonNull String opPackageName, boolean restricted, int statsClient,
|
||||
boolean allowBackgroundAuthentication,
|
||||
@NonNull FingerprintStateCallback fingerprintStateCallback);
|
||||
boolean allowBackgroundAuthentication);
|
||||
|
||||
void startPreparedClient(int sensorId, int cookie);
|
||||
|
||||
@@ -169,6 +165,5 @@ public interface ServiceProvider {
|
||||
|
||||
@NonNull
|
||||
ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
|
||||
@NonNull FingerprintStateCallback fingerprintStateCallback,
|
||||
@NonNull String opPackageName);
|
||||
}
|
||||
|
||||
@@ -143,8 +143,7 @@ class BiometricTestSessionImpl extends ITestSession.Stub {
|
||||
Utils.checkPermission(mContext, TEST_BIOMETRIC);
|
||||
|
||||
mProvider.scheduleEnroll(mSensorId, new Binder(), new byte[69], userId, mReceiver,
|
||||
mContext.getOpPackageName(), FingerprintManager.ENROLL_ENROLL,
|
||||
mFingerprintStateCallback);
|
||||
mContext.getOpPackageName(), FingerprintManager.ENROLL_ENROLL);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -82,6 +82,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
private boolean mTestHalEnabled;
|
||||
|
||||
@NonNull private final Context mContext;
|
||||
@NonNull private final FingerprintStateCallback mFingerprintStateCallback;
|
||||
@NonNull private final String mHalInstanceName;
|
||||
@NonNull @VisibleForTesting
|
||||
final SparseArray<Sensor> mSensors; // Map of sensors that this HAL supports
|
||||
@@ -130,10 +131,13 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
}
|
||||
}
|
||||
|
||||
public FingerprintProvider(@NonNull Context context, @NonNull SensorProps[] props,
|
||||
@NonNull String halInstanceName, @NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
public FingerprintProvider(@NonNull Context context,
|
||||
@NonNull FingerprintStateCallback fingerprintStateCallback,
|
||||
@NonNull SensorProps[] props, @NonNull String halInstanceName,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
@NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
|
||||
mContext = context;
|
||||
mFingerprintStateCallback = fingerprintStateCallback;
|
||||
mHalInstanceName = halInstanceName;
|
||||
mSensors = new SparseArray<>();
|
||||
mHandler = new Handler(Looper.getMainLooper());
|
||||
@@ -335,8 +339,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
public void scheduleEnroll(int sensorId, @NonNull IBinder token,
|
||||
@NonNull byte[] hardwareAuthToken, int userId,
|
||||
@NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName,
|
||||
@FingerprintManager.EnrollReason int enrollReason,
|
||||
@NonNull FingerprintStateCallback fingerprintStateCallback) {
|
||||
@FingerprintManager.EnrollReason int enrollReason) {
|
||||
mHandler.post(() -> {
|
||||
final int maxTemplatesPerUser = mSensors.get(sensorId).getSensorProperties()
|
||||
.maxEnrollmentsPerUser;
|
||||
@@ -350,13 +353,13 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
|
||||
@Override
|
||||
public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
|
||||
fingerprintStateCallback.onClientStarted(clientMonitor);
|
||||
mFingerprintStateCallback.onClientStarted(clientMonitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
|
||||
boolean success) {
|
||||
fingerprintStateCallback.onClientFinished(clientMonitor, success);
|
||||
mFingerprintStateCallback.onClientFinished(clientMonitor, success);
|
||||
if (success) {
|
||||
scheduleLoadAuthenticatorIdsForUser(sensorId, userId);
|
||||
scheduleInvalidationRequest(sensorId, userId);
|
||||
@@ -374,17 +377,15 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
@Override
|
||||
public long scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId,
|
||||
@NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName,
|
||||
int statsClient,
|
||||
@NonNull FingerprintStateCallback fingerprintStateCallback) {
|
||||
int statsClient) {
|
||||
final long id = mRequestCounter.incrementAndGet();
|
||||
|
||||
mHandler.post(() -> {
|
||||
final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
|
||||
final FingerprintDetectClient client = new FingerprintDetectClient(mContext,
|
||||
mSensors.get(sensorId).getLazySession(), token, id, callback, userId,
|
||||
opPackageName, sensorId, mUdfpsOverlayController, isStrongBiometric,
|
||||
statsClient);
|
||||
scheduleForSensor(sensorId, client, fingerprintStateCallback);
|
||||
scheduleForSensor(sensorId, client, mFingerprintStateCallback);
|
||||
});
|
||||
|
||||
return id;
|
||||
@@ -394,8 +395,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
|
||||
int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback,
|
||||
@NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
|
||||
boolean allowBackgroundAuthentication,
|
||||
@NonNull FingerprintStateCallback fingerprintStateCallback) {
|
||||
boolean allowBackgroundAuthentication) {
|
||||
mHandler.post(() -> {
|
||||
final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
|
||||
final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient(
|
||||
@@ -405,7 +405,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
mTaskStackListener, mSensors.get(sensorId).getLockoutCache(),
|
||||
mUdfpsOverlayController, allowBackgroundAuthentication,
|
||||
mSensors.get(sensorId).getSensorProperties());
|
||||
scheduleForSensor(sensorId, client, fingerprintStateCallback);
|
||||
scheduleForSensor(sensorId, client, mFingerprintStateCallback);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -413,13 +413,11 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
public long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
|
||||
int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback,
|
||||
@NonNull String opPackageName, boolean restricted, int statsClient,
|
||||
boolean allowBackgroundAuthentication,
|
||||
@NonNull FingerprintStateCallback fingerprintStateCallback) {
|
||||
boolean allowBackgroundAuthentication) {
|
||||
final long id = mRequestCounter.incrementAndGet();
|
||||
|
||||
scheduleAuthenticate(sensorId, token, operationId, userId, cookie, callback,
|
||||
opPackageName, id, restricted, statsClient, allowBackgroundAuthentication,
|
||||
fingerprintStateCallback);
|
||||
opPackageName, id, restricted, statsClient, allowBackgroundAuthentication);
|
||||
|
||||
return id;
|
||||
}
|
||||
@@ -466,7 +464,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
new ClientMonitorCallbackConverter(receiver), fingerprintIds, userId,
|
||||
opPackageName, FingerprintUtils.getInstance(sensorId), sensorId,
|
||||
mSensors.get(sensorId).getAuthenticatorIds());
|
||||
scheduleForSensor(sensorId, client);
|
||||
scheduleForSensor(sensorId, client, mFingerprintStateCallback);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -481,7 +479,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
mContext.getOpPackageName(), sensorId, enrolledList,
|
||||
FingerprintUtils.getInstance(sensorId),
|
||||
mSensors.get(sensorId).getAuthenticatorIds());
|
||||
scheduleForSensor(sensorId, client, callback);
|
||||
scheduleForSensor(sensorId, client, new BaseClientMonitor.CompositeCallback(callback,
|
||||
mFingerprintStateCallback));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -626,9 +625,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
@NonNull
|
||||
@Override
|
||||
public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
|
||||
@NonNull FingerprintStateCallback fingerprintStateCallback,
|
||||
@NonNull String opPackageName) {
|
||||
return mSensors.get(sensorId).createTestSession(callback, fingerprintStateCallback);
|
||||
return mSensors.get(sensorId).createTestSession(callback, mFingerprintStateCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -143,8 +143,7 @@ public class BiometricTestSessionImpl extends ITestSession.Stub {
|
||||
Utils.checkPermission(mContext, TEST_BIOMETRIC);
|
||||
|
||||
mFingerprint21.scheduleEnroll(mSensorId, new Binder(), new byte[69], userId, mReceiver,
|
||||
mContext.getOpPackageName(), FingerprintManager.ENROLL_ENROLL,
|
||||
mFingerprintStateCallback);
|
||||
mContext.getOpPackageName(), FingerprintManager.ENROLL_ENROLL);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -102,6 +102,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
|
||||
private boolean mTestHalEnabled;
|
||||
|
||||
final Context mContext;
|
||||
@NonNull private final FingerprintStateCallback mFingerprintStateCallback;
|
||||
private final ActivityTaskManager mActivityTaskManager;
|
||||
@NonNull private final FingerprintSensorPropertiesInternal mSensorProperties;
|
||||
private final BiometricScheduler mScheduler;
|
||||
@@ -317,11 +318,13 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
|
||||
}
|
||||
|
||||
Fingerprint21(@NonNull Context context,
|
||||
@NonNull FingerprintStateCallback fingerprintStateCallback,
|
||||
@NonNull FingerprintSensorPropertiesInternal sensorProps,
|
||||
@NonNull BiometricScheduler scheduler, @NonNull Handler handler,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
@NonNull HalResultController controller) {
|
||||
mContext = context;
|
||||
mFingerprintStateCallback = fingerprintStateCallback;
|
||||
|
||||
mSensorProperties = sensorProps;
|
||||
mSensorId = sensorProps.sensorId;
|
||||
@@ -351,6 +354,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
|
||||
}
|
||||
|
||||
public static Fingerprint21 newInstance(@NonNull Context context,
|
||||
@NonNull FingerprintStateCallback fingerprintStateCallback,
|
||||
@NonNull FingerprintSensorPropertiesInternal sensorProps,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
@NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
|
||||
@@ -362,8 +366,8 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
|
||||
final HalResultController controller = new HalResultController(sensorProps.sensorId,
|
||||
context, handler,
|
||||
scheduler);
|
||||
return new Fingerprint21(context, sensorProps, scheduler, handler, lockoutResetDispatcher,
|
||||
controller);
|
||||
return new Fingerprint21(context, fingerprintStateCallback, sensorProps, scheduler, handler,
|
||||
lockoutResetDispatcher, controller);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -557,8 +561,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
|
||||
public void scheduleEnroll(int sensorId, @NonNull IBinder token,
|
||||
@NonNull byte[] hardwareAuthToken, int userId,
|
||||
@NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName,
|
||||
@FingerprintManager.EnrollReason int enrollReason,
|
||||
@NonNull FingerprintStateCallback fingerprintStateCallback) {
|
||||
@FingerprintManager.EnrollReason int enrollReason) {
|
||||
mHandler.post(() -> {
|
||||
scheduleUpdateActiveUserWithoutHandler(userId);
|
||||
|
||||
@@ -570,13 +573,13 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
|
||||
mScheduler.scheduleClientMonitor(client, new BaseClientMonitor.Callback() {
|
||||
@Override
|
||||
public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
|
||||
fingerprintStateCallback.onClientStarted(clientMonitor);
|
||||
mFingerprintStateCallback.onClientStarted(clientMonitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
|
||||
boolean success) {
|
||||
fingerprintStateCallback.onClientFinished(clientMonitor, success);
|
||||
mFingerprintStateCallback.onClientFinished(clientMonitor, success);
|
||||
if (success) {
|
||||
// Update authenticatorIds
|
||||
scheduleUpdateActiveUserWithoutHandler(clientMonitor.getTargetUserId(),
|
||||
@@ -597,10 +600,8 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
|
||||
@Override
|
||||
public long scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId,
|
||||
@NonNull ClientMonitorCallbackConverter listener, @NonNull String opPackageName,
|
||||
int statsClient,
|
||||
@NonNull FingerprintStateCallback fingerprintStateCallback) {
|
||||
int statsClient) {
|
||||
final long id = mRequestCounter.incrementAndGet();
|
||||
|
||||
mHandler.post(() -> {
|
||||
scheduleUpdateActiveUserWithoutHandler(userId);
|
||||
|
||||
@@ -609,7 +610,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
|
||||
mLazyDaemon, token, id, listener, userId, opPackageName,
|
||||
mSensorProperties.sensorId, mUdfpsOverlayController, isStrongBiometric,
|
||||
statsClient);
|
||||
mScheduler.scheduleClientMonitor(client, fingerprintStateCallback);
|
||||
mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback);
|
||||
});
|
||||
|
||||
return id;
|
||||
@@ -619,8 +620,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
|
||||
public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
|
||||
int userId, int cookie, @NonNull ClientMonitorCallbackConverter listener,
|
||||
@NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
|
||||
boolean allowBackgroundAuthentication,
|
||||
@NonNull FingerprintStateCallback fingerprintStateCallback) {
|
||||
boolean allowBackgroundAuthentication) {
|
||||
mHandler.post(() -> {
|
||||
scheduleUpdateActiveUserWithoutHandler(userId);
|
||||
|
||||
@@ -631,7 +631,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
|
||||
mSensorProperties.sensorId, isStrongBiometric, statsClient,
|
||||
mTaskStackListener, mLockoutTracker, mUdfpsOverlayController,
|
||||
allowBackgroundAuthentication, mSensorProperties);
|
||||
mScheduler.scheduleClientMonitor(client, fingerprintStateCallback);
|
||||
mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -639,13 +639,11 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
|
||||
public long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
|
||||
int userId, int cookie, @NonNull ClientMonitorCallbackConverter listener,
|
||||
@NonNull String opPackageName, boolean restricted, int statsClient,
|
||||
boolean allowBackgroundAuthentication,
|
||||
@NonNull FingerprintStateCallback fingerprintStateCallback) {
|
||||
boolean allowBackgroundAuthentication) {
|
||||
final long id = mRequestCounter.incrementAndGet();
|
||||
|
||||
scheduleAuthenticate(sensorId, token, operationId, userId, cookie, listener,
|
||||
opPackageName, id, restricted, statsClient, allowBackgroundAuthentication,
|
||||
fingerprintStateCallback);
|
||||
opPackageName, id, restricted, statsClient, allowBackgroundAuthentication);
|
||||
|
||||
return id;
|
||||
}
|
||||
@@ -672,7 +670,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
|
||||
mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), fingerId,
|
||||
userId, opPackageName, FingerprintUtils.getLegacyInstance(mSensorId),
|
||||
mSensorProperties.sensorId, mAuthenticatorIds);
|
||||
mScheduler.scheduleClientMonitor(client);
|
||||
mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -689,7 +687,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
|
||||
0 /* fingerprintId */, userId, opPackageName,
|
||||
FingerprintUtils.getLegacyInstance(mSensorId),
|
||||
mSensorProperties.sensorId, mAuthenticatorIds);
|
||||
mScheduler.scheduleClientMonitor(client);
|
||||
mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -711,7 +709,8 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
|
||||
@Override
|
||||
public void scheduleInternalCleanup(int sensorId, int userId,
|
||||
@Nullable BaseClientMonitor.Callback callback) {
|
||||
scheduleInternalCleanup(userId, callback);
|
||||
scheduleInternalCleanup(userId, new BaseClientMonitor.CompositeCallback(callback,
|
||||
mFingerprintStateCallback));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -919,9 +918,8 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
|
||||
@NonNull
|
||||
@Override
|
||||
public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
|
||||
@NonNull FingerprintStateCallback fingerprintStateCallback,
|
||||
@NonNull String opPackageName) {
|
||||
return new BiometricTestSessionImpl(mContext, mSensorProperties.sensorId, callback,
|
||||
fingerprintStateCallback, this, mHalResultController);
|
||||
mFingerprintStateCallback, this, mHalResultController);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
|
||||
import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
|
||||
import android.hardware.fingerprint.FingerprintSensorProperties;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.hardware.fingerprint.FingerprintStateListener;
|
||||
import android.hardware.fingerprint.IUdfpsOverlayController;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
@@ -42,6 +43,7 @@ import com.android.server.biometrics.sensors.BaseClientMonitor;
|
||||
import com.android.server.biometrics.sensors.BiometricScheduler;
|
||||
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
|
||||
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
|
||||
import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback;
|
||||
import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -270,6 +272,7 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
|
||||
}
|
||||
|
||||
public static Fingerprint21UdfpsMock newInstance(@NonNull Context context,
|
||||
@NonNull FingerprintStateCallback fingerprintStateCallback,
|
||||
@NonNull FingerprintSensorPropertiesInternal sensorProps,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
@NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
|
||||
@@ -280,8 +283,8 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
|
||||
new TestableBiometricScheduler(TAG, gestureAvailabilityDispatcher);
|
||||
final MockHalResultController controller =
|
||||
new MockHalResultController(sensorProps.sensorId, context, handler, scheduler);
|
||||
return new Fingerprint21UdfpsMock(context, sensorProps, scheduler, handler,
|
||||
lockoutResetDispatcher, controller);
|
||||
return new Fingerprint21UdfpsMock(context, fingerprintStateCallback, sensorProps, scheduler,
|
||||
handler, lockoutResetDispatcher, controller);
|
||||
}
|
||||
|
||||
private static abstract class FakeFingerRunnable implements Runnable {
|
||||
@@ -400,17 +403,19 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
|
||||
// internal preemption logic is not run.
|
||||
mFingerprint21.scheduleAuthenticate(mFingerprint21.mSensorProperties.sensorId, token,
|
||||
operationId, user, cookie, listener, opPackageName, restricted, statsClient,
|
||||
isKeyguard, null /* fingerprintStateCallback */);
|
||||
isKeyguard);
|
||||
}
|
||||
}
|
||||
|
||||
private Fingerprint21UdfpsMock(@NonNull Context context,
|
||||
@NonNull FingerprintStateCallback fingerprintStateCallback,
|
||||
@NonNull FingerprintSensorPropertiesInternal sensorProps,
|
||||
@NonNull TestableBiometricScheduler scheduler,
|
||||
@NonNull Handler handler,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
@NonNull MockHalResultController controller) {
|
||||
super(context, sensorProps, scheduler, handler, lockoutResetDispatcher, controller);
|
||||
super(context, fingerprintStateCallback, sensorProps, scheduler, handler,
|
||||
lockoutResetDispatcher, controller);
|
||||
mScheduler = scheduler;
|
||||
mScheduler.init(this);
|
||||
mHandler = handler;
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.biometrics.sensors;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
@Presubmit
|
||||
@SmallTest
|
||||
public class CompositeCallbackTest {
|
||||
|
||||
@Test
|
||||
public void testNullCallback() {
|
||||
BaseClientMonitor.Callback callback1 = mock(BaseClientMonitor.Callback.class);
|
||||
BaseClientMonitor.Callback callback2 = mock(BaseClientMonitor.Callback.class);
|
||||
BaseClientMonitor.Callback callback3 = null;
|
||||
|
||||
BaseClientMonitor.CompositeCallback callback = new BaseClientMonitor.CompositeCallback(
|
||||
callback1, callback2, callback3);
|
||||
|
||||
BaseClientMonitor clientMonitor = mock(BaseClientMonitor.class);
|
||||
|
||||
callback.onClientStarted(clientMonitor);
|
||||
verify(callback1).onClientStarted(eq(clientMonitor));
|
||||
verify(callback2).onClientStarted(eq(clientMonitor));
|
||||
|
||||
callback.onClientFinished(clientMonitor, true /* success */);
|
||||
verify(callback1).onClientFinished(eq(clientMonitor), eq(true));
|
||||
verify(callback2).onClientFinished(eq(clientMonitor), eq(true));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.biometrics.sensors.fingerprint;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.hardware.fingerprint.FingerprintStateListener;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.server.biometrics.sensors.AuthenticationClient;
|
||||
import com.android.server.biometrics.sensors.EnrollClient;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@Presubmit
|
||||
@SmallTest
|
||||
public class FingerprintStateCallbackTest {
|
||||
|
||||
private FingerprintStateCallback mCallback;
|
||||
|
||||
@Mock
|
||||
FingerprintStateListener mFingerprintStateListener;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mCallback = new FingerprintStateCallback();
|
||||
mCallback.registerFingerprintStateListener(mFingerprintStateListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoEnrollmentsToEnrollments_callbackNotified() {
|
||||
testEnrollmentCallback(true /* changed */, true /* isNowEnrolled */,
|
||||
true /* expectCallback */, true /* expectedCallbackValue */);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnrollmentsToNoEnrollments_callbackNotified() {
|
||||
testEnrollmentCallback(true /* changed */, false /* isNowEnrolled */,
|
||||
true /* expectCallback */, false /* expectedCallbackValue */);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnrollmentsToEnrollments_callbackNotNotified() {
|
||||
testEnrollmentCallback(false /* changed */, true /* isNowEnrolled */,
|
||||
false /* expectCallback */, false /* expectedCallbackValue */);
|
||||
}
|
||||
|
||||
private void testEnrollmentCallback(boolean changed, boolean isNowEnrolled,
|
||||
boolean expectCallback, boolean expectedCallbackValue) {
|
||||
EnrollClient<?> client = mock(EnrollClient.class);
|
||||
|
||||
final int userId = 10;
|
||||
final int sensorId = 100;
|
||||
|
||||
when(client.hasEnrollmentStateChanged()).thenReturn(changed);
|
||||
when(client.hasEnrollments()).thenReturn(isNowEnrolled);
|
||||
when(client.getTargetUserId()).thenReturn(userId);
|
||||
when(client.getSensorId()).thenReturn(sensorId);
|
||||
|
||||
mCallback.onClientFinished(client, true /* success */);
|
||||
if (expectCallback) {
|
||||
verify(mFingerprintStateListener).onEnrollmentsChanged(eq(userId), eq(sensorId),
|
||||
eq(expectedCallbackValue));
|
||||
} else {
|
||||
verify(mFingerprintStateListener, never()).onEnrollmentsChanged(anyInt(), anyInt(),
|
||||
anyBoolean());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuthentication_enrollmentCallbackNeverNotified() {
|
||||
AuthenticationClient<?> client = mock(AuthenticationClient.class);
|
||||
mCallback.onClientFinished(client, true /* success */);
|
||||
verify(mFingerprintStateListener, never()).onEnrollmentsChanged(anyInt(), anyInt(),
|
||||
anyBoolean());
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ import androidx.test.filters.SmallTest;
|
||||
import com.android.server.biometrics.sensors.BiometricScheduler;
|
||||
import com.android.server.biometrics.sensors.HalClientMonitor;
|
||||
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
|
||||
import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback;
|
||||
import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -58,6 +59,8 @@ public class FingerprintProviderTest {
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
private GestureAvailabilityDispatcher mGestureAvailabilityDispatcher;
|
||||
@Mock
|
||||
private FingerprintStateCallback mFingerprintStateCallback;
|
||||
|
||||
private SensorProps[] mSensorProps;
|
||||
private LockoutResetDispatcher mLockoutResetDispatcher;
|
||||
@@ -87,8 +90,8 @@ public class FingerprintProviderTest {
|
||||
|
||||
mLockoutResetDispatcher = new LockoutResetDispatcher(mContext);
|
||||
|
||||
mFingerprintProvider = new TestableFingerprintProvider(mContext, mSensorProps, TAG,
|
||||
mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
|
||||
mFingerprintProvider = new TestableFingerprintProvider(mContext, mFingerprintStateCallback,
|
||||
mSensorProps, TAG, mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@@ -133,11 +136,12 @@ public class FingerprintProviderTest {
|
||||
|
||||
private static class TestableFingerprintProvider extends FingerprintProvider {
|
||||
public TestableFingerprintProvider(@NonNull Context context,
|
||||
@NonNull FingerprintStateCallback fingerprintStateCallback,
|
||||
@NonNull SensorProps[] props,
|
||||
@NonNull String halInstanceName,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
@NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
|
||||
super(context, props, halInstanceName, lockoutResetDispatcher,
|
||||
super(context, fingerprintStateCallback, props, halInstanceName, lockoutResetDispatcher,
|
||||
gestureAvailabilityDispatcher);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ import androidx.test.filters.SmallTest;
|
||||
import com.android.internal.R;
|
||||
import com.android.server.biometrics.sensors.BiometricScheduler;
|
||||
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
|
||||
import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -67,6 +68,8 @@ public class Fingerprint21Test {
|
||||
Fingerprint21.HalResultController mHalResultController;
|
||||
@Mock
|
||||
private BiometricScheduler mScheduler;
|
||||
@Mock
|
||||
private FingerprintStateCallback mFingerprintStateCallback;
|
||||
|
||||
private LockoutResetDispatcher mLockoutResetDispatcher;
|
||||
private Fingerprint21 mFingerprint21;
|
||||
@@ -96,8 +99,9 @@ public class Fingerprint21Test {
|
||||
componentInfo, FingerprintSensorProperties.TYPE_UNKNOWN,
|
||||
resetLockoutRequiresHardwareAuthToken);
|
||||
|
||||
mFingerprint21 = new TestableFingerprint21(mContext, sensorProps, mScheduler,
|
||||
new Handler(Looper.getMainLooper()), mLockoutResetDispatcher, mHalResultController);
|
||||
mFingerprint21 = new TestableFingerprint21(mContext, mFingerprintStateCallback, sensorProps,
|
||||
mScheduler, new Handler(Looper.getMainLooper()), mLockoutResetDispatcher,
|
||||
mHalResultController);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -118,11 +122,13 @@ public class Fingerprint21Test {
|
||||
private static class TestableFingerprint21 extends Fingerprint21 {
|
||||
|
||||
TestableFingerprint21(@NonNull Context context,
|
||||
@NonNull FingerprintStateCallback fingerprintStateCallback,
|
||||
@NonNull FingerprintSensorPropertiesInternal sensorProps,
|
||||
@NonNull BiometricScheduler scheduler, @NonNull Handler handler,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
@NonNull HalResultController controller) {
|
||||
super(context, sensorProps, scheduler, handler, lockoutResetDispatcher, controller);
|
||||
super(context, fingerprintStateCallback, sensorProps, scheduler, handler,
|
||||
lockoutResetDispatcher, controller);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user