3/n: Add and use Fingerprint AIDL stop/start user clients
Bug: 181984005 Test: atest com.android.server.biometrics Test: atest CtsBiometricsTestCases Change-Id: If7dd9342629471419498f2d502bddfe031ad11b1
This commit is contained in:
@@ -25,18 +25,27 @@ import android.os.IBinder;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.biometrics.BiometricsProto;
|
||||
|
||||
public abstract class StartUserClient<T> extends HalClientMonitor<T> {
|
||||
/**
|
||||
* Abstract class for starting a new user.
|
||||
* @param <T> Interface to request a new user.
|
||||
* @param <U> Newly created user object.
|
||||
*/
|
||||
public abstract class StartUserClient<T, U> extends HalClientMonitor<T> {
|
||||
|
||||
public interface UserStartedCallback {
|
||||
void onUserStarted(int newUserId);
|
||||
/**
|
||||
* Invoked when the new user is started.
|
||||
* @param <U> New user object.
|
||||
*/
|
||||
public interface UserStartedCallback<U> {
|
||||
void onUserStarted(int newUserId, U newUser);
|
||||
}
|
||||
|
||||
@NonNull @VisibleForTesting
|
||||
protected final UserStartedCallback mUserStartedCallback;
|
||||
protected final UserStartedCallback<U> mUserStartedCallback;
|
||||
|
||||
public StartUserClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
|
||||
@Nullable IBinder token, int userId, int sensorId,
|
||||
@NonNull UserStartedCallback callback) {
|
||||
@NonNull UserStartedCallback<U> callback) {
|
||||
super(context, lazyDaemon, token, null /* listener */, userId, context.getOpPackageName(),
|
||||
0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN,
|
||||
BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
|
||||
|
||||
@@ -25,6 +25,10 @@ import android.os.IBinder;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.biometrics.BiometricsProto;
|
||||
|
||||
/**
|
||||
* Abstract class for stopping a user.
|
||||
* @param <T> Interface for stopping the user.
|
||||
*/
|
||||
public abstract class StopUserClient<T> extends HalClientMonitor<T> {
|
||||
|
||||
public interface UserStoppedCallback {
|
||||
@@ -32,7 +36,12 @@ public abstract class StopUserClient<T> extends HalClientMonitor<T> {
|
||||
}
|
||||
|
||||
@NonNull @VisibleForTesting
|
||||
protected final UserStoppedCallback mUserStoppedCallback;
|
||||
private final UserStoppedCallback mUserStoppedCallback;
|
||||
|
||||
public void onUserStopped() {
|
||||
mUserStoppedCallback.onUserStopped();
|
||||
getCallback().onClientFinished(this, true /* success */);
|
||||
}
|
||||
|
||||
public StopUserClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
|
||||
@Nullable IBinder token, int userId, int sensorId,
|
||||
|
||||
@@ -45,7 +45,7 @@ public class UserAwareBiometricScheduler extends BiometricScheduler {
|
||||
|
||||
public interface UserSwitchCallback {
|
||||
@NonNull StopUserClient<?> getStopUserClient(int userId);
|
||||
@NonNull StartUserClient<?> getStartUserClient(int newUserId);
|
||||
@NonNull StartUserClient<?, ?> getStartUserClient(int newUserId);
|
||||
}
|
||||
|
||||
@NonNull private final CurrentUserRetriever mCurrentUserRetriever;
|
||||
|
||||
@@ -135,7 +135,8 @@ public class TestHal extends IFace.Stub {
|
||||
|
||||
@Override
|
||||
public void close(int cookie) throws RemoteException {
|
||||
cb.onStateChanged(cookie, SessionState.CLOSED);
|
||||
Slog.w(TAG, "close, cookie: " + cookie);
|
||||
cb.onSessionClosed();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -82,7 +82,6 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
@NonNull private final String mHalInstanceName;
|
||||
@NonNull @VisibleForTesting
|
||||
final SparseArray<Sensor> mSensors; // Map of sensors that this HAL supports
|
||||
@NonNull private final HalClientMonitor.LazyDaemon<IFingerprint> mLazyDaemon;
|
||||
@NonNull private final Handler mHandler;
|
||||
@NonNull private final LockoutResetDispatcher mLockoutResetDispatcher;
|
||||
@NonNull private final ActivityTaskManager mActivityTaskManager;
|
||||
@@ -131,7 +130,6 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
mContext = context;
|
||||
mHalInstanceName = halInstanceName;
|
||||
mSensors = new SparseArray<>();
|
||||
mLazyDaemon = this::getHalInstance;
|
||||
mHandler = new Handler(Looper.getMainLooper());
|
||||
mLockoutResetDispatcher = lockoutResetDispatcher;
|
||||
mActivityTaskManager = ActivityTaskManager.getInstance();
|
||||
@@ -169,7 +167,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private synchronized IFingerprint getHalInstance() {
|
||||
@VisibleForTesting
|
||||
synchronized IFingerprint getHalInstance() {
|
||||
if (mTestHalEnabled) {
|
||||
// Enabling the test HAL for a single sensor in a multi-sensor HAL currently enables
|
||||
// the test HAL for all sensors under that HAL. This can be updated in the future if
|
||||
@@ -224,21 +223,6 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client, callback);
|
||||
}
|
||||
|
||||
private void createNewSessionWithoutHandler(@NonNull IFingerprint daemon, int sensorId,
|
||||
int userId) throws RemoteException {
|
||||
// Note that per IFingerprint createSession contract, this method will block until all
|
||||
// existing operations are canceled/finished. However, also note that this is fine, since
|
||||
// this method "withoutHandler" means it should only ever be invoked from the worker thread,
|
||||
// so callers will never be blocked.
|
||||
mSensors.get(sensorId).createNewSession(daemon, sensorId, userId);
|
||||
|
||||
if (FingerprintUtils.getInstance(sensorId).isInvalidationInProgress(mContext, userId)) {
|
||||
Slog.w(getTag(), "Scheduling unfinished invalidation request for sensor: " + sensorId
|
||||
+ ", user: " + userId);
|
||||
scheduleInvalidationRequest(sensorId, userId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsSensor(int sensorId) {
|
||||
return mSensors.contains(sensorId);
|
||||
@@ -275,32 +259,16 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
|
||||
private void scheduleLoadAuthenticatorIdsForUser(int sensorId, int userId) {
|
||||
mHandler.post(() -> {
|
||||
final IFingerprint daemon = getHalInstance();
|
||||
if (daemon == null) {
|
||||
Slog.e(getTag(), "Null daemon during loadAuthenticatorIds, sensorId: " + sensorId);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!mSensors.get(sensorId).hasSessionForUser(userId)) {
|
||||
createNewSessionWithoutHandler(daemon, sensorId, userId);
|
||||
}
|
||||
|
||||
final FingerprintGetAuthenticatorIdClient client =
|
||||
new FingerprintGetAuthenticatorIdClient(mContext,
|
||||
mSensors.get(sensorId).getLazySession(), userId,
|
||||
mContext.getOpPackageName(), sensorId,
|
||||
mSensors.get(sensorId).getAuthenticatorIds());
|
||||
scheduleForSensor(sensorId, client);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(getTag(), "Remote exception when scheduling loadAuthenticatorId"
|
||||
+ ", sensorId: " + sensorId
|
||||
+ ", userId: " + userId, e);
|
||||
}
|
||||
final FingerprintGetAuthenticatorIdClient client =
|
||||
new FingerprintGetAuthenticatorIdClient(mContext,
|
||||
mSensors.get(sensorId).getLazySession(), userId,
|
||||
mContext.getOpPackageName(), sensorId,
|
||||
mSensors.get(sensorId).getAuthenticatorIds());
|
||||
scheduleForSensor(sensorId, client);
|
||||
});
|
||||
}
|
||||
|
||||
private void scheduleInvalidationRequest(int sensorId, int userId) {
|
||||
void scheduleInvalidationRequest(int sensorId, int userId) {
|
||||
mHandler.post(() -> {
|
||||
final InvalidationRequesterClient<Fingerprint> client =
|
||||
new InvalidationRequesterClient<>(mContext, userId, sensorId,
|
||||
@@ -312,25 +280,11 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
@Override
|
||||
public void scheduleResetLockout(int sensorId, int userId, @Nullable byte[] hardwareAuthToken) {
|
||||
mHandler.post(() -> {
|
||||
final IFingerprint daemon = getHalInstance();
|
||||
if (daemon == null) {
|
||||
Slog.e(getTag(), "Null daemon during resetLockout, sensorId: " + sensorId);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!mSensors.get(sensorId).hasSessionForUser(userId)) {
|
||||
createNewSessionWithoutHandler(daemon, sensorId, userId);
|
||||
}
|
||||
|
||||
final FingerprintResetLockoutClient client = new FingerprintResetLockoutClient(
|
||||
mContext, mSensors.get(sensorId).getLazySession(), userId,
|
||||
mContext.getOpPackageName(), sensorId, hardwareAuthToken,
|
||||
mSensors.get(sensorId).getLockoutCache(), mLockoutResetDispatcher);
|
||||
scheduleForSensor(sensorId, client);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(getTag(), "Remote exception when scheduling resetLockout", e);
|
||||
}
|
||||
final FingerprintResetLockoutClient client = new FingerprintResetLockoutClient(
|
||||
mContext, mSensors.get(sensorId).getLazySession(), userId,
|
||||
mContext.getOpPackageName(), sensorId, hardwareAuthToken,
|
||||
mSensors.get(sensorId).getLockoutCache(), mLockoutResetDispatcher);
|
||||
scheduleForSensor(sensorId, client);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -338,26 +292,12 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
public void scheduleGenerateChallenge(int sensorId, int userId, @NonNull IBinder token,
|
||||
@NonNull IFingerprintServiceReceiver receiver, String opPackageName) {
|
||||
mHandler.post(() -> {
|
||||
final IFingerprint daemon = getHalInstance();
|
||||
if (daemon == null) {
|
||||
Slog.e(getTag(), "Null daemon during generateChallenge, sensorId: " + sensorId);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!mSensors.get(sensorId).hasSessionForUser(userId)) {
|
||||
createNewSessionWithoutHandler(daemon, sensorId, userId);
|
||||
}
|
||||
|
||||
final FingerprintGenerateChallengeClient client =
|
||||
new FingerprintGenerateChallengeClient(mContext,
|
||||
mSensors.get(sensorId).getLazySession(), token,
|
||||
new ClientMonitorCallbackConverter(receiver), opPackageName,
|
||||
sensorId);
|
||||
scheduleForSensor(sensorId, client);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(getTag(), "Remote exception when scheduling generateChallenge", e);
|
||||
}
|
||||
final FingerprintGenerateChallengeClient client =
|
||||
new FingerprintGenerateChallengeClient(mContext,
|
||||
mSensors.get(sensorId).getLazySession(), token,
|
||||
new ClientMonitorCallbackConverter(receiver), opPackageName,
|
||||
sensorId);
|
||||
scheduleForSensor(sensorId, client);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -365,25 +305,11 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
public void scheduleRevokeChallenge(int sensorId, int userId, @NonNull IBinder token,
|
||||
@NonNull String opPackageName, long challenge) {
|
||||
mHandler.post(() -> {
|
||||
final IFingerprint daemon = getHalInstance();
|
||||
if (daemon == null) {
|
||||
Slog.e(getTag(), "Null daemon during revokeChallenge, sensorId: " + sensorId);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!mSensors.get(sensorId).hasSessionForUser(userId)) {
|
||||
createNewSessionWithoutHandler(daemon, sensorId, userId);
|
||||
}
|
||||
|
||||
final FingerprintRevokeChallengeClient client =
|
||||
new FingerprintRevokeChallengeClient(mContext,
|
||||
mSensors.get(sensorId).getLazySession(), token,
|
||||
opPackageName, sensorId, challenge);
|
||||
scheduleForSensor(sensorId, client);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(getTag(), "Remote exception when scheduling revokeChallenge", e);
|
||||
}
|
||||
final FingerprintRevokeChallengeClient client =
|
||||
new FingerprintRevokeChallengeClient(mContext,
|
||||
mSensors.get(sensorId).getLazySession(), token,
|
||||
opPackageName, sensorId, challenge);
|
||||
scheduleForSensor(sensorId, client);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -392,40 +318,23 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
int userId, @NonNull IFingerprintServiceReceiver receiver,
|
||||
@NonNull String opPackageName, @FingerprintManager.EnrollReason int enrollReason) {
|
||||
mHandler.post(() -> {
|
||||
final IFingerprint daemon = getHalInstance();
|
||||
if (daemon == null) {
|
||||
Slog.e(getTag(), "Null daemon during enroll, sensorId: " + sensorId);
|
||||
// If this happens, we need to send HW_UNAVAILABLE after the scheduler gets to
|
||||
// this operation. We should not send the callback yet, since the scheduler may
|
||||
// be processing something else.
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!mSensors.get(sensorId).hasSessionForUser(userId)) {
|
||||
createNewSessionWithoutHandler(daemon, sensorId, userId);
|
||||
}
|
||||
|
||||
final int maxTemplatesPerUser = mSensors.get(sensorId).getSensorProperties()
|
||||
.maxEnrollmentsPerUser;
|
||||
final FingerprintEnrollClient client = new FingerprintEnrollClient(mContext,
|
||||
mSensors.get(sensorId).getLazySession(), token,
|
||||
new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
|
||||
opPackageName, FingerprintUtils.getInstance(sensorId), sensorId,
|
||||
mUdfpsOverlayController, maxTemplatesPerUser, enrollReason);
|
||||
scheduleForSensor(sensorId, client, new BaseClientMonitor.Callback() {
|
||||
@Override
|
||||
public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
|
||||
boolean success) {
|
||||
if (success) {
|
||||
scheduleLoadAuthenticatorIdsForUser(sensorId, userId);
|
||||
scheduleInvalidationRequest(sensorId, userId);
|
||||
}
|
||||
final int maxTemplatesPerUser = mSensors.get(sensorId).getSensorProperties()
|
||||
.maxEnrollmentsPerUser;
|
||||
final FingerprintEnrollClient client = new FingerprintEnrollClient(mContext,
|
||||
mSensors.get(sensorId).getLazySession(), token,
|
||||
new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
|
||||
opPackageName, FingerprintUtils.getInstance(sensorId), sensorId,
|
||||
mUdfpsOverlayController, maxTemplatesPerUser, enrollReason);
|
||||
scheduleForSensor(sensorId, client, new BaseClientMonitor.Callback() {
|
||||
@Override
|
||||
public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
|
||||
boolean success) {
|
||||
if (success) {
|
||||
scheduleLoadAuthenticatorIdsForUser(sensorId, userId);
|
||||
scheduleInvalidationRequest(sensorId, userId);
|
||||
}
|
||||
});
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(getTag(), "Remote exception when scheduling enroll", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -439,29 +348,12 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
@NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName,
|
||||
int statsClient) {
|
||||
mHandler.post(() -> {
|
||||
final IFingerprint daemon = getHalInstance();
|
||||
if (daemon == null) {
|
||||
Slog.e(getTag(), "Null daemon during finger detect, sensorId: " + sensorId);
|
||||
// If this happens, we need to send HW_UNAVAILABLE after the scheduler gets to
|
||||
// this operation. We should not send the callback yet, since the scheduler may
|
||||
// be processing something else.
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!mSensors.get(sensorId).hasSessionForUser(userId)) {
|
||||
createNewSessionWithoutHandler(daemon, sensorId, userId);
|
||||
}
|
||||
|
||||
final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
|
||||
final FingerprintDetectClient client = new FingerprintDetectClient(mContext,
|
||||
mSensors.get(sensorId).getLazySession(), token, callback, userId,
|
||||
opPackageName, sensorId, mUdfpsOverlayController, isStrongBiometric,
|
||||
statsClient);
|
||||
scheduleForSensor(sensorId, client);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(getTag(), "Remote exception when scheduling finger detect", e);
|
||||
}
|
||||
final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
|
||||
final FingerprintDetectClient client = new FingerprintDetectClient(mContext,
|
||||
mSensors.get(sensorId).getLazySession(), token, callback, userId,
|
||||
opPackageName, sensorId, mUdfpsOverlayController, isStrongBiometric,
|
||||
statsClient);
|
||||
scheduleForSensor(sensorId, client);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -471,31 +363,14 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
@NonNull String opPackageName, boolean restricted, int statsClient,
|
||||
boolean allowBackgroundAuthentication) {
|
||||
mHandler.post(() -> {
|
||||
final IFingerprint daemon = getHalInstance();
|
||||
if (daemon == null) {
|
||||
Slog.e(getTag(), "Null daemon during authenticate, sensorId: " + sensorId);
|
||||
// If this happens, we need to send HW_UNAVAILABLE after the scheduler gets to
|
||||
// this operation. We should not send the callback yet, since the scheduler may
|
||||
// be processing something else.
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!mSensors.get(sensorId).hasSessionForUser(userId)) {
|
||||
createNewSessionWithoutHandler(daemon, sensorId, userId);
|
||||
}
|
||||
|
||||
final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
|
||||
final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient(
|
||||
mContext, mSensors.get(sensorId).getLazySession(), token, callback, userId,
|
||||
operationId, restricted, opPackageName, cookie,
|
||||
false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient,
|
||||
mTaskStackListener, mSensors.get(sensorId).getLockoutCache(),
|
||||
mUdfpsOverlayController, allowBackgroundAuthentication);
|
||||
scheduleForSensor(sensorId, client);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(getTag(), "Remote exception when scheduling authenticate", e);
|
||||
}
|
||||
final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
|
||||
final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient(
|
||||
mContext, mSensors.get(sensorId).getLazySession(), token, callback, userId,
|
||||
operationId, restricted, opPackageName, cookie,
|
||||
false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient,
|
||||
mTaskStackListener, mSensors.get(sensorId).getLockoutCache(),
|
||||
mUdfpsOverlayController, allowBackgroundAuthentication);
|
||||
scheduleForSensor(sensorId, client);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -535,29 +410,12 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
int[] fingerprintIds, int userId, @NonNull IFingerprintServiceReceiver receiver,
|
||||
@NonNull String opPackageName) {
|
||||
mHandler.post(() -> {
|
||||
final IFingerprint daemon = getHalInstance();
|
||||
if (daemon == null) {
|
||||
Slog.e(getTag(), "Null daemon during remove, sensorId: " + sensorId);
|
||||
// If this happens, we need to send HW_UNAVAILABLE after the scheduler gets to
|
||||
// this operation. We should not send the callback yet, since the scheduler may
|
||||
// be processing something else.
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!mSensors.get(sensorId).hasSessionForUser(userId)) {
|
||||
createNewSessionWithoutHandler(daemon, sensorId, userId);
|
||||
}
|
||||
|
||||
final FingerprintRemovalClient client = new FingerprintRemovalClient(mContext,
|
||||
mSensors.get(sensorId).getLazySession(), token,
|
||||
new ClientMonitorCallbackConverter(receiver), fingerprintIds, userId,
|
||||
opPackageName, FingerprintUtils.getInstance(sensorId), sensorId,
|
||||
mSensors.get(sensorId).getAuthenticatorIds());
|
||||
scheduleForSensor(sensorId, client);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(getTag(), "Remote exception when scheduling remove", e);
|
||||
}
|
||||
final FingerprintRemovalClient client = new FingerprintRemovalClient(mContext,
|
||||
mSensors.get(sensorId).getLazySession(), token,
|
||||
new ClientMonitorCallbackConverter(receiver), fingerprintIds, userId,
|
||||
opPackageName, FingerprintUtils.getInstance(sensorId), sensorId,
|
||||
mSensors.get(sensorId).getAuthenticatorIds());
|
||||
scheduleForSensor(sensorId, client);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -565,28 +423,14 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
public void scheduleInternalCleanup(int sensorId, int userId,
|
||||
@Nullable BaseClientMonitor.Callback callback) {
|
||||
mHandler.post(() -> {
|
||||
final IFingerprint daemon = getHalInstance();
|
||||
if (daemon == null) {
|
||||
Slog.e(getTag(), "Null daemon during internal cleanup, sensorId: " + sensorId);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!mSensors.get(sensorId).hasSessionForUser(userId)) {
|
||||
createNewSessionWithoutHandler(daemon, sensorId, userId);
|
||||
}
|
||||
|
||||
final List<Fingerprint> enrolledList = getEnrolledFingerprints(sensorId, userId);
|
||||
final FingerprintInternalCleanupClient client =
|
||||
new FingerprintInternalCleanupClient(mContext,
|
||||
mSensors.get(sensorId).getLazySession(), userId,
|
||||
mContext.getOpPackageName(), sensorId, enrolledList,
|
||||
FingerprintUtils.getInstance(sensorId),
|
||||
mSensors.get(sensorId).getAuthenticatorIds());
|
||||
scheduleForSensor(sensorId, client);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(getTag(), "Remote exception when scheduling internal cleanup", e);
|
||||
}
|
||||
final List<Fingerprint> enrolledList = getEnrolledFingerprints(sensorId, userId);
|
||||
final FingerprintInternalCleanupClient client =
|
||||
new FingerprintInternalCleanupClient(mContext,
|
||||
mSensors.get(sensorId).getLazySession(), userId,
|
||||
mContext.getOpPackageName(), sensorId, enrolledList,
|
||||
FingerprintUtils.getInstance(sensorId),
|
||||
mSensors.get(sensorId).getAuthenticatorIds());
|
||||
scheduleForSensor(sensorId, client);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -611,26 +455,11 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
public void scheduleInvalidateAuthenticatorId(int sensorId, int userId,
|
||||
@NonNull IInvalidationCallback callback) {
|
||||
mHandler.post(() -> {
|
||||
final IFingerprint daemon = getHalInstance();
|
||||
if (daemon == null) {
|
||||
Slog.e(getTag(), "Null daemon during scheduleInvalidateAuthenticatorId: "
|
||||
+ sensorId);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!mSensors.get(sensorId).hasSessionForUser(userId)) {
|
||||
createNewSessionWithoutHandler(daemon, sensorId, userId);
|
||||
}
|
||||
|
||||
final FingerprintInvalidationClient client =
|
||||
new FingerprintInvalidationClient(mContext,
|
||||
mSensors.get(sensorId).getLazySession(), userId, sensorId,
|
||||
mSensors.get(sensorId).getAuthenticatorIds(), callback);
|
||||
scheduleForSensor(sensorId, client);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(getTag(), "Remote exception", e);
|
||||
}
|
||||
final FingerprintInvalidationClient client =
|
||||
new FingerprintInvalidationClient(mContext,
|
||||
mSensors.get(sensorId).getLazySession(), userId, sensorId,
|
||||
mSensors.get(sensorId).getAuthenticatorIds(), callback);
|
||||
scheduleForSensor(sensorId, client);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.aidl;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.hardware.biometrics.fingerprint.IFingerprint;
|
||||
import android.hardware.biometrics.fingerprint.ISession;
|
||||
import android.hardware.biometrics.fingerprint.ISessionCallback;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.biometrics.sensors.StartUserClient;
|
||||
|
||||
public class FingerprintStartUserClient extends StartUserClient<IFingerprint, ISession> {
|
||||
private static final String TAG = "FingerprintStartUserClient";
|
||||
|
||||
@NonNull private final ISessionCallback mSessionCallback;
|
||||
|
||||
public FingerprintStartUserClient(@NonNull Context context,
|
||||
@NonNull LazyDaemon<IFingerprint> lazyDaemon,
|
||||
@Nullable IBinder token, int userId, int sensorId,
|
||||
@NonNull ISessionCallback sessionCallback,
|
||||
@NonNull UserStartedCallback<ISession> callback) {
|
||||
super(context, lazyDaemon, token, userId, sensorId, callback);
|
||||
mSessionCallback = sessionCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(@NonNull Callback callback) {
|
||||
super.start(callback);
|
||||
startHalOperation();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startHalOperation() {
|
||||
try {
|
||||
final ISession newSession = getFreshDaemon().createSession(getSensorId(),
|
||||
getTargetUserId(), mSessionCallback);
|
||||
mUserStartedCallback.onUserStarted(getTargetUserId(), newSession);
|
||||
getCallback().onClientFinished(this, true /* success */);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception", e);
|
||||
getCallback().onClientFinished(this, false /* success */);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unableToStart() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.aidl;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.hardware.biometrics.fingerprint.ISession;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.biometrics.sensors.StopUserClient;
|
||||
|
||||
public class FingerprintStopUserClient extends StopUserClient<ISession> {
|
||||
private static final String TAG = "FingerprintStopUserClient";
|
||||
|
||||
public FingerprintStopUserClient(@NonNull Context context,
|
||||
@NonNull LazyDaemon<ISession> lazyDaemon, @Nullable IBinder token, int userId,
|
||||
int sensorId, @NonNull UserStoppedCallback callback) {
|
||||
super(context, lazyDaemon, token, userId, sensorId, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(@NonNull Callback callback) {
|
||||
super.start(callback);
|
||||
startHalOperation();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startHalOperation() {
|
||||
try {
|
||||
getFreshDaemon().close(mSequentialId);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception", e);
|
||||
getCallback().onClientFinished(this, false /* success */);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unableToStart() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -24,15 +24,17 @@ import android.hardware.biometrics.BiometricsProtoEnums;
|
||||
import android.hardware.biometrics.ITestSession;
|
||||
import android.hardware.biometrics.ITestSessionCallback;
|
||||
import android.hardware.biometrics.fingerprint.Error;
|
||||
import android.hardware.biometrics.fingerprint.IFingerprint;
|
||||
import android.hardware.biometrics.fingerprint.ISession;
|
||||
import android.hardware.biometrics.fingerprint.ISessionCallback;
|
||||
import android.hardware.fingerprint.Fingerprint;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.hardware.keymaster.HardwareAuthToken;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.util.Slog;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
@@ -53,6 +55,9 @@ import com.android.server.biometrics.sensors.Interruptable;
|
||||
import com.android.server.biometrics.sensors.LockoutCache;
|
||||
import com.android.server.biometrics.sensors.LockoutConsumer;
|
||||
import com.android.server.biometrics.sensors.RemovalConsumer;
|
||||
import com.android.server.biometrics.sensors.StartUserClient;
|
||||
import com.android.server.biometrics.sensors.StopUserClient;
|
||||
import com.android.server.biometrics.sensors.UserAwareBiometricScheduler;
|
||||
import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
|
||||
import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
|
||||
|
||||
@@ -72,9 +77,10 @@ class Sensor {
|
||||
@NonNull private final String mTag;
|
||||
@NonNull private final FingerprintProvider mProvider;
|
||||
@NonNull private final Context mContext;
|
||||
@NonNull private final IBinder mToken;
|
||||
@NonNull private final Handler mHandler;
|
||||
@NonNull private final FingerprintSensorPropertiesInternal mSensorProperties;
|
||||
@NonNull private final BiometricScheduler mScheduler;
|
||||
@NonNull private final UserAwareBiometricScheduler mScheduler;
|
||||
@NonNull private final LockoutCache mLockoutCache;
|
||||
@NonNull private final Map<Integer, Long> mAuthenticatorIds;
|
||||
|
||||
@@ -407,7 +413,15 @@ class Sensor {
|
||||
@Override
|
||||
public void onSessionClosed() {
|
||||
mHandler.post(() -> {
|
||||
// TODO: implement this.
|
||||
final BaseClientMonitor client = mScheduler.getCurrentClient();
|
||||
if (!(client instanceof FingerprintStopUserClient)) {
|
||||
Slog.e(mTag, "onSessionClosed for wrong consumer: "
|
||||
+ Utils.getClientName(client));
|
||||
return;
|
||||
}
|
||||
|
||||
final FingerprintStopUserClient stopUserClient = (FingerprintStopUserClient) client;
|
||||
stopUserClient.onUserStopped();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -418,9 +432,53 @@ class Sensor {
|
||||
mTag = tag;
|
||||
mProvider = provider;
|
||||
mContext = context;
|
||||
mToken = new Binder();
|
||||
mHandler = handler;
|
||||
mSensorProperties = sensorProperties;
|
||||
mScheduler = new BiometricScheduler(tag, gestureAvailabilityDispatcher);
|
||||
mScheduler = new UserAwareBiometricScheduler(tag, gestureAvailabilityDispatcher,
|
||||
() -> mCurrentSession != null ? mCurrentSession.mUserId : UserHandle.USER_NULL,
|
||||
new UserAwareBiometricScheduler.UserSwitchCallback() {
|
||||
@NonNull
|
||||
@Override
|
||||
public StopUserClient<?> getStopUserClient(int userId) {
|
||||
return new FingerprintStopUserClient(mContext, mLazySession, mToken,
|
||||
userId, mSensorProperties.sensorId, () -> mCurrentSession = null);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public StartUserClient<?, ?> getStartUserClient(int newUserId) {
|
||||
final HalSessionCallback.Callback callback = () -> {
|
||||
Slog.e(mTag, "Got ERROR_HW_UNAVAILABLE");
|
||||
mCurrentSession = null;
|
||||
};
|
||||
|
||||
final int sensorId = mSensorProperties.sensorId;
|
||||
|
||||
final HalSessionCallback resultController = new HalSessionCallback(mContext,
|
||||
mHandler, mTag, mScheduler, sensorId, newUserId, callback);
|
||||
|
||||
final StartUserClient.UserStartedCallback<ISession> userStartedCallback =
|
||||
(userIdStarted, newSession) -> {
|
||||
mCurrentSession = new Session(mTag,
|
||||
newSession, userIdStarted, resultController);
|
||||
if (FingerprintUtils.getInstance(sensorId)
|
||||
.isInvalidationInProgress(mContext, userIdStarted)) {
|
||||
Slog.w(mTag,
|
||||
"Scheduling unfinished invalidation request for "
|
||||
+ "sensor: "
|
||||
+ sensorId
|
||||
+ ", user: " + userIdStarted);
|
||||
provider.scheduleInvalidationRequest(sensorId,
|
||||
userIdStarted);
|
||||
}
|
||||
};
|
||||
|
||||
return new FingerprintStartUserClient(mContext, provider::getHalInstance,
|
||||
mToken, newUserId, mSensorProperties.sensorId,
|
||||
resultController, userStartedCallback);
|
||||
}
|
||||
});
|
||||
mLockoutCache = new LockoutCache();
|
||||
mAuthenticatorIds = new HashMap<>();
|
||||
mLazySession = () -> mCurrentSession != null ? mCurrentSession.mSession : null;
|
||||
@@ -434,11 +492,6 @@ class Sensor {
|
||||
return mSensorProperties;
|
||||
}
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
boolean hasSessionForUser(int userId) {
|
||||
return mCurrentSession != null && mCurrentSession.mUserId == userId;
|
||||
}
|
||||
|
||||
@Nullable Session getSessionForUser(int userId) {
|
||||
if (mCurrentSession != null && mCurrentSession.mUserId == userId) {
|
||||
return mCurrentSession;
|
||||
@@ -452,20 +505,6 @@ class Sensor {
|
||||
mProvider, this);
|
||||
}
|
||||
|
||||
void createNewSession(@NonNull IFingerprint daemon, int sensorId, int userId)
|
||||
throws RemoteException {
|
||||
|
||||
final HalSessionCallback.Callback callback = () -> {
|
||||
Slog.e(mTag, "Got ERROR_HW_UNAVAILABLE");
|
||||
mCurrentSession = null;
|
||||
};
|
||||
final HalSessionCallback resultController = new HalSessionCallback(mContext, mHandler,
|
||||
mTag, mScheduler, sensorId, userId, callback);
|
||||
|
||||
final ISession newSession = daemon.createSession(sensorId, userId, resultController);
|
||||
mCurrentSession = new Session(mTag, newSession, userId, resultController);
|
||||
}
|
||||
|
||||
@NonNull BiometricScheduler getScheduler() {
|
||||
return mScheduler;
|
||||
}
|
||||
|
||||
@@ -121,7 +121,8 @@ public class TestHal extends IFingerprint.Stub {
|
||||
|
||||
@Override
|
||||
public void close(int cookie) throws RemoteException {
|
||||
cb.onStateChanged(cookie, SessionState.CLOSED);
|
||||
Slog.w(TAG, "close, cookie: " + cookie);
|
||||
cb.onSessionClosed();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -81,7 +81,7 @@ public class UserAwareBiometricSchedulerTest {
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public StartUserClient<?> getStartUserClient(int newUserId) {
|
||||
public StartUserClient<?, ?> getStartUserClient(int newUserId) {
|
||||
return new TestStartUserClient(mContext, Object::new, mToken, newUserId,
|
||||
TEST_SENSOR_ID, mUserStartedCallback);
|
||||
}
|
||||
@@ -157,12 +157,12 @@ public class UserAwareBiometricSchedulerTest {
|
||||
}
|
||||
}
|
||||
|
||||
private class TestUserStartedCallback implements StartUserClient.UserStartedCallback {
|
||||
private class TestUserStartedCallback implements StartUserClient.UserStartedCallback<Object> {
|
||||
|
||||
int numInvocations;
|
||||
|
||||
@Override
|
||||
public void onUserStarted(int newUserId) {
|
||||
public void onUserStarted(int newUserId, Object newObject) {
|
||||
numInvocations++;
|
||||
mCurrentUserId = newUserId;
|
||||
}
|
||||
@@ -183,8 +183,7 @@ public class UserAwareBiometricSchedulerTest {
|
||||
@Override
|
||||
public void start(@NonNull Callback callback) {
|
||||
super.start(callback);
|
||||
mUserStoppedCallback.onUserStopped();
|
||||
callback.onClientFinished(this, true /* success */);
|
||||
onUserStopped();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -193,10 +192,10 @@ public class UserAwareBiometricSchedulerTest {
|
||||
}
|
||||
}
|
||||
|
||||
private static class TestStartUserClient extends StartUserClient<Object> {
|
||||
private static class TestStartUserClient extends StartUserClient<Object, Object> {
|
||||
public TestStartUserClient(@NonNull Context context,
|
||||
@NonNull LazyDaemon<Object> lazyDaemon, @Nullable IBinder token, int userId,
|
||||
int sensorId, @NonNull UserStartedCallback callback) {
|
||||
int sensorId, @NonNull UserStartedCallback<Object> callback) {
|
||||
super(context, lazyDaemon, token, userId, sensorId, callback);
|
||||
}
|
||||
|
||||
@@ -208,7 +207,7 @@ public class UserAwareBiometricSchedulerTest {
|
||||
@Override
|
||||
public void start(@NonNull Callback callback) {
|
||||
super.start(callback);
|
||||
mUserStartedCallback.onUserStarted(getTargetUserId());
|
||||
mUserStartedCallback.onUserStarted(getTargetUserId(), new Object());
|
||||
callback.onClientFinished(this, true /* success */);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,10 +24,12 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.biometrics.common.CommonProps;
|
||||
import android.hardware.biometrics.fingerprint.IFingerprint;
|
||||
import android.hardware.biometrics.fingerprint.SensorProps;
|
||||
import android.os.UserManager;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
@@ -59,7 +61,7 @@ public class FingerprintProviderTest {
|
||||
|
||||
private SensorProps[] mSensorProps;
|
||||
private LockoutResetDispatcher mLockoutResetDispatcher;
|
||||
private FingerprintProvider mFingerprintProvider;
|
||||
private TestableFingerprintProvider mFingerprintProvider;
|
||||
|
||||
private static void waitForIdle() {
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
@@ -83,7 +85,7 @@ public class FingerprintProviderTest {
|
||||
|
||||
mLockoutResetDispatcher = new LockoutResetDispatcher(mContext);
|
||||
|
||||
mFingerprintProvider = new FingerprintProvider(mContext, mSensorProps, TAG,
|
||||
mFingerprintProvider = new TestableFingerprintProvider(mContext, mSensorProps, TAG,
|
||||
mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
|
||||
}
|
||||
|
||||
@@ -126,4 +128,20 @@ public class FingerprintProviderTest {
|
||||
assertEquals(0, scheduler.getCurrentPendingCount());
|
||||
}
|
||||
}
|
||||
|
||||
private static class TestableFingerprintProvider extends FingerprintProvider {
|
||||
public TestableFingerprintProvider(@NonNull Context context,
|
||||
@NonNull SensorProps[] props,
|
||||
@NonNull String halInstanceName,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
@NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
|
||||
super(context, props, halInstanceName, lockoutResetDispatcher,
|
||||
gestureAvailabilityDispatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized IFingerprint getHalInstance() {
|
||||
return mock(IFingerprint.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user