diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java index 8dc8d5b60943b..13e2700b3f54d 100644 --- a/core/java/android/hardware/face/FaceManager.java +++ b/core/java/android/hardware/face/FaceManager.java @@ -1059,7 +1059,7 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan * * @param face The face template that was removed. */ - public void onRemovalSucceeded(Face face, int remaining) { + public void onRemovalSucceeded(@Nullable Face face, int remaining) { } } @@ -1258,10 +1258,6 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan if (mRemovalCallback == null) { return; } - if (face == null) { - Slog.e(TAG, "Received MSG_REMOVED, but face is null"); - return; - } mRemovalCallback.onRemovalSucceeded(face, remaining); } diff --git a/core/java/android/hardware/face/FaceServiceReceiver.java b/core/java/android/hardware/face/FaceServiceReceiver.java new file mode 100644 index 0000000000000..f0f975dcea570 --- /dev/null +++ b/core/java/android/hardware/face/FaceServiceReceiver.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2021 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 android.hardware.face; + +import android.os.RemoteException; + +/** + * Provides default methods for callers who only need a subset of the functionality. + * @hide + */ +public class FaceServiceReceiver extends IFaceServiceReceiver.Stub { + @Override + public void onEnrollResult(Face face, int remaining) throws RemoteException { + + } + + @Override + public void onAcquired(int acquiredInfo, int vendorCode) throws RemoteException { + + } + + @Override + public void onAuthenticationSucceeded(Face face, int userId, boolean isStrongBiometric) + throws RemoteException { + + } + + @Override + public void onFaceDetected(int sensorId, int userId, boolean isStrongBiometric) + throws RemoteException { + + } + + @Override + public void onAuthenticationFailed() throws RemoteException { + + } + + @Override + public void onError(int error, int vendorCode) throws RemoteException { + + } + + @Override + public void onRemoved(Face face, int remaining) throws RemoteException { + + } + + @Override + public void onFeatureSet(boolean success, int feature) throws RemoteException { + + } + + @Override + public void onFeatureGet(boolean success, int feature, boolean value) throws RemoteException { + + } + + @Override + public void onChallengeGenerated(int sensorId, long challenge) throws RemoteException { + + } + + @Override + public void onChallengeInterrupted(int sensorId) throws RemoteException { + + } + + @Override + public void onChallengeInterruptFinished(int sensorId) throws RemoteException { + + } + + @Override + public void onAuthenticationFrame(FaceAuthenticationFrame frame) throws RemoteException { + + } + + @Override + public void onEnrollmentFrame(FaceEnrollFrame frame) throws RemoteException { + + } +} diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index 1c33b26dfa18a..7b6e1299e8e1e 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -452,7 +452,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing * {@link #remove} is called on a group, this should be the number of remaining * fingerprints in the group, and 0 after the last fingerprint is removed. */ - public void onRemovalSucceeded(Fingerprint fp, int remaining) { } + public void onRemovalSucceeded(@Nullable Fingerprint fp, int remaining) { } } /** diff --git a/core/java/android/hardware/fingerprint/FingerprintServiceReceiver.java b/core/java/android/hardware/fingerprint/FingerprintServiceReceiver.java new file mode 100644 index 0000000000000..798e87beb52a7 --- /dev/null +++ b/core/java/android/hardware/fingerprint/FingerprintServiceReceiver.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2021 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 android.hardware.fingerprint; + +import android.os.RemoteException; + +/** + * Provides default methods for callers who only need a subset of the functionality. + * @hide + */ +public class FingerprintServiceReceiver extends IFingerprintServiceReceiver.Stub { + @Override + public void onEnrollResult(Fingerprint fp, int remaining) throws RemoteException { + + } + + @Override + public void onAcquired(int acquiredInfo, int vendorCode) throws RemoteException { + + } + + @Override + public void onAuthenticationSucceeded(Fingerprint fp, int userId, boolean isStrongBiometric) + throws RemoteException { + + } + + @Override + public void onFingerprintDetected(int sensorId, int userId, boolean isStrongBiometric) + throws RemoteException { + + } + + @Override + public void onAuthenticationFailed() throws RemoteException { + + } + + @Override + public void onError(int error, int vendorCode) throws RemoteException { + + } + + @Override + public void onRemoved(Fingerprint fp, int remaining) throws RemoteException { + + } + + @Override + public void onChallengeGenerated(int sensorId, long challenge) throws RemoteException { + + } + + @Override + public void onUdfpsPointerDown(int sensorId) throws RemoteException { + + } + + @Override + public void onUdfpsPointerUp(int sensorId) throws RemoteException { + + } +} 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 8197edc97a053..383efce5bb2a4 100644 --- a/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java @@ -65,12 +65,10 @@ public abstract class RemovalClient properties = - FaceService.this.getSensorProperties(); - - Slog.d(TAG, "Retrieved sensor properties for: " + opPackageName - + ", sensors: " + properties.size()); - return properties; + return FaceService.this.getSensorProperties(); } @Override // Binder call @@ -394,10 +390,29 @@ public class FaceService extends SystemService implements BiometricServiceCallba final IFaceServiceReceiver receiver, final String opPackageName) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); + final FaceServiceReceiver internalReceiver = new FaceServiceReceiver() { + int sensorsFinishedRemoving = 0; + final int numSensors = getSensorPropertiesInternal( + getContext().getOpPackageName()).size(); + @Override + public void onRemoved(Face face, int remaining) throws RemoteException { + if (remaining == 0) { + sensorsFinishedRemoving++; + Slog.d(TAG, "sensorsFinishedRemoving: " + sensorsFinishedRemoving + + ", numSensors: " + numSensors); + if (sensorsFinishedRemoving == numSensors) { + receiver.onRemoved(null, 0 /* remaining */); + } + } + } + }; + + // This effectively iterates through all sensors, but has to do so by finding all + // sensors under each provider. for (ServiceProvider provider : mServiceProviders) { List props = provider.getSensorProperties(); for (FaceSensorPropertiesInternal prop : props) { - provider.scheduleRemoveAll(prop.sensorId, token, userId, receiver, + provider.scheduleRemoveAll(prop.sensorId, token, userId, internalReceiver, opPackageName); } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java index 79e361f531c7a..4ffbe06c11bae 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java @@ -398,7 +398,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { private synchronized IBiometricsFace getDaemon() { if (mTestHalEnabled) { - final TestHal testHal = new TestHal(); + final TestHal testHal = new TestHal(mContext, mSensorId); testHal.setCallback(mHalResultController); return testHal; } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/TestHal.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/TestHal.java index 84aa6d9ad1f8f..d9408599aa2bc 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/TestHal.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/TestHal.java @@ -16,23 +16,40 @@ package com.android.server.biometrics.sensors.face.hidl; +import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.Context; import android.hardware.biometrics.face.V1_0.FaceError; import android.hardware.biometrics.face.V1_0.IBiometricsFace; import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback; import android.hardware.biometrics.face.V1_0.OptionalBool; import android.hardware.biometrics.face.V1_0.OptionalUint64; import android.hardware.biometrics.face.V1_0.Status; +import android.hardware.face.Face; import android.os.RemoteException; import android.util.Slog; +import com.android.server.biometrics.sensors.face.FaceUtils; + import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; +import java.util.List; public class TestHal extends IBiometricsFace.Stub { private static final String TAG = "face.hidl.TestHal"; + + @NonNull + private final Context mContext; + private final int mSensorId; + @Nullable private IBiometricsFaceClientCallback mCallback; + private int mUserId; + + TestHal(@NonNull Context context, int sensorId) { + mContext = context; + mSensorId = sensorId; + } @Override public OptionalUint64 setCallback(IBiometricsFaceClientCallback clientCallback) { @@ -44,6 +61,7 @@ public class TestHal extends IBiometricsFace.Stub { @Override public int setActiveUser(int userId, String storePath) { + mUserId = userId; return 0; } @@ -110,8 +128,20 @@ public class TestHal extends IBiometricsFace.Stub { public int remove(int faceId) throws RemoteException { Slog.w(TAG, "remove"); if (mCallback != null) { - mCallback.onRemoved(0 /* deviceId */, new ArrayList(Arrays.asList(faceId)), - 0 /* userId */); + if (faceId == 0) { + // For this HAL interface, remove(0) means to remove all enrollments. + final List faces = FaceUtils.getInstance(mSensorId) + .getBiometricsForUser(mContext, mUserId); + final ArrayList faceIds = new ArrayList<>(); + for (Face face : faces) { + faceIds.add(face.getBiometricId()); + } + mCallback.onRemoved(0 /* deviceId */, faceIds, mUserId); + } else { + mCallback.onRemoved(0 /* deviceId */, + new ArrayList<>(Collections.singletonList(faceId)), + mUserId); + } } return 0; } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java index e4397fd158e11..cbef6609873eb 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java @@ -49,6 +49,7 @@ import android.hardware.biometrics.fingerprint.SensorProps; import android.hardware.fingerprint.Fingerprint; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; +import android.hardware.fingerprint.FingerprintServiceReceiver; import android.hardware.fingerprint.IFingerprintClientActiveCallback; import android.hardware.fingerprint.IFingerprintService; import android.hardware.fingerprint.IFingerprintServiceReceiver; @@ -145,12 +146,7 @@ public class FingerprintService extends SystemService implements BiometricServic Utils.checkPermission(getContext(), TEST_BIOMETRIC); } - final List properties = - FingerprintService.this.getSensorProperties(); - - Slog.d(TAG, "Retrieved sensor properties for: " + opPackageName - + ", sensors: " + properties.size()); - return properties; + return FingerprintService.this.getSensorProperties(); } @Override @@ -505,12 +501,31 @@ public class FingerprintService extends SystemService implements BiometricServic @Override // Binder call public void removeAll(final IBinder token, final int userId, final IFingerprintServiceReceiver receiver, final String opPackageName) { - Utils.checkPermission(getContext(), MANAGE_FINGERPRINT); + Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); + final FingerprintServiceReceiver internalReceiver = new FingerprintServiceReceiver() { + int sensorsFinishedRemoving = 0; + final int numSensors = getSensorPropertiesInternal( + getContext().getOpPackageName()).size(); + @Override + public void onRemoved(Fingerprint fp, int remaining) throws RemoteException { + if (remaining == 0) { + sensorsFinishedRemoving++; + Slog.d(TAG, "sensorsFinishedRemoving: " + sensorsFinishedRemoving + + ", numSensors: " + numSensors); + if (sensorsFinishedRemoving == numSensors) { + receiver.onRemoved(null, 0 /* remaining */); + } + } + } + }; + + // This effectively iterates through all sensors, but has to do so by finding all + // sensors under each provider. for (ServiceProvider provider : mServiceProviders) { List props = provider.getSensorProperties(); for (FingerprintSensorPropertiesInternal prop : props) { - provider.scheduleRemoveAll(prop.sensorId, token, receiver, userId, + provider.scheduleRemoveAll(prop.sensorId, token, internalReceiver, userId, opPackageName); } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java index f2992cccbe099..e149ca9428dde 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java @@ -402,7 +402,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider @VisibleForTesting synchronized IBiometricsFingerprint getDaemon() { if (mTestHalEnabled) { - final TestHal testHal = new TestHal(); + final TestHal testHal = new TestHal(mContext, mSensorId); testHal.setNotify(mHalResultController); return testHal; } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/TestHal.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/TestHal.java index 129f6a61df04c..986e92e244f0e 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/TestHal.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/TestHal.java @@ -16,22 +16,38 @@ package com.android.server.biometrics.sensors.fingerprint.hidl; +import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.Context; import android.hardware.biometrics.fingerprint.V2_1.FingerprintError; import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprintClientCallback; import android.hardware.biometrics.fingerprint.V2_3.IBiometricsFingerprint; +import android.hardware.fingerprint.Fingerprint; import android.os.RemoteException; import android.util.Slog; +import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils; + +import java.util.List; + /** * Test HAL that provides only provides no-ops. */ public class TestHal extends IBiometricsFingerprint.Stub { private static final String TAG = "fingerprint.hidl.TestHal"; + @NonNull + private final Context mContext; + private final int mSensorId; + @Nullable private IBiometricsFingerprintClientCallback mCallback; + TestHal(@NonNull Context context, int sensorId) { + mContext = context; + mSensorId = sensorId; + } + @Override public boolean isUdfps(int sensorId) { return false; @@ -96,7 +112,18 @@ public class TestHal extends IBiometricsFingerprint.Stub { public int remove(int gid, int fid) throws RemoteException { Slog.w(TAG, "Remove"); if (mCallback != null) { - mCallback.onRemoved(0 /* deviceId */, fid, gid, 0 /* remaining */); + if (fid == 0) { + // For this HAL interface, remove(0) means to remove all enrollments. + final List fingerprints = FingerprintUtils.getInstance(mSensorId) + .getBiometricsForUser(mContext, gid); + for (int i = 0; i < fingerprints.size(); i++) { + final Fingerprint fp = fingerprints.get(i); + mCallback.onRemoved(0 /* deviceId */, fp.getBiometricId(), gid, + fingerprints.size() - i - 1); + } + } else { + mCallback.onRemoved(0 /* deviceId */, fid, gid, 0 /* remaining */); + } } return 0; }