Merge "Check the Satellite modem state instead of enabled state only." into main
diff --git a/packages/SettingsLib/src/com/android/settingslib/satellite/SatelliteDialogUtils.kt b/packages/SettingsLib/src/com/android/settingslib/satellite/SatelliteDialogUtils.kt
index d69c87b..2dc2650 100644
--- a/packages/SettingsLib/src/com/android/settingslib/satellite/SatelliteDialogUtils.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/satellite/SatelliteDialogUtils.kt
@@ -21,6 +21,7 @@
import android.content.Intent
import android.os.OutcomeReceiver
import android.telephony.satellite.SatelliteManager
+import android.telephony.satellite.SatelliteModemStateCallback
import android.util.Log
import android.view.WindowManager
import androidx.lifecycle.LifecycleOwner
@@ -31,12 +32,19 @@
import kotlinx.coroutines.Dispatchers.Default
import kotlinx.coroutines.Job
import kotlinx.coroutines.asExecutor
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import java.util.concurrent.ExecutionException
import java.util.concurrent.TimeoutException
import kotlin.coroutines.resume
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.conflate
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.flowOn
/** A util for Satellite dialog */
object SatelliteDialogUtils {
@@ -70,7 +78,7 @@
coroutineScope.launch {
var isSatelliteModeOn = false
try {
- isSatelliteModeOn = requestIsEnabled(context)
+ isSatelliteModeOn = requestIsSessionStarted(context)
} catch (e: InterruptedException) {
Log.w(TAG, "Error to get satellite status : $e")
} catch (e: ExecutionException) {
@@ -134,6 +142,70 @@
}
}
+ private suspend fun requestIsSessionStarted(
+ context: Context
+ ): Boolean = withContext(Default) {
+ getIsSessionStartedFlow(context).conflate().first()
+ }
+
+ /**
+ * 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 session is started and `false` otherwise.
+ */
+ private fun getIsSessionStartedFlow(
+ context: Context
+ ): Flow<Boolean> {
+ val satelliteManager: SatelliteManager? =
+ context.getSystemService(SatelliteManager::class.java)
+ if (satelliteManager == null) {
+ Log.w(TAG, "SatelliteManager is null")
+ return flowOf(false)
+ }
+
+ return callbackFlow {
+ val callback = SatelliteModemStateCallback { state ->
+ val isSessionStarted = isSatelliteSessionStarted(state)
+ Log.i(TAG, "Satellite modem state changed: state=$state"
+ + ", isSessionStarted=$isSessionStarted")
+ trySend(isSessionStarted)
+ }
+
+ val registerResult = satelliteManager.registerForModemStateChanged(
+ Default.asExecutor(),
+ callback
+ )
+
+ 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) }
+ }.flowOn(Default)
+ }
+
+
+ /**
+ * Check if the modem is in a satellite session.
+ *
+ * @param state The SatelliteModemState provided by the SatelliteManager.
+ * @return `true` if the modem is in a satellite session, `false` otherwise.
+ */
+ fun isSatelliteSessionStarted(@SatelliteManager.SatelliteModemState state: Int): Boolean {
+ return when (state) {
+ SatelliteManager.SATELLITE_MODEM_STATE_OFF,
+ SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE,
+ SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN -> false
+ else -> true
+ }
+ }
+
const val TAG = "SatelliteDialogUtils"
const val EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG: String =
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/satellite/SatelliteDialogUtilsTest.kt b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/satellite/SatelliteDialogUtilsTest.kt
index aeda1ed6..31d7130 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/satellite/SatelliteDialogUtilsTest.kt
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/satellite/SatelliteDialogUtilsTest.kt
@@ -17,11 +17,12 @@
package com.android.settingslib.satellite
import android.content.Context
-import android.content.Intent
-import android.os.OutcomeReceiver
import android.platform.test.annotations.RequiresFlagsEnabled
import android.telephony.satellite.SatelliteManager
-import android.telephony.satellite.SatelliteManager.SatelliteException
+import android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_ENABLING_SATELLITE
+import android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_OFF
+import android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_ERROR
+import android.telephony.satellite.SatelliteModemStateCallback
import android.util.AndroidRuntimeException
import androidx.test.core.app.ApplicationProvider
import com.android.internal.telephony.flags.Flags
@@ -67,26 +68,21 @@
@Test
@RequiresFlagsEnabled(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
fun mayStartSatelliteWarningDialog_satelliteIsOn_showWarningDialog() = runBlocking {
- `when`(
- satelliteManager.requestIsEnabled(
- any(), any<OutcomeReceiver<Boolean, SatelliteManager.SatelliteException>>()
- )
- )
+ `when`(satelliteManager.registerForModemStateChanged(any(), any()))
.thenAnswer { invocation ->
- val receiver = invocation
- .getArgument<
- OutcomeReceiver<Boolean, SatelliteManager.SatelliteException>>(
+ val callback = invocation
+ .getArgument<SatelliteModemStateCallback>(
1
)
- receiver.onResult(true)
+ callback.onSatelliteModemStateChanged(SATELLITE_MODEM_STATE_ENABLING_SATELLITE)
null
}
try {
SatelliteDialogUtils.mayStartSatelliteWarningDialog(
context, coroutineScope, TYPE_IS_WIFI, allowClick = {
- assertTrue(it)
- })
+ assertTrue(it)
+ })
} catch (e: AndroidRuntimeException) {
// Catch exception of starting activity .
}
@@ -95,68 +91,49 @@
@Test
@RequiresFlagsEnabled(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
fun mayStartSatelliteWarningDialog_satelliteIsOff_notShowWarningDialog() = runBlocking {
- `when`(
- satelliteManager.requestIsEnabled(
- any(), any<OutcomeReceiver<Boolean, SatelliteManager.SatelliteException>>()
- )
- )
+ `when`(satelliteManager.registerForModemStateChanged(any(), any()))
.thenAnswer { invocation ->
- val receiver = invocation
- .getArgument<
- OutcomeReceiver<Boolean, SatelliteManager.SatelliteException>>(
+ val callback = invocation
+ .getArgument<SatelliteModemStateCallback>(
1
)
- receiver.onResult(false)
+ callback.onSatelliteModemStateChanged(SATELLITE_MODEM_STATE_OFF)
null
}
SatelliteDialogUtils.mayStartSatelliteWarningDialog(
- context, coroutineScope, TYPE_IS_WIFI, allowClick = {
- assertFalse(it)
- })
+ context, coroutineScope, TYPE_IS_WIFI, allowClick = {
+ assertFalse(it)
+ })
- verify(context, Times(0)).startActivity(any<Intent>())
+ verify(context, Times(0)).startActivity(any())
}
@Test
@RequiresFlagsEnabled(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
fun mayStartSatelliteWarningDialog_noSatelliteManager_notShowWarningDialog() = runBlocking {
- `when`(context.getSystemService(SatelliteManager::class.java))
- .thenReturn(null)
+ `when`(context.getSystemService(SatelliteManager::class.java)).thenReturn(null)
SatelliteDialogUtils.mayStartSatelliteWarningDialog(
- context, coroutineScope, TYPE_IS_WIFI, allowClick = {
- assertFalse(it)
- })
+ context, coroutineScope, TYPE_IS_WIFI, allowClick = {
+ assertFalse(it)
+ })
- verify(context, Times(0)).startActivity(any<Intent>())
+ verify(context, Times(0)).startActivity(any())
}
@Test
@RequiresFlagsEnabled(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
fun mayStartSatelliteWarningDialog_satelliteErrorResult_notShowWarningDialog() = runBlocking {
- `when`(
- satelliteManager.requestIsEnabled(
- any(), any<OutcomeReceiver<Boolean, SatelliteManager.SatelliteException>>()
- )
- )
- .thenAnswer { invocation ->
- val receiver = invocation
- .getArgument<
- OutcomeReceiver<Boolean, SatelliteManager.SatelliteException>>(
- 1
- )
- receiver.onError(SatelliteException(SatelliteManager.SATELLITE_RESULT_ERROR))
- null
- }
-
+ `when`(satelliteManager.registerForModemStateChanged(any(), any()))
+ .thenReturn(SATELLITE_RESULT_MODEM_ERROR)
SatelliteDialogUtils.mayStartSatelliteWarningDialog(
- context, coroutineScope, TYPE_IS_WIFI, allowClick = {
- assertFalse(it)
- })
+ context, coroutineScope, TYPE_IS_WIFI, allowClick = {
+ assertFalse(it)
+ })
- verify(context, Times(0)).startActivity(any<Intent>())
+ verify(context, Times(0)).startActivity(any())
}
}