summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Evan Laird <evanlaird@google.com> 2024-06-14 13:06:03 -0400
committer Evan Laird <evanlaird@google.com> 2024-06-19 01:08:23 +0000
commit3aaaa6923faa6876e78063b6c922b4a063819f56 (patch)
tree480a162c5512b242e6921bd8d8f2e1305f82b9f5
parent29c3e4f3cb3fefdc5089337ee0544dbc0330a0e4 (diff)
[Sat] Change the satellite provisioned check to eager; query when start
SatelliteManager does not fire the current state for registered callbacks at the time of registration. This change adds an initialization step to `registerForProvisionStateChanged` such that we always query the current status of the provisioned state and send it through the Flow before continuing with the callback registration. Also, we change the sharing strategy to `Eagerly` since we don't want to generate unnecessary IPC if the device goes in and out of OOS. Bug: 347083255 Test: DeviceBasedSatelliteRepositoryImplTest Flag: NONE bugfix Change-Id: Ic7025223ae803abd1b772e72fab3ccd11b175929 Merged-In: Ic7025223ae803abd1b772e72fab3ccd11b175929
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt73
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt144
2 files changed, 197 insertions, 20 deletions
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 86c6b18c62e1..80fbabe3a24f 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
@@ -345,32 +345,67 @@ constructor(
orElse = flowOf(false),
retrySignal = telephonyProcessCrashedEvent,
)
- .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+ .stateIn(scope, SharingStarted.Eagerly, false)
private fun satelliteProvisioned(sm: SupportedSatelliteManager): Flow<Boolean> =
conflatedCallbackFlow {
- val callback = SatelliteProvisionStateCallback { provisioned ->
- logBuffer.i {
- "onSatelliteProvisionStateChanged: " +
- if (provisioned) "provisioned" else "not provisioned"
+ // TODO(b/347992038): SatelliteManager should be sending the current provisioned
+ // status when we register a callback. Until then, we have to manually query here.
+
+ // First, check to see what the current status is, and send the result to the output
+ trySend(queryIsSatelliteProvisioned(sm))
+
+ val callback = SatelliteProvisionStateCallback { provisioned ->
+ logBuffer.i {
+ "onSatelliteProvisionStateChanged: " +
+ if (provisioned) "provisioned" else "not provisioned"
+ }
+ trySend(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)
+ var registered = false
+ try {
+ logBuffer.i { "registerForProvisionStateChanged" }
+ 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)
+ }
+ }
}
+ .flowOn(bgDispatcher)
+
+ /** Check the current satellite provisioning status. */
+ private suspend fun queryIsSatelliteProvisioned(sm: SupportedSatelliteManager): Boolean =
+ withContext(bgDispatcher) {
+ suspendCancellableCoroutine { continuation ->
+ val receiver =
+ object : OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> {
+ override fun onResult(result: Boolean) {
+ logBuffer.i { "requestIsProvisioned.onResult: $result" }
+ continuation.resume(result)
+ }
- awaitClose {
- if (registered) {
- sm.unregisterForProvisionStateChanged(callback)
+ override fun onError(exception: SatelliteManager.SatelliteException) {
+ logBuffer.e("requestIsProvisioned.onError:", exception)
+ continuation.resume(false)
+ }
+ }
+
+ logBuffer.i { "Query for current satellite provisioned state." }
+ try {
+ sm.requestIsProvisioned(bgDispatcher.asExecutor(), receiver)
+ } catch (e: Exception) {
+ logBuffer.e("Exception while calling SatelliteManager.requestIsProvisioned:", e)
+ continuation.resume(false)
}
}
}
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 d491d75955c8..ec8e92111d83 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
@@ -32,6 +32,7 @@ import android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_NOT_CO
import android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_OFF
import android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE
import android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN
+import android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_ERROR
import android.telephony.satellite.SatelliteManager.SatelliteException
import android.telephony.satellite.SatelliteModemStateCallback
import android.telephony.satellite.SatelliteProvisionStateCallback
@@ -62,6 +63,7 @@ import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.mockito.Mock
import org.mockito.Mockito
+import org.mockito.Mockito.atLeastOnce
import org.mockito.Mockito.doAnswer
import org.mockito.Mockito.never
import org.mockito.Mockito.times
@@ -354,13 +356,142 @@ class DeviceBasedSatelliteRepositoryImplTest : SysuiTestCase() {
}
@Test
- fun satelliteProvisioned_supported_tracksCallback() =
+ fun satelliteProvisioned_returnsException_defaultsToFalse() =
+ testScope.runTest {
+ // GIVEN satellite is supported on device
+ doAnswer {
+ val callback: OutcomeReceiver<Boolean, SatelliteException> =
+ it.getArgument(1) as OutcomeReceiver<Boolean, SatelliteException>
+ callback.onResult(true)
+ }
+ .whenever(satelliteManager)
+ .requestIsSupported(any(), any())
+
+ // GIVEN satellite returns an error when asked if provisioned
+ doAnswer {
+ val receiver = it.arguments[1] as OutcomeReceiver<Boolean, SatelliteException>
+ receiver.onError(SatelliteException(SATELLITE_RESULT_ERROR))
+ null
+ }
+ .whenever(satelliteManager)
+ .requestIsProvisioned(
+ any(),
+ any<OutcomeReceiver<Boolean, SatelliteException>>()
+ )
+
+ // GIVEN we've been up long enough to start querying
+ systemClock.setUptimeMillis(Process.getStartUptimeMillis() + MIN_UPTIME)
+
+ underTest =
+ DeviceBasedSatelliteRepositoryImpl(
+ Optional.of(satelliteManager),
+ telephonyManager,
+ dispatcher,
+ testScope.backgroundScope,
+ logBuffer = FakeLogBuffer.Factory.create(),
+ verboseLogBuffer = FakeLogBuffer.Factory.create(),
+ systemClock,
+ )
+
+ // WHEN we try to check for provisioned status
+ val provisioned by collectLastValue(underTest.isSatelliteProvisioned)
+
+ // THEN well, first we don't throw...
+ // AND THEN we assume that it's not provisioned
+ assertThat(provisioned).isFalse()
+ }
+
+ @Test
+ fun satelliteProvisioned_throwsWhenQuerying_defaultsToFalse() =
+ testScope.runTest {
+ // GIVEN satellite is supported on device
+ doAnswer {
+ val callback: OutcomeReceiver<Boolean, SatelliteException> =
+ it.getArgument(1) as OutcomeReceiver<Boolean, SatelliteException>
+ callback.onResult(true)
+ }
+ .whenever(satelliteManager)
+ .requestIsSupported(any(), any())
+
+ // GIVEN satellite throws when asked if provisioned
+ whenever(satelliteManager.requestIsProvisioned(any(), any()))
+ .thenThrow(SecurityException())
+
+ // GIVEN we've been up long enough to start querying
+ systemClock.setUptimeMillis(Process.getStartUptimeMillis() + MIN_UPTIME)
+
+ underTest =
+ DeviceBasedSatelliteRepositoryImpl(
+ Optional.of(satelliteManager),
+ telephonyManager,
+ dispatcher,
+ testScope.backgroundScope,
+ logBuffer = FakeLogBuffer.Factory.create(),
+ verboseLogBuffer = FakeLogBuffer.Factory.create(),
+ systemClock,
+ )
+
+ // WHEN we try to check for provisioned status
+ val provisioned by collectLastValue(underTest.isSatelliteProvisioned)
+
+ // THEN well, first we don't throw...
+ // AND THEN we assume that it's not provisioned
+ assertThat(provisioned).isFalse()
+ }
+
+ @Test
+ fun satelliteProvisioned_supported_provisioned_queriesInitialStateBeforeCallbacks() =
+ testScope.runTest {
+ // GIVEN satellite is supported, and provisioned
+ setUpRepo(
+ uptime = MIN_UPTIME,
+ satMan = satelliteManager,
+ satelliteSupported = true,
+ initialSatelliteIsProvisioned = true,
+ )
+
+ val provisioned by collectLastValue(underTest.isSatelliteProvisioned)
+
+ runCurrent()
+
+ // THEN the current state is requested
+ verify(satelliteManager, atLeastOnce()).requestIsProvisioned(any(), any())
+
+ // AND the state is correct
+ assertThat(provisioned).isTrue()
+ }
+
+ @Test
+ fun satelliteProvisioned_supported_notProvisioned_queriesInitialStateBeforeCallbacks() =
+ testScope.runTest {
+ // GIVEN satellite is supported, and provisioned
+ setUpRepo(
+ uptime = MIN_UPTIME,
+ satMan = satelliteManager,
+ satelliteSupported = true,
+ initialSatelliteIsProvisioned = false,
+ )
+
+ val provisioned by collectLastValue(underTest.isSatelliteProvisioned)
+
+ runCurrent()
+
+ // THEN the current state is requested
+ verify(satelliteManager, atLeastOnce()).requestIsProvisioned(any(), any())
+
+ // AND the state is correct
+ assertThat(provisioned).isFalse()
+ }
+
+ @Test
+ fun satelliteProvisioned_supported_notInitiallyProvisioned_tracksCallback() =
testScope.runTest {
// GIVEN satellite is not supported
setUpRepo(
uptime = MIN_UPTIME,
satMan = satelliteManager,
satelliteSupported = true,
+ initialSatelliteIsProvisioned = false,
)
val provisioned by collectLastValue(underTest.isSatelliteProvisioned)
@@ -416,6 +547,8 @@ class DeviceBasedSatelliteRepositoryImplTest : SysuiTestCase() {
// THEN listeners are re-registered
verify(satelliteManager, times(2)).registerForProvisionStateChanged(any(), any())
+ // AND the state is queried again
+ verify(satelliteManager, times(2)).requestIsProvisioned(any(), any())
}
@Test
@@ -632,6 +765,7 @@ class DeviceBasedSatelliteRepositoryImplTest : SysuiTestCase() {
uptime: Long = MIN_UPTIME,
satMan: SatelliteManager? = satelliteManager,
satelliteSupported: Boolean = true,
+ initialSatelliteIsProvisioned: Boolean = true,
) {
doAnswer {
val callback: OutcomeReceiver<Boolean, SatelliteException> =
@@ -641,6 +775,14 @@ class DeviceBasedSatelliteRepositoryImplTest : SysuiTestCase() {
.whenever(satelliteManager)
.requestIsSupported(any(), any())
+ doAnswer {
+ val callback: OutcomeReceiver<Boolean, SatelliteException> =
+ it.getArgument(1) as OutcomeReceiver<Boolean, SatelliteException>
+ callback.onResult(initialSatelliteIsProvisioned)
+ }
+ .whenever(satelliteManager)
+ .requestIsProvisioned(any(), any())
+
systemClock.setUptimeMillis(Process.getStartUptimeMillis() + uptime)
underTest =