diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index 23de303efae68..b76b877234d78 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -761,14 +761,14 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing * @hide */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) - public void onFingerDown(int sensorId, int x, int y, float minor, float major) { + public void onPointerDown(int sensorId, int x, int y, float minor, float major) { if (mService == null) { Slog.w(TAG, "onFingerDown: no fingerprint service"); return; } try { - mService.onFingerDown(sensorId, x, y, minor, major); + mService.onPointerDown(sensorId, x, y, minor, major); } catch (RemoteException e) { e.rethrowFromSystemServer(); } @@ -778,14 +778,14 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing * @hide */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) - public void onFingerUp(int sensorId) { + public void onPointerUp(int sensorId) { if (mService == null) { Slog.w(TAG, "onFingerDown: no fingerprint service"); return; } try { - mService.onFingerUp(sensorId); + mService.onPointerUp(sensorId); } catch (RemoteException e) { e.rethrowFromSystemServer(); } diff --git a/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java b/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java index d5ce9e3890b56..1f896cdf4298e 100644 --- a/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java +++ b/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java @@ -85,4 +85,9 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna return false; } } + + @Override + public String toString() { + return "ID: " + sensorId + ", Strength: " + sensorStrength + ", Type: " + sensorType; + } } diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl index 7af73800d64e5..f467b1dbd412b 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl @@ -121,10 +121,10 @@ interface IFingerprintService { void initializeConfiguration(int sensorId, int strength); // Notifies about a finger touching the sensor area. - void onFingerDown(int sensorId, int x, int y, float minor, float major); + void onPointerDown(int sensorId, int x, int y, float minor, float major); // Notifies about a finger leaving the sensor area. - void onFingerUp(int sensorId); + void onPointerUp(int sensorId); // Sets the controller for managing the UDFPS overlay. void setUdfpsOverlayController(in IUdfpsOverlayController controller); diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index c409d87a098a7..e3b00495f3dc5 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -63,7 +63,7 @@ import javax.inject.Inject; * Note that the current architecture is designed so that a single {@link UdfpsController} * controls/manages all UDFPS sensors. In other words, a single controller is registered with * {@link com.android.server.biometrics.sensors.fingerprint.FingerprintService}, and interfaces such - * as {@link FingerprintManager#onFingerDown(int, int, int, float, float)} or + * as {@link FingerprintManager#onPointerDown(int, int, int, float, float)} or * {@link IUdfpsOverlayController#showUdfpsOverlay(int)}should all have * {@code sensorId} parameters. */ @@ -374,7 +374,7 @@ class UdfpsController implements DozeReceiver { fw.write(mHbmEnableCommand); fw.close(); } - mFingerprintManager.onFingerDown(mUdfpsSensorId, x, y, minor, major); + mFingerprintManager.onPointerDown(mUdfpsSensorId, x, y, minor, major); } catch (IOException e) { mView.hideScrimAndDot(); Log.e(TAG, "onFingerDown | failed to enable HBM: " + e.getMessage()); @@ -382,7 +382,7 @@ class UdfpsController implements DozeReceiver { } private void onFingerUp() { - mFingerprintManager.onFingerUp(mUdfpsSensorId); + mFingerprintManager.onPointerUp(mUdfpsSensorId); // Hiding the scrim before disabling HBM results in less noticeable flicker. mView.hideScrimAndDot(); if (mHbmSupported) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java index 99e39b8097eb5..e24f4ca3581da 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java @@ -222,7 +222,7 @@ public class UdfpsControllerTest extends SysuiTestCase { mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event); event.recycle(); // THEN the event is passed to the FingerprintManager - verify(mFingerprintManager).onFingerDown(eq(mUdfpsController.mUdfpsSensorId), eq(0), eq(0), + verify(mFingerprintManager).onPointerDown(eq(mUdfpsController.mUdfpsSensorId), eq(0), eq(0), eq(0f), eq(0f)); // AND the scrim and dot is shown verify(mUdfpsView).showScrimAndDot(); @@ -236,7 +236,7 @@ public class UdfpsControllerTest extends SysuiTestCase { // WHEN fingerprint is requested because of AOD interrupt mUdfpsController.onAodInterrupt(0, 0); // THEN the event is passed to the FingerprintManager - verify(mFingerprintManager).onFingerDown(eq(mUdfpsController.mUdfpsSensorId), eq(0), eq(0), + verify(mFingerprintManager).onPointerDown(eq(mUdfpsController.mUdfpsSensorId), eq(0), eq(0), anyFloat(), anyFloat()); // AND the scrim and dot is shown verify(mUdfpsView).showScrimAndDot(); diff --git a/services/core/Android.bp b/services/core/Android.bp index addaa65686657..26c28d5c95b1d 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -109,6 +109,7 @@ java_library_static { "android.hardware.weaver-V1.0-java", "android.hardware.biometrics.face-V1.1-java", "android.hardware.biometrics.fingerprint-V2.3-java", + "android.hardware.biometrics.fingerprint-java", "android.hardware.oemlock-V1.0-java", "android.hardware.configstore-V1.0-java", "android.hardware.contexthub-V1.0-java", diff --git a/services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java index 3c9dddd0b9059..0dee81681fc48 100644 --- a/services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java +++ b/services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java @@ -73,7 +73,7 @@ public abstract class ClientMonitor extends LoggableMonitor implements IBinde T getDaemon(); } - private final int mSequentialId; + protected final int mSequentialId; @NonNull private final Context mContext; @NonNull protected final LazyDaemon mLazyDaemon; private final int mTargetUserId; 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 d353994b7f9ac..165755a2febe9 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 @@ -32,6 +32,8 @@ import android.content.pm.PackageManager; import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.IBiometricSensorReceiver; import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; +import android.hardware.biometrics.fingerprint.IFingerprint; +import android.hardware.biometrics.fingerprint.SensorProps; import android.hardware.fingerprint.Fingerprint; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.hardware.fingerprint.IFingerprintClientActiveCallback; @@ -40,9 +42,12 @@ import android.hardware.fingerprint.IFingerprintServiceReceiver; import android.hardware.fingerprint.IUdfpsOverlayController; import android.os.Binder; import android.os.Build; +import android.os.Handler; import android.os.IBinder; import android.os.NativeHandle; import android.os.Process; +import android.os.RemoteException; +import android.os.ServiceManager; import android.os.UserHandle; import android.provider.Settings; import android.util.EventLog; @@ -53,11 +58,13 @@ import android.view.Surface; import com.android.internal.R; import com.android.internal.util.DumpUtils; import com.android.internal.widget.LockPatternUtils; +import com.android.server.ServiceThread; import com.android.server.SystemService; import com.android.server.biometrics.Utils; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.LockoutResetDispatcher; import com.android.server.biometrics.sensors.LockoutTracker; +import com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintProvider; import com.android.server.biometrics.sensors.fingerprint.hidl.Fingerprint21; import com.android.server.biometrics.sensors.fingerprint.hidl.Fingerprint21UdfpsMock; @@ -506,7 +513,7 @@ public class FingerprintService extends SystemService { } @Override - public void onFingerDown(int sensorId, int x, int y, float minor, float major) { + public void onPointerDown(int sensorId, int x, int y, float minor, float major) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); final ServiceProvider provider = getProviderForSensor(sensorId); @@ -514,11 +521,11 @@ public class FingerprintService extends SystemService { Slog.w(TAG, "No matching provider for onFingerDown, sensorId: " + sensorId); return; } - provider.onFingerDown(sensorId, x, y, minor, major); + provider.onPointerDown(sensorId, x, y, minor, major); } @Override - public void onFingerUp(int sensorId) { + public void onPointerUp(int sensorId) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); final ServiceProvider provider = getProviderForSensor(sensorId); @@ -526,7 +533,7 @@ public class FingerprintService extends SystemService { Slog.w(TAG, "No matching provider for onFingerUp, sensorId: " + sensorId); return; } - provider.onFingerUp(sensorId); + provider.onPointerUp(sensorId); } @Override @@ -546,6 +553,39 @@ public class FingerprintService extends SystemService { mLockoutResetDispatcher = new LockoutResetDispatcher(context); mLockPatternUtils = new LockPatternUtils(context); mServiceProviders = new ArrayList<>(); + + initializeAidlHals(); + } + + private void initializeAidlHals() { + final String[] instances = ServiceManager.getDeclaredInstances(IFingerprint.DESCRIPTOR); + if (instances == null || instances.length == 0) { + return; + } + + // If for some reason the HAL is not started before the system service, do not block + // the rest of system server. Put this on a background thread. + final ServiceThread thread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND, + true /* allowIo */); + thread.start(); + final Handler handler = new Handler(thread.getLooper()); + + handler.post(() -> { + for (String instance : instances) { + final String fqName = IFingerprint.DESCRIPTOR + "/" + instance; + final IFingerprint fp = IFingerprint.Stub.asInterface( + ServiceManager.waitForDeclaredService(fqName)); + try { + final SensorProps[] props = fp.getSensorProps(); + final FingerprintProvider provider = + new FingerprintProvider(getContext(), props, fqName, + mLockoutResetDispatcher, mGestureAvailabilityDispatcher); + mServiceProviders.add(provider); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception when initializing instance: " + fqName); + } + } + }); } @Override @@ -571,6 +611,7 @@ public class FingerprintService extends SystemService { private Pair getSingleProvider() { final List properties = getSensorProperties(); if (properties.size() != 1) { + Slog.e(TAG, "Multiple sensors found: " + properties.size()); return null; } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java index d7338a02db67b..1162c9c1241f0 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java @@ -92,6 +92,8 @@ public interface ServiceProvider { @NonNull IFingerprintServiceReceiver receiver, int fingerId, int userId, @NonNull String opPackageName); + void scheduleInternalCleanup(int sensorId, int userId); + boolean isHardwareDetected(int sensorId); void rename(int sensorId, int fingerId, int userId, @NonNull String name); @@ -102,9 +104,9 @@ public interface ServiceProvider { long getAuthenticatorId(int sensorId, int userId); - void onFingerDown(int sensorId, int x, int y, float minor, float major); + void onPointerDown(int sensorId, int x, int y, float minor, float major); - void onFingerUp(int sensorId); + void onPointerUp(int sensorId); void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Udfps.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Udfps.java similarity index 85% rename from services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Udfps.java rename to services/core/java/com/android/server/biometrics/sensors/fingerprint/Udfps.java index 74cae02b37f40..0bf107a9be8ee 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Udfps.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Udfps.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.biometrics.sensors.fingerprint.hidl; +package com.android.server.biometrics.sensors.fingerprint; /** * Interface for under-display fingerprint sensors. @@ -22,6 +22,6 @@ package com.android.server.biometrics.sensors.fingerprint.hidl; * finger position (e.g. enroll, authenticate) should implement this. */ public interface Udfps { - void onFingerDown(int x, int y, float minor, float major); - void onFingerUp(); + void onPointerDown(int x, int y, float minor, float major); + void onPointerUp(); } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/UdfpsHelper.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/UdfpsHelper.java similarity index 89% rename from services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/UdfpsHelper.java rename to services/core/java/com/android/server/biometrics/sensors/fingerprint/UdfpsHelper.java index 0f1d6b462cacd..a2b871ee72c3c 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/UdfpsHelper.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/UdfpsHelper.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.biometrics.sensors.fingerprint.hidl; +package com.android.server.biometrics.sensors.fingerprint; import android.annotation.Nullable; import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint; @@ -29,7 +29,7 @@ public class UdfpsHelper { private static final String TAG = "UdfpsHelper"; - static void onFingerDown(IBiometricsFingerprint daemon, int x, int y, float minor, + public static void onFingerDown(IBiometricsFingerprint daemon, int x, int y, float minor, float major) { android.hardware.biometrics.fingerprint.V2_3.IBiometricsFingerprint extension = android.hardware.biometrics.fingerprint.V2_3.IBiometricsFingerprint.castFrom( @@ -46,7 +46,7 @@ public class UdfpsHelper { } } - static void onFingerUp(IBiometricsFingerprint daemon) { + public static void onFingerUp(IBiometricsFingerprint daemon) { android.hardware.biometrics.fingerprint.V2_3.IBiometricsFingerprint extension = android.hardware.biometrics.fingerprint.V2_3.IBiometricsFingerprint.castFrom( daemon); @@ -62,7 +62,7 @@ public class UdfpsHelper { } } - static void showUdfpsOverlay(int sensorId, + public static void showUdfpsOverlay(int sensorId, @Nullable IUdfpsOverlayController udfpsOverlayController) { if (udfpsOverlayController == null) { return; @@ -74,7 +74,7 @@ public class UdfpsHelper { } } - static void hideUdfpsOverlay(int sensorId, + public static void hideUdfpsOverlay(int sensorId, @Nullable IUdfpsOverlayController udfpsOverlayController) { if (udfpsOverlayController == null) { return; diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java new file mode 100644 index 0000000000000..f91a119681063 --- /dev/null +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java @@ -0,0 +1,111 @@ +/* + * 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.fingerprint.aidl; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.hardware.biometrics.BiometricFaceConstants; +import android.hardware.biometrics.BiometricFingerprintConstants; +import android.hardware.biometrics.common.ICancellationSignal; +import android.hardware.biometrics.fingerprint.ISession; +import android.hardware.fingerprint.IUdfpsOverlayController; +import android.hardware.keymaster.HardwareAuthToken; +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.EnrollClient; +import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils; +import com.android.server.biometrics.sensors.fingerprint.Udfps; +import com.android.server.biometrics.sensors.fingerprint.UdfpsHelper; + +public class FingerprintEnrollClient extends EnrollClient implements Udfps { + + private static final String TAG = "FingerprintEnrollClient"; + + @Nullable private final IUdfpsOverlayController mUdfpsOverlayController; + @Nullable private ICancellationSignal mCancellationSignal; + private final int mMaxTemplatesPerUser; + + public FingerprintEnrollClient(@NonNull Context context, + @NonNull LazyDaemon lazyDaemon, @NonNull IBinder token, + @NonNull ClientMonitorCallbackConverter listener, int userId, + @NonNull byte[] hardwareAuthToken, @NonNull String owner, @NonNull BiometricUtils utils, + int statsModality, int sensorId, + @Nullable IUdfpsOverlayController udfpsOvelayController, int maxTemplatesPerUser) { + super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils, + 0 /* timeoutSec */, statsModality, sensorId, true /* shouldVibrate */); + mUdfpsOverlayController = udfpsOvelayController; + mMaxTemplatesPerUser = maxTemplatesPerUser; + } + + @Override + protected boolean hasReachedEnrollmentLimit() { + return FingerprintUtils.getInstance() + .getBiometricsForUser(getContext(), getTargetUserId()).size() + >= mMaxTemplatesPerUser; + } + + @Override + protected void stopHalOperation() { + UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController); + if (mCancellationSignal != null) { + try { + mCancellationSignal.cancel(); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception when requesting cancel", e); + onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE, + 0 /* vendorCode */); + mCallback.onClientFinished(this, false /* success */); + } + } + } + + @Override + protected void startHalOperation() { + UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController); + try { + // TODO(b/170163175): Need a way to convert byte arrays to HardwareAuthToken + getFreshDaemon().enroll(mSequentialId, null /* hat */); + } 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 + public void onPointerDown(int x, int y, float minor, float major) { + try { + getFreshDaemon().onPointerDown(0 /* pointerId */, x, y, minor, major); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to send pointer down", e); + } + } + + @Override + public void onPointerUp() { + try { + getFreshDaemon().onPointerUp(0 /* pointerId */); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to send pointer up", e); + } + } +} diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGenerateChallengeClient.java new file mode 100644 index 0000000000000..3a6b11349b664 --- /dev/null +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGenerateChallengeClient.java @@ -0,0 +1,71 @@ +/* + * 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.fingerprint.aidl; + +import android.annotation.NonNull; +import android.content.Context; +import android.hardware.biometrics.fingerprint.IFingerprint; +import android.hardware.biometrics.fingerprint.IGenerateChallengeCallback; +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; + +/** + * Fingerprint-specific generateChallenge client for the {@link IFingerprint} AIDL HAL interface. + */ +public class FingerprintGenerateChallengeClient extends GenerateChallengeClient { + private static final String TAG = "FingerprintGenerateChallengeClient"; + private static final int CHALLENGE_TIMEOUT_SEC = 600; // 10 minutes + + private IGenerateChallengeCallback mGenerateChallengeCallback = + new IGenerateChallengeCallback.Stub() { + @Override + public void onChallengeGenerated(int sensorId, int userId, long challenge) { + try { + getListener().onChallengeGenerated(sensorId, challenge); + mCallback.onClientFinished(FingerprintGenerateChallengeClient.this, + true /* success */); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to send challenge", e); + mCallback.onClientFinished(FingerprintGenerateChallengeClient.this, + false /* success */); + } + } + }; + + public FingerprintGenerateChallengeClient(@NonNull Context context, + @NonNull LazyDaemon 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(getSensorId(), getTargetUserId(), + CHALLENGE_TIMEOUT_SEC, + mGenerateChallengeCallback); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to generateChallenge", e); + } + } +} diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java new file mode 100644 index 0000000000000..6245fd97d3945 --- /dev/null +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java @@ -0,0 +1,325 @@ +/* + * 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.fingerprint.aidl; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.ActivityManager; +import android.content.Context; +import android.hardware.biometrics.BiometricsProtoEnums; +import android.hardware.biometrics.fingerprint.IFingerprint; +import android.hardware.biometrics.fingerprint.SensorProps; +import android.hardware.fingerprint.Fingerprint; +import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; +import android.hardware.fingerprint.IFingerprintServiceReceiver; +import android.hardware.fingerprint.IUdfpsOverlayController; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Slog; +import android.util.SparseArray; +import android.view.Surface; + +import com.android.server.biometrics.sensors.ClientMonitor; +import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; +import com.android.server.biometrics.sensors.LockoutResetDispatcher; +import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils; +import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher; +import com.android.server.biometrics.sensors.fingerprint.ServiceProvider; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; + +/** + * Provider for a single instance of the {@link IFingerprint} HAL. + */ +public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvider { + + @NonNull private final Context mContext; + @NonNull private final String mHalInstanceName; + @NonNull private final SparseArray mSensors; // Map of sensors that this HAL supports + @NonNull private final ClientMonitor.LazyDaemon mLazyDaemon; + @NonNull private final Handler mHandler; + + @Nullable private IUdfpsOverlayController mUdfpsOverlayController; + + public FingerprintProvider(@NonNull Context context, @NonNull SensorProps[] props, + @NonNull String halInstanceName, @NonNull LockoutResetDispatcher lockoutResetDispatcher, + @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { + mContext = context; + mHalInstanceName = halInstanceName; + mSensors = new SparseArray<>(); + mLazyDaemon = this::getHalInstance; + mHandler = new Handler(Looper.getMainLooper()); + + for (SensorProps prop : props) { + final int sensorId = prop.commonProps.sensorId; + + final FingerprintSensorPropertiesInternal internalProp = + new FingerprintSensorPropertiesInternal(prop.commonProps.sensorId, + prop.commonProps.sensorStrength, + prop.commonProps.maxEnrollmentsPerUser, + prop.sensorType, + true /* resetLockoutRequiresHardwareAuthToken */); + final Sensor sensor = new Sensor(getTag() + "/" + sensorId, internalProp, + gestureAvailabilityDispatcher); + + mSensors.put(sensorId, sensor); + Slog.d(getTag(), "Added: " + internalProp); + } + } + + private String getTag() { + return "FingerprintProvider/" + mHalInstanceName; + } + + @Nullable + private synchronized IFingerprint getHalInstance() { + final IFingerprint daemon = IFingerprint.Stub.asInterface( + ServiceManager.waitForDeclaredService(mHalInstanceName)); + if (daemon == null) { + Slog.e(getTag(), "Unable to get daemon"); + return null; + } + + try { + daemon.asBinder().linkToDeath(this, 0 /* flags */); + } catch (RemoteException e) { + Slog.e(getTag(), "Unable to linkToDeath", e); + } + + for (int i = 0; i < mSensors.size(); i++) { + final int sensorId = mSensors.keyAt(i); + scheduleLoadAuthenticatorIds(sensorId); + scheduleInternalCleanup(sensorId, ActivityManager.getCurrentUser()); + } + + return daemon; + } + + private void scheduleForSensor(int sensorId, @NonNull ClientMonitor client) { + if (!mSensors.contains(sensorId)) { + throw new IllegalStateException("Unable to schedule client: " + client + + " for sensor: " + sensorId); + } + mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client); + } + + private void scheduleForSensor(int sensorId, @NonNull ClientMonitor client, + ClientMonitor.Callback callback) { + if (!mSensors.contains(sensorId)) { + throw new IllegalStateException("Unable to schedule client: " + client + + " for sensor: " + sensorId); + } + mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client, callback); + } + + private void scheduleCreateSessionWithoutHandler(@NonNull IFingerprint daemon, int sensorId, + int userId) throws RemoteException { + // Note that per IFingerprint createSession contract, this method will block until all + // existing operations are canceled/finished. However, also note that this is fine, since + // this method "withoutHandler" means it should only ever be invoked from the worker thread, + // so callers will never be blocked. + mSensors.get(sensorId).createNewSession(daemon, sensorId, userId); + } + + private void scheduleLoadAuthenticatorIdsWithoutHandler(int sensorId) { + + } + + private void scheduleLoadAuthenticatorIds(int sensorId) { + + } + + @Override + public boolean containsSensor(int sensorId) { + return mSensors.contains(sensorId); + } + + @NonNull + @Override + public List getSensorProperties() { + List props = new ArrayList<>(); + for (int i = 0; i < mSensors.size(); i++) { + props.add(mSensors.valueAt(i).getSensorProperties()); + } + return props; + } + + @Override + public void scheduleResetLockout(int sensorId, int userId, @Nullable byte[] hardwareAuthToken) { + + } + + @Override + public void scheduleGenerateChallenge(int sensorId, @NonNull IBinder token, + @NonNull IFingerprintServiceReceiver receiver, String opPackageName) { + mHandler.post(() -> { + final FingerprintGenerateChallengeClient client = + new FingerprintGenerateChallengeClient(mContext, mLazyDaemon, token, + new ClientMonitorCallbackConverter(receiver), opPackageName, sensorId); + mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client); + }); + } + + @Override + public void scheduleRevokeChallenge(int sensorId, @NonNull IBinder token, + @NonNull String opPackageName) { + + } + + @Override + public void scheduleEnroll(int sensorId, @NonNull IBinder token, byte[] hardwareAuthToken, + int userId, @NonNull IFingerprintServiceReceiver receiver, + @NonNull String opPackageName, @Nullable Surface surface) { + mHandler.post(() -> { + final IFingerprint daemon = getHalInstance(); + if (daemon == null) { + Slog.e(getTag(), "Null daemon during enroll, sensorId: " + sensorId); + return; + } + + try { + if (!mSensors.get(sensorId).hasSessionForUser(userId)) { + scheduleCreateSessionWithoutHandler(daemon, sensorId, userId); + } + + final int maxTemplatesPerUser = mSensors.get(sensorId).getSensorProperties() + .maxEnrollmentsPerUser; + final FingerprintEnrollClient client = new FingerprintEnrollClient(mContext, + mSensors.get(sensorId).getLazySession(), token, + new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken, + opPackageName, FingerprintUtils.getInstance(), + BiometricsProtoEnums.MODALITY_FINGERPRINT, sensorId, + mUdfpsOverlayController, maxTemplatesPerUser); + scheduleForSensor(sensorId, client, new ClientMonitor.Callback() { + @Override + public void onClientFinished(@NonNull ClientMonitor clientMonitor, + boolean success) { + if (success) { + scheduleLoadAuthenticatorIdsWithoutHandler(sensorId); + } + } + }); + } catch (RemoteException e) { + Slog.e(getTag(), "Remote exception when scheduling enroll", e); + } + }); + } + + @Override + public void cancelEnrollment(int sensorId, @NonNull IBinder token) { + + } + + @Override + public void scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId, + @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName, + @Nullable Surface surface, int statsClient) { + + } + + @Override + public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, + int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback, + @NonNull String opPackageName, boolean restricted, int statsClient, + boolean isKeyguard) { + + } + + @Override + public void startPreparedClient(int sensorId, int cookie) { + + } + + @Override + public void cancelAuthentication(int sensorId, @NonNull IBinder token) { + + } + + @Override + public void scheduleRemove(int sensorId, @NonNull IBinder token, + @NonNull IFingerprintServiceReceiver receiver, int fingerId, int userId, + @NonNull String opPackageName) { + + } + + @Override + public void scheduleInternalCleanup(int userId, int sensorId) { + + } + + @Override + public boolean isHardwareDetected(int sensorId) { + return false; + } + + @Override + public void rename(int sensorId, int fingerId, int userId, @NonNull String name) { + + } + + @NonNull + @Override + public List getEnrolledFingerprints(int sensorId, int userId) { + return new ArrayList<>(); + } + + @Override + public int getLockoutModeForUser(int sensorId, int userId) { + return 0; + } + + @Override + public long getAuthenticatorId(int sensorId, int userId) { + return 0; + } + + @Override + public void onPointerDown(int sensorId, int x, int y, float minor, float major) { + + } + + @Override + public void onPointerUp(int sensorId) { + + } + + @Override + public void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller) { + mUdfpsOverlayController = controller; + } + + @Override + public void dumpProto(int sensorId, @NonNull FileDescriptor fd) { + + } + + @Override + public void dumpInternal(int sensorId, @NonNull PrintWriter pw) { + + } + + @Override + public void binderDied() { + + } +} diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java new file mode 100644 index 0000000000000..4151f5a828114 --- /dev/null +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java @@ -0,0 +1,163 @@ +/* + * 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.fingerprint.aidl; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.hardware.biometrics.fingerprint.IFingerprint; +import android.hardware.biometrics.fingerprint.ISession; +import android.hardware.biometrics.fingerprint.ISessionCallback; +import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; +import android.hardware.keymaster.HardwareAuthToken; +import android.os.RemoteException; +import android.util.Slog; + +import com.android.server.biometrics.sensors.BiometricScheduler; +import com.android.server.biometrics.sensors.ClientMonitor; +import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher; + +/** + * Maintains the state of a single sensor within an instance of the + * {@link android.hardware.biometrics.fingerprint.IFingerprint} HAL. + */ +class Sensor { + @NonNull private final String mTag; + @NonNull private final FingerprintSensorPropertiesInternal mSensorProperties; + @NonNull private final BiometricScheduler mScheduler; + + @Nullable private Session mCurrentSession; // TODO: Death recipient + @NonNull private final ClientMonitor.LazyDaemon mLazySession; + + private static class Session { + @NonNull private final String mTag; + @NonNull private final ISession mSession; + private final int mUserId; + private final ISessionCallback mSessionCallback; + + Session(@NonNull String tag, @NonNull ISession session, int userId, + @NonNull ISessionCallback sessionCallback) { + mTag = tag; + mSession = session; + mUserId = userId; + mSessionCallback = sessionCallback; + Slog.d(mTag, "New session created for user: " + userId); + } + } + + Sensor(@NonNull String tag, + @NonNull FingerprintSensorPropertiesInternal sensorProperties, + @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { + mTag = tag; + mSensorProperties = sensorProperties; + mScheduler = new BiometricScheduler(tag, gestureAvailabilityDispatcher); + mLazySession = () -> mCurrentSession != null ? mCurrentSession.mSession : null; + } + + @NonNull ClientMonitor.LazyDaemon getLazySession() { + return mLazySession; + } + + @NonNull FingerprintSensorPropertiesInternal getSensorProperties() { + return mSensorProperties; + } + + boolean hasSessionForUser(int userId) { + return mCurrentSession != null && mCurrentSession.mUserId == userId; + } + + void createNewSession(@NonNull IFingerprint daemon, int sensorId, int userId) + throws RemoteException { + final ISessionCallback callback = new ISessionCallback.Stub() { + @Override + public void onStateChanged(int cookie, byte state) { + + } + + @Override + public void onAcquired(byte info, int vendorCode) { + + } + + @Override + public void onError(byte error, int vendorCode) { + + } + + @Override + public void onEnrollmentProgress(int enrollmentId, int remaining) { + + } + + @Override + public void onAuthenticationSucceeded(int enrollmentId, HardwareAuthToken hat) { + + } + + @Override + public void onAuthenticationFailed() { + + } + + @Override + public void onLockoutTimed(long durationMillis) { + + } + + @Override + public void onLockoutPermanent() { + + } + + @Override + public void onLockoutCleared() { + + } + + @Override + public void onInteractionDetected() { + + } + + @Override + public void onEnrollmentsEnumerated(int[] enrollmentIds) { + + } + + @Override + public void onEnrollmentsRemoved(int[] enrollmentIds) { + + } + + @Override + public void onAuthenticatorIdRetrieved(long authenticatorId) { + + } + + @Override + public void onAuthenticatorIdInvalidated() { + + } + }; + + final ISession newSession = daemon.createSession(sensorId, userId, callback); + mCurrentSession = new Session(mTag, newSession, userId, callback); + } + + @NonNull BiometricScheduler getScheduler() { + return mScheduler; + } +} 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 f890f57eb47bf..89d1d160bb3af 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 @@ -68,6 +68,7 @@ import com.android.server.biometrics.sensors.RemovalConsumer; import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils; import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher; import com.android.server.biometrics.sensors.fingerprint.ServiceProvider; +import com.android.server.biometrics.sensors.fingerprint.Udfps; import org.json.JSONArray; import org.json.JSONException; @@ -634,6 +635,11 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider }); } + @Override + public void scheduleInternalCleanup(int userId, int sensorId) { + scheduleInternalCleanup(userId); + } + @Override public boolean isHardwareDetected(int sensorId) { final IBiometricsFingerprint daemon = getDaemon(); @@ -664,25 +670,25 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider } @Override - public void onFingerDown(int sensorId, int x, int y, float minor, float major) { + public void onPointerDown(int sensorId, int x, int y, float minor, float major) { final ClientMonitor client = mScheduler.getCurrentClient(); if (!(client instanceof Udfps)) { Slog.w(TAG, "onFingerDown received during client: " + client); return; } final Udfps udfps = (Udfps) client; - udfps.onFingerDown(x, y, minor, major); + udfps.onPointerDown(x, y, minor, major); } @Override - public void onFingerUp(int sensorId) { + public void onPointerUp(int sensorId) { final ClientMonitor client = mScheduler.getCurrentClient(); if (!(client instanceof Udfps)) { Slog.w(TAG, "onFingerDown received during client: " + client); return; } final Udfps udfps = (Udfps) client; - udfps.onFingerUp(); + udfps.onPointerUp(); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java index 5dda5a8495c2a..e4933e40ccd53 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java @@ -461,7 +461,7 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage } @Override - public void onFingerDown(int sensorId, int x, int y, float minor, float major) { + public void onPointerDown(int sensorId, int x, int y, float minor, float major) { mHandler.post(() -> { Slog.d(TAG, "onFingerDown"); final AuthenticationConsumer lastAuthenticatedConsumer = @@ -508,7 +508,7 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage } @Override - public void onFingerUp(int sensorId) { + public void onPointerUp(int sensorId) { mHandler.post(() -> { Slog.d(TAG, "onFingerUp"); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java index 0658f957fecbe..46605d1a2d2b6 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java @@ -33,6 +33,8 @@ import android.util.Slog; import com.android.server.biometrics.sensors.AuthenticationClient; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.LockoutTracker; +import com.android.server.biometrics.sensors.fingerprint.Udfps; +import com.android.server.biometrics.sensors.fingerprint.UdfpsHelper; import java.util.ArrayList; @@ -138,12 +140,12 @@ class FingerprintAuthenticationClient extends AuthenticationClient } @Override - public void onFingerDown(int x, int y, float minor, float major) { + public void onPointerDown(int x, int y, float minor, float major) { UdfpsHelper.onFingerDown(getFreshDaemon(), x, y, minor, major); } @Override - public void onFingerUp() { + public void onPointerUp() { UdfpsHelper.onFingerUp(getFreshDaemon()); } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java index b1030bf367e87..975ac3d6f2bfe 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java @@ -30,6 +30,8 @@ import android.util.Slog; 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.fingerprint.Udfps; +import com.android.server.biometrics.sensors.fingerprint.UdfpsHelper; /** * Fingerprint-specific enroll client supporting the @@ -97,12 +99,12 @@ public class FingerprintEnrollClient extends EnrollClient