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

Commit 32cc62c4 authored by Evan Laird's avatar Evan Laird
Browse files

[Sat] Replace device provisioned check with satellite provisioned

While the DeviceBasedSatelliteInteractor was using the device
provisioned state (i.e., has setupwizard been completed) as the signal
on whether or not to show the icon (when all other conditions are met),
the better signal here is to use SatelliteManager's satellite
provisioning state.

This CL implements the callback for `SatelliteProvisionStateCallback` in
the same manner as the other callbacks, and replaces the usages of the
device provisioning state with the satellite provisioning state

Test: DeviceBasedSatelliteRepositoryImplTest
Test: DeviceBasedSatelliteViewModelTest
Test: DeviceBasedSatelliteInteractorTest
Bug: 341371444
Flag: NONE bugfix
Change-Id: Ib0f5bbf2aa37ffcc25cf8462f9834e5f05cf908f
Merged-In: Ib0f5bbf2aa37ffcc25cf8462f9834e5f05cf908f
parent 8cadc83b
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.systemui.statusbar.pipeline.satellite.data

import com.android.systemui.statusbar.pipeline.satellite.shared.model.SatelliteConnectionState
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow

/**
 * Device-based satellite refers to the capability of a device to connect directly to a satellite
@@ -25,6 +26,9 @@ import kotlinx.coroutines.flow.Flow
 * given mobile data subscription.
 */
interface DeviceBasedSatelliteRepository {
    /** The current status of satellite provisioning. If not false, we don't want to show an icon */
    val isSatelliteProvisioned: StateFlow<Boolean>

