Fix the "Use this SIM" switch does not disable during phone calls
If the registration failed (e.g., device doesn't support satellite), SatelliteManager will not emit the current state by callback. We send `false` value by ourself to make sure the flow has initial value. Bug: 315928920 Test: atest, manual Change-Id: Ic87f71bc576cfb1f8e4053c5784fca401adaec08
This commit is contained in:
@@ -33,6 +33,7 @@ import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import java.util.concurrent.Executor
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
|
||||
/**
|
||||
* A repository class for interacting with the SatelliteManager API.
|
||||
@@ -112,13 +113,13 @@ class SatelliteRepository(
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a Flow that emits the enabled state of the satellite modem. Updates are triggered
|
||||
* Provides a Flow that emits the session state of the satellite modem. Updates are triggered
|
||||
* when the modem state changes.
|
||||
*
|
||||
* @param defaultDispatcher The CoroutineDispatcher to use (Defaults to `Dispatchers.Default`).
|
||||
* @return A Flow emitting `true` when the modem is enabled and `false` otherwise.
|
||||
* @return A Flow emitting `true` when the session is started and `false` otherwise.
|
||||
*/
|
||||
fun getIsModemEnabledFlow(
|
||||
fun getIsSessionStartedFlow(
|
||||
defaultDispatcher: CoroutineDispatcher = Dispatchers.Default,
|
||||
): Flow<Boolean> {
|
||||
val satelliteManager: SatelliteManager? =
|
||||
@@ -130,42 +131,27 @@ class SatelliteRepository(
|
||||
|
||||
return callbackFlow {
|
||||
val callback = SatelliteModemStateCallback { state ->
|
||||
val isEnabled = convertSatelliteModemStateToEnabledState(state)
|
||||
Log.i(TAG, "Satellite modem state changed: state=$state, isEnabled=$isEnabled")
|
||||
trySend(isEnabled)
|
||||
val isSessionStarted = isSatelliteSessionStarted(state)
|
||||
Log.i(TAG, "Satellite modem state changed: state=$state"
|
||||
+ ", isSessionStarted=$isSessionStarted")
|
||||
trySend(isSessionStarted)
|
||||
}
|
||||
|
||||
val result = satelliteManager.registerForModemStateChanged(
|
||||
val registerResult = satelliteManager.registerForModemStateChanged(
|
||||
defaultDispatcher.asExecutor(),
|
||||
callback
|
||||
)
|
||||
Log.i(TAG, "Call registerForModemStateChanged: result=$result")
|
||||
|
||||
if (registerResult != SatelliteManager.SATELLITE_RESULT_SUCCESS) {
|
||||
// If the registration failed (e.g., device doesn't support satellite),
|
||||
// SatelliteManager will not emit the current state by callback.
|
||||
// We send `false` value by ourself to make sure the flow has initial value.
|
||||
Log.w(TAG, "Failed to register for satellite modem state change: $registerResult")
|
||||
trySend(false)
|
||||
}
|
||||
|
||||
awaitClose { satelliteManager.unregisterForModemStateChanged(callback) }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a [SatelliteManager.SatelliteModemState] to a boolean representing whether the modem
|
||||
* is enabled.
|
||||
*
|
||||
* @param state The SatelliteModemState provided by the SatelliteManager.
|
||||
* @return `true` if the modem is enabled, `false` otherwise.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
fun convertSatelliteModemStateToEnabledState(
|
||||
@SatelliteManager.SatelliteModemState state: Int,
|
||||
): Boolean {
|
||||
// Mapping table based on logic from b/315928920#comment24
|
||||
return when (state) {
|
||||
SatelliteManager.SATELLITE_MODEM_STATE_IDLE,
|
||||
SatelliteManager.SATELLITE_MODEM_STATE_LISTENING,
|
||||
SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING,
|
||||
SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_RETRYING,
|
||||
SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED,
|
||||
SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED -> true
|
||||
else -> false
|
||||
}
|
||||
}.flowOn(Dispatchers.Default)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -59,7 +59,7 @@ class MobileNetworkSwitchController @JvmOverloads constructor(
|
||||
val changeable by remember {
|
||||
combine(
|
||||
context.callStateFlow(subId).map { it == TelephonyManager.CALL_STATE_IDLE },
|
||||
satelliteRepository.getIsModemEnabledFlow()
|
||||
satelliteRepository.getIsSessionStartedFlow()
|
||||
) { isCallStateIdle, isSatelliteModemEnabled ->
|
||||
isCallStateIdle && !isSatelliteModemEnabled
|
||||
}
|
||||
|
@@ -120,7 +120,7 @@ class SatelliteRepositoryTest {
|
||||
@Test
|
||||
fun requestIsSessionStarted_registerFailed() = runBlocking {
|
||||
`when`(mockSatelliteManager.registerForModemStateChanged(any(), any())
|
||||
).thenAnswer { invocation ->
|
||||
).thenAnswer {
|
||||
SatelliteManager.SATELLITE_RESULT_ERROR
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ class SatelliteRepositoryTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getIsModemEnabledFlow_isSatelliteEnabledState() = runBlocking {
|
||||
fun getIsSessionStartedFlow_isSatelliteEnabledState() = runBlocking {
|
||||
`when`(
|
||||
mockSatelliteManager.registerForModemStateChanged(
|
||||
any(),
|
||||
@@ -199,13 +199,13 @@ class SatelliteRepositoryTest {
|
||||
SatelliteManager.SATELLITE_RESULT_SUCCESS
|
||||
}
|
||||
|
||||
val flow = repository.getIsModemEnabledFlow()
|
||||
val flow = repository.getIsSessionStartedFlow()
|
||||
|
||||
assertThat(flow.first()).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getIsModemEnabledFlow_isSatelliteDisabledState() = runBlocking {
|
||||
fun getIsSessionStartedFlow_isSatelliteDisabledState() = runBlocking {
|
||||
`when`(
|
||||
mockSatelliteManager.registerForModemStateChanged(
|
||||
any(),
|
||||
@@ -217,16 +217,28 @@ class SatelliteRepositoryTest {
|
||||
SatelliteManager.SATELLITE_RESULT_SUCCESS
|
||||
}
|
||||
|
||||
val flow = repository.getIsModemEnabledFlow()
|
||||
val flow = repository.getIsSessionStartedFlow()
|
||||
|
||||
assertThat(flow.first()).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getIsModemEnabledFlow_nullSatelliteManager() = runBlocking {
|
||||
fun getIsSessionStartedFlow_nullSatelliteManager() = runBlocking {
|
||||
`when`(spyContext.getSystemService(SatelliteManager::class.java)).thenReturn(null)
|
||||
|
||||
val flow = repository.getIsModemEnabledFlow()
|
||||
val flow = repository.getIsSessionStartedFlow()
|
||||
assertThat(flow.first()).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getIsSessionStartedFlow_registerFailed() = runBlocking {
|
||||
`when`(mockSatelliteManager.registerForModemStateChanged(any(), any())
|
||||
).thenAnswer {
|
||||
SatelliteManager.SATELLITE_RESULT_ERROR
|
||||
}
|
||||
|
||||
val flow = repository.getIsSessionStartedFlow()
|
||||
|
||||
assertThat(flow.first()).isFalse()
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user