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
This commit is contained in:
Kevin Chyn
2020-10-15 13:04:04 -07:00
parent a9d78c787e
commit 258534b4b5
7 changed files with 121 additions and 11 deletions

View File

@@ -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<S extends BiometricAuthenticator.Identifier,
}
@Override
public void onRemoved(BiometricAuthenticator.Identifier identifier, int remaining) {
if (identifier.getBiometricId() != 0) {
public void onRemoved(@Nullable BiometricAuthenticator.Identifier identifier, int remaining) {
if (identifier != null) {
mBiometricUtils.removeBiometricForUser(getContext(), getTargetUserId(),
identifier.getBiometricId());
}

View File

@@ -16,6 +16,7 @@
package com.android.server.biometrics.sensors;
import android.annotation.Nullable;
import android.hardware.biometrics.BiometricAuthenticator;
/**
@@ -28,5 +29,5 @@ public interface RemovalConsumer {
* @param remaining number of templates that still need to be removed before the operation in
* the HAL is complete (e.g. when removing all templates).
*/
void onRemoved(BiometricAuthenticator.Identifier identifier, int remaining);
void onRemoved(@Nullable BiometricAuthenticator.Identifier identifier, int remaining);
}

View File

@@ -219,8 +219,7 @@ class Face10 implements IHwBinder.DeathRecipient {
removalConsumer.onRemoved(face, remaining);
}
} else {
final Face face = new Face("", 0 /* identifier */, deviceId);
removalConsumer.onRemoved(face, 0 /* remaining */);
removalConsumer.onRemoved(null, 0 /* remaining */);
}
Settings.Secure.putIntForUser(mContext.getContentResolver(),

View File

@@ -78,4 +78,16 @@ class FingerprintDetectClient extends AcquisitionClient<ISession> {
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 */);
}
}
}

View File

@@ -25,16 +25,21 @@ import android.util.Slog;
import com.android.server.biometrics.sensors.ClientMonitor;
import java.util.Map;
class FingerprintGetAuthenticatorIdClient extends ClientMonitor<ISession> {
private static final String TAG = "FingerprintGetAuthenticatorIdClient";
private final Map<Integer, Long> mAuthenticatorIds;
FingerprintGetAuthenticatorIdClient(@NonNull Context context,
@NonNull LazyDaemon<ISession> lazyDaemon, int userId, @NonNull String owner,
int sensorId) {
int sensorId, Map<Integer, Long> 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<ISession> {
Slog.e(TAG, "Remote exception", e);
}
}
void onAuthenticatorIdRetrieved(long authenticatorId) {
mAuthenticatorIds.put(getTargetUserId(), authenticatorId);
mCallback.onClientFinished(this, true /* success */);
}
}

View File

@@ -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"

View File

@@ -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<Integer, Long> mAuthenticatorIds;
@Nullable private Session mCurrentSession; // TODO: Death recipient
@Nullable private Session mCurrentSession;
@NonNull private final ClientMonitor.LazyDaemon<ISession> 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);
}