    /** See [SatelliteConnectionState] for available states */
    val connectionState: Flow<SatelliteConnectionState>

+38 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.telephony.satellite.NtnSignalStrengthCallback
import android.telephony.satellite.SatelliteManager
import android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS
import android.telephony.satellite.SatelliteModemStateCallback
import android.telephony.satellite.SatelliteProvisionStateCallback
import android.telephony.satellite.SatelliteSupportedStateCallback
import androidx.annotation.VisibleForTesting
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
@@ -337,6 +338,43 @@ constructor(
            }
        }

    override val isSatelliteProvisioned: StateFlow<Boolean> =
        satelliteSupport
            .whenSupported(
                supported = ::satelliteProvisioned,
                orElse = flowOf(false),
                retrySignal = telephonyProcessCrashedEvent,
            )
            .stateIn(scope, SharingStarted.WhileSubscribed(), false)

    private fun satelliteProvisioned(sm: SupportedSatelliteManager): Flow<Boolean> =
        conflatedCallbackFlow {
            val callback = SatelliteProvisionStateCallback { provisioned ->
                logBuffer.i {
                    "onSatelliteProvisionStateChanged: " +
                        if (provisioned) "provisioned" else "not provisioned"
                }
                trySend(provisioned)
            }

            var registered = false
            try {
                sm.registerForProvisionStateChanged(
                    bgDispatcher.asExecutor(),
                    callback,
                )
                registered = true
            } catch (e: Exception) {
                logBuffer.e("error registering for provisioning state callback", e)
            }

            awaitClose {
                if (registered) {
                    sm.unregisterForProvisionStateChanged(callback)
                }
            }
        }

    /**
     * Signal that we should start polling [checkIsSatelliteAllowed]. We only need to poll if there
     * are active listeners to [isSatelliteAllowedForCurrentLocation]
+1 −3
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ import com.android.systemui.statusbar.pipeline.satellite.data.DeviceBasedSatelli
import com.android.systemui.statusbar.pipeline.satellite.shared.model.SatelliteConnectionState
import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -45,7 +44,6 @@ class DeviceBasedSatelliteInteractor
constructor(
    val repo: DeviceBasedSatelliteRepository,
    iconsInteractor: MobileIconsInteractor,
    deviceProvisioningInteractor: DeviceProvisioningInteractor,
    wifiInteractor: WifiInteractor,
    @Application scope: CoroutineScope,
    @DeviceBasedSatelliteInputLog private val logBuffer: LogBuffer,
@@ -78,7 +76,7 @@ constructor(
            }
            .stateIn(scope, SharingStarted.WhileSubscribed(), 0)

    val isDeviceProvisioned: Flow<Boolean> = deviceProvisioningInteractor.isDeviceProvisioned
    val isSatelliteProvisioned = repo.isSatelliteProvisioned

    val isWifiActive: Flow<Boolean> =
        wifiInteractor.wifiNetwork.map { it is WifiNetworkModel.Active }
+3 −3
Original line number Diff line number Diff line
@@ -79,11 +79,11 @@ constructor(
            } else {
                combine(
                    interactor.isSatelliteAllowed,
                    interactor.isDeviceProvisioned,
                    interactor.isSatelliteProvisioned,
                    interactor.isWifiActive,
                    airplaneModeRepository.isAirplaneMode
                ) { isSatelliteAllowed, isDeviceProvisioned, isWifiActive, isAirplaneMode ->
                    isSatelliteAllowed && isDeviceProvisioned && !isWifiActive && !isAirplaneMode
                ) { isSatelliteAllowed, isSatelliteProvisioned, isWifiActive, isAirplaneMode ->
                    isSatelliteAllowed && isSatelliteProvisioned && !isWifiActive && !isAirplaneMode
                }
            }
        }
+93 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_UNAVAI
import android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN
import android.telephony.satellite.SatelliteManager.SatelliteException
import android.telephony.satellite.SatelliteModemStateCallback
import android.telephony.satellite.SatelliteProvisionStateCallback
import android.telephony.satellite.SatelliteSupportedStateCallback
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
@@ -325,6 +326,98 @@ class DeviceBasedSatelliteRepositoryImplTest : SysuiTestCase() {
            assertThat(latest).isFalse()
        }

    @Test
    fun satelliteProvisioned_notSupported_defaultFalse() =
        testScope.runTest {
            // GIVEN satellite is not supported
            setUpRepo(
                uptime = MIN_UPTIME,
                satMan = satelliteManager,
                satelliteSupported = false,
            )

            assertThat(underTest.isSatelliteProvisioned.value).isFalse()
        }

    @Test
    fun satelliteProvisioned_supported_defaultFalse() =
        testScope.runTest {
            // GIVEN satellite is supported
            setUpRepo(
                uptime = MIN_UPTIME,
                satMan = satelliteManager,
                satelliteSupported = true,
            )

            // THEN default provisioned state is false
            assertThat(underTest.isSatelliteProvisioned.value).isFalse()
        }

    @Test
    fun satelliteProvisioned_supported_tracksCallback() =
        testScope.runTest {
            // GIVEN satellite is not supported
            setUpRepo(
                uptime = MIN_UPTIME,
                satMan = satelliteManager,
                satelliteSupported = true,
            )

            val provisioned by collectLastValue(underTest.isSatelliteProvisioned)
            runCurrent()

            val callback =
                withArgCaptor<SatelliteProvisionStateCallback> {
                    verify(satelliteManager).registerForProvisionStateChanged(any(), capture())
                }

            // WHEN provisioning state changes
            callback.onSatelliteProvisionStateChanged(true)

            // THEN the value is reflected in the repo
            assertThat(provisioned).isTrue()
        }

    @Test
    fun satelliteProvisioned_supported_tracksCallback_reRegistersOnCrash() =
        testScope.runTest {
            // GIVEN satellite is supported
            setUpRepo(
                uptime = MIN_UPTIME,
                satMan = satelliteManager,
                satelliteSupported = true,
            )

            val provisioned by collectLastValue(underTest.isSatelliteProvisioned)

            runCurrent()

            val callback =
                withArgCaptor<SatelliteProvisionStateCallback> {
                    verify(satelliteManager).registerForProvisionStateChanged(any(), capture())
                }
            val telephonyCallback =
                MobileTelephonyHelpers.getTelephonyCallbackForType<
                    TelephonyCallback.RadioPowerStateListener
                >(
                    telephonyManager
                )

            // GIVEN satellite is currently provisioned
            callback.onSatelliteProvisionStateChanged(true)

            assertThat(provisioned).isTrue()

            // WHEN a crash event happens (detected by radio state change)
            telephonyCallback.onRadioPowerStateChanged(TelephonyManager.RADIO_POWER_ON)
            runCurrent()
            telephonyCallback.onRadioPowerStateChanged(TelephonyManager.RADIO_POWER_OFF)
            runCurrent()

            // THEN listeners are re-registered
            verify(satelliteManager, times(2)).registerForProvisionStateChanged(any(), any())
        }

    @Test
    fun satelliteNotSupported_listenersAreNotRegistered() =
        testScope.runTest {
Loading