Loading services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java +2 −1 Original line number Diff line number Diff line Loading @@ -89,7 +89,8 @@ public final class ClientMonitorCallbackConverter { } } void onError(int sensorId, int cookie, int error, int vendorCode) throws RemoteException { public void onError(int sensorId, int cookie, int error, int vendorCode) throws RemoteException { if (mSensorReceiver != null) { mSensorReceiver.onError(sensorId, cookie, error, vendorCode); } else if (mFaceServiceReceiver != null) { Loading services/core/java/com/android/server/biometrics/sensors/LockoutConsumer.java 0 → 100644 +25 −0 Original line number Diff line number Diff line /* * 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; /** * Interface that clients interested/eligible for lockout events should implement. */ public interface LockoutConsumer { void onLockoutTimed(long durationMillis); void onLockoutPermanent(); } services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java 0 → 100644 +152 −0 Original line number Diff line number Diff line /* * 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.TaskStackListener; import android.content.Context; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricFingerprintConstants; import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.common.ICancellationSignal; import android.hardware.biometrics.fingerprint.ISession; import android.hardware.fingerprint.IUdfpsOverlayController; import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; import com.android.server.biometrics.sensors.AuthenticationClient; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.LockoutConsumer; 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; /** * Fingerprint-specific authentication client supporting the * {@link android.hardware.biometrics.fingerprint.IFingerprint} AIDL interface. */ public class FingerprintAuthenticationClient extends AuthenticationClient<ISession> implements Udfps, LockoutConsumer { private static final String TAG = "FingerprintAuthenticationClient"; @NonNull private final LockoutCache mLockoutCache; @Nullable private final IUdfpsOverlayController mUdfpsOverlayController; @Nullable private ICancellationSignal mCancellationSignal; public FingerprintAuthenticationClient(@NonNull Context context, @NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId, boolean restricted, @NonNull String owner, int cookie, boolean requireConfirmation, int sensorId, boolean isStrongBiometric, int statsClient, @Nullable TaskStackListener taskStackListener, @NonNull LockoutCache lockoutCache, @Nullable IUdfpsOverlayController udfpsOverlayController) { super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted, owner, cookie, requireConfirmation, sensorId, isStrongBiometric, BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener, lockoutCache); mLockoutCache = lockoutCache; mUdfpsOverlayController = udfpsOverlayController; } @Override public void onAuthenticated(BiometricAuthenticator.Identifier identifier, boolean authenticated, ArrayList<Byte> token) { super.onAuthenticated(identifier, authenticated, token); if (authenticated) { UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController); mCallback.onClientFinished(this, true /* success */); } } @Override protected void startHalOperation() { UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController); try { mCancellationSignal = getFreshDaemon().authenticate(mSequentialId, mOperationId); } catch (RemoteException e) { Slog.e(TAG, "Remote exception", e); onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */); UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController); mCallback.onClientFinished(this, false /* success */); } } @Override protected void stopHalOperation() { UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController); try { mCancellationSignal.cancel(); } catch (RemoteException e) { Slog.e(TAG, "Remote exception", e); onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE, 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, "Remote exception", e); } } @Override public void onPointerUp() { try { getFreshDaemon().onPointerUp(0 /* pointerId */); } catch (RemoteException e) { Slog.e(TAG, "Remote exception", e); } } @Override public void onLockoutTimed(long durationMillis) { mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_TIMED); // Lockout metrics are logged as an error code. final int error = BiometricFingerprintConstants.FINGERPRINT_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 = BiometricFingerprintConstants.FINGERPRINT_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); } } } services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java +98 −17 Original line number Diff line number Diff line Loading @@ -19,12 +19,14 @@ package com.android.server.biometrics.sensors.fingerprint.aidl; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.app.IActivityTaskManager; import android.app.TaskStackListener; 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.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.hardware.fingerprint.IFingerprintServiceReceiver; import android.hardware.fingerprint.IUdfpsOverlayController; Loading @@ -37,12 +39,15 @@ import android.util.Slog; import android.util.SparseArray; import android.view.Surface; import com.android.server.biometrics.Utils; import com.android.server.biometrics.sensors.AuthenticationClient; 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 com.android.server.biometrics.sensors.fingerprint.Udfps; import java.io.FileDescriptor; import java.io.PrintWriter; Loading @@ -52,6 +57,7 @@ import java.util.List; /** * Provider for a single instance of the {@link IFingerprint} HAL. */ @SuppressWarnings("deprecation") public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvider { @NonNull private final Context mContext; Loading @@ -60,9 +66,48 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @NonNull private final ClientMonitor.LazyDaemon<IFingerprint> mLazyDaemon; @NonNull private final Handler mHandler; @NonNull private final LockoutResetDispatcher mLockoutResetDispatcher; @NonNull private final IActivityTaskManager mActivityTaskManager; @NonNull private final BiometricTaskStackListener mTaskStackListener; @Nullable private IUdfpsOverlayController mUdfpsOverlayController; private final class BiometricTaskStackListener extends TaskStackListener { @Override public void onTaskStackChanged() { mHandler.post(() -> { for (int i = 0; i < mSensors.size(); i++) { final ClientMonitor<?> client = mSensors.get(i).getScheduler() .getCurrentClient(); if (!(client instanceof AuthenticationClient)) { Slog.e(getTag(), "Task stack changed for client: " + client); continue; } if (Utils.isKeyguard(mContext, client.getOwnerString())) { continue; // Keyguard is always allowed } try { final List<ActivityManager.RunningTaskInfo> runningTasks = mActivityTaskManager.getTasks(1); if (!runningTasks.isEmpty()) { final String topPackage = runningTasks.get(0).topActivity.getPackageName(); if (!topPackage.contentEquals(client.getOwnerString()) && !client.isAlreadyDone()) { Slog.e(getTag(), "Stopping background authentication, top: " + topPackage + " currentClient: " + client); mSensors.get(i).getScheduler() .cancelAuthentication(client.getToken()); } } } catch (RemoteException e) { Slog.e(getTag(), "Unable to get running tasks", e); } } }); } } public FingerprintProvider(@NonNull Context context, @NonNull SensorProps[] props, @NonNull String halInstanceName, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { Loading @@ -72,6 +117,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi mLazyDaemon = this::getHalInstance; mHandler = new Handler(Looper.getMainLooper()); mLockoutResetDispatcher = lockoutResetDispatcher; mActivityTaskManager = ActivityTaskManager.getService(); mTaskStackListener = new BiometricTaskStackListener(); for (SensorProps prop : props) { final int sensorId = prop.commonProps.sensorId; Loading Loading @@ -135,7 +182,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client, callback); } private void scheduleCreateSessionWithoutHandler(@NonNull IFingerprint daemon, int sensorId, private void createNewSessionWithoutHandler(@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 Loading Loading @@ -178,7 +225,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi try { if (!mSensors.get(sensorId).hasSessionForUser(userId)) { scheduleCreateSessionWithoutHandler(daemon, sensorId, userId); createNewSessionWithoutHandler(daemon, sensorId, userId); } final FingerprintResetLockoutClient client = new FingerprintResetLockoutClient( Loading Loading @@ -222,19 +269,15 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi final IFingerprint daemon = getHalInstance(); if (daemon == null) { Slog.e(getTag(), "Null daemon during enroll, sensorId: " + sensorId); try { receiver.onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */); } catch (RemoteException e) { Slog.e(getTag(), "Unable to send HW_UNAVAILABLE", e); } // If this happens, we need to send HW_UNAVAILABLE after the scheduler gets to // this operation. We should not send the callback yet, since the scheduler may // be processing something else. return; } try { if (!mSensors.get(sensorId).hasSessionForUser(userId)) { scheduleCreateSessionWithoutHandler(daemon, sensorId, userId); createNewSessionWithoutHandler(daemon, sensorId, userId); } final int maxTemplatesPerUser = mSensors.get(sensorId).getSensorProperties() Loading Loading @@ -262,7 +305,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @Override public void cancelEnrollment(int sensorId, @NonNull IBinder token) { mHandler.post(() -> mSensors.get(sensorId).getScheduler().cancelEnrollment(token)); } @Override Loading @@ -277,17 +320,43 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName, boolean restricted, int statsClient, boolean isKeyguard) { mHandler.post(() -> { final IFingerprint daemon = getHalInstance(); if (daemon == null) { Slog.e(getTag(), "Null daemon during authenticate, sensorId: " + sensorId); // If this happens, we need to send HW_UNAVAILABLE after the scheduler gets to // this operation. We should not send the callback yet, since the scheduler may // be processing something else. return; } try { if (!mSensors.get(sensorId).hasSessionForUser(userId)) { createNewSessionWithoutHandler(daemon, sensorId, userId); } final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId); final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient( mContext, mSensors.get(sensorId).getLazySession(), token, callback, userId, operationId, restricted, opPackageName, cookie, false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient, mTaskStackListener, mSensors.get(sensorId).getLockoutCache(), mUdfpsOverlayController); mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client); } catch (RemoteException e) { Slog.e(getTag(), "Remote exception when scheduling authenticate", e); } }); } @Override public void startPreparedClient(int sensorId, int cookie) { mHandler.post(() -> mSensors.get(sensorId).getScheduler().startPreparedClient(cookie)); } @Override public void cancelAuthentication(int sensorId, @NonNull IBinder token) { mHandler.post(() -> mSensors.get(sensorId).getScheduler().cancelAuthentication(token)); } @Override Loading Loading @@ -320,7 +389,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @Override public int getLockoutModeForUser(int sensorId, int userId) { return 0; return mSensors.get(sensorId).getLockoutCache().getLockoutModeForUser(userId); } @Override Loading @@ -330,12 +399,24 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @Override public void onPointerDown(int sensorId, int x, int y, float minor, float major) { final ClientMonitor<?> client = mSensors.get(sensorId).getScheduler().getCurrentClient(); if (!(client instanceof Udfps)) { Slog.e(getTag(), "onPointerDown received during client: " + client); return; } final Udfps udfps = (Udfps) client; udfps.onPointerDown(x, y, minor, major); } @Override public void onPointerUp(int sensorId) { final ClientMonitor<?> client = mSensors.get(sensorId).getScheduler().getCurrentClient(); if (!(client instanceof Udfps)) { Slog.e(getTag(), "onPointerUp received during client: " + client); return; } final Udfps udfps = (Udfps) client; udfps.onPointerUp(); } @Override Loading services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java +21 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import com.android.server.biometrics.sensors.AuthenticationConsumer; import com.android.server.biometrics.sensors.BiometricScheduler; import com.android.server.biometrics.sensors.ClientMonitor; import com.android.server.biometrics.sensors.Interruptable; import com.android.server.biometrics.sensors.LockoutConsumer; import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils; import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher; Loading Loading @@ -209,12 +210,32 @@ class Sensor { @Override public void onLockoutTimed(long durationMillis) { mHandler.post(() -> { final ClientMonitor<?> client = mScheduler.getCurrentClient(); if (!(client instanceof LockoutConsumer)) { Slog.e(mTag, "onLockoutTimed for non-lockout consumer: " + Utils.getClientName(client)); return; } final LockoutConsumer lockoutConsumer = (LockoutConsumer) client; lockoutConsumer.onLockoutTimed(durationMillis); }); } @Override public void onLockoutPermanent() { mHandler.post(() -> { final ClientMonitor<?> client = mScheduler.getCurrentClient(); if (!(client instanceof LockoutConsumer)) { Slog.e(mTag, "onLockoutPermanent for non-lockout consumer: " + Utils.getClientName(client)); return; } final LockoutConsumer lockoutConsumer = (LockoutConsumer) client; lockoutConsumer.onLockoutPermanent(); }); } @Override Loading Loading
services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java +2 −1 Original line number Diff line number Diff line Loading @@ -89,7 +89,8 @@ public final class ClientMonitorCallbackConverter { } } void onError(int sensorId, int cookie, int error, int vendorCode) throws RemoteException { public void onError(int sensorId, int cookie, int error, int vendorCode) throws RemoteException { if (mSensorReceiver != null) { mSensorReceiver.onError(sensorId, cookie, error, vendorCode); } else if (mFaceServiceReceiver != null) { Loading
services/core/java/com/android/server/biometrics/sensors/LockoutConsumer.java 0 → 100644 +25 −0 Original line number Diff line number Diff line /* * 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; /** * Interface that clients interested/eligible for lockout events should implement. */ public interface LockoutConsumer { void onLockoutTimed(long durationMillis); void onLockoutPermanent(); }
services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java 0 → 100644 +152 −0 Original line number Diff line number Diff line /* * 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.TaskStackListener; import android.content.Context; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricFingerprintConstants; import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.common.ICancellationSignal; import android.hardware.biometrics.fingerprint.ISession; import android.hardware.fingerprint.IUdfpsOverlayController; import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; import com.android.server.biometrics.sensors.AuthenticationClient; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.LockoutConsumer; 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; /** * Fingerprint-specific authentication client supporting the * {@link android.hardware.biometrics.fingerprint.IFingerprint} AIDL interface. */ public class FingerprintAuthenticationClient extends AuthenticationClient<ISession> implements Udfps, LockoutConsumer { private static final String TAG = "FingerprintAuthenticationClient"; @NonNull private final LockoutCache mLockoutCache; @Nullable private final IUdfpsOverlayController mUdfpsOverlayController; @Nullable private ICancellationSignal mCancellationSignal; public FingerprintAuthenticationClient(@NonNull Context context, @NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId, boolean restricted, @NonNull String owner, int cookie, boolean requireConfirmation, int sensorId, boolean isStrongBiometric, int statsClient, @Nullable TaskStackListener taskStackListener, @NonNull LockoutCache lockoutCache, @Nullable IUdfpsOverlayController udfpsOverlayController) { super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted, owner, cookie, requireConfirmation, sensorId, isStrongBiometric, BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener, lockoutCache); mLockoutCache = lockoutCache; mUdfpsOverlayController = udfpsOverlayController; } @Override public void onAuthenticated(BiometricAuthenticator.Identifier identifier, boolean authenticated, ArrayList<Byte> token) { super.onAuthenticated(identifier, authenticated, token); if (authenticated) { UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController); mCallback.onClientFinished(this, true /* success */); } } @Override protected void startHalOperation() { UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController); try { mCancellationSignal = getFreshDaemon().authenticate(mSequentialId, mOperationId); } catch (RemoteException e) { Slog.e(TAG, "Remote exception", e); onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */); UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController); mCallback.onClientFinished(this, false /* success */); } } @Override protected void stopHalOperation() { UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController); try { mCancellationSignal.cancel(); } catch (RemoteException e) { Slog.e(TAG, "Remote exception", e); onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE, 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, "Remote exception", e); } } @Override public void onPointerUp() { try { getFreshDaemon().onPointerUp(0 /* pointerId */); } catch (RemoteException e) { Slog.e(TAG, "Remote exception", e); } } @Override public void onLockoutTimed(long durationMillis) { mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_TIMED); // Lockout metrics are logged as an error code. final int error = BiometricFingerprintConstants.FINGERPRINT_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 = BiometricFingerprintConstants.FINGERPRINT_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); } } }
services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java +98 −17 Original line number Diff line number Diff line Loading @@ -19,12 +19,14 @@ package com.android.server.biometrics.sensors.fingerprint.aidl; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.app.IActivityTaskManager; import android.app.TaskStackListener; 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.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.hardware.fingerprint.IFingerprintServiceReceiver; import android.hardware.fingerprint.IUdfpsOverlayController; Loading @@ -37,12 +39,15 @@ import android.util.Slog; import android.util.SparseArray; import android.view.Surface; import com.android.server.biometrics.Utils; import com.android.server.biometrics.sensors.AuthenticationClient; 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 com.android.server.biometrics.sensors.fingerprint.Udfps; import java.io.FileDescriptor; import java.io.PrintWriter; Loading @@ -52,6 +57,7 @@ import java.util.List; /** * Provider for a single instance of the {@link IFingerprint} HAL. */ @SuppressWarnings("deprecation") public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvider { @NonNull private final Context mContext; Loading @@ -60,9 +66,48 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @NonNull private final ClientMonitor.LazyDaemon<IFingerprint> mLazyDaemon; @NonNull private final Handler mHandler; @NonNull private final LockoutResetDispatcher mLockoutResetDispatcher; @NonNull private final IActivityTaskManager mActivityTaskManager; @NonNull private final BiometricTaskStackListener mTaskStackListener; @Nullable private IUdfpsOverlayController mUdfpsOverlayController; private final class BiometricTaskStackListener extends TaskStackListener { @Override public void onTaskStackChanged() { mHandler.post(() -> { for (int i = 0; i < mSensors.size(); i++) { final ClientMonitor<?> client = mSensors.get(i).getScheduler() .getCurrentClient(); if (!(client instanceof AuthenticationClient)) { Slog.e(getTag(), "Task stack changed for client: " + client); continue; } if (Utils.isKeyguard(mContext, client.getOwnerString())) { continue; // Keyguard is always allowed } try { final List<ActivityManager.RunningTaskInfo> runningTasks = mActivityTaskManager.getTasks(1); if (!runningTasks.isEmpty()) { final String topPackage = runningTasks.get(0).topActivity.getPackageName(); if (!topPackage.contentEquals(client.getOwnerString()) && !client.isAlreadyDone()) { Slog.e(getTag(), "Stopping background authentication, top: " + topPackage + " currentClient: " + client); mSensors.get(i).getScheduler() .cancelAuthentication(client.getToken()); } } } catch (RemoteException e) { Slog.e(getTag(), "Unable to get running tasks", e); } } }); } } public FingerprintProvider(@NonNull Context context, @NonNull SensorProps[] props, @NonNull String halInstanceName, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { Loading @@ -72,6 +117,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi mLazyDaemon = this::getHalInstance; mHandler = new Handler(Looper.getMainLooper()); mLockoutResetDispatcher = lockoutResetDispatcher; mActivityTaskManager = ActivityTaskManager.getService(); mTaskStackListener = new BiometricTaskStackListener(); for (SensorProps prop : props) { final int sensorId = prop.commonProps.sensorId; Loading Loading @@ -135,7 +182,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client, callback); } private void scheduleCreateSessionWithoutHandler(@NonNull IFingerprint daemon, int sensorId, private void createNewSessionWithoutHandler(@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 Loading Loading @@ -178,7 +225,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi try { if (!mSensors.get(sensorId).hasSessionForUser(userId)) { scheduleCreateSessionWithoutHandler(daemon, sensorId, userId); createNewSessionWithoutHandler(daemon, sensorId, userId); } final FingerprintResetLockoutClient client = new FingerprintResetLockoutClient( Loading Loading @@ -222,19 +269,15 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi final IFingerprint daemon = getHalInstance(); if (daemon == null) { Slog.e(getTag(), "Null daemon during enroll, sensorId: " + sensorId); try { receiver.onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */); } catch (RemoteException e) { Slog.e(getTag(), "Unable to send HW_UNAVAILABLE", e); } // If this happens, we need to send HW_UNAVAILABLE after the scheduler gets to // this operation. We should not send the callback yet, since the scheduler may // be processing something else. return; } try { if (!mSensors.get(sensorId).hasSessionForUser(userId)) { scheduleCreateSessionWithoutHandler(daemon, sensorId, userId); createNewSessionWithoutHandler(daemon, sensorId, userId); } final int maxTemplatesPerUser = mSensors.get(sensorId).getSensorProperties() Loading Loading @@ -262,7 +305,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @Override public void cancelEnrollment(int sensorId, @NonNull IBinder token) { mHandler.post(() -> mSensors.get(sensorId).getScheduler().cancelEnrollment(token)); } @Override Loading @@ -277,17 +320,43 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName, boolean restricted, int statsClient, boolean isKeyguard) { mHandler.post(() -> { final IFingerprint daemon = getHalInstance(); if (daemon == null) { Slog.e(getTag(), "Null daemon during authenticate, sensorId: " + sensorId); // If this happens, we need to send HW_UNAVAILABLE after the scheduler gets to // this operation. We should not send the callback yet, since the scheduler may // be processing something else. return; } try { if (!mSensors.get(sensorId).hasSessionForUser(userId)) { createNewSessionWithoutHandler(daemon, sensorId, userId); } final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId); final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient( mContext, mSensors.get(sensorId).getLazySession(), token, callback, userId, operationId, restricted, opPackageName, cookie, false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient, mTaskStackListener, mSensors.get(sensorId).getLockoutCache(), mUdfpsOverlayController); mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client); } catch (RemoteException e) { Slog.e(getTag(), "Remote exception when scheduling authenticate", e); } }); } @Override public void startPreparedClient(int sensorId, int cookie) { mHandler.post(() -> mSensors.get(sensorId).getScheduler().startPreparedClient(cookie)); } @Override public void cancelAuthentication(int sensorId, @NonNull IBinder token) { mHandler.post(() -> mSensors.get(sensorId).getScheduler().cancelAuthentication(token)); } @Override Loading Loading @@ -320,7 +389,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @Override public int getLockoutModeForUser(int sensorId, int userId) { return 0; return mSensors.get(sensorId).getLockoutCache().getLockoutModeForUser(userId); } @Override Loading @@ -330,12 +399,24 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @Override public void onPointerDown(int sensorId, int x, int y, float minor, float major) { final ClientMonitor<?> client = mSensors.get(sensorId).getScheduler().getCurrentClient(); if (!(client instanceof Udfps)) { Slog.e(getTag(), "onPointerDown received during client: " + client); return; } final Udfps udfps = (Udfps) client; udfps.onPointerDown(x, y, minor, major); } @Override public void onPointerUp(int sensorId) { final ClientMonitor<?> client = mSensors.get(sensorId).getScheduler().getCurrentClient(); if (!(client instanceof Udfps)) { Slog.e(getTag(), "onPointerUp received during client: " + client); return; } final Udfps udfps = (Udfps) client; udfps.onPointerUp(); } @Override Loading
services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java +21 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import com.android.server.biometrics.sensors.AuthenticationConsumer; import com.android.server.biometrics.sensors.BiometricScheduler; import com.android.server.biometrics.sensors.ClientMonitor; import com.android.server.biometrics.sensors.Interruptable; import com.android.server.biometrics.sensors.LockoutConsumer; import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils; import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher; Loading Loading @@ -209,12 +210,32 @@ class Sensor { @Override public void onLockoutTimed(long durationMillis) { mHandler.post(() -> { final ClientMonitor<?> client = mScheduler.getCurrentClient(); if (!(client instanceof LockoutConsumer)) { Slog.e(mTag, "onLockoutTimed for non-lockout consumer: " + Utils.getClientName(client)); return; } final LockoutConsumer lockoutConsumer = (LockoutConsumer) client; lockoutConsumer.onLockoutTimed(durationMillis); }); } @Override public void onLockoutPermanent() { mHandler.post(() -> { final ClientMonitor<?> client = mScheduler.getCurrentClient(); if (!(client instanceof LockoutConsumer)) { Slog.e(mTag, "onLockoutPermanent for non-lockout consumer: " + Utils.getClientName(client)); return; } final LockoutConsumer lockoutConsumer = (LockoutConsumer) client; lockoutConsumer.onLockoutPermanent(); }); } @Override Loading