diff options
10 files changed, 158 insertions, 34 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepository.kt index d38e834ff1e2..1d08f2ba9522 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepository.kt @@ -25,6 +25,9 @@ import kotlinx.coroutines.flow.StateFlow * 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: StateFlow<SatelliteConnectionState> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcher.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcher.kt index 6b1bc65e86db..58c30e018efd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcher.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcher.kt @@ -97,6 +97,11 @@ constructor( } .stateIn(scope, SharingStarted.WhileSubscribed(), realImpl) + override val isSatelliteProvisioned: StateFlow<Boolean> = + activeRepo + .flatMapLatest { it.isSatelliteProvisioned } + .stateIn(scope, SharingStarted.WhileSubscribed(), realImpl.isSatelliteProvisioned.value) + override val connectionState: StateFlow<SatelliteConnectionState> = activeRepo .flatMapLatest { it.connectionState } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/demo/DemoDeviceBasedSatelliteRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/demo/DemoDeviceBasedSatelliteRepository.kt index 56034f08503d..6ad295e82645 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/demo/DemoDeviceBasedSatelliteRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/demo/DemoDeviceBasedSatelliteRepository.kt @@ -36,6 +36,7 @@ constructor( ) : DeviceBasedSatelliteRepository { private var demoCommandJob: Job? = null + override val isSatelliteProvisioned = MutableStateFlow(true) override val connectionState = MutableStateFlow(SatelliteConnectionState.Unknown) override val signalStrength = MutableStateFlow(0) override val isSatelliteAllowedForCurrentLocation = MutableStateFlow(true) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt index 1449e535c279..ec3af87f2b9b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt @@ -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] diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt index b66ace6b0fe3..03f88c74d38a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt @@ -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 } 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 0ed1b9b0f77a..48278d4208a2 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 @@ -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 } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt index d24d87c6f57a..890a2e40c94c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt @@ -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 @@ -326,6 +327,98 @@ class DeviceBasedSatelliteRepositoryImplTest : SysuiTestCase() { } @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 { // GIVEN satellite is not supported diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/FakeDeviceBasedSatelliteRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/FakeDeviceBasedSatelliteRepository.kt index 5fa2d33c9de0..55460bd5b801 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/FakeDeviceBasedSatelliteRepository.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/FakeDeviceBasedSatelliteRepository.kt @@ -21,6 +21,8 @@ import com.android.systemui.statusbar.pipeline.satellite.shared.model.SatelliteC import kotlinx.coroutines.flow.MutableStateFlow class FakeDeviceBasedSatelliteRepository() : DeviceBasedSatelliteRepository { + override val isSatelliteProvisioned = MutableStateFlow(true) + override val connectionState = MutableStateFlow(Off) override val signalStrength = MutableStateFlow(0) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt index d303976612c1..2e5ebb3e3194 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt @@ -31,8 +31,6 @@ import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnec import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel -import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository -import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat import kotlin.test.Test @@ -55,9 +53,6 @@ class DeviceBasedSatelliteInteractorTest : SysuiTestCase() { ) private val repo = FakeDeviceBasedSatelliteRepository() - private val deviceProvisionedRepository = FakeDeviceProvisioningRepository() - private val deviceProvisioningInteractor = - DeviceProvisioningInteractor(deviceProvisionedRepository) private val connectivityRepository = FakeConnectivityRepository() private val wifiRepository = FakeWifiRepository() private val wifiInteractor = @@ -69,7 +64,6 @@ class DeviceBasedSatelliteInteractorTest : SysuiTestCase() { DeviceBasedSatelliteInteractor( repo, iconsInteractor, - deviceProvisioningInteractor, wifiInteractor, testScope.backgroundScope, FakeLogBuffer.Factory.create(), @@ -113,7 +107,6 @@ class DeviceBasedSatelliteInteractorTest : SysuiTestCase() { DeviceBasedSatelliteInteractor( repo, iconsInteractor, - deviceProvisioningInteractor, wifiInteractor, testScope.backgroundScope, FakeLogBuffer.Factory.create(), @@ -162,7 +155,6 @@ class DeviceBasedSatelliteInteractorTest : SysuiTestCase() { DeviceBasedSatelliteInteractor( repo, iconsInteractor, - deviceProvisioningInteractor, wifiInteractor, testScope.backgroundScope, FakeLogBuffer.Factory.create(), @@ -219,7 +211,6 @@ class DeviceBasedSatelliteInteractorTest : SysuiTestCase() { DeviceBasedSatelliteInteractor( repo, iconsInteractor, - deviceProvisioningInteractor, wifiInteractor, testScope.backgroundScope, FakeLogBuffer.Factory.create(), @@ -538,7 +529,6 @@ class DeviceBasedSatelliteInteractorTest : SysuiTestCase() { DeviceBasedSatelliteInteractor( repo, iconsInteractor, - deviceProvisioningInteractor, wifiInteractor, testScope.backgroundScope, FakeLogBuffer.Factory.create(), 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 43b95688729c..c39e301155fe 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 @@ -32,8 +32,6 @@ import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnec import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel -import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository -import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat import kotlin.test.Test @@ -55,9 +53,6 @@ class DeviceBasedSatelliteViewModelTest : SysuiTestCase() { private val mobileIconsInteractor = FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock()) - private val deviceProvisionedRepository = FakeDeviceProvisioningRepository() - private val deviceProvisioningInteractor = - DeviceProvisioningInteractor(deviceProvisionedRepository) private val connectivityRepository = FakeConnectivityRepository() private val wifiRepository = FakeWifiRepository() private val wifiInteractor = @@ -72,7 +67,6 @@ class DeviceBasedSatelliteViewModelTest : SysuiTestCase() { DeviceBasedSatelliteInteractor( repo, mobileIconsInteractor, - deviceProvisioningInteractor, wifiInteractor, testScope.backgroundScope, FakeLogBuffer.Factory.create(), @@ -252,14 +246,14 @@ class DeviceBasedSatelliteViewModelTest : SysuiTestCase() { // GIVEN apm is disabled airplaneModeRepository.setIsAirplaneMode(false) - // GIVEN device is not provisioned - deviceProvisionedRepository.setDeviceProvisioned(false) + // GIVEN satellite is not provisioned + repo.isSatelliteProvisioned.value = false // THEN icon is null because the device is not provisioned assertThat(latest).isNull() - // GIVEN device becomes provisioned - deviceProvisionedRepository.setDeviceProvisioned(true) + // GIVEN satellite becomes provisioned + repo.isSatelliteProvisioned.value = true // Wait for delay to be completed advanceTimeBy(10.seconds) @@ -285,8 +279,8 @@ class DeviceBasedSatelliteViewModelTest : SysuiTestCase() { // GIVEN apm is disabled airplaneModeRepository.setIsAirplaneMode(false) - // GIVEN device is provisioned - deviceProvisionedRepository.setDeviceProvisioned(true) + // GIVEN satellite is provisioned + repo.isSatelliteProvisioned.value = true // GIVEN wifi network is active wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = 0, level = 1)) @@ -474,14 +468,14 @@ class DeviceBasedSatelliteViewModelTest : SysuiTestCase() { // GIVEN apm is disabled airplaneModeRepository.setIsAirplaneMode(false) - // GIVEN device is not provisioned - deviceProvisionedRepository.setDeviceProvisioned(false) + // GIVEN satellite is not provisioned + repo.isSatelliteProvisioned.value = false // THEN carrier text is null because the device is not provisioned assertThat(latest).isNull() - // GIVEN device becomes provisioned - deviceProvisionedRepository.setDeviceProvisioned(true) + // GIVEN satellite becomes provisioned + repo.isSatelliteProvisioned.value = true // Wait for delay to be completed advanceTimeBy(10.seconds) @@ -508,8 +502,8 @@ class DeviceBasedSatelliteViewModelTest : SysuiTestCase() { // GIVEN apm is disabled airplaneModeRepository.setIsAirplaneMode(false) - // GIVEN device is provisioned - deviceProvisionedRepository.setDeviceProvisioned(true) + // GIVEN satellite is provisioned + repo.isSatelliteProvisioned.value = true // GIVEN wifi network is active wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = 0, level = 1)) |