• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.settings.wifi
18 
19 import android.content.Context
20 import android.net.wifi.WifiManager
21 import android.security.advancedprotection.AdvancedProtectionManager
22 import androidx.compose.foundation.clickable
23 import androidx.compose.foundation.layout.Box
24 import androidx.compose.foundation.layout.fillMaxWidth
25 import androidx.compose.material3.Text
26 import androidx.compose.runtime.Composable
27 import androidx.compose.runtime.getValue
28 import androidx.compose.runtime.mutableStateOf
29 import androidx.compose.runtime.saveable.rememberSaveable
30 import androidx.compose.runtime.setValue
31 import androidx.compose.ui.Modifier
32 import androidx.compose.ui.res.stringResource
33 import androidx.compose.ui.semantics.Role
34 import androidx.compose.ui.text.style.TextAlign
35 import androidx.lifecycle.compose.collectAsStateWithLifecycle
36 import com.android.settings.R
37 import com.android.settings.spa.preference.ComposePreferenceController
38 import com.android.settingslib.spa.framework.compose.OverridableFlow
39 import com.android.settingslib.spa.widget.dialog.AlertDialogButton
40 import com.android.settingslib.spa.widget.dialog.SettingsAlertDialogWithIcon
41 import com.android.settingslib.spa.widget.preference.SwitchPreference
42 import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
43 import com.android.wifi.flags.Flags
44 import com.android.wifitrackerlib.WifiEntry
45 import kotlinx.coroutines.Dispatchers
46 import kotlinx.coroutines.asExecutor
47 import kotlinx.coroutines.channels.awaitClose
48 import kotlinx.coroutines.flow.callbackFlow
49 import kotlinx.coroutines.flow.flow
50 import kotlinx.coroutines.flow.flowOn
51 
52 /** Controller that controls whether the WEP network can be connected. */
53 class WepNetworksPreferenceController(context: Context, preferenceKey: String) :
54     ComposePreferenceController(context, preferenceKey) {
55 
56     var wifiManager = context.getSystemService(WifiManager::class.java)!!
57     var aapmManager = if (android.security.Flags.aapmApi() && Flags.wepDisabledInApm())
58         context.getSystemService(AdvancedProtectionManager::class.java)!!
59     else null
60 
61     override fun getAvailabilityStatus() =
62         if (Flags.androidVWifiApi()) AVAILABLE else UNSUPPORTED_ON_DEVICE
63 
64     @Composable
65     override fun Content() {
66         val isWepSupported: Boolean? =
67             isWepSupportedFlow.collectAsStateWithLifecycle(initialValue = null).value
68         val isWepAllowed: Boolean? =
69             wepAllowedFlow.flow.collectAsStateWithLifecycle(initialValue = null).value
70         val isAapmEnabled: Boolean? = if (android.security.Flags.aapmApi()
71             && Flags.wepDisabledInApm())
72                 isAapmEnabledFlow.collectAsStateWithLifecycle(initialValue = null).value
73         else false
74 
75         var openDialog by rememberSaveable { mutableStateOf(false) }
76 
77         RestrictionWrapper(
78             restricted = isAapmEnabled == true
79         ) {
80             SwitchPreference(
81                 object : SwitchPreferenceModel {
82                     override val title = stringResource(R.string.wifi_allow_wep_networks)
83                     override val summary = { getSummary(isWepSupported) }
84                     override val checked = {
85                         when {
86                             isWepSupported == false -> false
87                             isAapmEnabled == true -> false
88                             else -> isWepAllowed
89                         }
90                     }
91                     override val changeable: () -> Boolean
92                         get() = { isWepSupported == true && isAapmEnabled == false }
93 
94                     override val onCheckedChange: ((Boolean) -> Unit)? =
95                         if (isAapmEnabled == true) {
96                             null
97                         } else {
98                             { newChecked ->
99                                 val wifiInfo = wifiManager.connectionInfo
100                                 if (!newChecked &&
101                                     wifiInfo.currentSecurityType == WifiEntry.SECURITY_WEP
102                                 ) {
103                                     openDialog = true
104                                 } else {
105                                     wifiManager.setWepAllowed(newChecked)
106                                     wepAllowedFlow.override(newChecked)
107                                 }
108                             }
109                         }
110                 }
111             )
112         }
113         if (openDialog) {
114             SettingsAlertDialogWithIcon(
115                 onDismissRequest = { openDialog = false },
116                 confirmButton =
117                     AlertDialogButton(stringResource(R.string.sim_action_yes)) {
118                         wifiManager.setWepAllowed(false)
119                         wepAllowedFlow.override(false)
120                         openDialog = false
121                     },
122                 dismissButton =
123                     AlertDialogButton(stringResource(R.string.wifi_cancel)) { openDialog = false },
124                 title = stringResource(R.string.wifi_settings_wep_networks_disconnect_title),
125                 text = {
126                     Text(
127                         stringResource(R.string.wifi_settings_wep_networks_disconnect_summary),
128                         modifier = Modifier.fillMaxWidth(),
129                         textAlign = TextAlign.Center,
130                     )
131                 })
132         }
133     }
134 
135     @Composable
136     private fun RestrictionWrapper(restricted: Boolean, content: @Composable () -> Unit) {
137         if (restricted) {
138             Box(
139                 Modifier.clickable(
140                     enabled = true,
141                     role = Role.Switch,
142                     onClick = ::startSupportIntent
143                 )
144             ) { content() }
145         } else {
146             content()
147         }
148     }
149 
150     private fun getSummary(isWepSupported: Boolean?): String =
151         mContext.getString(
152             when (isWepSupported) {
153                 true -> R.string.wifi_allow_wep_networks_summary
154                 false -> R.string.wifi_allow_wep_networks_summary_carrier_not_allow
155                 null -> R.string.summary_placeholder
156             })
157 
158     private val isWepSupportedFlow =
159         flow { emit(wifiManager.isWepSupported) }.flowOn(Dispatchers.Default)
160 
161     private val isAapmEnabledFlow = flow {
162         emit(aapmManager?.isAdvancedProtectionEnabled ?: false) }.flowOn(Dispatchers.Default)
163 
164     private fun startSupportIntent() {
165         AdvancedProtectionManager.createSupportIntent(
166             AdvancedProtectionManager.FEATURE_ID_DISALLOW_WEP,
167             AdvancedProtectionManager.SUPPORT_DIALOG_TYPE_DISABLED_SETTING
168         ).let { mContext.startActivity(it) }
169     }
170 
171     val wepAllowedFlow =
172         OverridableFlow(
173             callbackFlow {
174                 wifiManager.queryWepAllowed(Dispatchers.Default.asExecutor(), ::trySend)
175 
176                 awaitClose {}
177             })
178 }
179