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

Commit 58f43a56 authored by Olivier St-Onge's avatar Olivier St-Onge
Browse files

Wait 10 seconds after APM is disabled before showing satellite icon

We want to avoid showing the satellite icon when a mobile network is available. We wait 10 seconds after APM is disabled in case we happen to have service.

Fixes: 323051828
Flag: none
Test: DeviceBasedSatelliteViewModelTest#icon_satelliteIsOn
Change-Id: Ia35b62d3bc4e3e8757cd71c8dfb5a15fb74eff07
parent 99be895f
Loading
Loading
Loading
Loading
+42 −11
Original line number Diff line number Diff line
@@ -18,15 +18,22 @@ package com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel

import com.android.systemui.common.shared.model.Icon
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.LogLevel
import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepository
import com.android.systemui.statusbar.pipeline.dagger.OemSatelliteInputLog
import com.android.systemui.statusbar.pipeline.satellite.domain.interactor.DeviceBasedSatelliteInteractor
import com.android.systemui.statusbar.pipeline.satellite.ui.model.SatelliteIconModel
import javax.inject.Inject
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.stateIn
@@ -42,10 +49,10 @@ constructor(
    interactor: DeviceBasedSatelliteInteractor,
    @Application scope: CoroutineScope,
    airplaneModeRepository: AirplaneModeRepository,
    @OemSatelliteInputLog logBuffer: LogBuffer,
) {
    private val shouldShowIcon: StateFlow<Boolean> =
        interactor.areAllConnectionsOutOfService
            .flatMapLatest { allOos ->
    private val shouldShowIcon: Flow<Boolean> =
        interactor.areAllConnectionsOutOfService.flatMapLatest { allOos ->
            if (!allOos) {
                flowOf(false)
            } else {
@@ -56,11 +63,30 @@ constructor(
                }
            }
        }

    // This adds a 10 seconds delay before showing the icon
    private val shouldActuallyShowIcon: StateFlow<Boolean> =
        shouldShowIcon
            .distinctUntilChanged()
            .flatMapLatest { shouldShow ->
                if (shouldShow) {
                    logBuffer.log(
                        TAG,
                        LogLevel.INFO,
                        { long1 = DELAY_DURATION.inWholeSeconds },
                        { "Waiting $long1 seconds before showing the satellite icon" }
                    )
                    delay(DELAY_DURATION)
                    flowOf(true)
                } else {
                    flowOf(false)
                }
            }
            .stateIn(scope, SharingStarted.WhileSubscribed(), false)

    val icon: StateFlow<Icon?> =
        combine(
                shouldShowIcon,
                shouldActuallyShowIcon,
                interactor.connectionState,
                interactor.signalStrength,
            ) { shouldShow, state, signalStrength ->
@@ -71,4 +97,9 @@ constructor(
                }
            }
            .stateIn(scope, SharingStarted.WhileSubscribed(), null)

    companion object {
        private const val TAG = "DeviceBasedSatelliteViewModel"
        private val DELAY_DURATION = 10.seconds
    }
}
+46 −2
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.log.core.FakeLogBuffer
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
@@ -28,7 +29,10 @@ import com.android.systemui.statusbar.pipeline.satellite.domain.interactor.Devic
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import kotlin.test.Test
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.mockito.MockitoAnnotations
@@ -61,6 +65,7 @@ class DeviceBasedSatelliteViewModelTest : SysuiTestCase() {
                interactor,
                testScope.backgroundScope,
                airplaneModeRepository,
                FakeLogBuffer.Factory.create(),
            )
    }

@@ -121,8 +126,9 @@ class DeviceBasedSatelliteViewModelTest : SysuiTestCase() {
            assertThat(latest).isNull()
        }

    @OptIn(ExperimentalCoroutinesApi::class)
    @Test
    fun icon_satelliteIsOff() =
    fun icon_satelliteIsOn() =
        testScope.runTest {
            val latest by collectLastValue(underTest.icon)

@@ -133,7 +139,45 @@ class DeviceBasedSatelliteViewModelTest : SysuiTestCase() {
            val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
            i1.isInService.value = false

            // THEN icon is null because we have service
            // GIVEN apm is disabled
            airplaneModeRepository.setIsAirplaneMode(false)

            // Wait for delay to be completed
            advanceTimeBy(10.seconds)

            // THEN icon is set because we don't have service
            assertThat(latest).isInstanceOf(Icon::class.java)
        }

    @OptIn(ExperimentalCoroutinesApi::class)
    @Test
    fun icon_hysteresisWhenEnablingIcon() =
        testScope.runTest {
            val latest by collectLastValue(underTest.icon)

            // GIVEN satellite is allowed
            repo.isSatelliteAllowedForCurrentLocation.value = true

            // GIVEN all icons are OOS
            val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
            i1.isInService.value = false

            // GIVEN apm is disabled
            airplaneModeRepository.setIsAirplaneMode(false)

            // THEN icon is null because of the hysteresis
            assertThat(latest).isNull()

            // Wait for delay to be completed
            advanceTimeBy(10.seconds)

            // THEN icon is set after the delay
            assertThat(latest).isInstanceOf(Icon::class.java)

            // GIVEN apm is enabled
            airplaneModeRepository.setIsAirplaneMode(true)

            // THEN icon is null immediately
            assertThat(latest).isNull()
        }
}