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

Commit 0444f44e authored by Chandru S's avatar Chandru S Committed by Android (Google) Code Review
Browse files

Merge "Revert "SFPS indicator and BiometricPrompt MVVM cleanup"" into main

parents 60267f64 2c006d11
Loading
Loading
Loading
Loading
+0 −75
Original line number Diff line number Diff line
@@ -27,17 +27,6 @@ import android.hardware.face.FaceSensorProperties
import android.hardware.face.FaceSensorPropertiesInternal
import android.hardware.fingerprint.FingerprintSensorProperties
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import com.android.keyguard.keyguardUpdateMonitor
import com.android.systemui.SysuiTestableContext
import com.android.systemui.biometrics.data.repository.biometricStatusRepository
import com.android.systemui.biometrics.shared.model.AuthenticationReason
import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.res.R
import com.android.systemui.util.mockito.whenever
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent

/** Create [FingerprintSensorPropertiesInternal] for a test. */
internal fun fingerprintSensorPropertiesInternal(
@@ -156,67 +145,3 @@ internal fun promptInfo(
    info.negativeButtonText = negativeButton
    return info
}

@OptIn(ExperimentalCoroutinesApi::class)
internal fun TestScope.updateSfpsIndicatorRequests(
    kosmos: Kosmos,
    mContext: SysuiTestableContext,
    primaryBouncerRequest: Boolean? = null,
    alternateBouncerRequest: Boolean? = null,
    biometricPromptRequest: Boolean? = null,
    // TODO(b/365182034): update when rest to unlock feature is implemented
    //    progressBarShowing: Boolean? = null
) {
    biometricPromptRequest?.let { hasBiometricPromptRequest ->
        if (hasBiometricPromptRequest) {
            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
                AuthenticationReason.BiometricPromptAuthentication
            )
        } else {
            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
                AuthenticationReason.NotRunning
            )
        }
    }

    primaryBouncerRequest?.let { hasPrimaryBouncerRequest ->
        updatePrimaryBouncer(
            kosmos,
            mContext,
            isShowing = hasPrimaryBouncerRequest,
            isAnimatingAway = false,
            fpsDetectionRunning = true,
            isUnlockingWithFpAllowed = true
        )
    }

    alternateBouncerRequest?.let { hasAlternateBouncerRequest ->
        kosmos.keyguardBouncerRepository.setAlternateVisible(hasAlternateBouncerRequest)
    }

    // TODO(b/365182034): set progress bar visibility when rest to unlock feature is implemented

    runCurrent()
}

internal fun updatePrimaryBouncer(
    kosmos: Kosmos,
    mContext: SysuiTestableContext,
    isShowing: Boolean,
    isAnimatingAway: Boolean,
    fpsDetectionRunning: Boolean,
    isUnlockingWithFpAllowed: Boolean,
) {
    kosmos.keyguardBouncerRepository.setPrimaryShow(isShowing)
    kosmos.keyguardBouncerRepository.setPrimaryStartingToHide(false)
    val primaryStartDisappearAnimation = if (isAnimatingAway) Runnable {} else null
    kosmos.keyguardBouncerRepository.setPrimaryStartDisappearAnimation(
        primaryStartDisappearAnimation
    )

    whenever(kosmos.keyguardUpdateMonitor.isFingerprintDetectionRunning)
        .thenReturn(fpsDetectionRunning)
    whenever(kosmos.keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed)
        .thenReturn(isUnlockingWithFpAllowed)
    mContext.orCreateTestableResources.addOverride(R.bool.config_show_sidefps_hint_on_bouncer, true)
}
+0 −174
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.biometrics.domain.interactor

import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.data.repository.biometricStatusRepository
import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
import com.android.systemui.biometrics.shared.model.AuthenticationReason
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
import com.android.systemui.biometrics.shared.model.SensorStrength
import com.android.systemui.biometrics.updateSfpsIndicatorRequests
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.display.data.repository.displayRepository
import com.android.systemui.display.data.repository.displayStateRepository
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith

@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
class SideFpsOverlayInteractorTest : SysuiTestCase() {
    private val kosmos = testKosmos()
    private val underTest = kosmos.sideFpsOverlayInteractor

    @Test
    fun verifyIsShowingFalse_whenInRearDisplayMode() {
        kosmos.testScope.runTest {
            val isShowing by collectLastValue(underTest.isShowing)
            setupTestConfiguration(isInRearDisplayMode = true)

            updateSfpsIndicatorRequests(kosmos, mContext, primaryBouncerRequest = true)
            runCurrent()

            assertThat(isShowing).isFalse()
        }
    }

