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