diff --git a/res/values/strings.xml b/res/values/strings.xml index c5d0017e7d0..ee77cdc488e 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2044,6 +2044,10 @@ Allow WEP Close + + Disconnect from %1$s? + + You\u0027re connected to a WEP network. If you block these networks, you\u0027ll be disconnected. diff --git a/src/com/android/settings/wifi/WepNetworksPreferenceController.kt b/src/com/android/settings/wifi/WepNetworksPreferenceController.kt index c84e79aa597..2db0e0201a6 100644 --- a/src/com/android/settings/wifi/WepNetworksPreferenceController.kt +++ b/src/com/android/settings/wifi/WepNetworksPreferenceController.kt @@ -18,24 +18,33 @@ package com.android.settings.wifi import android.content.Context import android.net.wifi.WifiManager +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.fragment.app.Fragment import androidx.lifecycle.compose.collectAsStateWithLifecycle -import androidx.preference.Preference -import androidx.preference.PreferenceScreen import com.android.settings.R import com.android.settings.spa.preference.ComposePreferenceController import com.android.settingslib.spa.framework.compose.OverridableFlow +import com.android.settingslib.spa.widget.dialog.AlertDialogButton +import com.android.settingslib.spa.widget.dialog.SettingsAlertDialogWithIcon import com.android.settingslib.spa.widget.preference.SwitchPreference import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel import com.android.wifi.flags.Flags +import com.android.wifitrackerlib.WifiEntry import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.asExecutor import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.callbackFlow -/** Controller that controls whether the Wi-Fi Wakeup feature should be enabled. */ +/** Controller that controls whether the WEP network can be connected. */ class WepNetworksPreferenceController(context: Context, preferenceKey: String) : ComposePreferenceController(context, preferenceKey) { @@ -47,6 +56,8 @@ class WepNetworksPreferenceController(context: Context, preferenceKey: String) : @Composable override fun Content() { val checked by wepAllowedFlow.flow.collectAsStateWithLifecycle(initialValue = null) + var openDialog by rememberSaveable { mutableStateOf(false) } + val wifiInfo = wifiManager.connectionInfo SwitchPreference(object : SwitchPreferenceModel { override val title = stringResource(R.string.wifi_allow_wep_networks) override val summary = { getSummary() } @@ -54,10 +65,40 @@ class WepNetworksPreferenceController(context: Context, preferenceKey: String) : override val changeable: () -> Boolean get() = { carrierAllowed } override val onCheckedChange: (Boolean) -> Unit = { newChecked -> - wifiManager.setWepAllowed(newChecked) - wepAllowedFlow.override(newChecked) + if (!newChecked && wifiInfo.currentSecurityType == WifiEntry.SECURITY_WEP) { + openDialog = true + } else { + wifiManager.setWepAllowed(newChecked) + wepAllowedFlow.override(newChecked) + } } }) + if (openDialog) { + SettingsAlertDialogWithIcon( + onDismissRequest = { openDialog = false }, + confirmButton = AlertDialogButton( + stringResource(R.string.wifi_disconnect_button_text) + ) { + wifiManager.setWepAllowed(false) + wepAllowedFlow.override(false) + openDialog = false + }, + dismissButton = + AlertDialogButton( + stringResource(R.string.wifi_cancel) + ) { openDialog = false }, + title = String.format( + stringResource(R.string.wifi_settings_wep_networks_disconnect_title), + wifiInfo.ssid.removeSurrounding("\"") + ), + text = { + Text( + stringResource(R.string.wifi_settings_wep_networks_disconnect_summary), + modifier = Modifier.fillMaxWidth(), + textAlign = TextAlign.Center + ) + }) + } } override fun getSummary(): String = mContext.getString( diff --git a/tests/spa_unit/src/com/android/settings/wifi/WepNetworksPreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/wifi/WepNetworksPreferenceControllerTest.kt index 994abbf5a60..49e6a171efd 100644 --- a/tests/spa_unit/src/com/android/settings/wifi/WepNetworksPreferenceControllerTest.kt +++ b/tests/spa_unit/src/com/android/settings/wifi/WepNetworksPreferenceControllerTest.kt @@ -20,6 +20,8 @@ import android.content.Context import android.net.wifi.WifiManager import androidx.compose.ui.test.assertIsOff import androidx.compose.ui.test.assertIsOn +import androidx.compose.ui.test.isDisplayed +import androidx.compose.ui.test.isNotDisplayed import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.onRoot @@ -28,12 +30,16 @@ import androidx.preference.PreferenceManager import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settings.R +import com.android.settings.dashboard.DashboardFragment import com.android.settings.spa.preference.ComposePreference +import com.android.settingslib.spa.testutils.onDialogText +import com.android.wifitrackerlib.WifiEntry import java.util.function.Consumer import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import org.mockito.Mockito import org.mockito.kotlin.any import org.mockito.kotlin.doAnswer import org.mockito.kotlin.doReturn @@ -48,25 +54,30 @@ class WepNetworksPreferenceControllerTest { private var wepAllowed = true - private val mockWifiManager = mock { + private var mockWifiInfo = mock { + on { it.currentSecurityType } doReturn WifiEntry.SECURITY_EAP + on { it.ssid } doReturn SSID + } + + private var mockWifiManager = mock { on { queryWepAllowed(any(), any()) } doAnswer { @Suppress("UNCHECKED_CAST") val consumer = it.arguments[1] as Consumer consumer.accept(wepAllowed) } on { it.isWepSupported } doReturn true + on { it.connectionInfo } doReturn mockWifiInfo } private var context: Context = spy(ApplicationProvider.getApplicationContext()) { on { getSystemService(WifiManager::class.java) } doReturn mockWifiManager } - private var controller = WepNetworksPreferenceController(context, TEST_KEY) + private var controller = WepNetworksPreferenceController(context, TEST_KEY) private val preference = ComposePreference(context).apply { key = TEST_KEY } private val preferenceScreen = PreferenceManager(context).createPreferenceScreen(context) - @Before fun setUp() { preferenceScreen.addPreference(preference) @@ -79,6 +90,7 @@ class WepNetworksPreferenceControllerTest { composeTestRule.setContent { controller.Content() } + composeTestRule.onNodeWithText(context.getString(R.string.wifi_allow_wep_networks)) .assertIsOn() } @@ -89,6 +101,7 @@ class WepNetworksPreferenceControllerTest { composeTestRule.setContent { controller.Content() } + composeTestRule.onNodeWithText(context.getString(R.string.wifi_allow_wep_networks)) .assertIsOff() } @@ -101,7 +114,6 @@ class WepNetworksPreferenceControllerTest { } composeTestRule.onRoot().performClick() - composeTestRule.onNodeWithText(context.getString(R.string.wifi_allow_wep_networks)) .assertIsOn() } @@ -114,12 +126,38 @@ class WepNetworksPreferenceControllerTest { } composeTestRule.onRoot().performClick() - composeTestRule.onNodeWithText(context.getString(R.string.wifi_allow_wep_networks)) .assertIsOff() } + @Test + fun whenClick_wepAllowed_openDialog() { + wepAllowed = true + Mockito.`when`(mockWifiInfo.currentSecurityType).thenReturn(WifiEntry.SECURITY_WEP) + composeTestRule.setContent { + controller.Content() + } + + composeTestRule.onRoot().performClick() + composeTestRule.onDialogText(context.getString(R.string.wifi_disconnect_button_text)) + .isDisplayed() + } + + @Test + fun whenClick_wepDisallowed_openDialog() { + wepAllowed = false + Mockito.`when`(mockWifiInfo.currentSecurityType).thenReturn(WifiEntry.SECURITY_WEP) + composeTestRule.setContent { + controller.Content() + } + + composeTestRule.onRoot().performClick() + composeTestRule.onDialogText(context.getString(R.string.wifi_disconnect_button_text)) + .isNotDisplayed() + } + private companion object { const val TEST_KEY = "test_key" + const val SSID = "ssid" } } \ No newline at end of file