Implement client monitors for face AIDL

This CL implements all of the monitors except for FaceGetFeatureClient
and FaceSetFeatureClient because the get/set feature methods aren't
currently supported in the AIDL interface.

Bug: 171335732
Test: build
Change-Id: Ib6eaff5d7a323b8e9333ca8408ec69f488108a31
This commit is contained in:
Ilya Matyukhin
2020-11-06 14:26:02 -08:00
parent 32f840b544
commit f54020f2b1
10 changed files with 786 additions and 0 deletions

View File

@@ -110,6 +110,7 @@ java_library_static {
"android.hardware.tv.cec-V1.0-java",
"android.hardware.weaver-V1.0-java",
"android.hardware.biometrics.face-V1.1-java",
"android.hardware.biometrics.face-java",
"android.hardware.biometrics.fingerprint-V2.3-java",
"android.hardware.biometrics.fingerprint-java",
"android.hardware.oemlock-V1.0-java",

View File

@@ -0,0 +1,221 @@
/*
* Copyright (C) 2020 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.face.aidl;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.NotificationManager;
import android.content.Context;
import android.content.res.Resources;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricFaceConstants;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.common.ICancellationSignal;
import android.hardware.biometrics.face.IFace;
import android.hardware.biometrics.face.ISession;
import android.hardware.face.FaceManager;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
import com.android.internal.R;
import com.android.server.biometrics.Utils;
import com.android.server.biometrics.sensors.AuthenticationClient;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.LockoutCache;
import com.android.server.biometrics.sensors.LockoutConsumer;
import com.android.server.biometrics.sensors.LockoutTracker;
import com.android.server.biometrics.sensors.face.UsageStats;
import java.util.ArrayList;
/**
* Face-specific authentication client for the {@link IFace} AIDL HAL interface.
*/
class FaceAuthenticationClient extends AuthenticationClient<ISession> implements LockoutConsumer {
private static final String TAG = "FaceAuthenticationClient";
@NonNull private final UsageStats mUsageStats;
@NonNull private final LockoutCache mLockoutCache;
@Nullable private final NotificationManager mNotificationManager;
@Nullable private ICancellationSignal mCancellationSignal;
private final int[] mBiometricPromptIgnoreList;
private final int[] mBiometricPromptIgnoreListVendor;
private final int[] mKeyguardIgnoreList;
private final int[] mKeyguardIgnoreListVendor;
private int mLastAcquire;
FaceAuthenticationClient(@NonNull Context context,
@NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token,
@NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
boolean restricted, String owner, int cookie, boolean requireConfirmation, int sensorId,
boolean isStrongBiometric, int statsClient, @NonNull UsageStats usageStats,
@NonNull LockoutCache lockoutCache) {
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */,
lockoutCache);
mUsageStats = usageStats;
mLockoutCache = lockoutCache;
mNotificationManager = context.getSystemService(NotificationManager.class);
final Resources resources = getContext().getResources();
mBiometricPromptIgnoreList = resources.getIntArray(
R.array.config_face_acquire_biometricprompt_ignorelist);
mBiometricPromptIgnoreListVendor = resources.getIntArray(
R.array.config_face_acquire_vendor_biometricprompt_ignorelist);
mKeyguardIgnoreList = resources.getIntArray(
R.array.config_face_acquire_keyguard_ignorelist);
mKeyguardIgnoreListVendor = resources.getIntArray(
R.array.config_face_acquire_vendor_keyguard_ignorelist);
}
@Override
protected void startHalOperation() {
try {
mCancellationSignal = getFreshDaemon().authenticate(mSequentialId, mOperationId);
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception when requesting auth", e);
onError(BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
mCallback.onClientFinished(this, false /* success */);
}
}
@Override
protected void stopHalOperation() {
if (mCancellationSignal != null) {
try {
mCancellationSignal.cancel();
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception when requesting cancel", e);
onError(BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
mCallback.onClientFinished(this, false /* success */);
}
}
}
private boolean wasUserDetected() {
// Do not provide haptic feedback if the user was not detected, and an error (usually
// ERROR_TIMEOUT) is received.
return mLastAcquire != FaceManager.FACE_ACQUIRED_NOT_DETECTED
&& mLastAcquire != FaceManager.FACE_ACQUIRED_SENSOR_DIRTY;
}
@Override
public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
boolean authenticated, ArrayList<Byte> token) {
super.onAuthenticated(identifier, authenticated, token);
mUsageStats.addEvent(new UsageStats.AuthenticationEvent(
getStartTimeMs(),
System.currentTimeMillis() - getStartTimeMs() /* latency */,
authenticated,
0 /* error */,
0 /* vendorError */,
getTargetUserId()));
// For face, the authentication lifecycle ends either when
// 1) Authenticated == true
// 2) Error occurred
// 3) Authenticated == false
mCallback.onClientFinished(this, true /* success */);
}
@Override
public void onError(int error, int vendorCode) {
mUsageStats.addEvent(new UsageStats.AuthenticationEvent(
getStartTimeMs(),
System.currentTimeMillis() - getStartTimeMs() /* latency */,
false /* authenticated */,
error,
vendorCode,
getTargetUserId()));
switch (error) {
case BiometricConstants.BIOMETRIC_ERROR_TIMEOUT:
if (!wasUserDetected() && !isBiometricPrompt()) {
// No vibration if user was not detected on keyguard
break;
}
case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT:
case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT:
if (mAuthAttempted) {
// Only vibrate if auth was attempted. If the user was already locked out prior
// to starting authentication, do not vibrate.
vibrateError();
}
break;
default:
break;
}
super.onError(error, vendorCode);
}
private int[] getAcquireIgnorelist() {
return isBiometricPrompt() ? mBiometricPromptIgnoreList : mKeyguardIgnoreList;
}
private int[] getAcquireVendorIgnorelist() {
return isBiometricPrompt() ? mBiometricPromptIgnoreListVendor : mKeyguardIgnoreListVendor;
}
private boolean shouldSend(int acquireInfo, int vendorCode) {
if (acquireInfo == FaceManager.FACE_ACQUIRED_VENDOR) {
return !Utils.listContains(getAcquireVendorIgnorelist(), vendorCode);
} else {
return !Utils.listContains(getAcquireIgnorelist(), acquireInfo);
}
}
@Override
public void onAcquired(int acquireInfo, int vendorCode) {
mLastAcquire = acquireInfo;
final boolean shouldSend = shouldSend(acquireInfo, vendorCode);
onAcquiredInternal(acquireInfo, vendorCode, shouldSend);
}
@Override public void onLockoutTimed(long durationMillis) {
mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_TIMED);
// Lockout metrics are logged as an error code.
final int error = BiometricFaceConstants.FACE_ERROR_LOCKOUT;
logOnError(getContext(), error, 0 /* vendorCode */, getTargetUserId());
try {
getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */);
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception", e);
}
}
@Override public void onLockoutPermanent() {
mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_PERMANENT);
// Lockout metrics are logged as an error code.
final int error = BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT;
logOnError(getContext(), error, 0 /* vendorCode */, getTargetUserId());
try {
getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */);
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception", e);
}
}
}

