summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Kevin Chyn <kchyn@google.com> 2021-03-18 03:24:08 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2021-03-18 03:24:08 +0000
commit741663a30dc7b4a2fab9936b5b07c8c046672f06 (patch)
tree93d860ec9be1f5e6400734bbc89e68494cba64a7
parent4e94266881e8d76b4e109c6fb40162f5fac9d717 (diff)
parent7f59ef96d12de1ae36784a5e91702c0048c0a4d0 (diff)
Merge "Add challenge-less resetLockout for new AIDL interfaces" into sc-dev
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceService.java13
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/TestHal.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java12
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java4
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintResetLockoutClient.java54
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/TestHal.java5
-rw-r--r--services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java101
7 files changed, 148 insertions, 49 deletions
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
index 6dbd590df851..a74e2da30077 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
@@ -393,14 +393,13 @@ public class FaceService extends SystemService implements BiometricServiceCallba
final IFaceServiceReceiver receiver, final String opPackageName) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
- final Pair<Integer, ServiceProvider> provider = getSingleProvider();
- if (provider == null) {
- Slog.w(TAG, "Null provider for removeAll");
- return;
+ for (ServiceProvider provider : mServiceProviders) {
+ List<FaceSensorPropertiesInternal> props = provider.getSensorProperties();
+ for (FaceSensorPropertiesInternal prop : props) {
+ provider.scheduleRemoveAll(prop.sensorId, token, userId, receiver,
+ opPackageName);
+ }
}
-
- provider.second.scheduleRemoveAll(provider.first, token, userId, receiver,
- opPackageName);
}
@Override // Binder call
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/TestHal.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/TestHal.java
index 4cdb68df70af..84aa6d9ad1f8 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/TestHal.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/TestHal.java
@@ -23,11 +23,11 @@ import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback;
import android.hardware.biometrics.face.V1_0.OptionalBool;
import android.hardware.biometrics.face.V1_0.OptionalUint64;
import android.hardware.biometrics.face.V1_0.Status;
-import android.os.NativeHandle;
import android.os.RemoteException;
import android.util.Slog;
import java.util.ArrayList;
+import java.util.Arrays;
public class TestHal extends IBiometricsFace.Stub {
private static final String TAG = "face.hidl.TestHal";
@@ -107,8 +107,12 @@ public class TestHal extends IBiometricsFace.Stub {
}
@Override
- public int remove(int faceId) {
+ public int remove(int faceId) throws RemoteException {
Slog.w(TAG, "remove");
+ if (mCallback != null) {
+ mCallback.onRemoved(0 /* deviceId */, new ArrayList<Integer>(Arrays.asList(faceId)),
+ 0 /* userId */);
+ }
return 0;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index 396dd5f42d4d..3f489e98d5f1 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -506,13 +506,13 @@ public class FingerprintService extends SystemService implements BiometricServic
final IFingerprintServiceReceiver receiver, final String opPackageName) {
Utils.checkPermission(getContext(), MANAGE_FINGERPRINT);
- final Pair<Integer, ServiceProvider> provider = getSingleProvider();
- if (provider == null) {
- Slog.w(TAG, "Null provider for removeAll");
- return;
+ for (ServiceProvider provider : mServiceProviders) {
+ List<FingerprintSensorPropertiesInternal> props = provider.getSensorProperties();
+ for (FingerprintSensorPropertiesInternal prop : props) {
+ provider.scheduleRemoveAll(prop.sensorId, token, receiver, userId,
+ opPackageName);
+ }
}
- provider.second.scheduleRemoveAll(provider.first, token, receiver, userId,
- opPackageName);
}
@Override // Binder call
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
index 50fdc2e8a856..7ff5ec305b88 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
@@ -527,7 +527,9 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
// Fingerprint2.1 keeps track of lockout in the framework. Let's just do it on the handler
// thread.
mHandler.post(() -> {
- mLockoutTracker.resetFailedAttemptsForUser(true /* clearAttemptCounter */, userId);
+ final FingerprintResetLockoutClient client = new FingerprintResetLockoutClient(mContext,
+ userId, mContext.getOpPackageName(), sensorId, mLockoutTracker);
+ mScheduler.scheduleClientMonitor(client);
});
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintResetLockoutClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintResetLockoutClient.java
new file mode 100644
index 000000000000..a39f4f8c4d7e
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintResetLockoutClient.java
@@ -0,0 +1,54 @@
+/*
+ * 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.hidl;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.hardware.biometrics.BiometricsProtoEnums;
+
+import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.sensors.BaseClientMonitor;
+
+/**
+ * Clears lockout, which is handled in the framework (and not the HAL) for the
+ * IBiometricsFingerprint@2.1 interface.
+ */
+public class FingerprintResetLockoutClient extends BaseClientMonitor {
+
+ @NonNull final LockoutFrameworkImpl mLockoutTracker;
+
+ public FingerprintResetLockoutClient(@NonNull Context context, int userId,
+ @NonNull String owner, int sensorId, @NonNull LockoutFrameworkImpl lockoutTracker) {
+ super(context, null /* token */, null /* listener */, userId, owner, 0 /* cookie */,
+ sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN,
+ BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
+ mLockoutTracker = lockoutTracker;
+ }
+
+ @Override
+ public void start(@NonNull Callback callback) {
+ super.start(callback);
+ mLockoutTracker.resetFailedAttemptsForUser(true /* clearAttemptCounter */,
+ getTargetUserId());
+ callback.onClientFinished(this, true /* success */);
+ }
+
+ @Override
+ public int getProtoEnum() {
+ return BiometricsProto.CM_RESET_LOCKOUT;
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/TestHal.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/TestHal.java
index 14fdb507b0b1..129f6a61df04 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/TestHal.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/TestHal.java
@@ -93,8 +93,11 @@ public class TestHal extends IBiometricsFingerprint.Stub {
}
@Override
- public int remove(int gid, int fid) {
+ public int remove(int gid, int fid) throws RemoteException {
Slog.w(TAG, "Remove");
+ if (mCallback != null) {
+ mCallback.onRemoved(0 /* deviceId */, fid, gid, 0 /* remaining */);
+ }
return 0;
}
diff --git a/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java b/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java
index 6d250ecb9fa4..6201b9414aaf 100644
--- a/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java
+++ b/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java
@@ -119,19 +119,11 @@ public class BiometricDeferredQueue {
for (UserAuthInfo userAuthInfo : pendingResetLockuts) {
Slog.d(TAG, "Resetting face lockout for sensor: " + sensorId
+ ", user: " + userAuthInfo.userId);
- final VerifyCredentialResponse response = spManager.verifyChallengeInternal(
- getGatekeeperService(), userAuthInfo.gatekeeperPassword, challenge,
- userAuthInfo.userId);
- if (response == null) {
- Slog.wtf(TAG, "VerifyChallenge failed, null response");
- continue;
+ final byte[] hat = requestHatFromGatekeeperPassword(spManager, userAuthInfo,
+ challenge);
+ if (hat != null) {
+ faceManager.resetLockout(sensorId, userAuthInfo.userId, hat);
}
- if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
- Slog.wtf(TAG, "VerifyChallenge failed, response: "
- + response.getResponseCode());
- }
- faceManager.resetLockout(sensorId, userAuthInfo.userId,
- response.getGatekeeperHAT());
}
sensorIds.remove(sensorId);
@@ -146,15 +138,6 @@ public class BiometricDeferredQueue {
finishCallback.onFinished();
}
}
-
- synchronized IGateKeeperService getGatekeeperService() {
- final IBinder service = ServiceManager.getService(Context.GATEKEEPER_SERVICE);
- if (service == null) {
- Slog.e(TAG, "Unable to acquire GateKeeperService");
- return null;
- }
- return IGateKeeperService.Stub.asInterface(service);
- }
}
@Nullable private FaceResetLockoutTask mFaceResetLockoutTask;
@@ -214,10 +197,19 @@ public class BiometricDeferredQueue {
mFingerprintManager.resetLockout(prop.sensorId, user.userId,
null /* hardwareAuthToken */);
}
+ } else if (!prop.resetLockoutRequiresChallenge) {
+ for (UserAuthInfo user : pendingResetLockouts) {
+ Slog.d(TAG, "Resetting fingerprint lockout for sensor: " + prop.sensorId
+ + ", user: " + user.userId);
+ final byte[] hat = requestHatFromGatekeeperPassword(mSpManager, user,
+ 0 /* challenge */);
+ if (hat != null) {
+ mFingerprintManager.resetLockout(prop.sensorId, user.userId, hat);
+ }
+ }
} else {
- Slog.e(TAG, "Fingerprint resetLockout with HAT not supported yet");
- // TODO(b/152414803): Implement this when resetLockout is implemented below
- // the framework.
+ Slog.w(TAG, "No fingerprint HAL interface requires HAT with challenge"
+ + ", sensorId: " + prop.sensorId);
}
}
}
@@ -228,11 +220,6 @@ public class BiometricDeferredQueue {
* in-flight challenge, we generate a single challenge to reset lockout for all profiles. This
* hopefully reduces/eliminates issues such as overwritten challenge, incorrectly revoked
* challenge, or other race conditions.
- *
- * TODO(b/162965646) This logic can be avoided if multiple in-flight challenges are supported.
- * Though it will need to continue to exist to support existing HIDLs, each profile that
- * requires resetLockout could have its own challenge, and the `mPendingResetLockouts` queue
- * can be avoided.
*/
private void processPendingLockoutsForFace(List<UserAuthInfo> pendingResetLockouts) {
if (mFaceManager != null) {
@@ -251,10 +238,60 @@ public class BiometricDeferredQueue {
mFaceResetLockoutTask = new FaceResetLockoutTask(mFaceFinishCallback, mFaceManager,
mSpManager, sensorIds, pendingResetLockouts);
for (final FaceSensorPropertiesInternal prop : faceSensorProperties) {
- // Generate a challenge for each sensor. The challenge does not need to be
- // per-user, since the HAT returned by gatekeeper contains userId.
- mFaceManager.generateChallenge(prop.sensorId, mFaceResetLockoutTask);
+ if (prop.resetLockoutRequiresHardwareAuthToken) {
+ if (prop.resetLockoutRequiresChallenge) {
+ // Generate a challenge for each sensor. The challenge does not need to be
+ // per-user, since the HAT returned by gatekeeper contains userId.
+ mFaceManager.generateChallenge(prop.sensorId, mFaceResetLockoutTask);
+ } else {
+ for (UserAuthInfo user : pendingResetLockouts) {
+ Slog.d(TAG, "Resetting face lockout for sensor: " + prop.sensorId
+ + ", user: " + user.userId);
+ final byte[] hat = requestHatFromGatekeeperPassword(mSpManager, user,
+ 0 /* challenge */);
+ if (hat != null) {
+ mFaceManager.resetLockout(prop.sensorId, user.userId, hat);
+ }
+ }
+ }
+ } else {
+ Slog.w(TAG, "Lockout is below the HAL for all face authentication interfaces"
+ + ", sensorId: " + prop.sensorId);
+ }
}
}
}
+
+ @Nullable
+ private static byte[] requestHatFromGatekeeperPassword(
+ @NonNull SyntheticPasswordManager spManager,
+ @NonNull UserAuthInfo userAuthInfo, long challenge) {
+ final VerifyCredentialResponse response = spManager.verifyChallengeInternal(
+ getGatekeeperService(), userAuthInfo.gatekeeperPassword, challenge,
+ userAuthInfo.userId);
+ if (response == null) {
+ Slog.wtf(TAG, "VerifyChallenge failed, null response");
+ return null;
+ }
+ if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
+ Slog.wtf(TAG, "VerifyChallenge failed, response: "
+ + response.getResponseCode());
+ return null;
+ }
+ if (response.getGatekeeperHAT() == null) {
+ Slog.e(TAG, "Null HAT received from spManager");
+ }
+
+ return response.getGatekeeperHAT();
+ }
+
+ @Nullable
+ private static synchronized IGateKeeperService getGatekeeperService() {
+ final IBinder service = ServiceManager.getService(Context.GATEKEEPER_SERVICE);
+ if (service == null) {
+ Slog.e(TAG, "Unable to acquire GateKeeperService");
+ return null;
+ }
+ return IGateKeeperService.Stub.asInterface(service);
+ }
}