From 9faf231dc4adeb901d9c54acfa634ac8d4a8262e Mon Sep 17 00:00:00 2001 From: Weng Su Date: Fri, 15 Nov 2024 12:11:22 +0800 Subject: [PATCH] [Catalyst] Migrate Wi-Fi switch preference NO_IFTTT=Add Catalyst preference Bug: 372733639 Flag: com.android.settings.flags.catalyst_internet_settings Test: Manual testing atest -c NetworkProviderSettingsTest \ NetworkProviderScreenTest atest -c WifiSwitchPreferenceTest Change-Id: Ic6023907608e831d0a946005dd0eb6fd88b301c0 --- res/xml/network_provider_settings.xml | 1 + .../settings/network/NetworkProviderScreen.kt | 5 +- .../network/NetworkProviderSettings.java | 4 + .../WifiSwitchPreferenceController.java | 2 + .../settings/wifi/WifiSwitchPreference.kt | 144 ++++++++++++++++++ .../settings/wifi/WifiSwitchPreferenceTest.kt | 90 +++++++++++ 6 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 src/com/android/settings/wifi/WifiSwitchPreference.kt create mode 100644 tests/unit/src/com/android/settings/wifi/WifiSwitchPreferenceTest.kt diff --git a/res/xml/network_provider_settings.xml b/res/xml/network_provider_settings.xml index 418bb8d6819..74ec948713c 100644 --- a/res/xml/network_provider_settings.xml +++ b/res/xml/network_provider_settings.xml @@ -53,6 +53,7 @@ android:key="main_toggle_wifi" android:title="@string/wifi" settings:keywords="@string/keywords_wifi" + settings:restrictedSwitchSummary="@string/not_allowed_by_ent" settings:allowDividerAbove="true"/> .isEnabled(context) + + override val restrictionKeys + get() = arrayOf(UserManager.DISALLOW_CHANGE_WIFI_STATE) + + override val useAdminDisabledSummary: Boolean + get() = true + + override fun getReadPermit(context: Context, myUid: Int, callingUid: Int) = + ReadWritePermit.ALLOW + + override fun getWritePermit(context: Context, value: Boolean?, myUid: Int, callingUid: Int) = + when { + isRadioAllowed(context, value) && !isSatelliteOn(context) -> ReadWritePermit.ALLOW + else -> ReadWritePermit.DISALLOW + } + + override fun storage(context: Context): KeyValueStore = WifiSwitchStore(context) + + @Suppress("UNCHECKED_CAST") + private class WifiSwitchStore(private val context: Context) : + NoOpKeyedObservable(), + KeyValueStore { + + override fun contains(key: String) = + key == KEY && context.getSystemService(WifiManager::class.java) != null + + override fun getValue(key: String, valueType: Class): T? = + context.getSystemService(WifiManager::class.java)?.isWifiEnabled as T? + + @Suppress("DEPRECATION") + override fun setValue(key: String, valueType: Class, value: T?) { + if (value is Boolean) { + context.getSystemService(WifiManager::class.java)?.isWifiEnabled = value + } + } + } + + override fun onCreate(context: PreferenceLifecycleContext) { + context.requirePreference(KEY).let { + it.onPreferenceChangeListener = + Preference.OnPreferenceChangeListener { _: Preference, newValue: Any -> + if (!isRadioAllowed(context, newValue as Boolean?)) { + Log.w(TAG, "Don't set APM, AIRPLANE_MODE_RADIOS is not allowed") + return@OnPreferenceChangeListener false + } + if (isSatelliteOn(context)) { + Log.w(TAG, "Don't set APM, the satellite is on") + return@OnPreferenceChangeListener false + } + return@OnPreferenceChangeListener true + } + val widget = GenericSwitchController(it) + wifiEnabler = WifiEnabler(context, widget, featureFactory.metricsFeatureProvider) + Log.i(TAG, "Create WifiEnabler:$wifiEnabler") + } + } + + override fun onResume(context: PreferenceLifecycleContext) { + wifiEnabler?.resume(context) + } + + override fun onPause(context: PreferenceLifecycleContext) { + wifiEnabler?.pause() + } + + override fun onDestroy(context: PreferenceLifecycleContext) { + wifiEnabler?.teardownSwitchController() + wifiEnabler = null + } + + private fun isRadioAllowed(context: Context, newValue: Boolean?): Boolean { + newValue?.let { if (!it) return true } ?: return false + return WirelessUtils.isRadioAllowed(context, Settings.Global.RADIO_WIFI) + } + + private fun isSatelliteOn(context: Context): Boolean { + try { + return SatelliteRepository(context) + .requestIsSessionStarted(Executors.newSingleThreadExecutor()) + .get(2000, TimeUnit.MILLISECONDS) + } catch (e: Exception) { + Log.e(TAG, "Error to get satellite status : $e") + } + return false + } + + companion object { + const val TAG = "WifiSwitchPreference" + const val KEY = "main_toggle_wifi" + } +} +// LINT.ThenChange(WifiSwitchPreferenceController.java) diff --git a/tests/unit/src/com/android/settings/wifi/WifiSwitchPreferenceTest.kt b/tests/unit/src/com/android/settings/wifi/WifiSwitchPreferenceTest.kt new file mode 100644 index 00000000000..49d36a9020a --- /dev/null +++ b/tests/unit/src/com/android/settings/wifi/WifiSwitchPreferenceTest.kt @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.wifi + +import android.content.ContextWrapper +import android.net.wifi.WifiManager +import androidx.preference.SwitchPreferenceCompat +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.settingslib.preference.createAndBindWidget +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock +import org.mockito.kotlin.stub + +@RunWith(AndroidJUnit4::class) +class WifiSwitchPreferenceTest { + + private var mockWifiManager = mock() + + private val context = + object : ContextWrapper(ApplicationProvider.getApplicationContext()) { + override fun getSystemService(name: String): Any? = + when (name) { + getSystemServiceName(WifiManager::class.java) -> mockWifiManager + else -> super.getSystemService(name) + } + } + + private val wifiSwitchPreference = WifiSwitchPreference() + + @Test + fun getValue_defaultOn_returnOn() { + mockWifiManager.stub { on { isWifiEnabled } doReturn true } + + val getValue = wifiSwitchPreference + .storage(context) + .getValue(WifiSwitchPreference.KEY, Boolean::class.javaObjectType) + + assertThat(getValue).isTrue() + } + + @Test + fun getValue_defaultOff_returnOff() { + mockWifiManager.stub { on { isWifiEnabled } doReturn false } + + val getValue = wifiSwitchPreference + .storage(context) + .getValue(WifiSwitchPreference.KEY, Boolean::class.javaObjectType) + + assertThat(getValue).isFalse() + } + + @Test + fun performClick_defaultOn_checkedIsFalse() { + mockWifiManager.stub { on { isWifiEnabled } doReturn true } + + val preference = getSwitchPreference().apply { performClick() } + + assertThat(preference.isChecked).isFalse() + } + + @Test + fun performClick_defaultOff_checkedIsTrue() { + mockWifiManager.stub { on { isWifiEnabled } doReturn false } + + val preference = getSwitchPreference().apply { performClick() } + + assertThat(preference.isChecked).isTrue() + } + + private fun getSwitchPreference(): SwitchPreferenceCompat = + wifiSwitchPreference.createAndBindWidget(context) +} \ No newline at end of file