Shows a warning dialog avoid using BT, Wifi and APM.

Flag: ACONFIG com.android.internal.telephony.flags.oem_enabled_satellite_flag
Fix: 329288009
Fix: 327039349
Test: Manual test
Test: atest passed
Change-Id: I0398dc3c8137219f7ab5723412566d5133f25790
diff --git a/packages/SettingsLib/src/com/android/settingslib/satellite/SatelliteDialogUtils.kt b/packages/SettingsLib/src/com/android/settingslib/satellite/SatelliteDialogUtils.kt
new file mode 100644
index 0000000..d69c87b
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/satellite/SatelliteDialogUtils.kt
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.satellite
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.os.OutcomeReceiver
+import android.telephony.satellite.SatelliteManager
+import android.util.Log
+import android.view.WindowManager
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.lifecycleScope
+import com.android.settingslib.wifi.WifiUtils
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Dispatchers.Default
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.asExecutor
+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
+
+/** A util for Satellite dialog */
+object SatelliteDialogUtils {
+
+    /**
+     * Uses to start Satellite dialog to prevent users from using the BT, Airplane Mode, and
+     * Wifi during the satellite mode is on.
+     */
+    @JvmStatic
+    fun mayStartSatelliteWarningDialog(
+            context: Context,
+            lifecycleOwner: LifecycleOwner,
+            type: Int,
+            allowClick: (isAllowed: Boolean) -> Unit
+    ): Job {
+        return mayStartSatelliteWarningDialog(
+                context, lifecycleOwner.lifecycleScope, type, allowClick)
+    }
+
+    /**
+     * Uses to start Satellite dialog to prevent users from using the BT, Airplane Mode, and
+     * Wifi during the satellite mode is on.
+     */
+    @JvmStatic
+    fun mayStartSatelliteWarningDialog(
+            context: Context,
+            coroutineScope: CoroutineScope,
+            type: Int,
+            allowClick: (isAllowed: Boolean) -> Unit
+    ): Job =
+            coroutineScope.launch {
+                var isSatelliteModeOn = false
+                try {
+                    isSatelliteModeOn = requestIsEnabled(context)
+                } catch (e: InterruptedException) {
+                    Log.w(TAG, "Error to get satellite status : $e")
+                } catch (e: ExecutionException) {
+                    Log.w(TAG, "Error to get satellite status : $e")
+                } catch (e: TimeoutException) {
+                    Log.w(TAG, "Error to get satellite status : $e")
+                }
+
+                if (isSatelliteModeOn) {
+                    startSatelliteWarningDialog(context, type)
+                }
+                withContext(Dispatchers.Main) {
+                    allowClick(!isSatelliteModeOn)
+                }
+            }
+
+    private fun startSatelliteWarningDialog(context: Context, type: Int) {
+        context.startActivity(Intent(Intent.ACTION_MAIN).apply {
+            component = ComponentName(
+                    "com.android.settings",
+                    "com.android.settings.network.SatelliteWarningDialogActivity"
+            )
+            putExtra(WifiUtils.DIALOG_WINDOW_TYPE,
+                    WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG)
+            putExtra(EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG, type)
+            addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP)
+        })
+    }
+
+    /**
+     * Checks if the satellite modem is enabled.
+     *
+     * @param executor The executor to run the asynchronous operation on
+     * @return A ListenableFuture that will resolve to `true` if the satellite modem enabled,
+     *         `false` otherwise.
+     */
+    private suspend fun requestIsEnabled(
+            context: Context,
+    ): Boolean = withContext(Default) {
+        val satelliteManager: SatelliteManager? =
+                context.getSystemService(SatelliteManager::class.java)
+        if (satelliteManager == null) {
+            Log.w(TAG, "SatelliteManager is null")
+            return@withContext false
+        }
+
+        suspendCancellableCoroutine {continuation ->
+            satelliteManager?.requestIsEnabled(Default.asExecutor(),
+                    object : OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> {
+                        override fun onResult(result: Boolean) {
+                            Log.i(TAG, "Satellite modem enabled status: $result")
+                            continuation.resume(result)
+                        }
+
+                        override fun onError(error: SatelliteManager.SatelliteException) {
+                            super.onError(error)
+                            Log.w(TAG, "Can't get satellite modem enabled status", error)
+                            continuation.resume(false)
+                        }
+                    })
+        }
+    }
+
+    const val TAG = "SatelliteDialogUtils"
+
+    const val EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG: String =
+            "extra_type_of_satellite_warning_dialog"
+    const val TYPE_IS_UNKNOWN = -1
+    const val TYPE_IS_WIFI = 0
+    const val TYPE_IS_BLUETOOTH = 1
+    const val TYPE_IS_AIRPLANE_MODE = 2
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/Android.bp b/packages/SettingsLib/tests/robotests/Android.bp
index f87b519..e125083 100644
--- a/packages/SettingsLib/tests/robotests/Android.bp
+++ b/packages/SettingsLib/tests/robotests/Android.bp
@@ -41,7 +41,10 @@
 //###########################################################
 android_robolectric_test {
     name: "SettingsLibRoboTests",
-    srcs: ["src/**/*.java"],
+    srcs: [
+        "src/**/*.java",
+        "src/**/*.kt",
+    ],
     static_libs: [
         "Settings_robolectric_meta_service_file",
         "Robolectric_shadows_androidx_fragment_upstream",
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
new file mode 100644
index 0000000..aeda1ed6
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/satellite/SatelliteDialogUtilsTest.kt
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+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.util.AndroidRuntimeException
+import androidx.test.core.app.ApplicationProvider
+import com.android.internal.telephony.flags.Flags
+import com.android.settingslib.satellite.SatelliteDialogUtils.TYPE_IS_WIFI
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.runBlocking
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.any
+import org.mockito.Mockito.`when`
+import org.mockito.Spy
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+import org.mockito.Mockito.verify
+import org.mockito.internal.verification.Times
+import org.robolectric.RobolectricTestRunner
+
+@RunWith(RobolectricTestRunner::class)
+class SatelliteDialogUtilsTest {
+    @JvmField
+    @Rule
+    val mockitoRule: MockitoRule = MockitoJUnit.rule()
+
+    @Spy
+    var context: Context = ApplicationProvider.getApplicationContext()
+    @Mock
+    private lateinit var satelliteManager: SatelliteManager
+
+    private val coroutineScope = CoroutineScope(Dispatchers.Main)
+
+    @Before
+    fun setUp() {
+        `when`(context.getSystemService(SatelliteManager::class.java))
+                .thenReturn(satelliteManager)
+    }
+
+    @Test
+    @RequiresFlagsEnabled(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+    fun mayStartSatelliteWarningDialog_satelliteIsOn_showWarningDialog() = runBlocking {
+        `when`(
+                satelliteManager.requestIsEnabled(
+                        any(), any<OutcomeReceiver<Boolean, SatelliteManager.SatelliteException>>()
+                )
+        )
+                .thenAnswer { invocation ->
+                    val receiver = invocation
+                            .getArgument<
+                                    OutcomeReceiver<Boolean, SatelliteManager.SatelliteException>>(
+                                    1
+                            )
+                    receiver.onResult(true)
+                    null
+                }
+
+        try {
+            SatelliteDialogUtils.mayStartSatelliteWarningDialog(
+                    context, coroutineScope, TYPE_IS_WIFI, allowClick = {
+                        assertTrue(it)
+                })
+        } catch (e: AndroidRuntimeException) {
+            // Catch exception of starting activity .
+        }
+    }
+
+    @Test
+    @RequiresFlagsEnabled(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+    fun mayStartSatelliteWarningDialog_satelliteIsOff_notShowWarningDialog() = runBlocking {
+        `when`(
+                satelliteManager.requestIsEnabled(
+                        any(), any<OutcomeReceiver<Boolean, SatelliteManager.SatelliteException>>()
+                )
+        )
+                .thenAnswer { invocation ->
+                    val receiver = invocation
+                            .getArgument<
+                                    OutcomeReceiver<Boolean, SatelliteManager.SatelliteException>>(
+                                    1
+                            )
+                    receiver.onResult(false)
+                    null
+                }
+
+
+        SatelliteDialogUtils.mayStartSatelliteWarningDialog(
+            context, coroutineScope, TYPE_IS_WIFI, allowClick = {
+                assertFalse(it)
+            })
+
+        verify(context, Times(0)).startActivity(any<Intent>())
+    }
+
+    @Test
+    @RequiresFlagsEnabled(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+    fun mayStartSatelliteWarningDialog_noSatelliteManager_notShowWarningDialog() = runBlocking {
+        `when`(context.getSystemService(SatelliteManager::class.java))
+                .thenReturn(null)
+
+        SatelliteDialogUtils.mayStartSatelliteWarningDialog(
+            context, coroutineScope, TYPE_IS_WIFI, allowClick = {
+                assertFalse(it)
+            })
+
+        verify(context, Times(0)).startActivity(any<Intent>())
+    }
+
+    @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
+                }
+
+
+        SatelliteDialogUtils.mayStartSatelliteWarningDialog(
+            context, coroutineScope, TYPE_IS_WIFI, allowClick = {
+                assertFalse(it)
+            })
+
+        verify(context, Times(0)).startActivity(any<Intent>())
+    }
+}