Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0fcce8f6 authored by Beverly Tai's avatar Beverly Tai Committed by Android (Google) Code Review
Browse files

Merge "Add UdfpsTouchOverlayViewModels" into main

parents 91edb435 ff0c50c2
Loading
Loading
Loading
Loading
+132 −133
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_OTHER
import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_SETTINGS
import android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROLL_ENROLLING
import android.hardware.biometrics.BiometricOverlayConstants.ShowReason
import android.hardware.fingerprint.FingerprintManager
import android.hardware.fingerprint.IUdfpsOverlayControllerCallback
import android.testing.TestableLooper.RunWithLooper
import android.view.LayoutInflater
@@ -40,6 +39,8 @@ import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.ActivityLaunchAnimator
import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams
import com.android.systemui.biometrics.ui.viewmodel.DefaultUdfpsTouchOverlayViewModel
import com.android.systemui.biometrics.ui.viewmodel.DeviceEntryUdfpsTouchOverlayViewModel
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.dump.DumpManager
@@ -67,8 +68,8 @@ import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.mock
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit
import org.mockito.Mockito.`when` as whenever
import org.mockito.junit.MockitoJUnit

private const val REQUEST_ID = 2L

@@ -86,7 +87,6 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {

    @JvmField @Rule var rule = MockitoJUnit.rule()

    @Mock private lateinit var fingerprintManager: FingerprintManager
    @Mock private lateinit var inflater: LayoutInflater
    @Mock private lateinit var windowManager: WindowManager
    @Mock private lateinit var accessibilityManager: AccessibilityManager
@@ -98,8 +98,8 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
    @Mock private lateinit var transitionController: LockscreenShadeTransitionController
    @Mock private lateinit var configurationController: ConfigurationController
    @Mock private lateinit var keyguardStateController: KeyguardStateController
    @Mock private lateinit var unlockedScreenOffAnimationController:
            UnlockedScreenOffAnimationController
    @Mock
    private lateinit var unlockedScreenOffAnimationController: UnlockedScreenOffAnimationController
    @Mock private lateinit var udfpsDisplayMode: UdfpsDisplayModeProvider
    @Mock private lateinit var secureSettings: SecureSettings
    @Mock private lateinit var controllerCallback: IUdfpsOverlayControllerCallback
@@ -110,8 +110,12 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
    @Mock private lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
    @Mock private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
    @Mock private lateinit var mSelectedUserInteractor: SelectedUserInteractor
    @Mock private lateinit var udfpsKeyguardAccessibilityDelegate:
            UdfpsKeyguardAccessibilityDelegate
    @Mock
    private lateinit var deviceEntryUdfpsTouchOverlayViewModel:
        DeviceEntryUdfpsTouchOverlayViewModel
    @Mock private lateinit var defaultUdfpsTouchOverlayViewModel: DefaultUdfpsTouchOverlayViewModel
    @Mock
    private lateinit var udfpsKeyguardAccessibilityDelegate: UdfpsKeyguardAccessibilityDelegate
    @Mock private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
    @Captor private lateinit var layoutParamsCaptor: ArgumentCaptor<WindowManager.LayoutParams>

@@ -121,8 +125,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {

    @Before
    fun setup() {
        whenever(inflater.inflate(R.layout.udfps_view, null, false))
                .thenReturn(udfpsView)
        whenever(inflater.inflate(R.layout.udfps_view, null, false)).thenReturn(udfpsView)
        whenever(inflater.inflate(R.layout.udfps_bp_view, null))
            .thenReturn(mock(UdfpsBpView::class.java))
        whenever(inflater.inflate(R.layout.udfps_keyguard_view_legacy, null))
@@ -142,7 +145,8 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
        } else {
            mSetFlagsRule.disableFlags(Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR)
        }
        controllerOverlay = UdfpsControllerOverlay(
        controllerOverlay =
            UdfpsControllerOverlay(
                context,
                inflater,
                windowManager,
@@ -168,27 +172,29 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
                udfpsKeyguardAccessibilityDelegate,
                keyguardTransitionInteractor,
                mSelectedUserInteractor,
                { deviceEntryUdfpsTouchOverlayViewModel },
                { defaultUdfpsTouchOverlayViewModel },
            )
        block()
    }

    @Test
    fun showUdfpsOverlay_bp() = withReason(REASON_AUTH_BP) { showUdfpsOverlay() }
    @Test fun showUdfpsOverlay_bp() = withReason(REASON_AUTH_BP) { showUdfpsOverlay() }

    @Test
    fun showUdfpsOverlay_keyguard() = withReason(REASON_AUTH_KEYGUARD) {
    fun showUdfpsOverlay_keyguard() =
        withReason(REASON_AUTH_KEYGUARD) {
            showUdfpsOverlay()
            verify(mUdfpsKeyguardViewLegacy).updateSensorLocation(eq(overlayParams.sensorBounds))
        }

    @Test
    fun showUdfpsOverlay_other() = withReason(REASON_AUTH_OTHER) { showUdfpsOverlay() }
    @Test fun showUdfpsOverlay_other() = withReason(REASON_AUTH_OTHER) { showUdfpsOverlay() }

    private fun withRotation(@Rotation rotation: Int, block: () -> Unit) {
        // Sensor that's in the top left corner of the display in natural orientation.
        val sensorBounds = Rect(0, 0, SENSOR_WIDTH, SENSOR_HEIGHT)
        val overlayBounds = Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT)
        overlayParams = UdfpsOverlayParams(
        overlayParams =
            UdfpsOverlayParams(
                sensorBounds,
                overlayBounds,
                DISPLAY_WIDTH,
@@ -200,13 +206,12 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
    }

    @Test
    fun showUdfpsOverlay_withRotation0() = withRotation(Surface.ROTATION_0) {
    fun showUdfpsOverlay_withRotation0() =
        withRotation(Surface.ROTATION_0) {
            withReason(REASON_AUTH_BP) {
                controllerOverlay.show(udfpsController, overlayParams)
            verify(windowManager).addView(
                    eq(controllerOverlay.getTouchOverlay()),
                    layoutParamsCaptor.capture()
            )
                verify(windowManager)
                    .addView(eq(controllerOverlay.getTouchOverlay()), layoutParamsCaptor.capture())

                // ROTATION_0 is the native orientation. Sensor should stay in the top left corner.
                val lp = layoutParamsCaptor.value
@@ -218,13 +223,12 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
        }

    @Test
    fun showUdfpsOverlay_withRotation180() = withRotation(Surface.ROTATION_180) {
    fun showUdfpsOverlay_withRotation180() =
        withRotation(Surface.ROTATION_180) {
            withReason(REASON_AUTH_BP) {
                controllerOverlay.show(udfpsController, overlayParams)
            verify(windowManager).addView(
                    eq(controllerOverlay.getTouchOverlay()),
                    layoutParamsCaptor.capture()
            )
                verify(windowManager)
                    .addView(eq(controllerOverlay.getTouchOverlay()), layoutParamsCaptor.capture())

                // ROTATION_180 is not supported. Sensor should stay in the top left corner.
                val lp = layoutParamsCaptor.value
@@ -236,13 +240,12 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
        }

    @Test
    fun showUdfpsOverlay_withRotation90() = withRotation(Surface.ROTATION_90) {
    fun showUdfpsOverlay_withRotation90() =
        withRotation(Surface.ROTATION_90) {
            withReason(REASON_AUTH_BP) {
                controllerOverlay.show(udfpsController, overlayParams)
            verify(windowManager).addView(
                    eq(controllerOverlay.getTouchOverlay()),
                    layoutParamsCaptor.capture()
            )
                verify(windowManager)
                    .addView(eq(controllerOverlay.getTouchOverlay()), layoutParamsCaptor.capture())

                // Sensor should be in the bottom left corner in ROTATION_90.
                val lp = layoutParamsCaptor.value
@@ -254,13 +257,12 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
        }

    @Test
    fun showUdfpsOverlay_withRotation270() = withRotation(Surface.ROTATION_270) {
    fun showUdfpsOverlay_withRotation270() =
        withRotation(Surface.ROTATION_270) {
            withReason(REASON_AUTH_BP) {
                controllerOverlay.show(udfpsController, overlayParams)
            verify(windowManager).addView(
                    eq(controllerOverlay.getTouchOverlay()),
                    layoutParamsCaptor.capture()
            )
                verify(windowManager)
                    .addView(eq(controllerOverlay.getTouchOverlay()), layoutParamsCaptor.capture())

                // Sensor should be in the top right corner in ROTATION_270.
                val lp = layoutParamsCaptor.value
@@ -285,17 +287,13 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
        assertThat(controllerOverlay.getTouchOverlay()).isNotNull()
    }

    @Test
    fun hideUdfpsOverlay_bp() = withReason(REASON_AUTH_BP) { hideUdfpsOverlay() }
    @Test fun hideUdfpsOverlay_bp() = withReason(REASON_AUTH_BP) { hideUdfpsOverlay() }

    @Test
    fun hideUdfpsOverlay_keyguard() = withReason(REASON_AUTH_KEYGUARD) { hideUdfpsOverlay() }
    @Test fun hideUdfpsOverlay_keyguard() = withReason(REASON_AUTH_KEYGUARD) { hideUdfpsOverlay() }

    @Test
    fun hideUdfpsOverlay_settings() = withReason(REASON_AUTH_SETTINGS) { hideUdfpsOverlay() }
    @Test fun hideUdfpsOverlay_settings() = withReason(REASON_AUTH_SETTINGS) { hideUdfpsOverlay() }

    @Test
    fun hideUdfpsOverlay_other() = withReason(REASON_AUTH_OTHER) { hideUdfpsOverlay() }
    @Test fun hideUdfpsOverlay_other() = withReason(REASON_AUTH_OTHER) { hideUdfpsOverlay() }

    private fun hideUdfpsOverlay() {
        val didShow = controllerOverlay.show(udfpsController, overlayParams)
@@ -313,24 +311,25 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
    }

    @Test
    fun canNotHide() = withReason(REASON_AUTH_BP) {
        assertThat(controllerOverlay.hide()).isFalse()
    }
    fun canNotHide() = withReason(REASON_AUTH_BP) { assertThat(controllerOverlay.hide()).isFalse() }

    @Test
    fun canNotReshow() = withReason(REASON_AUTH_BP) {
    fun canNotReshow() =
        withReason(REASON_AUTH_BP) {
            assertThat(controllerOverlay.show(udfpsController, overlayParams)).isTrue()
            assertThat(controllerOverlay.show(udfpsController, overlayParams)).isFalse()
        }

    @Test
    fun cancels() = withReason(REASON_AUTH_BP) {
    fun cancels() =
        withReason(REASON_AUTH_BP) {
            controllerOverlay.cancel()
            verify(controllerCallback).onUserCanceled()
        }

    @Test
    fun unconfigureDisplayOnHide() = withReason(REASON_AUTH_BP) {
    fun unconfigureDisplayOnHide() =
        withReason(REASON_AUTH_BP) {
            whenever(udfpsView.isDisplayConfigured).thenReturn(true)

            controllerOverlay.show(udfpsController, overlayParams)
@@ -339,22 +338,22 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
        }

    @Test
    fun matchesRequestIds() = withReason(REASON_AUTH_BP) {
    fun matchesRequestIds() =
        withReason(REASON_AUTH_BP) {
            assertThat(controllerOverlay.matchesRequestId(REQUEST_ID)).isTrue()
            assertThat(controllerOverlay.matchesRequestId(REQUEST_ID + 1)).isFalse()
        }

    @Test
    fun smallOverlayOnEnrollmentWithA11y() = withRotation(Surface.ROTATION_0) {
    fun smallOverlayOnEnrollmentWithA11y() =
        withRotation(Surface.ROTATION_0) {
            withReason(REASON_ENROLL_ENROLLING) {
                // When a11y enabled during enrollment
                whenever(accessibilityManager.isTouchExplorationEnabled).thenReturn(true)

                controllerOverlay.show(udfpsController, overlayParams)
            verify(windowManager).addView(
                    eq(controllerOverlay.getTouchOverlay()),
                    layoutParamsCaptor.capture()
            )
                verify(windowManager)
                    .addView(eq(controllerOverlay.getTouchOverlay()), layoutParamsCaptor.capture())

                // Layout params should use sensor bounds
                val lp = layoutParamsCaptor.value
+12 −1
Original line number Diff line number Diff line
@@ -81,6 +81,8 @@ import com.android.systemui.biometrics.udfps.InteractionEvent;
import com.android.systemui.biometrics.udfps.NormalizedTouchData;
import com.android.systemui.biometrics.udfps.SinglePointerTouchProcessor;
import com.android.systemui.biometrics.udfps.TouchProcessorResult;
import com.android.systemui.biometrics.ui.viewmodel.DefaultUdfpsTouchOverlayViewModel;
import com.android.systemui.biometrics.ui.viewmodel.DeviceEntryUdfpsTouchOverlayViewModel;
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.dump.DumpManager;
@@ -106,6 +108,8 @@ import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
import com.android.systemui.util.time.SystemClock;

import dagger.Lazy;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -241,6 +245,10 @@ public class UdfpsControllerTest extends SysuiTestCase {
    private FpsUnlockTracker mFpsUnlockTracker;
    @Mock
    private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
    @Mock
    private Lazy<DeviceEntryUdfpsTouchOverlayViewModel> mDeviceEntryUdfpsTouchOverlayViewModel;
    @Mock
    private Lazy<DefaultUdfpsTouchOverlayViewModel> mDefaultUdfpsTouchOverlayViewModel;

    @Before
    public void setUp() {
@@ -334,7 +342,10 @@ public class UdfpsControllerTest extends SysuiTestCase {
                mUdfpsKeyguardViewModels,
                mSelectedUserInteractor,
                mFpsUnlockTracker,
                mKeyguardTransitionInteractor
                mKeyguardTransitionInteractor,
                mDeviceEntryUdfpsTouchOverlayViewModel,
                mDefaultUdfpsTouchOverlayViewModel

        );
        verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
        mOverlayController = mOverlayCaptor.getValue();
+2 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static org.mockito.Mockito.when;
import android.content.Context;

import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Flags;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
@@ -94,6 +95,7 @@ public class UdfpsKeyguardViewLegacyControllerBaseTest extends SysuiTestCase {
    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mSetFlagsRule.disableFlags(Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR);
        when(mView.getContext()).thenReturn(mResourceContext);
        when(mResourceContext.getString(anyInt())).thenReturn("test string");
        when(mKeyguardViewMediator.isAnimatingScreenOff()).thenReturn(false);
+2 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import kotlinx.coroutines.test.TestScope
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
@@ -166,6 +167,7 @@ class AlternateBouncerInteractorTest : SysuiTestCase() {
    }

    @Test
    @Ignore("b/287599719")
    fun canShowAlternateBouncerForFingerprint_rearFps() {
        mSetFlagsRule.enableFlags(Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR)
        initializeUnderTest()
+23 −7
Original line number Diff line number Diff line
@@ -74,6 +74,8 @@ import com.android.systemui.biometrics.udfps.NormalizedTouchData;
import com.android.systemui.biometrics.udfps.SinglePointerTouchProcessor;
import com.android.systemui.biometrics.udfps.TouchProcessor;
import com.android.systemui.biometrics.udfps.TouchProcessorResult;
import com.android.systemui.biometrics.ui.viewmodel.DefaultUdfpsTouchOverlayViewModel;
import com.android.systemui.biometrics.ui.viewmodel.DeviceEntryUdfpsTouchOverlayViewModel;
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.dagger.SysUISingleton;
@@ -102,6 +104,8 @@ import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.concurrency.Execution;
import com.android.systemui.util.time.SystemClock;

import dagger.Lazy;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashSet;
@@ -164,6 +168,10 @@ public class UdfpsController implements DozeReceiver, Dumpable {
    @NonNull private final PrimaryBouncerInteractor mPrimaryBouncerInteractor;
    @Nullable private final TouchProcessor mTouchProcessor;
    @NonNull private final SessionTracker mSessionTracker;
    @NonNull private final Lazy<DeviceEntryUdfpsTouchOverlayViewModel>
            mDeviceEntryUdfpsTouchOverlayViewModel;
    @NonNull private final Lazy<DefaultUdfpsTouchOverlayViewModel>
            mDefaultUdfpsTouchOverlayViewModel;
    @NonNull private final AlternateBouncerInteractor mAlternateBouncerInteractor;
    @NonNull private final InputManager mInputManager;
    @NonNull private final UdfpsKeyguardAccessibilityDelegate mUdfpsKeyguardAccessibilityDelegate;
@@ -284,7 +292,9 @@ public class UdfpsController implements DozeReceiver, Dumpable {
                        mAlternateBouncerInteractor,
                        mUdfpsKeyguardAccessibilityDelegate,
                        mKeyguardTransitionInteractor,
                        mSelectedUserInteractor
                        mSelectedUserInteractor,
                        mDeviceEntryUdfpsTouchOverlayViewModel,
                        mDefaultUdfpsTouchOverlayViewModel
                    )));
        }

@@ -501,12 +511,14 @@ public class UdfpsController implements DozeReceiver, Dumpable {
                    + mOverlay.getRequestId());
            return false;
        }
        if (!DeviceEntryUdfpsRefactor.isEnabled()) {
            if ((mLockscreenShadeTransitionController.getQSDragProgress() != 0f
                    && !mAlternateBouncerInteractor.isVisibleState())
                    || mPrimaryBouncerInteractor.isInTransit()) {
                Log.w(TAG, "ignoring touch due to qsDragProcess or primaryBouncerInteractor");
                return false;
            }
        }
        if (event.getAction() == MotionEvent.ACTION_DOWN
                || event.getAction() == MotionEvent.ACTION_HOVER_ENTER) {
            // Reset on ACTION_DOWN, start of new gesture
@@ -657,7 +669,9 @@ public class UdfpsController implements DozeReceiver, Dumpable {
            @NonNull Provider<UdfpsKeyguardViewModels> udfpsKeyguardViewModelsProvider,
            @NonNull SelectedUserInteractor selectedUserInteractor,
            @NonNull FpsUnlockTracker fpsUnlockTracker,
            @NonNull KeyguardTransitionInteractor keyguardTransitionInteractor) {
            @NonNull KeyguardTransitionInteractor keyguardTransitionInteractor,
            Lazy<DeviceEntryUdfpsTouchOverlayViewModel> deviceEntryUdfpsTouchOverlayViewModel,
            Lazy<DefaultUdfpsTouchOverlayViewModel> defaultUdfpsTouchOverlayViewModel) {
        mContext = context;
        mExecution = execution;
        mVibrator = vibrator;
@@ -706,6 +720,8 @@ public class UdfpsController implements DozeReceiver, Dumpable {

        mTouchProcessor = singlePointerTouchProcessor;
        mSessionTracker = sessionTracker;
        mDeviceEntryUdfpsTouchOverlayViewModel = deviceEntryUdfpsTouchOverlayViewModel;
        mDefaultUdfpsTouchOverlayViewModel = defaultUdfpsTouchOverlayViewModel;

        mDumpManager.registerDumpable(TAG, this);

Loading