From 258534b4b59cfe0ce0a27fa195b0e5f87a1aa3a7 Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Thu, 15 Oct 2020 13:04:04 -0700 Subject: [PATCH] 11/n: Finish remainder of IFingerprint implementation With the exception of invalidateAuthenticatorId, all IFingerprint plumbing should be ready for testing. Updates RemovalConsumer#onRemoved to allow nullable identifiers, since enrollmentId=0 is now valid from the HAL. Fixes: 170497736 Test: Enroll, auth, remove on existing devices Change-Id: I070a5416a33e6aa926823a9babd3ae81238a3c08 --- .../biometrics/sensors/RemovalClient.java | 5 +- .../biometrics/sensors/RemovalConsumer.java | 3 +- .../biometrics/sensors/face/Face10.java | 3 +- .../aidl/FingerprintDetectClient.java | 12 +++ .../FingerprintGetAuthenticatorIdClient.java | 12 ++- .../fingerprint/aidl/FingerprintProvider.java | 3 +- .../sensors/fingerprint/aidl/Sensor.java | 94 ++++++++++++++++++- 7 files changed, 121 insertions(+), 11 deletions(-) diff --git a/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java b/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java index ce898fa3b2bfd..f79abd59dbb40 100644 --- a/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java @@ -17,6 +17,7 @@ package com.android.server.biometrics.sensors; import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.Context; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricsProtoEnums; @@ -64,8 +65,8 @@ public abstract class RemovalClient { mCallback.onClientFinished(this, false /* success */); } } + + void onInteractionDetected() { + vibrateSuccess(); + + try { + getListener().onDetected(getSensorId(), getTargetUserId(), mIsStrongBiometric); + mCallback.onClientFinished(this, true /* success */); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception when sending onDetected", e); + mCallback.onClientFinished(this, false /* success */); + } + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGetAuthenticatorIdClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGetAuthenticatorIdClient.java index bc89d5f6a96d0..fec3cff6d52f9 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGetAuthenticatorIdClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGetAuthenticatorIdClient.java @@ -25,16 +25,21 @@ import android.util.Slog; import com.android.server.biometrics.sensors.ClientMonitor; +import java.util.Map; + class FingerprintGetAuthenticatorIdClient extends ClientMonitor { private static final String TAG = "FingerprintGetAuthenticatorIdClient"; + private final Map mAuthenticatorIds; + FingerprintGetAuthenticatorIdClient(@NonNull Context context, @NonNull LazyDaemon lazyDaemon, int userId, @NonNull String owner, - int sensorId) { + int sensorId, Map authenticatorIds) { super(context, lazyDaemon, null /* token */, null /* listener */, userId, owner, 0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_FINGERPRINT, BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN); + mAuthenticatorIds = authenticatorIds; } @Override @@ -50,4 +55,9 @@ class FingerprintGetAuthenticatorIdClient extends ClientMonitor { Slog.e(TAG, "Remote exception", e); } } + + void onAuthenticatorIdRetrieved(long authenticatorId) { + mAuthenticatorIds.put(getTargetUserId(), authenticatorId); + mCallback.onClientFinished(this, true /* success */); + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java index 528fbb63bfcae..de3174ac3cee8 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java @@ -237,7 +237,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi final FingerprintGetAuthenticatorIdClient client = new FingerprintGetAuthenticatorIdClient(mContext, mSensors.get(sensorId).getLazySession(), userId, - mContext.getOpPackageName(), sensorId); + mContext.getOpPackageName(), sensorId, + mSensors.get(sensorId).getAuthenticatorIds()); mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client); } catch (RemoteException e) { Slog.e(getTag(), "Remote exception when scheduling loadAuthenticatorId" diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java index dacb441b881d1..0cc9fe7bb7868 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java @@ -19,25 +19,31 @@ package com.android.server.biometrics.sensors.fingerprint.aidl; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; +import android.hardware.biometrics.BiometricsProtoEnums; 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.Handler; +import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; +import com.android.internal.util.FrameworkStatsLog; import com.android.server.biometrics.HardwareAuthTokenUtils; import com.android.server.biometrics.Utils; import com.android.server.biometrics.sensors.AcquisitionClient; import com.android.server.biometrics.sensors.AuthenticationConsumer; import com.android.server.biometrics.sensors.BiometricScheduler; import com.android.server.biometrics.sensors.ClientMonitor; +import com.android.server.biometrics.sensors.EnumerateConsumer; import com.android.server.biometrics.sensors.Interruptable; import com.android.server.biometrics.sensors.LockoutConsumer; +import com.android.server.biometrics.sensors.RemovalConsumer; import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils; import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher; @@ -51,7 +57,8 @@ import java.util.Map; * Maintains the state of a single sensor within an instance of the * {@link android.hardware.biometrics.fingerprint.IFingerprint} HAL. */ -class Sensor { +@SuppressWarnings("deprecation") +class Sensor implements IBinder.DeathRecipient { @NonNull private final String mTag; @NonNull private final Context mContext; @NonNull private final Handler mHandler; @@ -60,9 +67,30 @@ class Sensor { @NonNull private final LockoutCache mLockoutCache; @NonNull private final Map mAuthenticatorIds; - @Nullable private Session mCurrentSession; // TODO: Death recipient + @Nullable private Session mCurrentSession; @NonNull private final ClientMonitor.LazyDaemon mLazySession; + @Override + public void binderDied() { + Slog.e(mTag, "Binder died"); + mHandler.post(() -> { + final ClientMonitor client = mScheduler.getCurrentClient(); + if (client instanceof Interruptable) { + Slog.e(mTag, "Sending ERROR_HW_UNAVAILABLE for client: " + client); + final Interruptable interruptable = (Interruptable) client; + interruptable.onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE, + 0 /* vendorCode */); + + mScheduler.recordCrashState(); + + FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, + BiometricsProtoEnums.MODALITY_FINGERPRINT, + BiometricsProtoEnums.ISSUE_HAL_DEATH); + mCurrentSession = null; + } + }); + } + private static class Session { @NonNull private final String mTag; @NonNull private final ISession mSession; @@ -110,7 +138,7 @@ class Sensor { final ISessionCallback callback = new ISessionCallback.Stub() { @Override public void onStateChanged(int cookie, byte state) { - + // TODO(b/162973174) } @Override @@ -261,31 +289,89 @@ class Sensor { @Override public void onInteractionDetected() { + mHandler.post(() -> { + final ClientMonitor client = mScheduler.getCurrentClient(); + if (!(client instanceof FingerprintDetectClient)) { + Slog.e(mTag, "onInteractionDetected for non-detect client: " + + Utils.getClientName(client)); + return; + } + final FingerprintDetectClient fingerprintDetectClient = + (FingerprintDetectClient) client; + fingerprintDetectClient.onInteractionDetected(); + }); } @Override public void onEnrollmentsEnumerated(int[] enrollmentIds) { + mHandler.post(() -> { + final ClientMonitor client = mScheduler.getCurrentClient(); + if (!(client instanceof EnumerateConsumer)) { + Slog.e(mTag, "onEnrollmentsEnumerated for non-enumerate consumer: " + + Utils.getClientName(client)); + return; + } + final EnumerateConsumer enumerateConsumer = + (EnumerateConsumer) client; + if (enrollmentIds.length > 0) { + for (int i = 0; i < enrollmentIds.length; i++) { + final Fingerprint fp = new Fingerprint("", enrollmentIds[i], sensorId); + enumerateConsumer.onEnumerationResult(fp, enrollmentIds.length - i - 1); + } + } else { + enumerateConsumer.onEnumerationResult(null /* identifier */, 0); + } + }); } @Override public void onEnrollmentsRemoved(int[] enrollmentIds) { + mHandler.post(() -> { + final ClientMonitor client = mScheduler.getCurrentClient(); + if (!(client instanceof RemovalConsumer)) { + Slog.e(mTag, "onRemoved for non-removal consumer: " + + Utils.getClientName(client)); + return; + } + final RemovalConsumer removalConsumer = (RemovalConsumer) client; + if (enrollmentIds.length > 0) { + for (int i = 0; i < enrollmentIds.length; i++) { + final Fingerprint fp = new Fingerprint("", enrollmentIds[i], sensorId); + removalConsumer.onRemoved(fp, enrollmentIds.length - i - 1); + } + } else { + removalConsumer.onRemoved(null, 0); + } + }); } @Override public void onAuthenticatorIdRetrieved(long authenticatorId) { + mHandler.post(() -> { + final ClientMonitor client = mScheduler.getCurrentClient(); + if (!(client instanceof FingerprintGetAuthenticatorIdClient)) { + Slog.e(mTag, "onAuthenticatorIdRetrieved for wrong consumer: " + + Utils.getClientName(client)); + return; + } + final FingerprintGetAuthenticatorIdClient getAuthenticatorIdClient = + (FingerprintGetAuthenticatorIdClient) client; + getAuthenticatorIdClient.onAuthenticatorIdRetrieved(authenticatorId); + }); } @Override public void onAuthenticatorIdInvalidated() { - + // TODO(159667191) } }; final ISession newSession = daemon.createSession(sensorId, userId, callback); + newSession.asBinder().linkToDeath(this, 0 /* flags */); mCurrentSession = new Session(mTag, newSession, userId, callback); }