From 4efa8adfa6ed66429c0d4595efa1368dbe1ee612 Mon Sep 17 00:00:00 2001 From: Hani Kazmi Date: Wed, 27 Nov 2024 10:37:39 +0000 Subject: [PATCH] [AAPM] UX for disabling WEP Toggle is restricted, and trying to connect shows an error Bug: 352420507 Change-Id: If20bf030d1c0aba55dac135a9f5f51e9a4255596 Test: Manually. Automated tests to follow Flag: com.android.wifi.flags.wep_disabled_in_apm --- .../wifi/WepNetworksPreferenceController.kt | 90 +++++++++++++++---- .../WepNetworksPreferenceControllerTest.kt | 28 ++++++ 2 files changed, 100 insertions(+), 18 deletions(-) diff --git a/src/com/android/settings/wifi/WepNetworksPreferenceController.kt b/src/com/android/settings/wifi/WepNetworksPreferenceController.kt index bad7201128c..92716bec4ff 100644 --- a/src/com/android/settings/wifi/WepNetworksPreferenceController.kt +++ b/src/com/android/settings/wifi/WepNetworksPreferenceController.kt @@ -18,6 +18,9 @@ package com.android.settings.wifi import android.content.Context import android.net.wifi.WifiManager +import android.security.advancedprotection.AdvancedProtectionManager +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -27,6 +30,7 @@ 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.semantics.Role import androidx.compose.ui.text.style.TextAlign import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.settings.R @@ -50,6 +54,9 @@ class WepNetworksPreferenceController(context: Context, preferenceKey: String) : ComposePreferenceController(context, preferenceKey) { var wifiManager = context.getSystemService(WifiManager::class.java)!! + var aapmManager = if (android.security.Flags.aapmApi() && Flags.wepDisabledInApm()) + context.getSystemService(AdvancedProtectionManager::class.java)!! + else null override fun getAvailabilityStatus() = if (Flags.androidVWifiApi()) AVAILABLE else UNSUPPORTED_ON_DEVICE @@ -60,27 +67,49 @@ class WepNetworksPreferenceController(context: Context, preferenceKey: String) : isWepSupportedFlow.collectAsStateWithLifecycle(initialValue = null).value val isWepAllowed: Boolean? = wepAllowedFlow.flow.collectAsStateWithLifecycle(initialValue = null).value - var openDialog by rememberSaveable { mutableStateOf(false) } - SwitchPreference( - object : SwitchPreferenceModel { - override val title = stringResource(R.string.wifi_allow_wep_networks) - override val summary = { getSummary(isWepSupported) } - override val checked = { - if (isWepSupported == true) isWepAllowed else isWepSupported - } - override val changeable: () -> Boolean - get() = { isWepSupported == true } + val isAapmEnabled: Boolean? = if (android.security.Flags.aapmApi() + && Flags.wepDisabledInApm()) + isAapmEnabledFlow.collectAsStateWithLifecycle(initialValue = null).value + else false - override val onCheckedChange: (Boolean) -> Unit = { newChecked -> - val wifiInfo = wifiManager.connectionInfo - if (!newChecked && wifiInfo.currentSecurityType == WifiEntry.SECURITY_WEP) { - openDialog = true - } else { - wifiManager.setWepAllowed(newChecked) - wepAllowedFlow.override(newChecked) + var openDialog by rememberSaveable { mutableStateOf(false) } + + RestrictionWrapper( + restricted = isAapmEnabled == true + ) { + SwitchPreference( + object : SwitchPreferenceModel { + override val title = stringResource(R.string.wifi_allow_wep_networks) + override val summary = { getSummary(isWepSupported) } + override val checked = { + when { + isWepSupported == false -> false + isAapmEnabled == true -> false + else -> isWepAllowed + } } + override val changeable: () -> Boolean + get() = { isWepSupported == true && isAapmEnabled == false } + + override val onCheckedChange: ((Boolean) -> Unit)? = + if (isAapmEnabled == true) { + null + } else { + { newChecked -> + val wifiInfo = wifiManager.connectionInfo + if (!newChecked && + wifiInfo.currentSecurityType == WifiEntry.SECURITY_WEP + ) { + openDialog = true + } else { + wifiManager.setWepAllowed(newChecked) + wepAllowedFlow.override(newChecked) + } + } + } } - }) + ) + } if (openDialog) { SettingsAlertDialogWithIcon( onDismissRequest = { openDialog = false }, @@ -103,6 +132,21 @@ class WepNetworksPreferenceController(context: Context, preferenceKey: String) : } } + @Composable + private fun RestrictionWrapper(restricted: Boolean, content: @Composable () -> Unit) { + if (restricted) { + Box( + Modifier.clickable( + enabled = true, + role = Role.Switch, + onClick = ::startSupportIntent + ) + ) { content() } + } else { + content() + } + } + private fun getSummary(isWepSupported: Boolean?): String = mContext.getString( when (isWepSupported) { @@ -114,6 +158,16 @@ class WepNetworksPreferenceController(context: Context, preferenceKey: String) : private val isWepSupportedFlow = flow { emit(wifiManager.isWepSupported) }.flowOn(Dispatchers.Default) + private val isAapmEnabledFlow = flow { + emit(aapmManager?.isAdvancedProtectionEnabled ?: false) }.flowOn(Dispatchers.Default) + + private fun startSupportIntent() { + aapmManager?.createSupportIntent( + AdvancedProtectionManager.FEATURE_ID_DISALLOW_WEP, + AdvancedProtectionManager.SUPPORT_DIALOG_TYPE_DISABLED_SETTING + )?.let { mContext.startActivity(it) } + } + val wepAllowedFlow = OverridableFlow( callbackFlow { 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 9183096fd7b..1f0a4916310 100644 --- a/tests/spa_unit/src/com/android/settings/wifi/WepNetworksPreferenceControllerTest.kt +++ b/tests/spa_unit/src/com/android/settings/wifi/WepNetworksPreferenceControllerTest.kt @@ -17,8 +17,10 @@ package com.android.settings.wifi import android.content.Context +import android.content.Intent import android.net.wifi.WifiInfo import android.net.wifi.WifiManager +import android.security.advancedprotection.AdvancedProtectionManager import androidx.compose.ui.test.assertIsOff import androidx.compose.ui.test.assertIsOn import androidx.compose.ui.test.isDisplayed @@ -43,9 +45,12 @@ import org.mockito.Mockito import org.mockito.kotlin.any import org.mockito.kotlin.doAnswer import org.mockito.kotlin.doReturn +import org.mockito.kotlin.doNothing import org.mockito.kotlin.mock import org.mockito.kotlin.spy import org.mockito.kotlin.stub +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever @RunWith(AndroidJUnit4::class) class WepNetworksPreferenceControllerTest { @@ -71,9 +76,15 @@ class WepNetworksPreferenceControllerTest { on { connectionInfo } doReturn mockWifiInfo } + private var mockAapmManager = + mock { + on { isAdvancedProtectionEnabled } doReturn false + } + private var context: Context = spy(ApplicationProvider.getApplicationContext()) { on { getSystemService(WifiManager::class.java) } doReturn mockWifiManager + on { getSystemService(AdvancedProtectionManager::class.java) } doReturn mockAapmManager } private var controller = WepNetworksPreferenceController(context, TEST_KEY) @@ -185,6 +196,23 @@ class WepNetworksPreferenceControllerTest { .isNotDisplayed() } + @Test + fun whenClick_aapmEnabled_openDialog() { + mockAapmManager.stub { + on { isAdvancedProtectionEnabled } doReturn true + on { createSupportIntent(any(), any()) } doReturn Intent() + } + doNothing().whenever(context).startActivity(any()) + composeTestRule.setContent { controller.Content() } + + composeTestRule.onRoot().performClick() + + composeTestRule + .onDialogText(context.getString(R.string.wifi_disconnect_button_text)) + .isNotDisplayed() + verify(context).startActivity(any()) + } + private companion object { const val TEST_KEY = "test_key" const val SSID = "ssid"