diff --git a/core/java/com/android/internal/util/LatencyTracker.java b/core/java/com/android/internal/util/LatencyTracker.java index e95ba884fed4f..1cd758c0f43b1 100644 --- a/core/java/com/android/internal/util/LatencyTracker.java +++ b/core/java/com/android/internal/util/LatencyTracker.java @@ -127,6 +127,11 @@ public class LatencyTracker { */ public static final int ACTION_SWITCH_DISPLAY_UNFOLD = 13; + /** + * Time it takes for a UDFPS sensor to appear ready after it is touched. + */ + public static final int ACTION_UDFPS_ILLUMINATE = 14; + private static final int[] ACTIONS_ALL = { ACTION_EXPAND_PANEL, ACTION_TOGGLE_RECENTS, @@ -141,7 +146,8 @@ public class LatencyTracker { ACTION_ROTATE_SCREEN_CAMERA_CHECK, ACTION_LOCKSCREEN_UNLOCK, ACTION_USER_SWITCH, - ACTION_SWITCH_DISPLAY_UNFOLD + ACTION_SWITCH_DISPLAY_UNFOLD, + ACTION_UDFPS_ILLUMINATE }; /** @hide */ @@ -159,7 +165,8 @@ public class LatencyTracker { ACTION_ROTATE_SCREEN_CAMERA_CHECK, ACTION_LOCKSCREEN_UNLOCK, ACTION_USER_SWITCH, - ACTION_SWITCH_DISPLAY_UNFOLD + ACTION_SWITCH_DISPLAY_UNFOLD, + ACTION_UDFPS_ILLUMINATE }) @Retention(RetentionPolicy.SOURCE) public @interface Action { @@ -179,7 +186,8 @@ public class LatencyTracker { FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN_CAMERA_CHECK, FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_LOCKSCREEN_UNLOCK, FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_USER_SWITCH, - FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_SWITCH_DISPLAY_UNFOLD + FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_SWITCH_DISPLAY_UNFOLD, + FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_UDFPS_ILLUMINATE }; private static LatencyTracker sLatencyTracker; @@ -267,6 +275,8 @@ public class LatencyTracker { return "ACTION_USER_SWITCH"; case 14: return "ACTION_SWITCH_DISPLAY_UNFOLD"; + case 15: + return "ACTION_UDFPS_ILLUMINATE"; default: throw new IllegalArgumentException("Invalid action"); } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index ebf73315c3031..fd7ae323e88f1 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -51,8 +51,8 @@ import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.LatencyTracker; import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.systemui.R; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.doze.DozeReceiver; @@ -125,6 +125,7 @@ public class UdfpsController implements DozeReceiver { @NonNull private final SystemClock mSystemClock; @NonNull private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; + @NonNull private final LatencyTracker mLatencyTracker; @VisibleForTesting @NonNull final BiometricDisplayListener mOrientationListener; // Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple // sensors, this, in addition to a lot of the code here, will be updated. @@ -349,6 +350,7 @@ public class UdfpsController implements DozeReceiver { boolean withinSensorArea = isWithinSensorArea(udfpsView, event.getX(), event.getY(), fromUdfpsView); if (withinSensorArea) { + mLatencyTracker.onActionStart(LatencyTracker.ACTION_UDFPS_ILLUMINATE); Trace.beginAsyncSection("UdfpsController.e2e.onPointerDown", 0); Log.v(TAG, "onTouch | action down"); // The pointer that causes ACTION_DOWN is always at index 0. @@ -484,7 +486,8 @@ public class UdfpsController implements DozeReceiver { @NonNull ConfigurationController configurationController, @NonNull SystemClock systemClock, @NonNull UnlockedScreenOffAnimationController unlockedScreenOffAnimationController, - @NonNull SystemUIDialogManager dialogManager) { + @NonNull SystemUIDialogManager dialogManager, + @NonNull LatencyTracker latencyTracker) { mContext = context; mExecution = execution; mVibrator = vibrator; @@ -512,6 +515,7 @@ public class UdfpsController implements DozeReceiver { mConfigurationController = configurationController; mSystemClock = systemClock; mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; + mLatencyTracker = latencyTracker; mSensorProps = findFirstUdfps(); // At least one UDFPS sensor exists @@ -751,6 +755,7 @@ public class UdfpsController implements DozeReceiver { Trace.beginAsyncSection("UdfpsController.e2e.startIllumination", 0); view.startIllumination(() -> { mFingerprintManager.onUiReady(mSensorProps.sensorId); + mLatencyTracker.onActionEnd(LatencyTracker.ACTION_UDFPS_ILLUMINATE); Trace.endAsyncSection("UdfpsController.e2e.startIllumination", 0); }); } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmOtherViewController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmOtherViewController.kt index f56b5d8af4717..98205cfb7966e 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmOtherViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmOtherViewController.kt @@ -15,7 +15,6 @@ */ package com.android.systemui.biometrics - import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.phone.SystemUIDialogManager 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 d5725786e0d27..2afcbda64fb57 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java @@ -24,6 +24,7 @@ import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; 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.verify; @@ -53,6 +54,7 @@ import android.view.accessibility.AccessibilityManager; import androidx.test.filters.SmallTest; +import com.android.internal.util.LatencyTracker; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; @@ -81,6 +83,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; +import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -154,7 +157,8 @@ public class UdfpsControllerTest extends SysuiTestCase { private SystemClock mSystemClock; @Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; - + @Mock + private LatencyTracker mLatencyTracker; private FakeExecutor mFgExecutor; // Stuff for configuring mocks @@ -247,7 +251,8 @@ public class UdfpsControllerTest extends SysuiTestCase { mConfigurationController, mSystemClock, mUnlockedScreenOffAnimationController, - mSystemUIDialogManager); + mSystemUIDialogManager, + mLatencyTracker); verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture()); mOverlayController = mOverlayCaptor.getValue(); verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture()); @@ -463,11 +468,15 @@ public class UdfpsControllerTest extends SysuiTestCase { // THEN FingerprintManager is notified about onPointerDown verify(mFingerprintManager).onPointerDown(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()); + verify(mLatencyTracker, never()).onActionEnd(eq(LatencyTracker.ACTION_UDFPS_ILLUMINATE)); // AND onIlluminatedRunnable notifies FingerprintManager about onUiReady mOnIlluminatedRunnableCaptor.getValue().run(); - verify(mFingerprintManager).onUiReady(eq(mUdfpsController.mSensorProps.sensorId)); + InOrder inOrder = inOrder(mFingerprintManager, mLatencyTracker); + inOrder.verify(mFingerprintManager).onUiReady(eq(mUdfpsController.mSensorProps.sensorId)); + inOrder.verify(mLatencyTracker).onActionEnd(eq(LatencyTracker.ACTION_UDFPS_ILLUMINATE)); } @Test