View File

@@ -0,0 +1,120 @@
/*
* Copyright (C) 2020 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.face.aidl;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.hardware.biometrics.BiometricFaceConstants;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.common.ICancellationSignal;
import android.hardware.biometrics.face.IFace;
import android.hardware.biometrics.face.ISession;
import android.hardware.face.Face;
import android.hardware.face.FaceManager;
import android.os.IBinder;
import android.os.NativeHandle;
import android.os.RemoteException;
import android.util.Slog;
import com.android.internal.R;
import com.android.server.biometrics.HardwareAuthTokenUtils;
import com.android.server.biometrics.Utils;
import com.android.server.biometrics.sensors.BiometricUtils;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.EnrollClient;
import com.android.server.biometrics.sensors.face.FaceUtils;
import java.util.ArrayList;
/**
* Face-specific enroll client for the {@link IFace} AIDL HAL interface.
*/
public class FaceEnrollClient extends EnrollClient<ISession> {
private static final String TAG = "FaceEnrollClient";
@NonNull private final int[] mEnrollIgnoreList;
@NonNull private final int[] mEnrollIgnoreListVendor;
@Nullable private ICancellationSignal mCancellationSignal;
private final int mMaxTemplatesPerUser;
FaceEnrollClient(@NonNull Context context, @NonNull LazyDaemon<ISession> lazyDaemon,
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
@NonNull byte[] hardwareAuthToken, @NonNull String opPackageName,
@NonNull BiometricUtils<Face> utils, @NonNull int[] disabledFeatures, int timeoutSec,
@Nullable NativeHandle previewSurface, int sensorId, int maxTemplatesPerUser) {
super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, opPackageName, utils,
timeoutSec, BiometricsProtoEnums.MODALITY_FACE, sensorId,
false /* shouldVibrate */);
mEnrollIgnoreList = getContext().getResources()
.getIntArray(R.array.config_face_acquire_enroll_ignorelist);
mEnrollIgnoreListVendor = getContext().getResources()
.getIntArray(R.array.config_face_acquire_vendor_enroll_ignorelist);
mMaxTemplatesPerUser = maxTemplatesPerUser;
}
@Override
protected boolean hasReachedEnrollmentLimit() {
return FaceUtils.getInstance(getSensorId()).getBiometricsForUser(getContext(),
getTargetUserId()).size() >= mMaxTemplatesPerUser;
}
@Override
public void onAcquired(int acquireInfo, int vendorCode) {
final boolean shouldSend;
if (acquireInfo == FaceManager.FACE_ACQUIRED_VENDOR) {
shouldSend = !Utils.listContains(mEnrollIgnoreListVendor, vendorCode);
} else {
shouldSend = !Utils.listContains(mEnrollIgnoreList, acquireInfo);
}
onAcquiredInternal(acquireInfo, vendorCode, shouldSend);
}
@Override
protected void startHalOperation() {
final ArrayList<Byte> token = new ArrayList<>();
for (byte b : mHardwareAuthToken) {
token.add(b);
}
try {
// TODO(b/172593978): Pass features.
// TODO(b/172593521): Pass mPreviewSurface as android.hardware.common.NativeHandle.
mCancellationSignal = getFreshDaemon().enroll(mSequentialId,
HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken),
null /* mPreviewSurface */);
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception when requesting enroll", e);
onError(BiometricFaceConstants.FACE_ERROR_UNABLE_TO_PROCESS, 0 /* vendorCode */);
mCallback.onClientFinished(this, false /* success */);
}
}
@Override
protected void stopHalOperation() {
if (mCancellationSignal != null) {
try {
mCancellationSignal.cancel();
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception when requesting cancel", e);
onError(BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
mCallback.onClientFinished(this, false /* success */);
}
}
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) 2020 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.face.aidl;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.face.IFace;
import android.hardware.biometrics.face.ISession;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.GenerateChallengeClient;
/**
* Face-specific generateChallenge client for the {@link IFace} AIDL HAL interface.
*/
public class FaceGenerateChallengeClient extends GenerateChallengeClient<ISession> {
private static final String TAG = "FaceGenerateChallengeClient";
private static final int CHALLENGE_TIMEOUT_SEC = 600; // 10 minutes
FaceGenerateChallengeClient(@NonNull Context context,
@NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token,
@NonNull ClientMonitorCallbackConverter listener, @NonNull String owner, int sensorId) {
super(context, lazyDaemon, token, listener, owner, sensorId);
}
@Override
protected void startHalOperation() {
try {
getFreshDaemon().generateChallenge(mSequentialId, CHALLENGE_TIMEOUT_SEC);
} catch (RemoteException e) {
Slog.e(TAG, "Unable to generateChallenge", e);
}
}
void onChallengeGenerated(int sensorId, int userId, long challenge) {
try {
getListener().onChallengeGenerated(sensorId, challenge);
mCallback.onClientFinished(this, true /* success */);
} catch (RemoteException e) {
Slog.e(TAG, "Unable to send challenge", e);
mCallback.onClientFinished(this, false /* success */);
}
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2020 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.face.aidl;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.ISession;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.sensors.ClientMonitor;
import java.util.Map;
class FaceGetAuthenticatorIdClient extends ClientMonitor<ISession> {
private static final String TAG = "FaceGetAuthenticatorIdClient";
private final Map<Integer, Long> mAuthenticatorIds;
FaceGetAuthenticatorIdClient(@NonNull Context context, @NonNull LazyDaemon<ISession> lazyDaemon,
int userId, @NonNull String opPackageName, int sensorId,
Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, null /* token */, null /* listener */, userId, opPackageName,
0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_FACE,
BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
mAuthenticatorIds = authenticatorIds;
}
@Override
public void unableToStart() {
// Nothing to do here
}
@Override
protected void startHalOperation() {
try {
getFreshDaemon().getAuthenticatorId(mSequentialId);
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception", e);
}
}
void onAuthenticatorIdRetrieved(long authenticatorId) {
mAuthenticatorIds.put(getTargetUserId(), authenticatorId);
mCallback.onClientFinished(this, true /* success */);
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (C) 2020 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.face.aidl;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.IFace;
import android.hardware.biometrics.face.ISession;
import android.hardware.face.Face;
import android.os.IBinder;
import com.android.server.biometrics.sensors.BiometricUtils;
import com.android.server.biometrics.sensors.InternalCleanupClient;
import com.android.server.biometrics.sensors.InternalEnumerateClient;
import com.android.server.biometrics.sensors.RemovalClient;
import java.util.List;
import java.util.Map;
/**
* Face-specific internal cleanup client for the {@link IFace} AIDL HAL interface.
*/
class FaceInternalCleanupClient extends InternalCleanupClient<Face, ISession> {
FaceInternalCleanupClient(@NonNull Context context,
@NonNull LazyDaemon<ISession> lazyDaemon, int userId, @NonNull String owner,
int sensorId, @NonNull List<Face> enrolledList, @NonNull BiometricUtils<Face> utils,
@NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, userId, owner, sensorId, BiometricsProtoEnums.MODALITY_FACE,
enrolledList, utils, authenticatorIds);
}
@Override
protected InternalEnumerateClient<ISession> getEnumerateClient(Context context,
LazyDaemon<ISession> lazyDaemon, IBinder token, int userId, String owner,
List<Face> enrolledList, BiometricUtils<Face> utils, int sensorId) {
return new FaceInternalEnumerateClient(context, lazyDaemon, token, userId, owner,
enrolledList, utils, sensorId);
}
@Override
protected RemovalClient<Face, ISession> getRemovalClient(Context context,
LazyDaemon<ISession> lazyDaemon, IBinder token,
int biometricId, int userId, String owner, BiometricUtils<Face> utils, int sensorId,
Map<Integer, Long> authenticatorIds) {
// Internal remove does not need to send results to anyone. Cleanup (enumerate + remove)
// is all done internally.
return new FaceRemovalClient(context, lazyDaemon, token,
null /* ClientMonitorCallbackConverter */, biometricId, userId, owner, utils,
sensorId, authenticatorIds);
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (C) 2020 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.face.aidl;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.IFace;
import android.hardware.biometrics.face.ISession;
import android.hardware.face.Face;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.sensors.BiometricUtils;
import com.android.server.biometrics.sensors.InternalEnumerateClient;
import java.util.List;
/**
* Face-specific internal enumerate client for the {@link IFace} AIDL HAL interface.
*/
class FaceInternalEnumerateClient extends InternalEnumerateClient<ISession> {
private static final String TAG = "FaceInternalEnumerateClient";
FaceInternalEnumerateClient(@NonNull Context context,
@NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token, int userId,
@NonNull String owner, @NonNull List<Face> enrolledList,
@NonNull BiometricUtils<Face> utils, int sensorId) {
super(context, lazyDaemon, token, userId, owner, enrolledList, utils, sensorId,
BiometricsProtoEnums.MODALITY_FACE);
}
@Override
protected void startHalOperation() {
try {
getFreshDaemon().enumerateEnrollments(mSequentialId);
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception when requesting enumerate", e);
mCallback.onClientFinished(this, false /* success */);
}
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2020 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.face.aidl;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.IFace;
import android.hardware.biometrics.face.ISession;
import android.hardware.face.Face;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.sensors.BiometricUtils;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.RemovalClient;
import java.util.Map;
/**
* Face-specific removal client for the {@link IFace} AIDL HAL interface.
*/
class FaceRemovalClient extends RemovalClient<Face, ISession> {
private static final String TAG = "FaceRemovalClient";
FaceRemovalClient(@NonNull Context context, @NonNull LazyDaemon<ISession> lazyDaemon,
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener,
int biometricId, int userId, @NonNull String owner, @NonNull BiometricUtils<Face> utils,
int sensorId, @NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, token, listener, biometricId, userId, owner, utils, sensorId,
authenticatorIds, BiometricsProtoEnums.MODALITY_FACE);
}
@Override
protected void startHalOperation() {
try {
final int[] ids = new int[]{mBiometricId};
getFreshDaemon().removeEnrollments(mSequentialId, ids);
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception when requesting remove", e);
mCallback.onClientFinished(this, false /* success */);
}
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (C) 2020 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.face.aidl;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.IFace;
import android.hardware.biometrics.face.ISession;
import android.hardware.keymaster.HardwareAuthToken;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.HardwareAuthTokenUtils;
import com.android.server.biometrics.sensors.ClientMonitor;
import com.android.server.biometrics.sensors.LockoutCache;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.LockoutTracker;
/**
* Face-specific resetLockout client for the {@link IFace} AIDL HAL interface.
* Updates the framework's lockout cache and notifies clients such as Keyguard when lockout is
* cleared.
*/
public class FaceResetLockoutClient extends ClientMonitor<ISession> {
private static final String TAG = "FaceResetLockoutClient";
private final HardwareAuthToken mHardwareAuthToken;
private final LockoutCache mLockoutCache;
private final LockoutResetDispatcher mLockoutResetDispatcher;
FaceResetLockoutClient(@NonNull Context context,
@NonNull LazyDaemon<ISession> lazyDaemon, int userId, String owner, int sensorId,
@NonNull byte[] hardwareAuthToken, @NonNull LockoutCache lockoutTracker,
@NonNull LockoutResetDispatcher lockoutResetDispatcher) {
super(context, lazyDaemon, null /* token */, null /* listener */, userId, owner,
0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN,
BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
mHardwareAuthToken = HardwareAuthTokenUtils.toHardwareAuthToken(hardwareAuthToken);
mLockoutCache = lockoutTracker;
mLockoutResetDispatcher = lockoutResetDispatcher;
}
@Override
public void unableToStart() {
// Nothing to do here
}
@Override
protected void startHalOperation() {
try {
getFreshDaemon().resetLockout(mSequentialId, mHardwareAuthToken);
} catch (RemoteException e) {
Slog.e(TAG, "Unable to reset lockout", e);
mCallback.onClientFinished(this, false /* success */);
}
}
void onLockoutCleared() {
mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_NONE);
mLockoutResetDispatcher.notifyLockoutResetCallbacks(getSensorId());
mCallback.onClientFinished(this, true /* success */);
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2020 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.face.aidl;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.face.IFace;
import android.hardware.biometrics.face.ISession;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.sensors.RevokeChallengeClient;
/**
* Face-specific revokeChallenge client for the {@link IFace} AIDL HAL interface.
*/
public class FaceRevokeChallengeClient extends RevokeChallengeClient<ISession> {
private static final String TAG = "FaceRevokeChallengeClient";
private final long mChallenge;
FaceRevokeChallengeClient(@NonNull Context context,
@NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token,
@NonNull String owner, int sensorId, long challenge) {
super(context, lazyDaemon, token, owner, sensorId);
mChallenge = challenge;
}
@Override
protected void startHalOperation() {
try {
getFreshDaemon().revokeChallenge(mSequentialId, mChallenge);
} catch (RemoteException e) {
Slog.e(TAG, "Unable to revokeChallenge", e);
}
}
void onChallengeRevoked(int sensorId, int userId, long challenge) {
final boolean success = challenge == mChallenge;
mCallback.onClientFinished(this, success);
}
}