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