Disable SIM On/Off operation when device is in a Satellite session
Bug: 330585109
Test: SatelliteManagerTestOnMockService SatelliteSessionControllerTest SatelliteControllerTest
Manual test with demo and real mode
Change-Id: Iade6426981f76a0b9b71828e0c86d3088c3e974e
diff --git a/src/com/android/settings/network/SatelliteRepository.kt b/src/com/android/settings/network/SatelliteRepository.kt
index 4145e01..09b7781 100644
--- a/src/com/android/settings/network/SatelliteRepository.kt
+++ b/src/com/android/settings/network/SatelliteRepository.kt
@@ -25,7 +25,6 @@
import androidx.concurrent.futures.CallbackToFutureAdapter
import com.google.common.util.concurrent.Futures.immediateFuture
import com.google.common.util.concurrent.ListenableFuture
-import java.util.concurrent.Executor
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.asExecutor
@@ -33,6 +32,7 @@
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.flowOf
+import java.util.concurrent.Executor
/**
* A repository class for interacting with the SatelliteManager API.
@@ -75,6 +75,41 @@
}
/**
+ * Checks if a satellite session has started.
+ *
+ * @param executor The executor to run the asynchronous operation on
+ * @return A ListenableFuture that will resolve to `true` if a satellite session has started,
+ * `false` otherwise.
+ */
+ fun requestIsSessionStarted(executor: Executor): ListenableFuture<Boolean> {
+ val satelliteManager: SatelliteManager? =
+ context.getSystemService(SatelliteManager::class.java)
+ if (satelliteManager == null) {
+ Log.w(TAG, "SatelliteManager is null")
+ return immediateFuture(false)
+ }
+
+ return CallbackToFutureAdapter.getFuture { completer ->
+ val callback = object : SatelliteModemStateCallback {
+ override fun onSatelliteModemStateChanged(state: Int) {
+ val isSessionStarted = isSatelliteSessionStarted(state)
+ Log.i(TAG, "Satellite modem state changed: state=$state"
+ + ", isSessionStarted=$isSessionStarted")
+ completer.set(isSessionStarted)
+ satelliteManager.unregisterForModemStateChanged(this)
+ }
+ }
+
+ val registerResult = satelliteManager.registerForModemStateChanged(executor, callback)
+ if (registerResult != SatelliteManager.SATELLITE_RESULT_SUCCESS) {
+ Log.w(TAG, "Failed to register for satellite modem state change: $registerResult")
+ completer.set(false)
+ }
+ "requestIsSessionStarted"
+ }
+ }
+
+ /**
* Provides a Flow that emits the enabled state of the satellite modem. Updates are triggered
* when the modem state changes.
*
@@ -134,5 +169,20 @@
companion object {
private const val TAG: String = "SatelliteRepository"
}
+
+ /**
+ * 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
+ }
+ }
}
diff --git a/src/com/android/settings/sim/receivers/SimSlotChangeReceiver.java b/src/com/android/settings/sim/receivers/SimSlotChangeReceiver.java
index 4920bb8..406e083 100644
--- a/src/com/android/settings/sim/receivers/SimSlotChangeReceiver.java
+++ b/src/com/android/settings/sim/receivers/SimSlotChangeReceiver.java
@@ -56,22 +56,23 @@
public static void runOnBackgroundThread(Context context) {
if (shouldHandleSlotChange(context)) {
- Log.d(TAG, "Checking satellite enabled status");
+ Log.d(TAG, "Checking satellite session status");
Executor executor = Executors.newSingleThreadExecutor();
- ListenableFuture<Boolean> satelliteEnabledFuture = new SatelliteRepository(context)
- .requestIsEnabled(executor);
- satelliteEnabledFuture.addListener(() -> {
- boolean isSatelliteEnabled = false;
+ ListenableFuture<Boolean> isSatelliteSessionStartedFuture =
+ new SatelliteRepository(context).requestIsSessionStarted(executor);
+ isSatelliteSessionStartedFuture.addListener(() -> {
+ boolean isSatelliteSessionStarted = false;
try {
- isSatelliteEnabled = satelliteEnabledFuture.get();
+ isSatelliteSessionStarted = isSatelliteSessionStartedFuture.get();
} catch (ExecutionException | InterruptedException e) {
- Log.w(TAG, "Can't get satellite enabled status", e);
+ Log.w(TAG, "Can't get satellite session status", e);
}
- if (isSatelliteEnabled) {
- Log.i(TAG, "Satellite is enabled. Unable to handle SIM slot changes");
+ if (isSatelliteSessionStarted) {
+ Log.i(TAG, "Device is in a satellite session. Unable to handle SIM slot"
+ + " changes");
} else {
- Log.i(TAG, "Satellite is disabled. Handle slot changes");
+ Log.i(TAG, "Not in a satellite session. Handle slot changes");
SimSlotChangeHandler.get().onSlotsStatusChange(context.getApplicationContext());
}
}, executor);
diff --git a/tests/robotests/src/com/android/settings/network/SatelliteRepositoryTest.kt b/tests/robotests/src/com/android/settings/network/SatelliteRepositoryTest.kt
index 432048c..5c6e7eb 100644
--- a/tests/robotests/src/com/android/settings/network/SatelliteRepositoryTest.kt
+++ b/tests/robotests/src/com/android/settings/network/SatelliteRepositoryTest.kt
@@ -24,7 +24,6 @@
import androidx.test.core.app.ApplicationProvider
import com.google.common.truth.Truth.assertThat
import com.google.common.util.concurrent.ListenableFuture
-import java.util.concurrent.Executor
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertFalse
@@ -35,12 +34,12 @@
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
-import org.mockito.Mockito.any
-import org.mockito.Mockito.`when`
+import org.mockito.Mockito.*
import org.mockito.Spy
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule
import org.robolectric.RobolectricTestRunner
+import java.util.concurrent.Executor
@RunWith(RobolectricTestRunner::class)
@@ -91,6 +90,55 @@
}
@Test
+ fun requestIsSessionStarted_resultIsTrue() = runBlocking {
+ `when`(mockSatelliteManager.registerForModemStateChanged(any(), any())
+ ).thenAnswer { invocation ->
+ val callback = invocation.getArgument<SatelliteModemStateCallback>(1)
+ callback.onSatelliteModemStateChanged(SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED)
+ SatelliteManager.SATELLITE_RESULT_SUCCESS
+ }
+
+ val result: ListenableFuture<Boolean> = repository.requestIsSessionStarted(mockExecutor)
+ assertTrue(result.get())
+ verify(mockSatelliteManager).unregisterForModemStateChanged(any())
+ }
+
+ @Test
+ fun requestIsSessionStarted_resultIsFalse() = runBlocking {
+ `when`(mockSatelliteManager.registerForModemStateChanged(any(), any())
+ ).thenAnswer { invocation ->
+ val callback = invocation.getArgument<SatelliteModemStateCallback>(1)
+ callback.onSatelliteModemStateChanged(SatelliteManager.SATELLITE_MODEM_STATE_OFF)
+ SatelliteManager.SATELLITE_RESULT_SUCCESS
+ }
+
+ val result: ListenableFuture<Boolean> = repository.requestIsSessionStarted(mockExecutor)
+ assertFalse(result.get())
+ verify(mockSatelliteManager).unregisterForModemStateChanged(any())
+ }
+
+ @Test
+ fun requestIsSessionStarted_registerFailed() = runBlocking {
+ `when`(mockSatelliteManager.registerForModemStateChanged(any(), any())
+ ).thenAnswer { invocation ->
+ SatelliteManager.SATELLITE_RESULT_ERROR
+ }
+
+ val result: ListenableFuture<Boolean> = repository.requestIsSessionStarted(mockExecutor)
+ assertFalse(result.get())
+ verify(mockSatelliteManager, never()).unregisterForModemStateChanged(any())
+ }
+
+ @Test
+ fun requestIsSessionStarted_nullSatelliteManager() = runBlocking {
+ `when`(spyContext.getSystemService(SatelliteManager::class.java)).thenReturn(null)
+
+ val result: ListenableFuture<Boolean> = repository.requestIsSessionStarted(mockExecutor)
+ assertFalse(result.get())
+ verifyNoInteractions(mockSatelliteManager)
+ }
+
+ @Test
fun requestIsEnabled_resultIsFalse() = runBlocking {
`when`(
mockSatelliteManager.requestIsEnabled(