From e435401edd5f65dc56108042780854f1d93d40c2 Mon Sep 17 00:00:00 2001 From: Grace Cheng Date: Mon, 9 May 2022 21:46:11 +0000 Subject: [PATCH] Schedule UDFPS IPCs on the dedicated biometric thread Schedules UDFPS calls to onPointerDown, onPointerUp, and onUiReady on the dedicated biometric executor Fixes: 231240223 Test: atest UdfpsControllerTest Change-Id: I3d46e46db888bcf5a54faa009d96ce53611ca077 --- .../systemui/biometrics/UdfpsController.java | 23 +++++++++++----- .../biometrics/UdfpsControllerTest.java | 26 ++++++++++++++++++- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index 6a6a265874f08..348653849134b 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -53,6 +53,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.LatencyTracker; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.animation.ActivityLaunchAnimator; +import com.android.systemui.biometrics.dagger.BiometricsBackground; import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; @@ -76,6 +77,7 @@ import com.android.systemui.util.time.SystemClock; import java.util.HashSet; import java.util.Optional; import java.util.Set; +import java.util.concurrent.Executor; import javax.inject.Inject; @@ -107,6 +109,7 @@ public class UdfpsController implements DozeReceiver { @NonNull private final LayoutInflater mInflater; private final WindowManager mWindowManager; private final DelayableExecutor mFgExecutor; + @NonNull private final Executor mBiometricExecutor; @NonNull private final PanelExpansionStateManager mPanelExpansionStateManager; @NonNull private final StatusBarStateController mStatusBarStateController; @NonNull private final KeyguardStateController mKeyguardStateController; @@ -576,7 +579,8 @@ public class UdfpsController implements DozeReceiver { @NonNull LatencyTracker latencyTracker, @NonNull ActivityLaunchAnimator activityLaunchAnimator, @NonNull Optional aternateTouchProvider, - @NonNull BroadcastSender broadcastSender) { + @NonNull BroadcastSender broadcastSender, + @BiometricsBackground Executor biometricsExecutor) { mContext = context; mExecution = execution; mVibrator = vibrator; @@ -607,6 +611,7 @@ public class UdfpsController implements DozeReceiver { mActivityLaunchAnimator = activityLaunchAnimator; mAlternateTouchProvider = aternateTouchProvider.orElse(null); mBroadcastSender = broadcastSender; + mBiometricExecutor = biometricsExecutor; mOrientationListener = new BiometricDisplayListener( context, @@ -810,7 +815,9 @@ public class UdfpsController implements DozeReceiver { } mOnFingerDown = true; if (mAlternateTouchProvider != null) { - mAlternateTouchProvider.onPointerDown(requestId, x, y, minor, major); + mBiometricExecutor.execute(() -> { + mAlternateTouchProvider.onPointerDown(requestId, x, y, minor, major); + }); mFgExecutor.execute(() -> { if (mKeyguardUpdateMonitor.isFingerprintDetectionRunning()) { mKeyguardUpdateMonitor.onUdfpsPointerDown((int) requestId); @@ -820,16 +827,18 @@ public class UdfpsController implements DozeReceiver { mFingerprintManager.onPointerDown(requestId, mSensorId, x, y, minor, major); } Trace.endAsyncSection("UdfpsController.e2e.onPointerDown", 0); - final UdfpsView view = mOverlay.getOverlayView(); if (view != null) { view.startIllumination(() -> { if (mAlternateTouchProvider != null) { - mAlternateTouchProvider.onUiReady(); + mBiometricExecutor.execute(() -> { + mAlternateTouchProvider.onUiReady(); + mLatencyTracker.onActionEnd(LatencyTracker.ACTION_UDFPS_ILLUMINATE); + }); } else { mFingerprintManager.onUiReady(requestId, mSensorId); + mLatencyTracker.onActionEnd(LatencyTracker.ACTION_UDFPS_ILLUMINATE); } - mLatencyTracker.onActionEnd(LatencyTracker.ACTION_UDFPS_ILLUMINATE); }); } @@ -844,7 +853,9 @@ public class UdfpsController implements DozeReceiver { mAcquiredReceived = false; if (mOnFingerDown) { if (mAlternateTouchProvider != null) { - mAlternateTouchProvider.onPointerUp(requestId); + mBiometricExecutor.execute(() -> { + mAlternateTouchProvider.onPointerUp(requestId); + }); mFgExecutor.execute(() -> { if (mKeyguardUpdateMonitor.isFingerprintDetectionRunning()) { mKeyguardUpdateMonitor.onUdfpsPointerUp((int) requestId); 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 e6832a24833f9..554e27dde5ec8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java @@ -117,6 +117,7 @@ public class UdfpsControllerTest extends SysuiTestCase { private UdfpsController mUdfpsController; // Dependencies + private FakeExecutor mBiometricsExecutor; private Execution mExecution; @Mock private LayoutInflater mLayoutInflater; @@ -234,6 +235,10 @@ public class UdfpsControllerTest extends SysuiTestCase { true /* resetLockoutRequiresHardwareAuthToken */)); when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(props); mFgExecutor = new FakeExecutor(new FakeSystemClock()); + + // Create a fake background executor. + mBiometricsExecutor = new FakeExecutor(new FakeSystemClock()); + mUdfpsController = new UdfpsController( mContext, mExecution, @@ -265,7 +270,8 @@ public class UdfpsControllerTest extends SysuiTestCase { mLatencyTracker, mActivityLaunchAnimator, Optional.of(mAlternateTouchProvider), - mBroadcastSender); + mBroadcastSender, + mBiometricsExecutor); verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture()); mOverlayController = mOverlayCaptor.getValue(); verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture()); @@ -298,6 +304,7 @@ public class UdfpsControllerTest extends SysuiTestCase { verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture()); MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent); + mBiometricsExecutor.runAllReady(); downEvent.recycle(); // THEN notify keyguard authenticate to dismiss the keyguard @@ -336,6 +343,7 @@ public class UdfpsControllerTest extends SysuiTestCase { mFgExecutor.runAllReady(); } mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); + mBiometricsExecutor.runAllReady(); moveEvent.recycle(); // THEN notify keyguard authenticate to dismiss the keyguard @@ -359,10 +367,12 @@ public class UdfpsControllerTest extends SysuiTestCase { verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture()); MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent); + mBiometricsExecutor.runAllReady(); downEvent.recycle(); MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, 0, 0); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); + mBiometricsExecutor.runAllReady(); moveEvent.recycle(); // THEN notify keyguard authenticate to dismiss the keyguard @@ -516,9 +526,11 @@ public class UdfpsControllerTest extends SysuiTestCase { MotionEvent event = obtainMotionEvent(ACTION_DOWN, displayWidth, displayHeight, touchMinor, touchMajor); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event); + mBiometricsExecutor.runAllReady(); event.recycle(); event = obtainMotionEvent(ACTION_MOVE, displayWidth, displayHeight, touchMinor, touchMajor); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event); + mBiometricsExecutor.runAllReady(); event.recycle(); verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(expectedX), eq(expectedY), eq(expectedMinor), eq(expectedMajor)); @@ -530,9 +542,11 @@ public class UdfpsControllerTest extends SysuiTestCase { Surface.ROTATION_90)); event = obtainMotionEvent(ACTION_DOWN, displayHeight, 0, touchMinor, touchMajor); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event); + mBiometricsExecutor.runAllReady(); event.recycle(); event = obtainMotionEvent(ACTION_MOVE, displayHeight, 0, touchMinor, touchMajor); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event); + mBiometricsExecutor.runAllReady(); event.recycle(); verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(expectedX), eq(expectedY), eq(expectedMinor), eq(expectedMajor)); @@ -544,9 +558,11 @@ public class UdfpsControllerTest extends SysuiTestCase { Surface.ROTATION_270)); event = obtainMotionEvent(ACTION_DOWN, 0, displayWidth, touchMinor, touchMajor); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event); + mBiometricsExecutor.runAllReady(); event.recycle(); event = obtainMotionEvent(ACTION_MOVE, 0, displayWidth, touchMinor, touchMajor); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event); + mBiometricsExecutor.runAllReady(); event.recycle(); verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(expectedX), eq(expectedY), eq(expectedMinor), eq(expectedMajor)); @@ -559,9 +575,11 @@ public class UdfpsControllerTest extends SysuiTestCase { // ROTATION_180 is not supported. It should be treated like ROTATION_0. event = obtainMotionEvent(ACTION_DOWN, displayWidth, displayHeight, touchMinor, touchMajor); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event); + mBiometricsExecutor.runAllReady(); event.recycle(); event = obtainMotionEvent(ACTION_MOVE, displayWidth, displayHeight, touchMinor, touchMajor); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event); + mBiometricsExecutor.runAllReady(); event.recycle(); verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(expectedX), eq(expectedY), eq(expectedMinor), eq(expectedMajor)); @@ -582,11 +600,13 @@ public class UdfpsControllerTest extends SysuiTestCase { verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture()); MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent); + mBiometricsExecutor.runAllReady(); downEvent.recycle(); MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, 0, 0); // FIX THIS TEST mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); + mBiometricsExecutor.runAllReady(); moveEvent.recycle(); mFgExecutor.runAllReady(); // THEN FingerprintManager is notified about onPointerDown @@ -601,6 +621,7 @@ public class UdfpsControllerTest extends SysuiTestCase { verify(mKeyguardUpdateMonitor).onUdfpsPointerDown(eq((int) TEST_REQUEST_ID)); // AND onIlluminatedRunnable notifies FingerprintManager about onUiReady mOnIlluminatedRunnableCaptor.getValue().run(); + mBiometricsExecutor.runAllReady(); InOrder inOrder = inOrder(mAlternateTouchProvider, mLatencyTracker); inOrder.verify(mAlternateTouchProvider).onUiReady(); inOrder.verify(mLatencyTracker).onActionEnd(eq(LatencyTracker.ACTION_UDFPS_ILLUMINATE)); @@ -621,6 +642,7 @@ public class UdfpsControllerTest extends SysuiTestCase { // AND onIlluminatedRunnable that notifies FingerprintManager is set verify(mUdfpsView).startIllumination(mOnIlluminatedRunnableCaptor.capture()); mOnIlluminatedRunnableCaptor.getValue().run(); + mBiometricsExecutor.runAllReady(); verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(0), eq(0), eq(3f) /* minor */, eq(2f) /* major */); verify(mFingerprintManager, never()).onPointerDown(anyLong(), anyInt(), anyInt(), anyInt(), @@ -746,9 +768,11 @@ public class UdfpsControllerTest extends SysuiTestCase { verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture()); MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent); + mBiometricsExecutor.runAllReady(); downEvent.recycle(); MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, 0, 0); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); + mBiometricsExecutor.runAllReady(); moveEvent.recycle(); // THEN NO haptic played