1 /*
<lambda>null2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settingslib.satellite
18 
19 import android.content.ComponentName
20 import android.content.Context
21 import android.content.Intent
22 import android.os.OutcomeReceiver
23 import android.telephony.satellite.SatelliteManager
24 import android.util.Log
25 import android.view.WindowManager
26 import androidx.lifecycle.LifecycleOwner
27 import androidx.lifecycle.lifecycleScope
28 import com.android.settingslib.wifi.WifiUtils
29 import kotlinx.coroutines.CoroutineScope
30 import kotlinx.coroutines.Dispatchers
31 import kotlinx.coroutines.Dispatchers.Default
32 import kotlinx.coroutines.Job
33 import kotlinx.coroutines.asExecutor
34 import kotlinx.coroutines.launch
35 import kotlinx.coroutines.suspendCancellableCoroutine
36 import kotlinx.coroutines.withContext
37 import java.util.concurrent.ExecutionException
38 import java.util.concurrent.TimeoutException
39 import kotlin.coroutines.resume
40 
41 /** A util for Satellite dialog */
42 object SatelliteDialogUtils {
43 
44     /**
45      * Uses to start Satellite dialog to prevent users from using the BT, Airplane Mode, and
46      * Wifi during the satellite mode is on.
47      */
48     @JvmStatic
49     fun mayStartSatelliteWarningDialog(
50             context: Context,
51             lifecycleOwner: LifecycleOwner,
52             type: Int,
53             allowClick: (isAllowed: Boolean) -> Unit
54     ): Job {
55         return mayStartSatelliteWarningDialog(
56                 context, lifecycleOwner.lifecycleScope, type, allowClick)
57     }
58 
59     /**
60      * Uses to start Satellite dialog to prevent users from using the BT, Airplane Mode, and
61      * Wifi during the satellite mode is on.
62      */
63     @JvmStatic
64     fun mayStartSatelliteWarningDialog(
65             context: Context,
66             coroutineScope: CoroutineScope,
67             type: Int,
68             allowClick: (isAllowed: Boolean) -> Unit
69     ): Job =
70             coroutineScope.launch {
71                 var isSatelliteModeOn = false
72                 try {
73                     isSatelliteModeOn = requestIsEnabled(context)
74                 } catch (e: InterruptedException) {
75                     Log.w(TAG, "Error to get satellite status : $e")
76                 } catch (e: ExecutionException) {
77                     Log.w(TAG, "Error to get satellite status : $e")
78                 } catch (e: TimeoutException) {
79                     Log.w(TAG, "Error to get satellite status : $e")
80                 }
81 
82                 if (isSatelliteModeOn) {
83                     startSatelliteWarningDialog(context, type)
84                 }
85                 withContext(Dispatchers.Main) {
86                     allowClick(!isSatelliteModeOn)
87                 }
88             }
89 
90     private fun startSatelliteWarningDialog(context: Context, type: Int) {
91         context.startActivity(Intent(Intent.ACTION_MAIN).apply {
92             component = ComponentName(
93                     "com.android.settings",
94                     "com.android.settings.network.SatelliteWarningDialogActivity"
95             )
96             putExtra(WifiUtils.DIALOG_WINDOW_TYPE,
97                     WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG)
98             putExtra(EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG, type)
99             addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP)
100         })
101     }
102 
103     /**
104      * Checks if the satellite modem is enabled.
105      *
106      * @param executor The executor to run the asynchronous operation on
107      * @return A ListenableFuture that will resolve to `true` if the satellite modem enabled,
108      *         `false` otherwise.
109      */
110     private suspend fun requestIsEnabled(
111             context: Context,
112     ): Boolean = withContext(Default) {
113         val satelliteManager: SatelliteManager? =
114                 context.getSystemService(SatelliteManager::class.java)
115         if (satelliteManager == null) {
116             Log.w(TAG, "SatelliteManager is null")
117             return@withContext false
118         }
119 
120         suspendCancellableCoroutine {continuation ->
121             satelliteManager?.requestIsEnabled(Default.asExecutor(),
122                     object : OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> {
123                         override fun onResult(result: Boolean) {
124                             Log.i(TAG, "Satellite modem enabled status: $result")
125                             continuation.resume(result)
126                         }
127 
128                         override fun onError(error: SatelliteManager.SatelliteException) {
129                             super.onError(error)
130                             Log.w(TAG, "Can't get satellite modem enabled status", error)
131                             continuation.resume(false)
132                         }
133                     })
134         }
135     }
136 
137     const val TAG = "SatelliteDialogUtils"
138 
139     const val EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG: String =
140             "extra_type_of_satellite_warning_dialog"
141     const val TYPE_IS_UNKNOWN = -1
142     const val TYPE_IS_WIFI = 0
143     const val TYPE_IS_BLUETOOTH = 1
144     const val TYPE_IS_AIRPLANE_MODE = 2
145 }