From 0cab3b4252cf66d02d0683c9220251a5266de8c3 Mon Sep 17 00:00:00 2001 From: Joe Bolinger Date: Tue, 1 Mar 2022 01:21:12 +0000 Subject: [PATCH] Invoke lifecycle callbacks while waiting for cookies. Operations that wait for cookies (authentication) do not set their lifecycle callback until started. This leaves a small window when failures are not propogated to callers (i.e. fast/immediate failures). This also adds some additional checking for stale UI events (point up/down) that are delivered after the operation has ended. Fix: 216071532 Test: atest com.android.systemui.biometrics com.android.server.biometrics Change-Id: I7f7500db0a42b2ea97e171e26148ee68b15f5ae8 --- .../fingerprint/FingerprintManager.java | 13 ++-- .../fingerprint/IFingerprintService.aidl | 6 +- .../fingerprint/IUdfpsOverlayController.aidl | 2 +- .../systemui/biometrics/UdfpsController.java | 59 ++++++++++------ .../biometrics/UdfpsControllerOverlay.kt | 4 ++ .../biometrics/UdfpsControllerOverlayTest.kt | 10 ++- .../biometrics/UdfpsControllerTest.java | 70 ++++++++++++------- .../biometrics/sensors/BaseClientMonitor.java | 18 +++-- .../sensors/BiometricScheduler.java | 14 +++- .../sensors/BiometricSchedulerOperation.java | 5 +- .../biometrics/sensors/SensorOverlays.java | 3 +- .../fingerprint/FingerprintService.java | 13 ++-- .../sensors/fingerprint/ServiceProvider.java | 6 +- .../fingerprint/aidl/FingerprintProvider.java | 22 +++--- .../fingerprint/hidl/Fingerprint21.java | 22 +++--- .../hidl/Fingerprint21UdfpsMock.java | 5 +- .../BiometricSchedulerOperationTest.java | 66 +++++++++-------- .../sensors/BiometricSchedulerTest.java | 6 +- .../sensors/SensorOverlaysTest.java | 12 +++- .../FingerprintAuthenticationClientTest.java | 5 +- .../aidl/FingerprintEnrollClientTest.java | 5 +- 21 files changed, 227 insertions(+), 139 deletions(-) diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index 7e070bc06056c..29221b801ef6b 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -923,14 +923,15 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing * @hide */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) - public void onPointerDown(int sensorId, int x, int y, float minor, float major) { + public void onPointerDown(long requestId, int sensorId, int x, int y, + float minor, float major) { if (mService == null) { Slog.w(TAG, "onFingerDown: no fingerprint service"); return; } try { - mService.onPointerDown(sensorId, x, y, minor, major); + mService.onPointerDown(requestId, sensorId, x, y, minor, major); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -940,14 +941,14 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing * @hide */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) - public void onPointerUp(int sensorId) { + public void onPointerUp(long requestId, int sensorId) { if (mService == null) { Slog.w(TAG, "onFingerDown: no fingerprint service"); return; } try { - mService.onPointerUp(sensorId); + mService.onPointerUp(requestId, sensorId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -957,14 +958,14 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing * @hide */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) - public void onUiReady(int sensorId) { + public void onUiReady(long requestId, int sensorId) { if (mService == null) { Slog.w(TAG, "onUiReady: no fingerprint service"); return; } try { - mService.onUiReady(sensorId); + mService.onUiReady(requestId, sensorId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl index cbff8b11a72a6..12114aa3fa336 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl @@ -155,13 +155,13 @@ interface IFingerprintService { void addAuthenticatorsRegisteredCallback(IFingerprintAuthenticatorsRegisteredCallback callback); // Notifies about a finger touching the sensor area. - void onPointerDown(int sensorId, int x, int y, float minor, float major); + void onPointerDown(long requestId, int sensorId, int x, int y, float minor, float major); // Notifies about a finger leaving the sensor area. - void onPointerUp(int sensorId); + void onPointerUp(long requestId, int sensorId); // Notifies about the fingerprint UI being ready (e.g. HBM illumination is enabled). - void onUiReady(int sensorId); + void onUiReady(long requestId, int sensorId); // Sets the controller for managing the UDFPS overlay. void setUdfpsOverlayController(in IUdfpsOverlayController controller); diff --git a/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl b/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl index 3cca1b38e5e27..dbb8e40f3a717 100644 --- a/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl +++ b/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl @@ -23,7 +23,7 @@ import android.hardware.fingerprint.IUdfpsOverlayControllerCallback; */ oneway interface IUdfpsOverlayController { // Shows the overlay for the given sensor with a reason from BiometricOverlayConstants. - void showUdfpsOverlay(int sensorId, int reason, IUdfpsOverlayControllerCallback callback); + void showUdfpsOverlay(long requestId, int sensorId, int reason, IUdfpsOverlayControllerCallback callback); // Hides the overlay. void hideUdfpsOverlay(int sensorId); diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index bc7a3f6f4b13c..975e0c5b32cd0 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -49,7 +49,6 @@ import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.Surface; import android.view.VelocityTracker; -import android.view.View; import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; @@ -92,7 +91,7 @@ import kotlin.Unit; * 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#onPointerDown(int, int, int, float, float)} or + * as {@link FingerprintManager#onPointerDown(long, int, int, int, float, float)} or * {@link IUdfpsOverlayController#showUdfpsOverlay} should all have * {@code sensorId} parameters. */ @@ -193,7 +192,7 @@ public class UdfpsController implements DozeReceiver { public class UdfpsOverlayController extends IUdfpsOverlayController.Stub { @Override - public void showUdfpsOverlay(int sensorId, int reason, + public void showUdfpsOverlay(long requestId, int sensorId, int reason, @NonNull IUdfpsOverlayControllerCallback callback) { mFgExecutor.execute( () -> UdfpsController.this.showUdfpsOverlay(new UdfpsControllerOverlay( @@ -203,8 +202,10 @@ public class UdfpsController implements DozeReceiver { mKeyguardUpdateMonitor, mDialogManager, mDumpManager, mLockscreenShadeTransitionController, mConfigurationController, mSystemClock, mKeyguardStateController, - mUnlockedScreenOffAnimationController, mSensorProps, mHbmProvider, - reason, callback, UdfpsController.this::onTouch, + mUnlockedScreenOffAnimationController, mSensorProps, + mHbmProvider, requestId, reason, callback, + (view, event, fromUdfpsView) -> + onTouch(requestId, event, fromUdfpsView), mActivityLaunchAnimator))); } @@ -318,7 +319,8 @@ public class UdfpsController implements DozeReceiver { if (mOverlay == null || mOverlay.isHiding()) { return false; } - return onTouch(mOverlay.getOverlayView(), event, false); + // TODO(b/225068271): may not be correct but no way to get the id yet + return onTouch(mOverlay.getRequestId(), event, false); } /** @@ -342,8 +344,18 @@ public class UdfpsController implements DozeReceiver { && getSensorLocation().contains(x, y); } - private boolean onTouch(@NonNull View view, @NonNull MotionEvent event, boolean fromUdfpsView) { - UdfpsView udfpsView = (UdfpsView) view; + private boolean onTouch(long requestId, @NonNull MotionEvent event, boolean fromUdfpsView) { + if (mOverlay == null) { + Log.w(TAG, "ignoring onTouch with null overlay"); + return false; + } + if (!mOverlay.matchesRequestId(requestId)) { + Log.w(TAG, "ignoring stale touch event: " + requestId + " current: " + + mOverlay.getRequestId()); + return false; + } + + final UdfpsView udfpsView = mOverlay.getOverlayView(); final boolean isIlluminationRequested = udfpsView.isIlluminationRequested(); boolean handled = false; switch (event.getActionMasked()) { @@ -453,7 +465,7 @@ public class UdfpsController implements DozeReceiver { // Do nothing to stay in portrait mode. } - onFingerDown(x, y, minor, major); + onFingerDown(requestId, x, y, minor, major); Log.v(TAG, "onTouch | finger down: " + touchInfo); mTouchLogTime = mSystemClock.elapsedRealtime(); mPowerManager.userActivity(mSystemClock.uptimeMillis(), @@ -465,7 +477,7 @@ public class UdfpsController implements DozeReceiver { } } else { Log.v(TAG, "onTouch | finger outside"); - onFingerUp(udfpsView); + onFingerUp(requestId, udfpsView); } } Trace.endSection(); @@ -482,7 +494,7 @@ public class UdfpsController implements DozeReceiver { } Log.v(TAG, "onTouch | finger up"); mAttemptedToDismissKeyguard = false; - onFingerUp(udfpsView); + onFingerUp(requestId, udfpsView); mFalsingManager.isFalseTouch(UDFPS_AUTHENTICATION); Trace.endSection(); break; @@ -679,7 +691,7 @@ public class UdfpsController implements DozeReceiver { // Reset the controller back to its starting state. final UdfpsView oldView = mOverlay.getOverlayView(); if (oldView != null) { - onFingerUp(oldView); + onFingerUp(mOverlay.getRequestId(), oldView); } final boolean removed = mOverlay.hide(); if (mKeyguardViewManager.isShowingAlternateAuth()) { @@ -710,6 +722,8 @@ public class UdfpsController implements DozeReceiver { return; } + // TODO(b/225068271): this may not be correct but there isn't a way to track it + final long requestId = mOverlay != null ? mOverlay.getRequestId() : -1; mAodInterruptRunnable = () -> { mIsAodInterruptActive = true; // Since the sensor that triggers the AOD interrupt doesn't provide @@ -719,10 +733,10 @@ public class UdfpsController implements DozeReceiver { mCancelAodTimeoutAction = mFgExecutor.executeDelayed(this::onCancelUdfps, AOD_INTERRUPT_TIMEOUT_MILLIS); // using a hard-coded value for major and minor until it is available from the sensor - onFingerDown(screenX, screenY, minor, major); + onFingerDown(requestId, screenX, screenY, minor, major); }; - if (mScreenOn && mAodInterruptRunnable != null) { + if (mScreenOn) { mAodInterruptRunnable.run(); mAodInterruptRunnable = null; } @@ -755,7 +769,7 @@ public class UdfpsController implements DozeReceiver { */ void onCancelUdfps() { if (mOverlay != null && mOverlay.getOverlayView() != null) { - onFingerUp(mOverlay.getOverlayView()); + onFingerUp(mOverlay.getRequestId(), mOverlay.getOverlayView()); } if (!mIsAodInterruptActive) { return; @@ -771,12 +785,17 @@ public class UdfpsController implements DozeReceiver { return mOnFingerDown; } - private void onFingerDown(int x, int y, float minor, float major) { + private void onFingerDown(long requestId, int x, int y, float minor, float major) { mExecution.assertIsMainThread(); if (mOverlay == null) { Log.w(TAG, "Null request in onFingerDown"); return; } + if (!mOverlay.matchesRequestId(requestId)) { + Log.w(TAG, "Mismatched fingerDown: " + requestId + + " current: " + mOverlay.getRequestId()); + return; + } if (mOverlay.getAnimationViewController() instanceof UdfpsKeyguardViewController && !mStatusBarStateController.isDozing()) { @@ -791,14 +810,14 @@ public class UdfpsController implements DozeReceiver { } } mOnFingerDown = true; - mFingerprintManager.onPointerDown(mSensorProps.sensorId, x, y, minor, major); + mFingerprintManager.onPointerDown(requestId, mSensorProps.sensorId, x, y, minor, major); Trace.endAsyncSection("UdfpsController.e2e.onPointerDown", 0); final UdfpsView view = mOverlay.getOverlayView(); if (view != null) { Trace.beginAsyncSection("UdfpsController.e2e.startIllumination", 0); view.startIllumination(() -> { - mFingerprintManager.onUiReady(mSensorProps.sensorId); + mFingerprintManager.onUiReady(requestId, mSensorProps.sensorId); mLatencyTracker.onActionEnd(LatencyTracker.ACTION_UDFPS_ILLUMINATE); Trace.endAsyncSection("UdfpsController.e2e.startIllumination", 0); }); @@ -809,12 +828,12 @@ public class UdfpsController implements DozeReceiver { } } - private void onFingerUp(@NonNull UdfpsView view) { + private void onFingerUp(long requestId, @NonNull UdfpsView view) { mExecution.assertIsMainThread(); mActivePointerId = -1; mAcquiredReceived = false; if (mOnFingerDown) { - mFingerprintManager.onPointerUp(mSensorProps.sensorId); + mFingerprintManager.onPointerUp(requestId, mSensorProps.sensorId); for (Callback cb : mCallbacks) { cb.onFingerUp(); } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt index 086894d2e6705..ee43e932b344b 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt @@ -80,6 +80,7 @@ class UdfpsControllerOverlay( private val unlockedScreenOffAnimationController: UnlockedScreenOffAnimationController, private val sensorProps: FingerprintSensorPropertiesInternal, private var hbmProvider: UdfpsHbmProvider, + val requestId: Long, @ShowReason val requestReason: Int, private val controllerCallback: IUdfpsOverlayControllerCallback, private val onTouch: (View, MotionEvent, Boolean) -> Boolean, @@ -276,6 +277,9 @@ class UdfpsControllerOverlay( } } + /** Checks if the id is relevant for this overlay. */ + fun matchesRequestId(id: Long): Boolean = requestId == -1L || requestId == id + private fun WindowManager.LayoutParams.updateForLocation( location: SensorLocationInternal, animation: UdfpsAnimationViewController<*>? diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt index ef82c3ec3322f..fd49766dafef8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt @@ -61,6 +61,8 @@ import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit import org.mockito.Mockito.`when` as whenever +private const val REQUEST_ID = 2L + @SmallTest @RunWith(AndroidTestingRunner::class) @RunWithLooper(setAsMainLooper = true) @@ -119,7 +121,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { statusBarStateController, panelExpansionStateManager, statusBarKeyguardViewManager, keyguardUpdateMonitor, dialogManager, dumpManager, transitionController, configurationController, systemClock, keyguardStateController, - unlockedScreenOffAnimationController, sensorProps, hbmProvider, reason, + unlockedScreenOffAnimationController, sensorProps, hbmProvider, REQUEST_ID, reason, controllerCallback, onTouch, activityLaunchAnimator) block() } @@ -263,6 +265,12 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { controllerOverlay.hide() verify(udfpsView).stopIllumination() } + + @Test + fun matchesRequestIds() = withReason(REASON_AUTH_BP) { + assertThat(controllerOverlay.matchesRequestId(REQUEST_ID)).isTrue() + assertThat(controllerOverlay.matchesRequestId(REQUEST_ID + 1)).isFalse() + } } private class EnrollListener( 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 613931f1341f8..406ed5c17b0c6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java @@ -27,6 +27,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -102,6 +103,7 @@ public class UdfpsControllerTest extends SysuiTestCase { // Use this for inputs going into SystemUI. Use UdfpsController.mUdfpsSensorId for things // leaving SystemUI. private static final int TEST_UDFPS_SENSOR_ID = 1; + private static final long TEST_REQUEST_ID = 70; @Rule public MockitoRule rule = MockitoJUnit.rule(); @@ -278,7 +280,7 @@ public class UdfpsControllerTest extends SysuiTestCase { @Test public void dozeTimeTick() throws RemoteException { - mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID, BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); mFgExecutor.runAllReady(); mUdfpsController.dozeTimeTick(); @@ -293,7 +295,7 @@ public class UdfpsControllerTest extends SysuiTestCase { when(mUdfpsView.getAnimationViewController()).thenReturn(mUdfpsKeyguardViewController); // GIVEN that the overlay is showing - mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID, BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); mFgExecutor.runAllReady(); @@ -316,7 +318,7 @@ public class UdfpsControllerTest extends SysuiTestCase { when(mStatusBarStateController.isDozing()).thenReturn(true); // GIVEN that the overlay is showing - mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID, BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); mFgExecutor.runAllReady(); @@ -339,7 +341,7 @@ public class UdfpsControllerTest extends SysuiTestCase { when(mStatusBarStateController.isDozing()).thenReturn(false); // GIVEN that the overlay is showing - mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID, BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); mFgExecutor.runAllReady(); @@ -362,7 +364,7 @@ public class UdfpsControllerTest extends SysuiTestCase { (UdfpsAnimationViewController) mock(UdfpsEnrollViewController.class)); // GIVEN that the overlay is showing - mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID, BiometricOverlayConstants.REASON_ENROLL_ENROLLING, mUdfpsOverlayControllerCallback); mFgExecutor.runAllReady(); @@ -377,25 +379,42 @@ public class UdfpsControllerTest extends SysuiTestCase { } @Test - public void onActionMoveTouch_whenCanDismissLockScreen_entersDevice() throws RemoteException { + public void onActionMoveTouch_whenCanDismissLockScreen_entersDevice() + throws RemoteException { + onActionMoveTouch_whenCanDismissLockScreen_entersDevice(false /* stale */); + } + + @Test + public void onActionMoveTouch_whenCanDismissLockScreen_entersDevice_ignoreStale() + throws RemoteException { + onActionMoveTouch_whenCanDismissLockScreen_entersDevice(true /* stale */); + } + + public void onActionMoveTouch_whenCanDismissLockScreen_entersDevice(boolean stale) + throws RemoteException { // GIVEN can dismiss lock screen and the current animation is an UdfpsKeyguardViewController when(mKeyguardStateController.canDismissLockScreen()).thenReturn(true); when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true); when(mUdfpsView.getAnimationViewController()).thenReturn(mUdfpsKeyguardViewController); // GIVEN that the overlay is showing - mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID, BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); mFgExecutor.runAllReady(); // WHEN ACTION_MOVE is received verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture()); MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, 0, 0); + if (stale) { + mOverlayController.hideUdfpsOverlay(TEST_UDFPS_SENSOR_ID); + mFgExecutor.runAllReady(); + } mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); moveEvent.recycle(); // THEN notify keyguard authenticate to dismiss the keyguard - verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(anyBoolean()); + verify(mStatusBarKeyguardViewManager, stale ? never() : times(1)) + .notifyKeyguardAuthenticated(anyBoolean()); } @Test @@ -406,7 +425,7 @@ public class UdfpsControllerTest extends SysuiTestCase { when(mUdfpsView.getAnimationViewController()).thenReturn(mUdfpsKeyguardViewController); // GIVEN that the overlay is showing - mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID, BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); mFgExecutor.runAllReady(); @@ -427,7 +446,7 @@ public class UdfpsControllerTest extends SysuiTestCase { @Test public void hideUdfpsOverlay_resetsAltAuthBouncerWhenShowing() throws RemoteException { // GIVEN overlay was showing and the udfps bouncer is showing - mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID, BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); when(mStatusBarKeyguardViewManager.isShowingAlternateAuth()).thenReturn(true); @@ -441,7 +460,7 @@ public class UdfpsControllerTest extends SysuiTestCase { @Test public void testSubscribesToOrientationChangesWhenShowingOverlay() throws Exception { - mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID, BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); mFgExecutor.runAllReady(); @@ -460,7 +479,7 @@ public class UdfpsControllerTest extends SysuiTestCase { when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true); // GIVEN that the overlay is showing - mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID, BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); mFgExecutor.runAllReady(); // WHEN ACTION_DOWN is received @@ -472,8 +491,9 @@ public class UdfpsControllerTest extends SysuiTestCase { mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); moveEvent.recycle(); // THEN FingerprintManager is notified about onPointerDown - verify(mFingerprintManager).onPointerDown(eq(mUdfpsController.mSensorProps.sensorId), eq(0), - eq(0), eq(0f), eq(0f)); + verify(mFingerprintManager).onPointerDown(eq(TEST_REQUEST_ID), + eq(mUdfpsController.mSensorProps.sensorId), + eq(0), eq(0), eq(0f), eq(0f)); verify(mLatencyTracker).onActionStart(eq(LatencyTracker.ACTION_UDFPS_ILLUMINATE)); // AND illumination begins verify(mUdfpsView).startIllumination(mOnIlluminatedRunnableCaptor.capture()); @@ -481,14 +501,15 @@ public class UdfpsControllerTest extends SysuiTestCase { // AND onIlluminatedRunnable notifies FingerprintManager about onUiReady mOnIlluminatedRunnableCaptor.getValue().run(); InOrder inOrder = inOrder(mFingerprintManager, mLatencyTracker); - inOrder.verify(mFingerprintManager).onUiReady(eq(mUdfpsController.mSensorProps.sensorId)); + inOrder.verify(mFingerprintManager).onUiReady( + eq(TEST_REQUEST_ID), eq(mUdfpsController.mSensorProps.sensorId)); inOrder.verify(mLatencyTracker).onActionEnd(eq(LatencyTracker.ACTION_UDFPS_ILLUMINATE)); } @Test public void aodInterrupt() throws RemoteException { // GIVEN that the overlay is showing and screen is on and fp is running - mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID, BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); mScreenObserver.onScreenTurnedOn(); mFgExecutor.runAllReady(); @@ -499,14 +520,15 @@ public class UdfpsControllerTest extends SysuiTestCase { // AND onIlluminatedRunnable that notifies FingerprintManager is set verify(mUdfpsView).startIllumination(mOnIlluminatedRunnableCaptor.capture()); mOnIlluminatedRunnableCaptor.getValue().run(); - verify(mFingerprintManager).onPointerDown(eq(mUdfpsController.mSensorProps.sensorId), eq(0), - eq(0), eq(3f) /* minor */, eq(2f) /* major */); + verify(mFingerprintManager).onPointerDown(eq(TEST_REQUEST_ID), + eq(mUdfpsController.mSensorProps.sensorId), + eq(0), eq(0), eq(3f) /* minor */, eq(2f) /* major */); } @Test public void cancelAodInterrupt() throws RemoteException { // GIVEN AOD interrupt - mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID, BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); mScreenObserver.onScreenTurnedOn(); mFgExecutor.runAllReady(); @@ -522,7 +544,7 @@ public class UdfpsControllerTest extends SysuiTestCase { @Test public void aodInterruptTimeout() throws RemoteException { // GIVEN AOD interrupt - mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID, BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); mScreenObserver.onScreenTurnedOn(); mFgExecutor.runAllReady(); @@ -539,7 +561,7 @@ public class UdfpsControllerTest extends SysuiTestCase { @Test public void aodInterruptScreenOff() throws RemoteException { // GIVEN screen off - mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID, BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); mScreenObserver.onScreenTurnedOff(); mFgExecutor.runAllReady(); @@ -555,7 +577,7 @@ public class UdfpsControllerTest extends SysuiTestCase { @Test public void aodInterrupt_fingerprintNotRunning() throws RemoteException { // GIVEN showing overlay - mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID, BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); mScreenObserver.onScreenTurnedOn(); @@ -577,7 +599,7 @@ public class UdfpsControllerTest extends SysuiTestCase { // GIVEN that the overlay is showing and a11y touch exploration enabled when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(true); - mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID, BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); mFgExecutor.runAllReady(); @@ -612,7 +634,7 @@ public class UdfpsControllerTest extends SysuiTestCase { // GIVEN that the overlay is showing and a11y touch exploration NOT enabled when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(false); - mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID, BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback); mFgExecutor.runAllReady(); diff --git a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java index 1b2e606117e76..1370fd83f6a8b 100644 --- a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java +++ b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java @@ -38,7 +38,7 @@ import java.util.NoSuchElementException; */ public abstract class BaseClientMonitor implements IBinder.DeathRecipient { - private static final String TAG = "Biometrics/ClientMonitor"; + private static final String TAG = "BaseClientMonitor"; protected static final boolean DEBUG = true; // Counter used to distinguish between ClientMonitor instances to help debugging. @@ -119,9 +119,19 @@ public abstract class BaseClientMonitor implements IBinder.DeathRecipient { return false; } + /** + * Sets the lifecycle callback before the operation is started via + * {@link #start(ClientMonitorCallback)} when the client must wait for a cookie before starting. + * + * @param callback lifecycle callback (typically same callback used for starting the operation) + */ + public void waitForCookie(@NonNull ClientMonitorCallback callback) { + mCallback = callback; + } + /** * Starts the ClientMonitor's lifecycle. - * @param callback invoked when the operation is complete (succeeds, fails, etc) + * @param callback invoked when the operation is complete (succeeds, fails, etc.) */ public void start(@NonNull ClientMonitorCallback callback) { mCallback = wrapCallbackForStart(callback); @@ -246,12 +256,12 @@ public abstract class BaseClientMonitor implements IBinder.DeathRecipient { } /** Unique request id. */ - public final long getRequestId() { + public long getRequestId() { return mRequestId; } /** If a unique id has been set via {@link #setRequestId(long)} */ - public final boolean hasRequestId() { + public boolean hasRequestId() { return mRequestId > 0; } diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java index d0ec4470d3e6d..19a93f30937fd 100644 --- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java +++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java @@ -285,7 +285,7 @@ public class BiometricScheduler { // Not all operations start immediately. BiometricPrompt waits for its operation // to arrive at the head of the queue, before pinging it to start. - final int cookie = mCurrentOperation.isReadyToStart(); + final int cookie = mCurrentOperation.isReadyToStart(mInternalCallback); if (cookie == 0) { if (!mCurrentOperation.start(mInternalCallback)) { // Note down current length of queue @@ -463,6 +463,18 @@ public class BiometricScheduler { return mCurrentOperation != null ? mCurrentOperation.getClientMonitor() : null; } + /** The current operation if the requestId is set and matches. */ + @Deprecated + @Nullable + public BaseClientMonitor getCurrentClientIfMatches(long requestId) { + if (mCurrentOperation != null) { + if (mCurrentOperation.isMatchingRequestId(requestId)) { + return mCurrentOperation.getClientMonitor(); + } + } + return null; + } + public int getCurrentPendingCount() { return mPendingOperations.size(); } diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricSchedulerOperation.java b/services/core/java/com/android/server/biometrics/sensors/BiometricSchedulerOperation.java index 15f0cadced991..968146a166ed3 100644 --- a/services/core/java/com/android/server/biometrics/sensors/BiometricSchedulerOperation.java +++ b/services/core/java/com/android/server/biometrics/sensors/BiometricSchedulerOperation.java @@ -123,11 +123,12 @@ public class BiometricSchedulerOperation { * * @return cookie or 0 if ready/started */ - public int isReadyToStart() { + public int isReadyToStart(@NonNull ClientMonitorCallback callback) { if (mState == STATE_WAITING_FOR_COOKIE || mState == STATE_WAITING_IN_QUEUE) { final int cookie = mClientMonitor.getCookie(); if (cookie != 0) { mState = STATE_WAITING_FOR_COOKIE; + mClientMonitor.waitForCookie(getWrappedCallback(callback)); } return cookie; } @@ -137,7 +138,7 @@ public class BiometricSchedulerOperation { /** * Start this operation without waiting for a cookie - * (i.e. {@link #isReadyToStart() returns zero} + * (i.e. {@link #isReadyToStart(ClientMonitorCallback)} returns zero} * * @param callback lifecycle callback * @return if this operation started diff --git a/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java b/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java index 008717899abaf..aeb6b6e2a9073 100644 --- a/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java +++ b/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java @@ -84,7 +84,8 @@ public final class SensorOverlays { }; try { - mUdfpsOverlayController.get().showUdfpsOverlay(sensorId, reason, callback); + mUdfpsOverlayController.get().showUdfpsOverlay( + client.getRequestId(), sensorId, reason, callback); } catch (RemoteException e) { Slog.e(TAG, "Remote exception when showing the UDFPS overlay", e); } 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 b4befd23671fd..e8d8fb8285424 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 @@ -928,7 +928,8 @@ public class FingerprintService extends SystemService { } @Override - public void onPointerDown(int sensorId, int x, int y, float minor, float major) { + public void onPointerDown(long requestId, int sensorId, int x, int y, + float minor, float major) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); final ServiceProvider provider = getProviderForSensor(sensorId); @@ -936,11 +937,11 @@ public class FingerprintService extends SystemService { Slog.w(TAG, "No matching provider for onFingerDown, sensorId: " + sensorId); return; } - provider.onPointerDown(sensorId, x, y, minor, major); + provider.onPointerDown(requestId, sensorId, x, y, minor, major); } @Override - public void onPointerUp(int sensorId) { + public void onPointerUp(long requestId, int sensorId) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); final ServiceProvider provider = getProviderForSensor(sensorId); @@ -948,11 +949,11 @@ public class FingerprintService extends SystemService { Slog.w(TAG, "No matching provider for onFingerUp, sensorId: " + sensorId); return; } - provider.onPointerUp(sensorId); + provider.onPointerUp(requestId, sensorId); } @Override - public void onUiReady(int sensorId) { + public void onUiReady(long requestId, int sensorId) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); final ServiceProvider provider = getProviderForSensor(sensorId); @@ -960,7 +961,7 @@ public class FingerprintService extends SystemService { Slog.w(TAG, "No matching provider for onUiReady, sensorId: " + sensorId); return; } - provider.onUiReady(sensorId); + provider.onUiReady(requestId, sensorId); } @Override 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 0bdc4ebad66e5..9cdbdc9158fb6 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 @@ -142,11 +142,11 @@ public interface ServiceProvider { long getAuthenticatorId(int sensorId, int userId); - void onPointerDown(int sensorId, int x, int y, float minor, float major); + void onPointerDown(long requestId, int sensorId, int x, int y, float minor, float major); - void onPointerUp(int sensorId); + void onPointerUp(long requestId, int sensorId); - void onUiReady(int sensorId); + void onUiReady(long requestId, int sensorId); void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller); 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 index f810bca9707df..1fac8a8ce5c9d 100644 --- 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 @@ -580,39 +580,37 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi } @Override - public void onPointerDown(int sensorId, int x, int y, float minor, float major) { + public void onPointerDown(long requestId, int sensorId, int x, int y, + float minor, float major) { final BaseClientMonitor client = - mSensors.get(sensorId).getScheduler().getCurrentClient(); + mSensors.get(sensorId).getScheduler().getCurrentClientIfMatches(requestId); if (!(client instanceof Udfps)) { Slog.e(getTag(), "onPointerDown received during client: " + client); return; } - final Udfps udfps = (Udfps) client; - udfps.onPointerDown(x, y, minor, major); + ((Udfps) client).onPointerDown(x, y, minor, major); } @Override - public void onPointerUp(int sensorId) { + public void onPointerUp(long requestId, int sensorId) { final BaseClientMonitor client = - mSensors.get(sensorId).getScheduler().getCurrentClient(); + mSensors.get(sensorId).getScheduler().getCurrentClientIfMatches(requestId); if (!(client instanceof Udfps)) { Slog.e(getTag(), "onPointerUp received during client: " + client); return; } - final Udfps udfps = (Udfps) client; - udfps.onPointerUp(); + ((Udfps) client).onPointerUp(); } @Override - public void onUiReady(int sensorId) { + public void onUiReady(long requestId, int sensorId) { final BaseClientMonitor client = - mSensors.get(sensorId).getScheduler().getCurrentClient(); + mSensors.get(sensorId).getScheduler().getCurrentClientIfMatches(requestId); if (!(client instanceof Udfps)) { Slog.e(getTag(), "onUiReady received during client: " + client); return; } - final Udfps udfps = (Udfps) client; - udfps.onUiReady(); + ((Udfps) client).onUiReady(); } @Override 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 9d60859a4a217..1d2a3655021c0 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 @@ -792,36 +792,34 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider } @Override - public void onPointerDown(int sensorId, int x, int y, float minor, float major) { - final BaseClientMonitor client = mScheduler.getCurrentClient(); + public void onPointerDown(long requestId, int sensorId, int x, int y, + float minor, float major) { + final BaseClientMonitor client = mScheduler.getCurrentClientIfMatches(requestId); if (!(client instanceof Udfps)) { Slog.w(TAG, "onFingerDown received during client: " + client); return; } - final Udfps udfps = (Udfps) client; - udfps.onPointerDown(x, y, minor, major); + ((Udfps) client).onPointerDown(x, y, minor, major); } @Override - public void onPointerUp(int sensorId) { - final BaseClientMonitor client = mScheduler.getCurrentClient(); + public void onPointerUp(long requestId, int sensorId) { + final BaseClientMonitor client = mScheduler.getCurrentClientIfMatches(requestId); if (!(client instanceof Udfps)) { Slog.w(TAG, "onFingerDown received during client: " + client); return; } - final Udfps udfps = (Udfps) client; - udfps.onPointerUp(); + ((Udfps) client).onPointerUp(); } @Override - public void onUiReady(int sensorId) { - final BaseClientMonitor client = mScheduler.getCurrentClient(); + public void onUiReady(long requestId, int sensorId) { + final BaseClientMonitor client = mScheduler.getCurrentClientIfMatches(requestId); if (!(client instanceof Udfps)) { Slog.w(TAG, "onUiReady received during client: " + client); return; } - final Udfps udfps = (Udfps) client; - udfps.onUiReady(); + ((Udfps) client).onUiReady(); } @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 149526f21fdb7..a4e343e786c1d 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 @@ -441,7 +441,8 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage } @Override - public void onPointerDown(int sensorId, int x, int y, float minor, float major) { + public void onPointerDown(long requestId, int sensorId, int x, int y, float minor, + float major) { mHandler.post(() -> { Slog.d(TAG, "onFingerDown"); final AuthenticationConsumer lastAuthenticatedConsumer = @@ -488,7 +489,7 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage } @Override - public void onPointerUp(int sensorId) { + public void onPointerUp(long requestId, int sensorId) { mHandler.post(() -> { Slog.d(TAG, "onFingerUp"); diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerOperationTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerOperationTest.java index eab96c09a00a8..c17347320f524 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerOperationTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerOperationTest.java @@ -72,9 +72,11 @@ public class BiometricSchedulerOperationTest { @Mock private ClientMonitorCallback mClientCallback; @Mock + private ClientMonitorCallback mOnStartCallback; + @Mock private FakeHal mHal; @Captor - ArgumentCaptor mStartCallback; + ArgumentCaptor mStartedCallbackCaptor; private Handler mHandler; private BiometricSchedulerOperation mOperation; @@ -91,17 +93,17 @@ public class BiometricSchedulerOperationTest { when(mClientMonitor.getCookie()).thenReturn(cookie); when(mClientMonitor.getFreshDaemon()).thenReturn(mHal); - assertThat(mOperation.isReadyToStart()).isEqualTo(cookie); + assertThat(mOperation.isReadyToStart(mOnStartCallback)).isEqualTo(cookie); assertThat(mOperation.isStarted()).isFalse(); assertThat(mOperation.isCanceling()).isFalse(); assertThat(mOperation.isFinished()).isFalse(); + verify(mClientMonitor).waitForCookie(any()); - final boolean started = mOperation.startWithCookie( - mock(ClientMonitorCallback.class), cookie); + final boolean started = mOperation.startWithCookie(mOnStartCallback, cookie); assertThat(started).isTrue(); - verify(mClientMonitor).start(mStartCallback.capture()); - mStartCallback.getValue().onClientStarted(mClientMonitor); + verify(mClientMonitor).start(mStartedCallbackCaptor.capture()); + mStartedCallbackCaptor.getValue().onClientStarted(mClientMonitor); assertThat(mOperation.isStarted()).isTrue(); } @@ -112,14 +114,15 @@ public class BiometricSchedulerOperationTest { when(mClientMonitor.getCookie()).thenReturn(goodCookie); when(mClientMonitor.getFreshDaemon()).thenReturn(mHal); - assertThat(mOperation.isReadyToStart()).isEqualTo(goodCookie); - final boolean started = mOperation.startWithCookie( - mock(ClientMonitorCallback.class), badCookie); + assertThat(mOperation.isReadyToStart(mOnStartCallback)).isEqualTo(goodCookie); + final boolean started = mOperation.startWithCookie(mOnStartCallback, badCookie); assertThat(started).isFalse(); assertThat(mOperation.isStarted()).isFalse(); assertThat(mOperation.isCanceling()).isFalse(); assertThat(mOperation.isFinished()).isFalse(); + verify(mClientMonitor).waitForCookie(any()); + verify(mClientMonitor, never()).start(any()); } @Test @@ -127,26 +130,25 @@ public class BiometricSchedulerOperationTest { when(mClientMonitor.getCookie()).thenReturn(0); when(mClientMonitor.getFreshDaemon()).thenReturn(mHal); - final ClientMonitorCallback cb = mock(ClientMonitorCallback.class); - mOperation.start(cb); - verify(mClientMonitor).start(mStartCallback.capture()); - mStartCallback.getValue().onClientStarted(mClientMonitor); + mOperation.start(mOnStartCallback); + verify(mClientMonitor).start(mStartedCallbackCaptor.capture()); + mStartedCallbackCaptor.getValue().onClientStarted(mClientMonitor); assertThat(mOperation.isStarted()).isTrue(); assertThat(mOperation.isCanceling()).isFalse(); assertThat(mOperation.isFinished()).isFalse(); verify(mClientCallback).onClientStarted(eq(mClientMonitor)); - verify(cb).onClientStarted(eq(mClientMonitor)); + verify(mOnStartCallback).onClientStarted(eq(mClientMonitor)); verify(mClientCallback, never()).onClientFinished(any(), anyBoolean()); - verify(cb, never()).onClientFinished(any(), anyBoolean()); + verify(mOnStartCallback, never()).onClientFinished(any(), anyBoolean()); - mStartCallback.getValue().onClientFinished(mClientMonitor, true); + mStartedCallbackCaptor.getValue().onClientFinished(mClientMonitor, true); assertThat(mOperation.isFinished()).isTrue(); assertThat(mOperation.isCanceling()).isFalse(); verify(mClientMonitor).destroy(); - verify(cb).onClientFinished(eq(mClientMonitor), eq(true)); + verify(mOnStartCallback).onClientFinished(eq(mClientMonitor), eq(true)); } @Test @@ -154,8 +156,7 @@ public class BiometricSchedulerOperationTest { when(mClientMonitor.getCookie()).thenReturn(0); when(mClientMonitor.getFreshDaemon()).thenReturn(null); - final ClientMonitorCallback cb = mock(ClientMonitorCallback.class); - mOperation.start(cb); + mOperation.start(mOnStartCallback); verify(mClientMonitor, never()).start(any()); assertThat(mOperation.isStarted()).isFalse(); @@ -163,9 +164,9 @@ public class BiometricSchedulerOperationTest { assertThat(mOperation.isFinished()).isTrue(); verify(mClientCallback, never()).onClientStarted(eq(mClientMonitor)); - verify(cb, never()).onClientStarted(eq(mClientMonitor)); + verify(mOnStartCallback, never()).onClientStarted(eq(mClientMonitor)); verify(mClientCallback).onClientFinished(eq(mClientMonitor), eq(false)); - verify(cb).onClientFinished(eq(mClientMonitor), eq(false)); + verify(mOnStartCallback).onClientFinished(eq(mClientMonitor), eq(false)); } @Test @@ -179,7 +180,7 @@ public class BiometricSchedulerOperationTest { public void cannotRestart() { when(mClientMonitor.getFreshDaemon()).thenReturn(mHal); - mOperation.start(mock(ClientMonitorCallback.class)); + mOperation.start(mOnStartCallback); assertThrows(IllegalStateException.class, () -> mOperation.start(mock(ClientMonitorCallback.class))); @@ -202,7 +203,7 @@ public class BiometricSchedulerOperationTest { public void cannotAbortRunning() { when(mClientMonitor.getFreshDaemon()).thenReturn(mHal); - mOperation.start(mock(ClientMonitorCallback.class)); + mOperation.start(mOnStartCallback); assertThrows(IllegalStateException.class, () -> mOperation.abort()); } @@ -211,11 +212,10 @@ public class BiometricSchedulerOperationTest { public void cancel() { when(mClientMonitor.getFreshDaemon()).thenReturn(mHal); - final ClientMonitorCallback startCb = mock(ClientMonitorCallback.class); final ClientMonitorCallback cancelCb = mock(ClientMonitorCallback.class); - mOperation.start(startCb); - verify(mClientMonitor).start(mStartCallback.capture()); - mStartCallback.getValue().onClientStarted(mClientMonitor); + mOperation.start(mOnStartCallback); + verify(mClientMonitor).start(mStartedCallbackCaptor.capture()); + mStartedCallbackCaptor.getValue().onClientStarted(mClientMonitor); mOperation.cancel(mHandler, cancelCb); assertThat(mOperation.isCanceling()).isTrue(); @@ -223,7 +223,7 @@ public class BiometricSchedulerOperationTest { verify(mClientMonitor, never()).cancelWithoutStarting(any()); verify(mClientMonitor, never()).destroy(); - mStartCallback.getValue().onClientFinished(mClientMonitor, true); + mStartedCallbackCaptor.getValue().onClientFinished(mClientMonitor, true); assertThat(mOperation.isFinished()).isTrue(); assertThat(mOperation.isCanceling()).isFalse(); @@ -315,12 +315,10 @@ public class BiometricSchedulerOperationTest { private void cancelWatchdog(boolean start) { when(mClientMonitor.getFreshDaemon()).thenReturn(mHal); - final ClientMonitorCallback opStartCallback = mock(ClientMonitorCallback.class); - mOperation.start(opStartCallback); + mOperation.start(mOnStartCallback); if (start) { - verify(mClientMonitor).start(mStartCallback.capture()); - mStartCallback.getValue().onClientStarted(mClientMonitor); - verify(opStartCallback).onClientStarted(eq(mClientMonitor)); + verify(mClientMonitor).start(mStartedCallbackCaptor.capture()); + mStartedCallbackCaptor.getValue().onClientStarted(mClientMonitor); } mOperation.cancel(mHandler, mock(ClientMonitorCallback.class)); @@ -331,7 +329,7 @@ public class BiometricSchedulerOperationTest { assertThat(mOperation.isFinished()).isTrue(); assertThat(mOperation.isCanceling()).isFalse(); - verify(opStartCallback).onClientFinished(eq(mClientMonitor), eq(false)); + verify(mOnStartCallback).onClientFinished(eq(mClientMonitor), eq(false)); verify(mClientMonitor).destroy(); } } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java index 0fa2b41e8b321..45e3b43732666 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java @@ -196,7 +196,8 @@ public class BiometricSchedulerTest { // Schedule a BiometricPrompt authentication request mScheduler.scheduleClientMonitor(client1, callback1); - assertNotEquals(0, mScheduler.mCurrentOperation.isReadyToStart()); + assertNotEquals(0, mScheduler.mCurrentOperation.isReadyToStart( + mock(ClientMonitorCallback.class))); assertEquals(client1, mScheduler.mCurrentOperation.getClientMonitor()); assertEquals(0, mScheduler.mPendingOperations.size()); @@ -436,7 +437,8 @@ public class BiometricSchedulerTest { if (started || isEnroll) { // prep'd auth clients and enroll clients assertTrue(mScheduler.mCurrentOperation.isStarted()); } else { - assertNotEquals(0, mScheduler.mCurrentOperation.isReadyToStart()); + assertNotEquals(0, mScheduler.mCurrentOperation.isReadyToStart( + mock(ClientMonitorCallback.class))); } } } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorOverlaysTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorOverlaysTest.java index dc39b6d573dbb..5012335b533fa 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorOverlaysTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorOverlaysTest.java @@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.hardware.biometrics.BiometricOverlayConstants; import android.hardware.fingerprint.ISidefpsController; @@ -29,6 +30,7 @@ import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; @@ -43,6 +45,7 @@ import java.util.List; public class SensorOverlaysTest { private static final int SENSOR_ID = 11; + private static final long REQUEST_ID = 8; @Rule public final MockitoRule mockito = MockitoJUnit.rule(); @@ -50,6 +53,12 @@ public class SensorOverlaysTest { @Mock private ISidefpsController mSidefpsController; @Mock private AcquisitionClient mAcquisitionClient; + @Before + public void setup() { + when(mAcquisitionClient.getRequestId()).thenReturn(REQUEST_ID); + when(mAcquisitionClient.hasRequestId()).thenReturn(true); + } + @Test public void noopWhenBothNull() { final SensorOverlays useless = new SensorOverlays(null, null); @@ -92,7 +101,8 @@ public class SensorOverlaysTest { sensorOverlays.show(SENSOR_ID, reason, mAcquisitionClient); if (udfps != null) { - verify(mUdfpsOverlayController).showUdfpsOverlay(eq(SENSOR_ID), eq(reason), any()); + verify(mUdfpsOverlayController).showUdfpsOverlay( + eq(REQUEST_ID), eq(SENSOR_ID), eq(reason), any()); } if (sidefps != null) { verify(mSidefpsController).show(eq(SENSOR_ID), eq(reason)); diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java index de0f038e8ec5a..6c50ca35be790 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java @@ -71,6 +71,7 @@ public class FingerprintAuthenticationClientTest { private static final int USER_ID = 8; private static final long OP_ID = 7; + private static final long REQUEST_ID = 88; private static final int POINTER_ID = 0; private static final int TOUCH_X = 8; private static final int TOUCH_Y = 20; @@ -259,7 +260,7 @@ public class FingerprintAuthenticationClientTest { client.start(mCallback); - verify(mUdfpsOverlayController).showUdfpsOverlay(anyInt(), anyInt(), any()); + verify(mUdfpsOverlayController).showUdfpsOverlay(eq(REQUEST_ID), anyInt(), anyInt(), any()); verify(mSideFpsController).show(anyInt(), anyInt()); block.accept(client); @@ -277,7 +278,7 @@ public class FingerprintAuthenticationClientTest { final AidlSession aidl = new AidlSession(version, mHal, USER_ID, mHalSessionCallback); return new FingerprintAuthenticationClient(mContext, () -> aidl, mToken, - 2 /* requestId */, mClientMonitorCallbackConverter, 5 /* targetUserId */, OP_ID, + REQUEST_ID, mClientMonitorCallbackConverter, 5 /* targetUserId */, OP_ID, false /* restricted */, "test-owner", 4 /* cookie */, false /* requireConfirmation */, 9 /* sensorId */, mBiometricLogger, mBiometricContext, true /* isStrongBiometric */, diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java index 5a96f5cca52a1..f77eb0bcc59f6 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java @@ -72,6 +72,7 @@ public class FingerprintEnrollClientTest { private static final byte[] HAT = new byte[69]; private static final int USER_ID = 8; + private static final long REQUEST_ID = 9; private static final int POINTER_ID = 0; private static final int TOUCH_X = 8; private static final int TOUCH_Y = 20; @@ -256,7 +257,7 @@ public class FingerprintEnrollClientTest { client.start(mCallback); - verify(mUdfpsOverlayController).showUdfpsOverlay(anyInt(), anyInt(), any()); + verify(mUdfpsOverlayController).showUdfpsOverlay(eq(REQUEST_ID), anyInt(), anyInt(), any()); verify(mSideFpsController).show(anyInt(), anyInt()); block.accept(client); @@ -273,7 +274,7 @@ public class FingerprintEnrollClientTest { when(mHal.getInterfaceVersion()).thenReturn(version); final AidlSession aidl = new AidlSession(version, mHal, USER_ID, mHalSessionCallback); - return new FingerprintEnrollClient(mContext, () -> aidl, mToken, 6 /* requestId */, + return new FingerprintEnrollClient(mContext, () -> aidl, mToken, REQUEST_ID, mClientMonitorCallbackConverter, 0 /* userId */, HAT, "owner", mBiometricUtils, 8 /* sensorId */, mBiometricLogger, mBiometricContext, mSensorProps, mUdfpsOverlayController,