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

Commit 216503e2 authored by Tianfan Zhang's avatar Tianfan Zhang
Browse files

Fix unintentional CurBar timeout bug.

The current logic:
1. Hide it when it's unexpanded/collapsed and not touched for 15 seconds.
2. Never hide it when it's expanded.

Bug: 417977577
Bug: 403422950
Flag: com.android.systemui.enable_underlay
Test: atest AmbientCueViewModelTest
Change-Id: I15d445bec19268ec1ec81860b302bb2ad2c5483f
parent 0b8f4843
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -42,7 +42,16 @@ fun AmbientCueContainer(
    // TODO: b/414507396 - Replace with the height of the navbar
    val chipsBottomPadding = 46.dp

    LaunchedEffect(expanded) { onShouldInterceptTouches(expanded) }
    LaunchedEffect(expanded) {
        onShouldInterceptTouches(expanded)
        if (expanded) {
            viewModel.cancelDeactivation()
        } else {
            viewModel.delayAndDeactivateCueBar()
        }
    }

    LaunchedEffect(actions) { viewModel.delayAndDeactivateCueBar() }

    Box(
        modifier.clickable(enabled = expanded, indication = null, interactionSource = null) {
+25 −16
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@ import com.android.systemui.lifecycle.activateIn
import com.android.systemui.res.R
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.launch
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -64,22 +66,6 @@ class AmbientCueViewModelTest : SysuiTestCase() {
            assertThat(viewModel.isVisible).isFalse()
        }

    @Test
    fun isVisible_whenExpanded_doesntTimeOut() =
        kosmos.runTest {
            initializeIsVisible()
            assertThat(viewModel.isVisible).isTrue()

            // Doesn't time out when expanded
            viewModel.expand()
            advanceTimeBy(AmbientCueViewModel.AMBIENT_CUE_TIMEOUT_SEC)
            runCurrent()
            ambientCueRepository.fake.updateRootViewAttached()
            runCurrent()

            assertThat(viewModel.isVisible).isTrue()
        }

    @Test
    fun isVisible_imeNotVisible_true() =
        kosmos.runTest {
@@ -122,6 +108,29 @@ class AmbientCueViewModelTest : SysuiTestCase() {
            assertThat(viewModel.isExpanded).isFalse()
        }

    @Test
    fun delayAndDeactivateCueBar_refreshTimeout() =
        kosmos.runTest {
            ambientCueInteractor.setDeactivated(false)
            testScope.backgroundScope.launch { viewModel.delayAndDeactivateCueBar() }
            advanceTimeBy(10.seconds)
            runCurrent()
            assertThat(ambientCueRepository.isDeactivated.value).isFalse()

            testScope.backgroundScope.launch { viewModel.delayAndDeactivateCueBar() }
            advanceTimeBy(AmbientCueViewModel.AMBIENT_CUE_TIMEOUT_SEC - 10.seconds)
            runCurrent()
            // 5 seconds after calling delayAndDeactivateCueBar() again (totally 15 seconds after
            // test begins), isDeactivated should still be false.
            assertThat(ambientCueRepository.isDeactivated.value).isFalse()
            advanceTimeBy(10.seconds)
            runCurrent()

            // 15 seconds after calling delayAndDeactivateCueBar() again, isDeactivated should be
            // true.
            assertThat(ambientCueRepository.isDeactivated.value).isTrue()
        }

    private fun testActions(applicationContext: Context) =
        listOf(
            ActionModel(
+22 −4
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import com.android.systemui.lifecycle.Hydrator
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.Job
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest
@@ -95,17 +96,34 @@ constructor(private val ambientCueInteractor: AmbientCueInteractor) : ExclusiveA
        isExpanded = false
    }

    private var deactivateCueBarJob: Job? = null

    fun cancelDeactivation() {
        deactivateCueBarJob?.cancel()
    }

    suspend fun delayAndDeactivateCueBar() {
        deactivateCueBarJob?.cancel()

        coroutineScopeTraced("AmbientCueViewModel") {
            deactivateCueBarJob = launch {
                delay(AMBIENT_CUE_TIMEOUT_SEC)
                ambientCueInteractor.setDeactivated(true)
            }
        }
    }

    override suspend fun onActivated(): Nothing {
        coroutineScopeTraced("AmbientCueViewModel") {
            launch { hydrator.activate() }
            launch {
                // Hide the UI if the user doesn't interact with it after N seconds
                ambientCueInteractor.isRootViewAttached.collectLatest { isAttached ->
                    if (!isAttached) return@collectLatest
                    delay(AMBIENT_CUE_TIMEOUT_SEC)
                    if (!isExpanded) {
                        ambientCueInteractor.setDeactivated(true)
                    if (!isAttached) {
                        cancelDeactivation()
                        return@collectLatest
                    }
                    delayAndDeactivateCueBar()
                }
            }
            awaitCancellation()