Loading src/com/android/settings/wifi/WepNetworksPreferenceController.kt +72 −18 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -60,27 +67,49 @@ class WepNetworksPreferenceController(context: Context, preferenceKey: String) : isWepSupportedFlow.collectAsStateWithLifecycle(initialValue = null).value val isWepAllowed: Boolean? = wepAllowedFlow.flow.collectAsStateWithLifecycle(initialValue = null).value val isAapmEnabled: Boolean? = if (android.security.Flags.aapmApi() && Flags.wepDisabledInApm()) isAapmEnabledFlow.collectAsStateWithLifecycle(initialValue = null).value else false 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 = { if (isWepSupported == true) isWepAllowed else isWepSupported when { isWepSupported == false -> false isAapmEnabled == true -> false else -> isWepAllowed } } override val changeable: () -> Boolean get() = { isWepSupported == true } get() = { isWepSupported == true && isAapmEnabled == false } override val onCheckedChange: (Boolean) -> Unit = { newChecked -> override val onCheckedChange: ((Boolean) -> Unit)? = if (isAapmEnabled == true) { null } else { { newChecked -> val wifiInfo = wifiManager.connectionInfo if (!newChecked && wifiInfo.currentSecurityType == WifiEntry.SECURITY_WEP) { if (!newChecked && wifiInfo.currentSecurityType == WifiEntry.SECURITY_WEP ) { openDialog = true } else { wifiManager.setWepAllowed(newChecked) wepAllowedFlow.override(newChecked) } } }) } } ) } if (openDialog) { SettingsAlertDialogWithIcon( onDismissRequest = { openDialog = false }, Loading @@ -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) { Loading @@ -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 { Loading tests/spa_unit/src/com/android/settings/wifi/WepNetworksPreferenceControllerTest.kt +28 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 { Loading @@ -71,9 +76,15 @@ class WepNetworksPreferenceControllerTest { on { connectionInfo } doReturn mockWifiInfo } private var mockAapmManager = mock<AdvancedProtectionManager> { 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) Loading Loading @@ -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" Loading Loading
src/com/android/settings/wifi/WepNetworksPreferenceController.kt +72 −18 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -60,27 +67,49 @@ class WepNetworksPreferenceController(context: Context, preferenceKey: String) : isWepSupportedFlow.collectAsStateWithLifecycle(initialValue = null).value val isWepAllowed: Boolean? = wepAllowedFlow.flow.collectAsStateWithLifecycle(initialValue = null).value val isAapmEnabled: Boolean? = if (android.security.Flags.aapmApi() && Flags.wepDisabledInApm()) isAapmEnabledFlow.collectAsStateWithLifecycle(initialValue = null).value else false 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 = { if (isWepSupported == true) isWepAllowed else isWepSupported when { isWepSupported == false -> false isAapmEnabled == true -> false else -> isWepAllowed } } override val changeable: () -> Boolean get() = { isWepSupported == true } get() = { isWepSupported == true && isAapmEnabled == false } override val onCheckedChange: (Boolean) -> Unit = { newChecked -> override val onCheckedChange: ((Boolean) -> Unit)? = if (isAapmEnabled == true) { null } else { { newChecked -> val wifiInfo = wifiManager.connectionInfo if (!newChecked && wifiInfo.currentSecurityType == WifiEntry.SECURITY_WEP) { if (!newChecked && wifiInfo.currentSecurityType == WifiEntry.SECURITY_WEP ) { openDialog = true } else { wifiManager.setWepAllowed(newChecked) wepAllowedFlow.override(newChecked) } } }) } } ) } if (openDialog) { SettingsAlertDialogWithIcon( onDismissRequest = { openDialog = false }, Loading @@ -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) { Loading @@ -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 { Loading
tests/spa_unit/src/com/android/settings/wifi/WepNetworksPreferenceControllerTest.kt +28 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 { Loading @@ -71,9 +76,15 @@ class WepNetworksPreferenceControllerTest { on { connectionInfo } doReturn mockWifiInfo } private var mockAapmManager = mock<AdvancedProtectionManager> { 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) Loading Loading @@ -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" Loading