diff options
| author | 2024-09-23 22:44:15 +0000 | |
|---|---|---|
| committer | 2024-09-24 00:16:27 +0000 | |
| commit | 2c006d11ea5bf5dfb77b14d57764e3ed7c26e431 (patch) | |
| tree | 3069d67b28ba1f34c7b15692fa8b783c213602d2 | |
| parent | c244eb6595d080a755a947a049f4a28e3dc47382 (diff) | |
Revert "SFPS indicator and BiometricPrompt MVVM cleanup"
This reverts commit c244eb6595d080a755a947a049f4a28e3dc47382.
Reason for revert: Reverting to verify locally if this is causing the recent issues around Side FPS indicator not showing up.
Fixes: 361209015
Fixes: 367706213
Change-Id: Ic2ffd5a1f4420121b958cadb726c3e805cda1434
17 files changed, 424 insertions, 461 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt index 4bc71fd6d363..75a77cf781d2 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt @@ -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) -} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/SideFpsOverlayInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/SideFpsOverlayInteractorTest.kt deleted file mode 100644 index 298b54a5be5a..000000000000 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/SideFpsOverlayInteractorTest.kt +++ /dev/null @@ -1,174 +0,0 @@ -/* - * 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 - } -} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt index 2eea6681ecca..7fa165c19f60 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt @@ -16,48 +16,64 @@ package com.android.systemui.biometrics.ui.binder +import android.animation.Animator +import android.graphics.Rect +import android.hardware.biometrics.SensorLocationInternal +import android.hardware.display.DisplayManager +import android.hardware.display.DisplayManagerGlobal import android.testing.TestableLooper +import android.view.Display +import android.view.DisplayInfo import android.view.LayoutInflater import android.view.View +import android.view.ViewPropertyAnimator +import android.view.WindowInsets import android.view.WindowManager +import android.view.WindowMetrics import android.view.layoutInflater import android.view.windowManager import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.airbnb.lottie.LottieAnimationView +import com.android.keyguard.keyguardUpdateMonitor 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.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.SensorStrength -import com.android.systemui.biometrics.updateSfpsIndicatorRequests +import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository 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 import com.android.systemui.util.mockito.eq +import com.android.systemui.util.mockito.whenever import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before -import org.junit.Ignore import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import org.mockito.ArgumentCaptor -import org.mockito.Captor import org.mockito.Mock +import org.mockito.Mockito import org.mockito.Mockito.any import org.mockito.Mockito.inOrder import org.mockito.Mockito.mock import org.mockito.Mockito.never +import org.mockito.Mockito.spy import org.mockito.Mockito.verify import org.mockito.Mockito.`when` import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoRule -import org.mockito.kotlin.firstValue +import org.mockito.kotlin.argumentCaptor @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @@ -67,25 +83,84 @@ class SideFpsOverlayViewBinderTest : SysuiTestCase() { private val kosmos = testKosmos() @JvmField @Rule var mockitoRule: MockitoRule = MockitoJUnit.rule() + @Mock private lateinit var displayManager: DisplayManager + @Mock + private lateinit var fingerprintInteractiveToAuthProvider: FingerprintInteractiveToAuthProvider @Mock private lateinit var layoutInflater: LayoutInflater @Mock private lateinit var sideFpsView: View - @Captor private lateinit var viewCaptor: ArgumentCaptor<View> + + private val contextDisplayInfo = DisplayInfo() + + private var displayWidth: Int = 0 + private var displayHeight: Int = 0 + private var boundsWidth: Int = 0 + private var boundsHeight: Int = 0 + + private lateinit var deviceConfig: DeviceConfig + private lateinit var sensorLocation: SensorLocationInternal + + enum class DeviceConfig { + X_ALIGNED, + Y_ALIGNED, + } @Before fun setup() { allowTestableLooperAsMainThread() // repeatWhenAttached requires the main thread + + mContext = spy(mContext) + + val resources = mContext.resources + whenever(mContext.display) + .thenReturn( + Display(mock(DisplayManagerGlobal::class.java), 1, contextDisplayInfo, resources) + ) + kosmos.layoutInflater = layoutInflater + + whenever(fingerprintInteractiveToAuthProvider.enabledForCurrentUser) + .thenReturn(MutableStateFlow(false)) + + context.addMockSystemService(DisplayManager::class.java, displayManager) context.addMockSystemService(WindowManager::class.java, kosmos.windowManager) + `when`(layoutInflater.inflate(R.layout.sidefps_view, null, false)).thenReturn(sideFpsView) `when`(sideFpsView.requireViewById<LottieAnimationView>(eq(R.id.sidefps_animation))) .thenReturn(mock(LottieAnimationView::class.java)) + with(mock(ViewPropertyAnimator::class.java)) { + `when`(sideFpsView.animate()).thenReturn(this) + `when`(alpha(Mockito.anyFloat())).thenReturn(this) + `when`(setStartDelay(Mockito.anyLong())).thenReturn(this) + `when`(setDuration(Mockito.anyLong())).thenReturn(this) + `when`(setListener(any())).thenAnswer { + (it.arguments[0] as Animator.AnimatorListener).onAnimationEnd( + mock(Animator::class.java) + ) + this + } + } } @Test fun verifyIndicatorNotAdded_whenInRearDisplayMode() { kosmos.testScope.runTest { - setupTestConfiguration(isInRearDisplayMode = true) - updateSfpsIndicatorRequests(kosmos, mContext, primaryBouncerRequest = true) + setupTestConfiguration( + DeviceConfig.X_ALIGNED, + rotation = DisplayRotation.ROTATION_0, + isInRearDisplayMode = true + ) + kosmos.biometricStatusRepository.setFingerprintAuthenticationReason( + AuthenticationReason.NotRunning + ) + kosmos.sideFpsProgressBarViewModel.setVisible(false) + updatePrimaryBouncer( + isShowing = true, + isAnimatingAway = false, + fpsDetectionRunning = true, + isUnlockingWithFpAllowed = true + ) + runCurrent() + verify(kosmos.windowManager, never()).addView(any(), any()) } } @@ -93,14 +168,33 @@ class SideFpsOverlayViewBinderTest : SysuiTestCase() { @Test fun verifyIndicatorShowAndHide_onPrimaryBouncerShowAndHide() { kosmos.testScope.runTest { - setupTestConfiguration(isInRearDisplayMode = false) - updateSfpsIndicatorRequests(kosmos, mContext, primaryBouncerRequest = true) + setupTestConfiguration( + DeviceConfig.X_ALIGNED, + rotation = DisplayRotation.ROTATION_0, + isInRearDisplayMode = false + ) + kosmos.biometricStatusRepository.setFingerprintAuthenticationReason( + AuthenticationReason.NotRunning + ) + kosmos.sideFpsProgressBarViewModel.setVisible(false) + // Show primary bouncer + updatePrimaryBouncer( + isShowing = true, + isAnimatingAway = false, + fpsDetectionRunning = true, + isUnlockingWithFpAllowed = true + ) runCurrent() verify(kosmos.windowManager).addView(any(), any()) // Hide primary bouncer - updateSfpsIndicatorRequests(kosmos, mContext, primaryBouncerRequest = false) + updatePrimaryBouncer( + isShowing = false, + isAnimatingAway = false, + fpsDetectionRunning = true, + isUnlockingWithFpAllowed = true + ) runCurrent() verify(kosmos.windowManager).removeView(any()) @@ -110,19 +204,30 @@ class SideFpsOverlayViewBinderTest : SysuiTestCase() { @Test fun verifyIndicatorShowAndHide_onAlternateBouncerShowAndHide() { kosmos.testScope.runTest { - setupTestConfiguration(isInRearDisplayMode = false) - updateSfpsIndicatorRequests(kosmos, mContext, alternateBouncerRequest = true) + setupTestConfiguration( + DeviceConfig.X_ALIGNED, + rotation = DisplayRotation.ROTATION_0, + isInRearDisplayMode = false + ) + kosmos.biometricStatusRepository.setFingerprintAuthenticationReason( + AuthenticationReason.NotRunning + ) + kosmos.sideFpsProgressBarViewModel.setVisible(false) + // Show alternate bouncer + kosmos.keyguardBouncerRepository.setAlternateVisible(true) runCurrent() verify(kosmos.windowManager).addView(any(), any()) + var viewCaptor = argumentCaptor<View>() verify(kosmos.windowManager).addView(viewCaptor.capture(), any()) verify(viewCaptor.firstValue) .announceForAccessibility( mContext.getText(R.string.accessibility_side_fingerprint_indicator_label) ) - updateSfpsIndicatorRequests(kosmos, mContext, alternateBouncerRequest = false) + // Hide alternate bouncer + kosmos.keyguardBouncerRepository.setAlternateVisible(false) runCurrent() verify(kosmos.windowManager).removeView(any()) @@ -132,14 +237,30 @@ class SideFpsOverlayViewBinderTest : SysuiTestCase() { @Test fun verifyIndicatorShownAndHidden_onSystemServerAuthenticationStartedAndStopped() { kosmos.testScope.runTest { - setupTestConfiguration(isInRearDisplayMode = false) - updateSfpsIndicatorRequests(kosmos, mContext, biometricPromptRequest = true) + setupTestConfiguration( + DeviceConfig.X_ALIGNED, + rotation = DisplayRotation.ROTATION_0, + isInRearDisplayMode = false + ) + kosmos.sideFpsProgressBarViewModel.setVisible(false) + updatePrimaryBouncer( + isShowing = false, + isAnimatingAway = false, + fpsDetectionRunning = true, + isUnlockingWithFpAllowed = true + ) + // System server authentication started + kosmos.biometricStatusRepository.setFingerprintAuthenticationReason( + AuthenticationReason.BiometricPromptAuthentication + ) runCurrent() verify(kosmos.windowManager).addView(any(), any()) // System server authentication stopped - updateSfpsIndicatorRequests(kosmos, mContext, biometricPromptRequest = false) + kosmos.biometricStatusRepository.setFingerprintAuthenticationReason( + AuthenticationReason.NotRunning + ) runCurrent() verify(kosmos.windowManager).removeView(any()) @@ -148,35 +269,45 @@ class SideFpsOverlayViewBinderTest : SysuiTestCase() { // 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 verifyIndicatorProgressBarInteraction() { kosmos.testScope.runTest { // Pre-auth conditions - setupTestConfiguration(isInRearDisplayMode = false) - updateSfpsIndicatorRequests(kosmos, mContext, primaryBouncerRequest = true) + setupTestConfiguration( + DeviceConfig.X_ALIGNED, + rotation = DisplayRotation.ROTATION_0, + isInRearDisplayMode = false + ) + kosmos.biometricStatusRepository.setFingerprintAuthenticationReason( + AuthenticationReason.NotRunning + ) + kosmos.sideFpsProgressBarViewModel.setVisible(false) + + // Show primary bouncer + updatePrimaryBouncer( + isShowing = true, + isAnimatingAway = false, + fpsDetectionRunning = true, + isUnlockingWithFpAllowed = true + ) runCurrent() val inOrder = inOrder(kosmos.windowManager) + // Verify indicator shown inOrder.verify(kosmos.windowManager).addView(any(), any()) // Set progress bar visible - // updateSfpsIndicatorRequests( - // kosmos, mContext, primaryBouncerRequest = true, progressBarShowing = - // true - // ) + kosmos.sideFpsProgressBarViewModel.setVisible(true) + runCurrent() // Verify indicator hidden inOrder.verify(kosmos.windowManager).removeView(any()) // Set progress bar invisible - // updateSfpsIndicatorRequests( - // kosmos, mContext, primaryBouncerRequest = true, progressBarShowing = - // false - // ) + kosmos.sideFpsProgressBarViewModel.setVisible(false) + runCurrent() // Verify indicator shown @@ -184,18 +315,78 @@ class SideFpsOverlayViewBinderTest : SysuiTestCase() { } } - private suspend fun TestScope.setupTestConfiguration(isInRearDisplayMode: Boolean) { + 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, + isInRearDisplayMode: Boolean, + ) { + this@SideFpsOverlayViewBinderTest.deviceConfig = deviceConfig + + when (deviceConfig) { + DeviceConfig.X_ALIGNED -> { + displayWidth = 3000 + displayHeight = 1500 + boundsWidth = 200 + boundsHeight = 100 + sensorLocation = SensorLocationInternal("", 2500, 0, boundsWidth / 2) + } + DeviceConfig.Y_ALIGNED -> { + displayWidth = 2500 + displayHeight = 2000 + boundsWidth = 100 + boundsHeight = 200 + sensorLocation = SensorLocationInternal("", displayWidth, 300, boundsHeight / 2) + } + } + + whenever(kosmos.windowManager.maximumWindowMetrics) + .thenReturn( + WindowMetrics( + Rect(0, 0, displayWidth, displayHeight), + mock(WindowInsets::class.java), + ) + ) + + contextDisplayInfo.uniqueId = DISPLAY_ID + kosmos.fingerprintPropertyRepository.setProperties( sensorId = 1, strength = SensorStrength.STRONG, sensorType = FingerprintSensorType.POWER_BUTTON, - sensorLocations = emptyMap() + sensorLocations = mapOf(DISPLAY_ID to sensorLocation) ) kosmos.displayStateRepository.setIsInRearDisplayMode(isInRearDisplayMode) - kosmos.displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_0) + kosmos.displayStateRepository.setCurrentRotation(rotation) kosmos.displayRepository.emitDisplayChangeEvent(0) kosmos.sideFpsOverlayViewBinder.start() runCurrent() } + + companion object { + private const val DISPLAY_ID = "displayId" + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt index 27b1371deb12..0db7b62b8ef1 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt @@ -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, diff --git a/packages/SystemUI/res/layout/biometric_prompt_one_pane_layout.xml b/packages/SystemUI/res/layout/biometric_prompt_one_pane_layout.xml index 91cd019c85d1..3b3ed39c8993 100644 --- a/packages/SystemUI/res/layout/biometric_prompt_one_pane_layout.xml +++ b/packages/SystemUI/res/layout/biometric_prompt_one_pane_layout.xml @@ -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> diff --git a/packages/SystemUI/res/layout/biometric_prompt_two_pane_layout.xml b/packages/SystemUI/res/layout/biometric_prompt_two_pane_layout.xml index 51117a7845df..2a00495e9d01 100644 --- a/packages/SystemUI/res/layout/biometric_prompt_two_pane_layout.xml +++ b/packages/SystemUI/res/layout/biometric_prompt_two_pane_layout.xml @@ -40,6 +40,19 @@ android:layout_height="match_parent"> app:layout_constraintTop_toTopOf="parent" 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" /> + <ScrollView android:id="@+id/scrollView" android:layout_width="0dp" diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/BiometricsDomainLayerModule.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/BiometricsDomainLayerModule.kt index 7ecbb88099cb..ec3fd9f7da35 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/BiometricsDomainLayerModule.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/BiometricsDomainLayerModule.kt @@ -25,8 +25,6 @@ import com.android.systemui.biometrics.domain.interactor.LogContextInteractor import com.android.systemui.biometrics.domain.interactor.LogContextInteractorImpl import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractorImpl -import com.android.systemui.biometrics.domain.interactor.SideFpsOverlayInteractor -import com.android.systemui.biometrics.domain.interactor.SideFpsOverlayInteractorImpl import com.android.systemui.dagger.SysUISingleton import dagger.Binds import dagger.Module @@ -48,12 +46,6 @@ interface BiometricsDomainLayerModule { @Binds @SysUISingleton - fun providesSideFpsOverlayInteractor( - impl: SideFpsOverlayInteractorImpl - ): SideFpsOverlayInteractor - - @Binds - @SysUISingleton fun providesCredentialInteractor(impl: CredentialInteractorImpl): CredentialInteractor @Binds diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsOverlayInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsOverlayInteractor.kt deleted file mode 100644 index 10c3483de452..000000000000 --- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsOverlayInteractor.kt +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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.util.Log -import com.android.systemui.biometrics.shared.model.AuthenticationReason.NotRunning -import com.android.systemui.keyguard.domain.interactor.DeviceEntrySideFpsOverlayInteractor -import com.android.systemui.util.kotlin.sample -import javax.inject.Inject -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.flatMapLatest -import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.flow.onEach - -/** Encapsulates business logic for showing and hiding the side fingerprint sensor indicator. */ -interface SideFpsOverlayInteractor { - /** Whether the side fingerprint sensor indicator is currently showing. */ - val isShowing: Flow<Boolean> -} - -@OptIn(ExperimentalCoroutinesApi::class) -class SideFpsOverlayInteractorImpl -@Inject -constructor( - biometricStatusInteractor: BiometricStatusInteractor, - displayStateInteractor: DisplayStateInteractor, - deviceEntrySideFpsOverlayInteractor: DeviceEntrySideFpsOverlayInteractor, - sfpsSensorInteractor: SideFpsSensorInteractor, - // TODO(b/365182034): add progress bar input when rest to unlock feature is implemented -) : SideFpsOverlayInteractor { - private val sfpsOverlayEnabled: Flow<Boolean> = - sfpsSensorInteractor.isAvailable.sample(displayStateInteractor.isInRearDisplayMode) { - isAvailable: Boolean, - isInRearDisplayMode: Boolean -> - isAvailable && !isInRearDisplayMode - } - - private val showSideFpsOverlay: Flow<Boolean> = - combine( - biometricStatusInteractor.sfpsAuthenticationReason, - deviceEntrySideFpsOverlayInteractor.showIndicatorForDeviceEntry, - // TODO(b/365182034): add progress bar input when rest to unlock feature is implemented - ) { systemServerAuthReason, showIndicatorForDeviceEntry -> - Log.d( - TAG, - "systemServerAuthReason = $systemServerAuthReason, " + - "showIndicatorForDeviceEntry = $showIndicatorForDeviceEntry, " - ) - systemServerAuthReason != NotRunning || showIndicatorForDeviceEntry - } - - override val isShowing: Flow<Boolean> = - sfpsOverlayEnabled - .flatMapLatest { sfpsOverlayEnabled -> - if (!sfpsOverlayEnabled) { - flowOf(false) - } else { - showSideFpsOverlay - } - } - .onEach { Log.d(TAG, "isShowing: $it") } - - companion object { - private const val TAG = "SideFpsOverlayInteractor" - } -} diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt index a15765e5641f..85c3ae3f214e 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt @@ -18,11 +18,13 @@ package com.android.systemui.biometrics.ui.binder import android.animation.Animator import android.animation.AnimatorSet +import android.animation.ValueAnimator import android.graphics.Outline import android.graphics.Rect import android.transition.AutoTransition import android.transition.TransitionManager import android.util.TypedValue +import android.view.Surface import android.view.View import android.view.ViewGroup import android.view.ViewOutlineProvider @@ -158,13 +160,16 @@ object BiometricViewSizeBinder { fun setVisibilities(hideSensorIcon: Boolean, size: PromptSize) { viewsToHideWhenSmall.forEach { it.showContentOrHide(forceHide = size.isSmall) } largeConstraintSet.setVisibility(iconHolderView.id, View.GONE) + largeConstraintSet.setVisibility(R.id.biometric_icon_overlay, View.GONE) largeConstraintSet.setVisibility(R.id.indicator, View.GONE) largeConstraintSet.setVisibility(R.id.scrollView, View.GONE) if (hideSensorIcon) { smallConstraintSet.setVisibility(iconHolderView.id, View.GONE) + smallConstraintSet.setVisibility(R.id.biometric_icon_overlay, View.GONE) smallConstraintSet.setVisibility(R.id.indicator, View.GONE) mediumConstraintSet.setVisibility(iconHolderView.id, View.GONE) + mediumConstraintSet.setVisibility(R.id.biometric_icon_overlay, View.GONE) mediumConstraintSet.setVisibility(R.id.indicator, View.GONE) } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt index 9fe1dc51f4c2..9578da4238ee 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt @@ -33,44 +33,89 @@ import com.airbnb.lottie.LottieProperty import com.android.app.animation.Interpolators import com.android.keyguard.KeyguardPINView import com.android.systemui.CoreStartable -import com.android.systemui.biometrics.domain.interactor.SideFpsOverlayInteractor +import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractor +import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor +import com.android.systemui.biometrics.domain.interactor.SideFpsSensorInteractor +import com.android.systemui.biometrics.shared.model.AuthenticationReason.NotRunning import com.android.systemui.biometrics.shared.model.LottieCallback import com.android.systemui.biometrics.ui.viewmodel.SideFpsOverlayViewModel import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.keyguard.domain.interactor.DeviceEntrySideFpsOverlayInteractor +import com.android.systemui.keyguard.ui.viewmodel.SideFpsProgressBarViewModel import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.res.R +import com.android.systemui.util.kotlin.sample import dagger.Lazy import javax.inject.Inject import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.launch /** Binds the side fingerprint sensor indicator view to [SideFpsOverlayViewModel]. */ +@OptIn(ExperimentalCoroutinesApi::class) @SysUISingleton class SideFpsOverlayViewBinder @Inject constructor( @Application private val applicationScope: CoroutineScope, @Application private val applicationContext: Context, + private val biometricStatusInteractor: Lazy<BiometricStatusInteractor>, + private val displayStateInteractor: Lazy<DisplayStateInteractor>, + private val deviceEntrySideFpsOverlayInteractor: Lazy<DeviceEntrySideFpsOverlayInteractor>, private val layoutInflater: Lazy<LayoutInflater>, - private val sideFpsOverlayInteractor: Lazy<SideFpsOverlayInteractor>, - private val sideFpsOverlayViewModel: Lazy<SideFpsOverlayViewModel>, + private val sideFpsProgressBarViewModel: Lazy<SideFpsProgressBarViewModel>, + private val sfpsSensorInteractor: Lazy<SideFpsSensorInteractor>, private val windowManager: Lazy<WindowManager> ) : CoreStartable { - private var overlayView: View? = null override fun start() { - applicationScope.launch { - sideFpsOverlayInteractor.get().isShowing.collect { isShowing: Boolean -> - if (isShowing) { - show() - } else { - hide() + applicationScope + .launch { + sfpsSensorInteractor.get().isAvailable.collect { isSfpsAvailable -> + if (isSfpsAvailable) { + combine( + biometricStatusInteractor.get().sfpsAuthenticationReason, + deviceEntrySideFpsOverlayInteractor + .get() + .showIndicatorForDeviceEntry, + sideFpsProgressBarViewModel.get().isVisible, + ::Triple + ) + .sample(displayStateInteractor.get().isInRearDisplayMode, ::Pair) + .collect { (combinedFlows, isInRearDisplayMode: Boolean) -> + val ( + systemServerAuthReason, + showIndicatorForDeviceEntry, + progressBarIsVisible) = + combinedFlows + Log.d( + TAG, + "systemServerAuthReason = $systemServerAuthReason, " + + "showIndicatorForDeviceEntry = " + + "$showIndicatorForDeviceEntry, " + + "progressBarIsVisible = $progressBarIsVisible" + ) + if (!isInRearDisplayMode) { + if (progressBarIsVisible) { + hide() + } else if (systemServerAuthReason != NotRunning) { + show() + } else if (showIndicatorForDeviceEntry) { + show() + } else { + hide() + } + } + } + } } } - } } + private var overlayView: View? = null + /** Show the side fingerprint sensor indicator */ private fun show() { if (overlayView?.isAttachedToWindow == true) { @@ -80,10 +125,17 @@ constructor( ) return } + overlayView = layoutInflater.get().inflate(R.layout.sidefps_view, null, false) - val overlayViewModel = sideFpsOverlayViewModel.get() - bind(overlayView!!, overlayViewModel, windowManager.get()) + val overlayViewModel = + SideFpsOverlayViewModel( + applicationContext, + deviceEntrySideFpsOverlayInteractor.get(), + displayStateInteractor.get(), + sfpsSensorInteractor.get(), + ) + bind(overlayView!!, overlayViewModel, windowManager.get()) overlayView!!.visibility = View.INVISIBLE Log.d(TAG, "show(): adding overlayView $overlayView") windowManager.get().addView(overlayView, overlayViewModel.defaultOverlayViewParams) @@ -109,20 +161,6 @@ constructor( companion object { private const val TAG = "SideFpsOverlayViewBinder" - private val accessibilityDelegate = - object : View.AccessibilityDelegate() { - override fun dispatchPopulateAccessibilityEvent( - host: View, - event: AccessibilityEvent - ): Boolean { - return if (event.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) { - true - } else { - super.dispatchPopulateAccessibilityEvent(host, event) - } - } - } - /** Binds overlayView (side fingerprint sensor indicator view) to SideFpsOverlayViewModel */ fun bind( overlayView: View, @@ -146,7 +184,24 @@ constructor( overlayShowAnimator.start() - it.accessibilityDelegate = accessibilityDelegate + it.setAccessibilityDelegate( + object : View.AccessibilityDelegate() { + override fun dispatchPopulateAccessibilityEvent( + host: View, + event: AccessibilityEvent + ): Boolean { + return if ( + event.getEventType() === + android.view.accessibility.AccessibilityEvent + .TYPE_WINDOW_STATE_CHANGED + ) { + true + } else { + super.dispatchPopulateAccessibilityEvent(host, event) + } + } + } + ) repeatOnLifecycle(Lifecycle.State.STARTED) { launch { diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt index 90cd86f72140..4c2fe07f92bb 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt @@ -74,11 +74,11 @@ import kotlinx.coroutines.launch class PromptViewModel @Inject constructor( - private val displayStateInteractor: DisplayStateInteractor, + displayStateInteractor: DisplayStateInteractor, private val promptSelectorInteractor: PromptSelectorInteractor, @Application private val context: Context, - udfpsOverlayInteractor: UdfpsOverlayInteractor, - biometricStatusInteractor: BiometricStatusInteractor, + private val udfpsOverlayInteractor: UdfpsOverlayInteractor, + private val biometricStatusInteractor: BiometricStatusInteractor, private val udfpsUtils: UdfpsUtils, private val iconProvider: IconProvider, private val activityTaskManager: ActivityTaskManager, @@ -131,13 +131,11 @@ constructor( R.dimen.biometric_prompt_landscape_medium_horizontal_padding ) - val currentRotation: StateFlow<DisplayRotation> = displayStateInteractor.currentRotation - val udfpsOverlayParams: StateFlow<UdfpsOverlayParams> = udfpsOverlayInteractor.udfpsOverlayParams private val udfpsSensorBounds: Flow<Rect> = - combine(udfpsOverlayParams, currentRotation) { params, rotation -> + combine(udfpsOverlayParams, displayStateInteractor.currentRotation) { params, rotation -> val rotatedBounds = Rect(params.sensorBounds) RotationUtils.rotateBounds( rotatedBounds, @@ -259,7 +257,7 @@ constructor( _forceLargeSize, promptKind, displayStateInteractor.isLargeScreen, - currentRotation, + displayStateInteractor.currentRotation, modalities ) { forceLarge, promptKind, isLargeScreen, rotation, modalities -> when { @@ -451,7 +449,7 @@ constructor( /** Padding for prompt UI elements */ val promptPadding: Flow<Rect> = - combine(size, currentRotation) { size, rotation -> + combine(size, displayStateInteractor.currentRotation) { size, rotation -> if (size != PromptSize.LARGE) { val navBarInsets = Utils.getNavbarInsets(context) if (rotation == DisplayRotation.ROTATION_90) { diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModel.kt index 7c1984e506c9..c2a4ee36dec6 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModel.kt @@ -147,7 +147,8 @@ constructor( _lottieBounds, sensorLocation, displayRotation, - ) { _: Rect?, sensorLocation: SideFpsSensorLocation, _: DisplayRotation -> + ) { bounds: Rect?, sensorLocation: SideFpsSensorLocation, displayRotation: DisplayRotation + -> val topLeft = Point(sensorLocation.left, sensorLocation.top) defaultOverlayViewParams.apply { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModel.kt index 75e38714f1fa..c5909ed24c50 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModel.kt @@ -107,8 +107,6 @@ constructor( } } - // TODO(b/365182034): move to interactor, add as dependency of SideFpsOverlayInteractor when - // rest to unlock feature is implemented val isVisible: Flow<Boolean> = _visible.asStateFlow() val progress: Flow<Float> = _progress.asStateFlow() diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt index 95d964cdcba8..4fc41669b2c9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt @@ -51,7 +51,6 @@ import com.android.systemui.biometrics.data.repository.biometricStatusRepository import com.android.systemui.biometrics.data.repository.fakeFingerprintPropertyRepository import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor import com.android.systemui.biometrics.domain.interactor.promptSelectorInteractor -import com.android.systemui.biometrics.domain.interactor.sideFpsOverlayInteractor import com.android.systemui.biometrics.domain.interactor.udfpsOverlayInteractor import com.android.systemui.biometrics.extractAuthenticatorTypes import com.android.systemui.biometrics.faceSensorPropertiesInternal @@ -1331,15 +1330,11 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa @Test fun switch_to_credential_fallback() = runGenericTest { val size by collectLastValue(kosmos.promptViewModel.size) - val isShowingSfpsIndicator by collectLastValue(kosmos.sideFpsOverlayInteractor.isShowing) // TODO(b/251476085): remove Spaghetti, migrate logic, and update this test kosmos.promptViewModel.onSwitchToCredential() assertThat(size).isEqualTo(PromptSize.LARGE) - if (testCase.modalities.hasSfps) { - assertThat(isShowingSfpsIndicator).isFalse() - } } @Test diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/domain/interactor/SideFpsOverlayInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/domain/interactor/SideFpsOverlayInteractorKosmos.kt deleted file mode 100644 index 15c7e25f8a5c..000000000000 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/domain/interactor/SideFpsOverlayInteractorKosmos.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 com.android.systemui.keyguard.domain.interactor.deviceEntrySideFpsOverlayInteractor -import com.android.systemui.kosmos.Kosmos -import com.android.systemui.kosmos.Kosmos.Fixture -import kotlinx.coroutines.ExperimentalCoroutinesApi - -@OptIn(ExperimentalCoroutinesApi::class) -val Kosmos.sideFpsOverlayInteractor by Fixture { - SideFpsOverlayInteractorImpl( - biometricStatusInteractor, - displayStateInteractor, - deviceEntrySideFpsOverlayInteractor, - sideFpsSensorInteractor, - ) -} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderKosmos.kt index 59809e3d253f..79d58a1d4e40 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderKosmos.kt @@ -19,19 +19,27 @@ package com.android.systemui.biometrics.ui.binder import android.content.applicationContext import android.view.layoutInflater import android.view.windowManager -import com.android.systemui.biometrics.domain.interactor.sideFpsOverlayInteractor -import com.android.systemui.biometrics.ui.viewmodel.sideFpsOverlayViewModel +import com.android.systemui.biometrics.domain.interactor.biometricStatusInteractor +import com.android.systemui.biometrics.domain.interactor.displayStateInteractor +import com.android.systemui.biometrics.domain.interactor.sideFpsSensorInteractor +import com.android.systemui.keyguard.domain.interactor.deviceEntrySideFpsOverlayInteractor +import com.android.systemui.keyguard.ui.viewmodel.sideFpsProgressBarViewModel import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture import com.android.systemui.kosmos.applicationCoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +@OptIn(ExperimentalCoroutinesApi::class) val Kosmos.sideFpsOverlayViewBinder by Fixture { SideFpsOverlayViewBinder( - applicationCoroutineScope, - applicationContext, + applicationScope = applicationCoroutineScope, + applicationContext = applicationContext, + { biometricStatusInteractor }, + { displayStateInteractor }, + { deviceEntrySideFpsOverlayInteractor }, { layoutInflater }, - { sideFpsOverlayInteractor }, - { sideFpsOverlayViewModel }, + { sideFpsProgressBarViewModel }, + { sideFpsSensorInteractor }, { windowManager } ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelKosmos.kt index e10b2dd6497d..de038559fc38 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelKosmos.kt @@ -27,9 +27,9 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi @OptIn(ExperimentalCoroutinesApi::class) val Kosmos.sideFpsOverlayViewModel by Fixture { SideFpsOverlayViewModel( - applicationContext, - deviceEntrySideFpsOverlayInteractor, - displayStateInteractor, - sideFpsSensorInteractor, + applicationContext = applicationContext, + deviceEntrySideFpsOverlayInteractor = deviceEntrySideFpsOverlayInteractor, + displayStateInteractor = displayStateInteractor, + sfpsSensorInteractor = sideFpsSensorInteractor, ) } |