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:
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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 */);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 */);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user