    @Test
    fun verifyIsShowingUpdates_onPrimaryBouncerShowAndHide() {
        kosmos.testScope.runTest {
            val isShowing by collectLastValue(underTest.isShowing)
            setupTestConfiguration(isInRearDisplayMode = false)

            // Show primary bouncer
            updateSfpsIndicatorRequests(kosmos, mContext, primaryBouncerRequest = true)
            runCurrent()

            assertThat(isShowing).isTrue()

            // Hide primary bouncer
            updateSfpsIndicatorRequests(kosmos, mContext, primaryBouncerRequest = false)
            runCurrent()

            assertThat(isShowing).isFalse()
        }
    }

    @Test
    fun verifyIsShowingUpdates_onAlternateBouncerShowAndHide() {
        kosmos.testScope.runTest {
            val isShowing by collectLastValue(underTest.isShowing)
            setupTestConfiguration(isInRearDisplayMode = false)

            updateSfpsIndicatorRequests(kosmos, mContext, alternateBouncerRequest = true)
            runCurrent()

            assertThat(isShowing).isTrue()

            // Hide alternate bouncer
            updateSfpsIndicatorRequests(kosmos, mContext, alternateBouncerRequest = false)
            runCurrent()

            assertThat(isShowing).isFalse()
        }
    }

    @Test
    fun verifyIsShowingUpdates_onSystemServerAuthenticationStartedAndStopped() {
        kosmos.testScope.runTest {
            val isShowing by collectLastValue(underTest.isShowing)
            setupTestConfiguration(isInRearDisplayMode = false)

            updateSfpsIndicatorRequests(kosmos, mContext, biometricPromptRequest = true)
            runCurrent()

            assertThat(isShowing).isTrue()

            // System server authentication stopped
            updateSfpsIndicatorRequests(kosmos, mContext, biometricPromptRequest = false)
            runCurrent()

            assertThat(isShowing).isFalse()
        }
    }

    // On progress bar shown - hide indicator
    // On progress bar hidden - show indicator
    // TODO(b/365182034): update + enable when rest to unlock feature is implemented
    @Ignore("b/365182034")
    @Test
    fun verifyIsShowingUpdates_onProgressBarInteraction() {
        kosmos.testScope.runTest {
            val isShowing by collectLastValue(underTest.isShowing)
            setupTestConfiguration(isInRearDisplayMode = false)

            updateSfpsIndicatorRequests(kosmos, mContext, primaryBouncerRequest = true)
            runCurrent()

            assertThat(isShowing).isTrue()

            //            updateSfpsIndicatorRequests(
            //                kosmos, mContext, primaryBouncerRequest = true, progressBarShowing =
            // true
            //            )
            runCurrent()

            assertThat(isShowing).isFalse()

            // Set progress bar invisible
            //            updateSfpsIndicatorRequests(
            //                kosmos, mContext, primaryBouncerRequest = true, progressBarShowing =
            // false
            //            )
            runCurrent()

            // Verify indicator shown
            assertThat(isShowing).isTrue()
        }
    }

    private suspend fun TestScope.setupTestConfiguration(isInRearDisplayMode: Boolean) {
        kosmos.fingerprintPropertyRepository.setProperties(
            sensorId = 1,
            strength = SensorStrength.STRONG,
            sensorType = FingerprintSensorType.POWER_BUTTON,
            sensorLocations = emptyMap()
        )

        kosmos.displayStateRepository.setIsInRearDisplayMode(isInRearDisplayMode)
        kosmos.displayRepository.emitDisplayChangeEvent(0)
        runCurrent()

        kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
            AuthenticationReason.NotRunning
        )
        // TODO(b/365182034): set progress bar visibility once rest to unlock feature is implemented
    }
}
+223 −32

File changed.

Preview size limit exceeded, changes collapsed.

