Stop co-routines whenever the rest to unlock settings toggle is not enabled.

The previously launched co-routines are still running even when the settings toggle is disabled.

Bug: 305271359
Flag: LEGACY REST_TO_UNLOCK DEVELOPMENT
Test: Enabled/disabled the touch_to_unlock settings toggle and verified that the progress bar is not visible.
Test: pending for the viewModel, will add in a follow-up CL
Change-Id: I2db36b66285918291e024961986598326a30bb18
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractor.kt
index 2bb19cd..f513799 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractor.kt
@@ -26,8 +26,6 @@
 import com.android.systemui.biometrics.shared.model.FingerprintSensorType
 import com.android.systemui.biometrics.shared.model.isDefaultOrientation
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.flags.FeatureFlagsClassic
-import com.android.systemui.flags.Flags
 import com.android.systemui.log.SideFpsLogger
 import com.android.systemui.res.R
 import java.util.Optional
@@ -48,7 +46,6 @@
     fingerprintPropertyRepository: FingerprintPropertyRepository,
     windowManager: WindowManager,
     displayStateInteractor: DisplayStateInteractor,
-    featureFlags: FeatureFlagsClassic,
     fingerprintInteractiveToAuthProvider: Optional<FingerprintInteractiveToAuthProvider>,
     private val logger: SideFpsLogger,
 ) {
@@ -65,14 +62,11 @@
     val isAvailable: Flow<Boolean> =
         fingerprintPropertyRepository.sensorType.map { it == FingerprintSensorType.POWER_BUTTON }
 
-    val authenticationDuration: Flow<Long> =
-        flowOf(context.resources?.getInteger(R.integer.config_restToUnlockDuration)?.toLong() ?: 0L)
+    val authenticationDuration: Long =
+        context.resources?.getInteger(R.integer.config_restToUnlockDuration)?.toLong() ?: 0L
 
     val isProlongedTouchRequiredForAuthentication: Flow<Boolean> =
-        if (
-            fingerprintInteractiveToAuthProvider.isEmpty ||
-                !featureFlags.isEnabled(Flags.REST_TO_UNLOCK)
-        ) {
+        if (fingerprintInteractiveToAuthProvider.isEmpty) {
             flowOf(false)
         } else {
             combine(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/SideFpsProgressBarViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/SideFpsProgressBarViewBinder.kt
index ba4876f..0bee48a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/SideFpsProgressBarViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/SideFpsProgressBarViewBinder.kt
@@ -22,6 +22,8 @@
 import com.android.systemui.biometrics.SideFpsController
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.flags.FeatureFlagsClassic
+import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.ui.view.SideFpsProgressBar
 import com.android.systemui.keyguard.ui.viewmodel.SideFpsProgressBarViewModel
 import com.android.systemui.log.SideFpsLogger
@@ -31,6 +33,7 @@
 import java.io.PrintWriter
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
 import kotlinx.coroutines.flow.collectLatest
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.launch
@@ -47,15 +50,23 @@
     private val sfpsController: dagger.Lazy<SideFpsController>,
     private val logger: SideFpsLogger,
     private val commandRegistry: CommandRegistry,
+    private val featureFlagsClassic: FeatureFlagsClassic,
 ) : CoreStartable {
 
     override fun start() {
+        if (!featureFlagsClassic.isEnabled(Flags.REST_TO_UNLOCK)) {
+            return
+        }
+        // When the rest to unlock feature is disabled by the user, stop any coroutines that are
+        // not required.
+        var layoutJob: Job? = null
+        var progressJob: Job? = null
         commandRegistry.registerCommand(spfsProgressBarCommand) { SfpsProgressBarCommand() }
         applicationScope.launch {
             viewModel.isProlongedTouchRequiredForAuthentication.collectLatest { enabled ->
                 logger.isProlongedTouchRequiredForAuthenticationChanged(enabled)
                 if (enabled) {
-                    launch {
+                    layoutJob = launch {
                         combine(
                                 viewModel.isVisible,
                                 viewModel.progressBarLocation,
@@ -76,9 +87,13 @@
                                 )
                             }
                     }
-                    launch { viewModel.progress.collectLatest { view.setProgress(it) } }
+                    progressJob = launch {
+                        viewModel.progress.collectLatest { view.setProgress(it) }
+                    }
                 } else {
                     view.hide()
+                    layoutJob?.cancel()
+                    progressJob?.cancel()
                 }
             }
         }
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 f8996b7..a0f5baf 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
@@ -26,6 +26,8 @@
 import com.android.systemui.biometrics.shared.model.isDefaultOrientation
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.flags.FeatureFlagsClassic
+import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
 import com.android.systemui.keyguard.shared.model.AcquiredFingerprintAuthenticationStatus
 import com.android.systemui.keyguard.shared.model.ErrorFingerprintAuthenticationStatus
@@ -34,13 +36,17 @@
 import com.android.systemui.res.R
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.collectLatest
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onCompletion
+import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.launch
 
 @SysUISingleton
@@ -52,10 +58,12 @@
     private val sfpsSensorInteractor: SideFpsSensorInteractor,
     displayStateInteractor: DisplayStateInteractor,
     @Application private val applicationScope: CoroutineScope,
+    private val featureFlagsClassic: FeatureFlagsClassic,
 ) {
     private val _progress = MutableStateFlow(0.0f)
     private val _visible = MutableStateFlow(false)
     private var _animator: ValueAnimator? = null
+    private var animatorJob: Job? = null
 
     private fun onFingerprintCaptureCompleted() {
         _visible.value = false
@@ -147,26 +155,32 @@
         sfpsSensorInteractor.isProlongedTouchRequiredForAuthentication
 
     init {
-        applicationScope.launch {
-            combine(
-                    sfpsSensorInteractor.isProlongedTouchRequiredForAuthentication,
-                    sfpsSensorInteractor.authenticationDuration,
-                    ::Pair
-                )
-                .collectLatest { (enabled, authDuration) ->
-                    if (!enabled) return@collectLatest
+        if (featureFlagsClassic.isEnabled(Flags.REST_TO_UNLOCK)) {
+            launchAnimator()
+        }
+    }
 
-                    launch {
-                        fpAuthRepository.authenticationStatus.collectLatest { authStatus ->
+    private fun launchAnimator() {
+        applicationScope.launch {
+            sfpsSensorInteractor.isProlongedTouchRequiredForAuthentication.collectLatest { enabled
+                ->
+                if (!enabled) {
+                    animatorJob?.cancel()
+                    return@collectLatest
+                }
+                animatorJob =
+                    fpAuthRepository.authenticationStatus
+                        .onEach { authStatus ->
                             when (authStatus) {
                                 is AcquiredFingerprintAuthenticationStatus -> {
                                     if (authStatus.fingerprintCaptureStarted) {
-
                                         _visible.value = true
                                         _animator?.cancel()
                                         _animator =
                                             ValueAnimator.ofFloat(0.0f, 1.0f)
-                                                .setDuration(authDuration)
+                                                .setDuration(
+                                                    sfpsSensorInteractor.authenticationDuration
+                                                )
                                                 .apply {
                                                     addUpdateListener {
                                                         _progress.value = it.animatedValue as Float
@@ -196,8 +210,9 @@
                                 else -> Unit
                             }
                         }
-                    }
-                }
+                        .onCompletion { _animator?.cancel() }
+                        .launchIn(applicationScope)
+            }
         }
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractorTest.kt
index 3fbdeec..67d3a20 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractorTest.kt
@@ -37,8 +37,6 @@
 import com.android.systemui.biometrics.shared.model.SensorStrength
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.dump.logcatLogBuffer
-import com.android.systemui.flags.FakeFeatureFlagsClassic
-import com.android.systemui.flags.Flags.REST_TO_UNLOCK
 import com.android.systemui.log.SideFpsLogger
 import com.android.systemui.res.R
 import com.android.systemui.util.mockito.whenever
@@ -94,7 +92,6 @@
         whenever(displayStateInteractor.currentRotation).thenReturn(currentRotation)
 
         contextDisplayInfo.uniqueId = "current-display"
-        val featureFlags = FakeFeatureFlagsClassic().apply { set(REST_TO_UNLOCK, true) }
         whenever(fingerprintInteractiveToAuthProvider.enabledForCurrentUser)
             .thenReturn(isRestToUnlockEnabled)
         underTest =
@@ -103,7 +100,6 @@
                 fingerprintRepository,
                 windowManager,
                 displayStateInteractor,
-                featureFlags,
                 Optional.of(fingerprintInteractiveToAuthProvider),
                 SideFpsLogger(logcatLogBuffer("SfpsLogger"))
             )
@@ -136,7 +132,7 @@
     @Test
     fun authenticationDurationIsAvailableWhenSFPSSensorIsAvailable() =
         testScope.runTest {
-            assertThat(collectLastValue(underTest.authenticationDuration)())
+            assertThat(underTest.authenticationDuration)
                 .isEqualTo(context.resources.getInteger(R.integer.config_restToUnlockDuration))
         }