diff options
| author | 2024-02-06 15:44:07 -0500 | |
|---|---|---|
| committer | 2024-02-20 14:02:21 -0500 | |
| commit | 58f43a56c776497d167b92c8c7c80fc977a9ff32 (patch) | |
| tree | 36f6de65aaffa410df8ccbb976ebc837eb3751b1 | |
| parent | 99be895f96580a6529e95a2efcd1a502505ce7a2 (diff) | |
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
2 files changed, 88 insertions, 13 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt index 1c33d3fd0288..bef6b0ba483f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt @@ -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,25 +49,44 @@ constructor( interactor: DeviceBasedSatelliteInteractor, @Application scope: CoroutineScope, airplaneModeRepository: AirplaneModeRepository, + @OemSatelliteInputLog logBuffer: LogBuffer, ) { - private val shouldShowIcon: StateFlow<Boolean> = - interactor.areAllConnectionsOutOfService - .flatMapLatest { allOos -> - if (!allOos) { - flowOf(false) + private val shouldShowIcon: Flow<Boolean> = + interactor.areAllConnectionsOutOfService.flatMapLatest { allOos -> + if (!allOos) { + flowOf(false) + } else { + combine(interactor.isSatelliteAllowed, airplaneModeRepository.isAirplaneMode) { + isSatelliteAllowed, + isAirplaneMode -> + isSatelliteAllowed && !isAirplaneMode + } + } + } + + // 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 { - combine(interactor.isSatelliteAllowed, airplaneModeRepository.isAirplaneMode) { - isSatelliteAllowed, - isAirplaneMode -> - isSatelliteAllowed && !isAirplaneMode - } + 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 + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt index f53fc46d8ab2..cd0652e53657 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt @@ -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() } } |