+61 −4
Original line number Diff line number Diff line
@@ -30,19 +30,23 @@ import android.view.windowManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.airbnb.lottie.model.KeyPath
import com.android.keyguard.keyguardUpdateMonitor
import com.android.settingslib.Utils
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider
import com.android.systemui.biometrics.data.repository.biometricStatusRepository
import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
import com.android.systemui.biometrics.domain.interactor.displayStateInteractor
import com.android.systemui.biometrics.shared.model.AuthenticationReason
import com.android.systemui.biometrics.shared.model.DisplayRotation
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
import com.android.systemui.biometrics.shared.model.LottieCallback
import com.android.systemui.biometrics.shared.model.SensorStrength
import com.android.systemui.biometrics.updateSfpsIndicatorRequests
import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.display.data.repository.displayRepository
import com.android.systemui.display.data.repository.displayStateRepository
import com.android.systemui.keyguard.ui.viewmodel.sideFpsProgressBarViewModel
import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
import com.android.systemui.testKosmos
@@ -280,7 +284,17 @@ class SideFpsOverlayViewModelTest : SysuiTestCase() {
        kosmos.testScope.runTest {
            val lottieCallbacks by collectLastValue(kosmos.sideFpsOverlayViewModel.lottieCallbacks)

            updateSfpsIndicatorRequests(kosmos, mContext, primaryBouncerRequest = true)
            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
                AuthenticationReason.NotRunning
            )
            kosmos.sideFpsProgressBarViewModel.setVisible(false)

            updatePrimaryBouncer(
                isShowing = true,
                isAnimatingAway = false,
                fpsDetectionRunning = true,
                isUnlockingWithFpAllowed = true
            )
            runCurrent()

            assertThat(lottieCallbacks)
@@ -298,7 +312,17 @@ class SideFpsOverlayViewModelTest : SysuiTestCase() {
            val lottieCallbacks by collectLastValue(kosmos.sideFpsOverlayViewModel.lottieCallbacks)
            setDarkMode(true)

            updateSfpsIndicatorRequests(kosmos, mContext, biometricPromptRequest = true)
            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
                AuthenticationReason.BiometricPromptAuthentication
            )
            kosmos.sideFpsProgressBarViewModel.setVisible(false)

            updatePrimaryBouncer(
                isShowing = false,
                isAnimatingAway = false,
                fpsDetectionRunning = true,
                isUnlockingWithFpAllowed = true
            )
            runCurrent()

            assertThat(lottieCallbacks)
@@ -314,7 +338,17 @@ class SideFpsOverlayViewModelTest : SysuiTestCase() {
            val lottieCallbacks by collectLastValue(kosmos.sideFpsOverlayViewModel.lottieCallbacks)
            setDarkMode(false)

            updateSfpsIndicatorRequests(kosmos, mContext, biometricPromptRequest = true)
            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
                AuthenticationReason.BiometricPromptAuthentication
            )
            kosmos.sideFpsProgressBarViewModel.setVisible(false)

            updatePrimaryBouncer(
                isShowing = false,
                isAnimatingAway = false,
                fpsDetectionRunning = true,
                isUnlockingWithFpAllowed = true
            )
            runCurrent()

            assertThat(lottieCallbacks)
@@ -337,6 +371,29 @@ class SideFpsOverlayViewModelTest : SysuiTestCase() {
        mContext.resources.configuration.uiMode = uiMode
    }

    private fun updatePrimaryBouncer(
        isShowing: Boolean,
        isAnimatingAway: Boolean,
        fpsDetectionRunning: Boolean,
        isUnlockingWithFpAllowed: Boolean,
    ) {
        kosmos.keyguardBouncerRepository.setPrimaryShow(isShowing)
        kosmos.keyguardBouncerRepository.setPrimaryStartingToHide(false)
        val primaryStartDisappearAnimation = if (isAnimatingAway) Runnable {} else null
        kosmos.keyguardBouncerRepository.setPrimaryStartDisappearAnimation(
            primaryStartDisappearAnimation
        )

        whenever(kosmos.keyguardUpdateMonitor.isFingerprintDetectionRunning)
            .thenReturn(fpsDetectionRunning)
        whenever(kosmos.keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed)
            .thenReturn(isUnlockingWithFpAllowed)
        mContext.orCreateTestableResources.addOverride(
            R.bool.config_show_sidefps_hint_on_bouncer,
            true
        )
    }

    private suspend fun TestScope.setupTestConfiguration(
        deviceConfig: DeviceConfig,
        rotation: DisplayRotation = DisplayRotation.ROTATION_0,
+13 −0
Original line number Diff line number Diff line
@@ -215,4 +215,17 @@
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="1.0"
        tools:srcCompat="@tools:sample/avatars" />

    <com.android.systemui.biometrics.BiometricPromptLottieViewWrapper
        android:id="@+id/biometric_icon_overlay"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_gravity="center"
        android:contentDescription="@null"
        android:scaleType="fitXY"
        android:importantForAccessibility="no"
        app:layout_constraintBottom_toBottomOf="@+id/biometric_icon"
        app:layout_constraintEnd_toEndOf="@+id/biometric_icon"
        app:layout_constraintStart_toStartOf="@+id/biometric_icon"
        app:layout_constraintTop_toTopOf="@+id/biometric_icon" />
</androidx.constraintlayout.widget.ConstraintLayout>
Loading