Loading src/com/android/settings/network/AdaptiveConnectivityScreen.kt +5 −1 Original line number Diff line number Diff line Loading @@ -37,6 +37,10 @@ class AdaptiveConnectivityScreen : PreferenceScreenCreator { override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(context, this) { +AdaptiveConnectivityTogglePreference() if (Flags.enableNestedToggleSwitches()) { +WifiScorerTogglePreference() +AdaptiveMobileNetworkTogglePreference() } } override fun hasCompleteHierarchy() = false Loading src/com/android/settings/network/AdaptiveConnectivitySettings.java +19 −10 Original line number Diff line number Diff line Loading @@ -15,9 +15,14 @@ */ package com.android.settings.network; import static android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED; import static android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_WIFI_ENABLED; import android.app.settings.SettingsEnums; import android.content.Context; import android.net.wifi.WifiManager; import android.os.Bundle; import android.provider.Settings; import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; Loading @@ -31,12 +36,7 @@ import com.android.settingslib.search.SearchIndexable; /** Adaptive connectivity is a feature which automatically manages network connections. */ @SearchIndexable public class AdaptiveConnectivitySettings extends DashboardFragment { private static final String TAG = "AdaptiveConnectivitySettings"; protected static final String ADAPTIVE_CONNECTIVITY_WIFI_ENABLED = "adaptive_connectivity_wifi_enabled"; protected static final String ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED = "adaptive_connectivity_mobile_network_enabled"; @Override public int getMetricsCategory() { Loading Loading @@ -65,16 +65,25 @@ public class AdaptiveConnectivitySettings extends DashboardFragment { public void onCreatePreferences(@NonNull Bundle savedInstanceState, @NonNull String rootKey) { Log.i("Settings", "onCreatePreferences"); super.onCreatePreferences(savedInstanceState, rootKey); if (Flags.enableNestedToggleSwitches()) { setSwitchVisibility(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED, true); setSwitchVisibility(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED, true); if (Flags.enableNestedToggleSwitches() && !isCatalystEnabled()) { setupSwitchPreferenceCompat(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED); setupSwitchPreferenceCompat(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED); } } private void setSwitchVisibility(String key, boolean isVisible) { private void setupSwitchPreferenceCompat(String key) { SwitchPreferenceCompat switchPreference = findPreference(key); if (switchPreference != null) { switchPreference.setVisible(isVisible); switchPreference.setOnPreferenceChangeListener( (preference, newValue) -> { boolean isChecked = (Boolean) newValue; Settings.Secure.putInt(getContentResolver(), key, isChecked ? 1 : 0); if (preference.getKey().equals(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED)) { getSystemService(WifiManager.class).setWifiScoringEnabled(isChecked); } return true; }); switchPreference.setVisible(true); } } } src/com/android/settings/network/AdaptiveMobileNetworkTogglePreference.kt 0 → 100644 +89 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.network import android.app.settings.SettingsEnums.ACTION_ADAPTIVE_CONNECTIVITY import android.content.Context import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED import com.android.settings.R import com.android.settings.contract.KEY_ADAPTIVE_CONNECTIVITY import com.android.settings.metrics.PreferenceActionMetricsProvider import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.KeyValueStoreDelegate import com.android.settingslib.datastore.SettingsSecureStore import com.android.settingslib.datastore.SettingsStore import com.android.settingslib.metadata.ReadWritePermit import com.android.settingslib.metadata.SensitivityLevel import com.android.settingslib.metadata.SwitchPreference class AdaptiveMobileNetworkTogglePreference() : SwitchPreference( KEY, R.string.adaptive_connectivity_mobile_network_switch_title, ), PreferenceActionMetricsProvider { override val preferenceActionMetrics: Int get() = ACTION_ADAPTIVE_CONNECTIVITY override val key: String get() = KEY override fun tags(context: Context) = arrayOf(KEY_ADAPTIVE_CONNECTIVITY) override fun storage(context: Context): KeyValueStore = AdaptiveMobileNetworkToggleStorage(context) override fun getReadPermissions(context: Context) = SettingsSecureStore.getReadPermissions() override fun getWritePermissions(context: Context) = SettingsSecureStore.getWritePermissions() override fun getReadPermit(context: Context, callingPid: Int, callingUid: Int) = ReadWritePermit.ALLOW override fun getWritePermit( context: Context, value: Boolean?, callingPid: Int, callingUid: Int, ) = ReadWritePermit.ALLOW override val sensitivityLevel get() = SensitivityLevel.NO_SENSITIVITY @Suppress("UNCHECKED_CAST") private class AdaptiveMobileNetworkToggleStorage( private val context: Context, private val settingsStore: SettingsStore = SettingsSecureStore.get(context), ) : KeyValueStoreDelegate { override val keyValueStoreDelegate get() = settingsStore override fun <T : Any> getDefaultValue(key: String, valueType: Class<T>) = DEFAULT_VALUE as T override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) { settingsStore.setValue(key, valueType, value) } } companion object { const val KEY = ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED const val DEFAULT_VALUE = true } } No newline at end of file src/com/android/settings/network/WifiScorerTogglePreference.kt 0 → 100644 +101 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.network import android.Manifest import android.app.settings.SettingsEnums.ACTION_ADAPTIVE_CONNECTIVITY import android.content.Context import android.net.wifi.WifiManager import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_WIFI_ENABLED import androidx.annotation.RequiresPermission import com.android.settings.R import com.android.settings.contract.KEY_ADAPTIVE_CONNECTIVITY import com.android.settings.metrics.PreferenceActionMetricsProvider import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.KeyValueStoreDelegate import com.android.settingslib.datastore.SettingsSecureStore import com.android.settingslib.datastore.SettingsStore import com.android.settingslib.datastore.and import com.android.settingslib.metadata.ReadWritePermit import com.android.settingslib.metadata.SensitivityLevel import com.android.settingslib.metadata.SwitchPreference class WifiScorerTogglePreference() : SwitchPreference( KEY, R.string.adaptive_connectivity_wifi_switch_title ), PreferenceActionMetricsProvider { override val preferenceActionMetrics: Int get() = ACTION_ADAPTIVE_CONNECTIVITY override val key: String get() = KEY override fun tags(context: Context) = arrayOf(KEY_ADAPTIVE_CONNECTIVITY) override fun storage(context: Context): KeyValueStore = WifiScorerToggleStorage(context) override fun getReadPermissions(context: Context) = SettingsSecureStore.getReadPermissions() override fun getWritePermissions(context: Context) = SettingsSecureStore.getWritePermissions() and Manifest.permission.NETWORK_SETTINGS override fun getReadPermit(context: Context, callingPid: Int, callingUid: Int) = ReadWritePermit.ALLOW override fun getWritePermit( context: Context, value: Boolean?, callingPid: Int, callingUid: Int, ) = ReadWritePermit.ALLOW override val sensitivityLevel get() = SensitivityLevel.NO_SENSITIVITY @Suppress("UNCHECKED_CAST") private class WifiScorerToggleStorage( private val context: Context, private val settingsStore: SettingsStore = SettingsSecureStore.get(context), ) : KeyValueStoreDelegate { override val keyValueStoreDelegate get() = settingsStore override fun <T : Any> getDefaultValue(key: String, valueType: Class<T>) = DEFAULT_VALUE as T @RequiresPermission(Manifest.permission.NETWORK_SETTINGS) override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) { settingsStore.setValue(key, valueType, value) context .getSystemService(WifiManager::class.java) ?.setWifiScoringEnabled( (value as Boolean?) ?: DEFAULT_VALUE ) } } companion object { const val KEY = ADAPTIVE_CONNECTIVITY_WIFI_ENABLED const val DEFAULT_VALUE = true } } No newline at end of file tests/robotests/src/com/android/settings/network/AdaptiveConnectivityScreenTest.kt +121 −13 Original line number Diff line number Diff line Loading @@ -16,11 +16,18 @@ package com.android.settings.network import android.content.Context import android.platform.test.annotations.EnableFlags import android.provider.Settings import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_WIFI_ENABLED import androidx.fragment.app.testing.launchFragmentInContainer import androidx.preference.SwitchPreferenceCompat import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settings.flags.Flags import com.android.settings.network.AdaptiveConnectivitySettings.ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED import com.android.settings.network.AdaptiveConnectivitySettings.ADAPTIVE_CONNECTIVITY_WIFI_ENABLED import com.android.settingslib.metadata.PreferenceHierarchy import com.android.settingslib.preference.CatalystScreenTestCase import com.google.common.truth.Truth.assertThat import org.junit.Test Loading @@ -28,11 +35,12 @@ import org.junit.runner.RunWith @Suppress("DEPRECATION") @RunWith(AndroidJUnit4::class) class AdaptiveConnectivityScreenTest : CatalystScreenTestCase() { class AdaptiveConnectivityScreenTest() : CatalystScreenTestCase() { override val preferenceScreenCreator = AdaptiveConnectivityScreen() override val flagName get() = Flags.FLAG_CATALYST_ADAPTIVE_CONNECTIVITY private lateinit var fragment: AdaptiveConnectivitySettings private val mContext: Context = ApplicationProvider.getApplicationContext() override fun migration() {} @Test Loading @@ -40,22 +48,122 @@ class AdaptiveConnectivityScreenTest : CatalystScreenTestCase() { assertThat(preferenceScreenCreator.key).isEqualTo(AdaptiveConnectivityScreen.KEY) } @Test fun getPreferenceHierarchy_returnsHierarchy() { val hierarchy: PreferenceHierarchy = preferenceScreenCreator.getPreferenceHierarchy(mContext) (appContext) assertThat(hierarchy.find(ADAPTIVE_CONNECTIVITY_ENABLED)).isNotNull() assertThat(hierarchy.find(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED)).isNull() assertThat(hierarchy.find(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED)).isNull() } @Test @EnableFlags(Flags.FLAG_ENABLE_NESTED_TOGGLE_SWITCHES) fun getPreferenceHierarchy_flagEnabled_returnsHierarchyWithNestedToggle() { val hierarchy: PreferenceHierarchy = preferenceScreenCreator.getPreferenceHierarchy(mContext) (appContext) assertThat(hierarchy.find(ADAPTIVE_CONNECTIVITY_ENABLED)).isNotNull() assertThat(hierarchy.find(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED)).isNotNull() assertThat(hierarchy.find(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED)).isNotNull() } @Test fun flagDefaultDisabled_noSwitchPreferenceCompatExists() { // create fragment val fragment: AdaptiveConnectivitySettings = preferenceScreenCreator.fragmentClass().newInstance() // check if switch preference exists assertSwitchPreferenceCompatIsNull(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED, fragment) assertSwitchPreferenceCompatIsNull(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED, fragment) val scenario = launchFragmentInContainer<AdaptiveConnectivitySettings>() scenario.onFragment { fragment -> this.fragment = fragment assertSwitchPreferenceCompatVisibility( ADAPTIVE_CONNECTIVITY_WIFI_ENABLED, fragment, false ) assertSwitchPreferenceCompatVisibility( ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED, fragment, false ) } } @Test @EnableFlags(Flags.FLAG_ENABLE_NESTED_TOGGLE_SWITCHES) fun flagEnabled_switchPreferenceCompatExists() { val scenario = launchFragmentInContainer<AdaptiveConnectivitySettings>() scenario.onFragment { fragment -> this.fragment = fragment assertSwitchPreferenceCompatVisibility( ADAPTIVE_CONNECTIVITY_WIFI_ENABLED, fragment, true ) assertSwitchPreferenceCompatVisibility( ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED, fragment, true ) } } @Test @EnableFlags(Flags.FLAG_ENABLE_NESTED_TOGGLE_SWITCHES) fun flagEnabled_onWifiScorerSwitchClick_shouldUpdateSetting() { val scenario = launchFragmentInContainer<AdaptiveConnectivitySettings>() scenario.onFragment { fragment: AdaptiveConnectivitySettings -> this.fragment = fragment val switchPreference = fragment.findPreference<SwitchPreferenceCompat>(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED) assertThat(switchPreference?.isChecked).isTrue() switchPreference?.performClick() assertThat(switchPreference?.isChecked).isFalse() assertThat(updateSetting(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED)).isFalse() switchPreference?.performClick() assertThat(switchPreference?.isChecked).isTrue() assertThat(updateSetting(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED)).isTrue() } } @Test @EnableFlags(Flags.FLAG_ENABLE_NESTED_TOGGLE_SWITCHES) fun flagEnabled_onAdaptiveMobileNetworkSwitchClick_shouldUpdateSetting() { val scenario = launchFragmentInContainer<AdaptiveConnectivitySettings>() scenario.onFragment { fragment: AdaptiveConnectivitySettings -> this.fragment = fragment val switchPreference = fragment.findPreference<SwitchPreferenceCompat>( ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED ) assertThat(switchPreference?.isChecked).isTrue() switchPreference?.performClick() assertThat(switchPreference?.isChecked).isFalse() assertThat(updateSetting(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED)).isFalse() switchPreference?.performClick() assertThat(switchPreference?.isChecked).isTrue() assertThat(updateSetting(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED)).isTrue() } } /** * Helper function to get the setting value from Settings.Secure. * * @param key the key of the setting to get. */ private fun updateSetting(key: String): Boolean { return (Settings.Secure.getInt( mContext.contentResolver, key, 0 ) == 1) } private fun assertSwitchPreferenceCompatIsNull( private fun assertSwitchPreferenceCompatVisibility( key: String, fragment: AdaptiveConnectivitySettings fragment: AdaptiveConnectivitySettings, isVisible: Boolean ) { val switchPreference = fragment.findPreference<SwitchPreferenceCompat>(key) assertThat(switchPreference).isNull() assertThat(switchPreference?.isVisible).isEqualTo(isVisible) } } Loading
src/com/android/settings/network/AdaptiveConnectivityScreen.kt +5 −1 Original line number Diff line number Diff line Loading @@ -37,6 +37,10 @@ class AdaptiveConnectivityScreen : PreferenceScreenCreator { override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(context, this) { +AdaptiveConnectivityTogglePreference() if (Flags.enableNestedToggleSwitches()) { +WifiScorerTogglePreference() +AdaptiveMobileNetworkTogglePreference() } } override fun hasCompleteHierarchy() = false Loading
src/com/android/settings/network/AdaptiveConnectivitySettings.java +19 −10 Original line number Diff line number Diff line Loading @@ -15,9 +15,14 @@ */ package com.android.settings.network; import static android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED; import static android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_WIFI_ENABLED; import android.app.settings.SettingsEnums; import android.content.Context; import android.net.wifi.WifiManager; import android.os.Bundle; import android.provider.Settings; import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; Loading @@ -31,12 +36,7 @@ import com.android.settingslib.search.SearchIndexable; /** Adaptive connectivity is a feature which automatically manages network connections. */ @SearchIndexable public class AdaptiveConnectivitySettings extends DashboardFragment { private static final String TAG = "AdaptiveConnectivitySettings"; protected static final String ADAPTIVE_CONNECTIVITY_WIFI_ENABLED = "adaptive_connectivity_wifi_enabled"; protected static final String ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED = "adaptive_connectivity_mobile_network_enabled"; @Override public int getMetricsCategory() { Loading Loading @@ -65,16 +65,25 @@ public class AdaptiveConnectivitySettings extends DashboardFragment { public void onCreatePreferences(@NonNull Bundle savedInstanceState, @NonNull String rootKey) { Log.i("Settings", "onCreatePreferences"); super.onCreatePreferences(savedInstanceState, rootKey); if (Flags.enableNestedToggleSwitches()) { setSwitchVisibility(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED, true); setSwitchVisibility(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED, true); if (Flags.enableNestedToggleSwitches() && !isCatalystEnabled()) { setupSwitchPreferenceCompat(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED); setupSwitchPreferenceCompat(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED); } } private void setSwitchVisibility(String key, boolean isVisible) { private void setupSwitchPreferenceCompat(String key) { SwitchPreferenceCompat switchPreference = findPreference(key); if (switchPreference != null) { switchPreference.setVisible(isVisible); switchPreference.setOnPreferenceChangeListener( (preference, newValue) -> { boolean isChecked = (Boolean) newValue; Settings.Secure.putInt(getContentResolver(), key, isChecked ? 1 : 0); if (preference.getKey().equals(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED)) { getSystemService(WifiManager.class).setWifiScoringEnabled(isChecked); } return true; }); switchPreference.setVisible(true); } } }
src/com/android/settings/network/AdaptiveMobileNetworkTogglePreference.kt 0 → 100644 +89 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.network import android.app.settings.SettingsEnums.ACTION_ADAPTIVE_CONNECTIVITY import android.content.Context import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED import com.android.settings.R import com.android.settings.contract.KEY_ADAPTIVE_CONNECTIVITY import com.android.settings.metrics.PreferenceActionMetricsProvider import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.KeyValueStoreDelegate import com.android.settingslib.datastore.SettingsSecureStore import com.android.settingslib.datastore.SettingsStore import com.android.settingslib.metadata.ReadWritePermit import com.android.settingslib.metadata.SensitivityLevel import com.android.settingslib.metadata.SwitchPreference class AdaptiveMobileNetworkTogglePreference() : SwitchPreference( KEY, R.string.adaptive_connectivity_mobile_network_switch_title, ), PreferenceActionMetricsProvider { override val preferenceActionMetrics: Int get() = ACTION_ADAPTIVE_CONNECTIVITY override val key: String get() = KEY override fun tags(context: Context) = arrayOf(KEY_ADAPTIVE_CONNECTIVITY) override fun storage(context: Context): KeyValueStore = AdaptiveMobileNetworkToggleStorage(context) override fun getReadPermissions(context: Context) = SettingsSecureStore.getReadPermissions() override fun getWritePermissions(context: Context) = SettingsSecureStore.getWritePermissions() override fun getReadPermit(context: Context, callingPid: Int, callingUid: Int) = ReadWritePermit.ALLOW override fun getWritePermit( context: Context, value: Boolean?, callingPid: Int, callingUid: Int, ) = ReadWritePermit.ALLOW override val sensitivityLevel get() = SensitivityLevel.NO_SENSITIVITY @Suppress("UNCHECKED_CAST") private class AdaptiveMobileNetworkToggleStorage( private val context: Context, private val settingsStore: SettingsStore = SettingsSecureStore.get(context), ) : KeyValueStoreDelegate { override val keyValueStoreDelegate get() = settingsStore override fun <T : Any> getDefaultValue(key: String, valueType: Class<T>) = DEFAULT_VALUE as T override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) { settingsStore.setValue(key, valueType, value) } } companion object { const val KEY = ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED const val DEFAULT_VALUE = true } } No newline at end of file
src/com/android/settings/network/WifiScorerTogglePreference.kt 0 → 100644 +101 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.network import android.Manifest import android.app.settings.SettingsEnums.ACTION_ADAPTIVE_CONNECTIVITY import android.content.Context import android.net.wifi.WifiManager import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_WIFI_ENABLED import androidx.annotation.RequiresPermission import com.android.settings.R import com.android.settings.contract.KEY_ADAPTIVE_CONNECTIVITY import com.android.settings.metrics.PreferenceActionMetricsProvider import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.KeyValueStoreDelegate import com.android.settingslib.datastore.SettingsSecureStore import com.android.settingslib.datastore.SettingsStore import com.android.settingslib.datastore.and import com.android.settingslib.metadata.ReadWritePermit import com.android.settingslib.metadata.SensitivityLevel import com.android.settingslib.metadata.SwitchPreference class WifiScorerTogglePreference() : SwitchPreference( KEY, R.string.adaptive_connectivity_wifi_switch_title ), PreferenceActionMetricsProvider { override val preferenceActionMetrics: Int get() = ACTION_ADAPTIVE_CONNECTIVITY override val key: String get() = KEY override fun tags(context: Context) = arrayOf(KEY_ADAPTIVE_CONNECTIVITY) override fun storage(context: Context): KeyValueStore = WifiScorerToggleStorage(context) override fun getReadPermissions(context: Context) = SettingsSecureStore.getReadPermissions() override fun getWritePermissions(context: Context) = SettingsSecureStore.getWritePermissions() and Manifest.permission.NETWORK_SETTINGS override fun getReadPermit(context: Context, callingPid: Int, callingUid: Int) = ReadWritePermit.ALLOW override fun getWritePermit( context: Context, value: Boolean?, callingPid: Int, callingUid: Int, ) = ReadWritePermit.ALLOW override val sensitivityLevel get() = SensitivityLevel.NO_SENSITIVITY @Suppress("UNCHECKED_CAST") private class WifiScorerToggleStorage( private val context: Context, private val settingsStore: SettingsStore = SettingsSecureStore.get(context), ) : KeyValueStoreDelegate { override val keyValueStoreDelegate get() = settingsStore override fun <T : Any> getDefaultValue(key: String, valueType: Class<T>) = DEFAULT_VALUE as T @RequiresPermission(Manifest.permission.NETWORK_SETTINGS) override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) { settingsStore.setValue(key, valueType, value) context .getSystemService(WifiManager::class.java) ?.setWifiScoringEnabled( (value as Boolean?) ?: DEFAULT_VALUE ) } } companion object { const val KEY = ADAPTIVE_CONNECTIVITY_WIFI_ENABLED const val DEFAULT_VALUE = true } } No newline at end of file
tests/robotests/src/com/android/settings/network/AdaptiveConnectivityScreenTest.kt +121 −13 Original line number Diff line number Diff line Loading @@ -16,11 +16,18 @@ package com.android.settings.network import android.content.Context import android.platform.test.annotations.EnableFlags import android.provider.Settings import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_WIFI_ENABLED import androidx.fragment.app.testing.launchFragmentInContainer import androidx.preference.SwitchPreferenceCompat import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settings.flags.Flags import com.android.settings.network.AdaptiveConnectivitySettings.ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED import com.android.settings.network.AdaptiveConnectivitySettings.ADAPTIVE_CONNECTIVITY_WIFI_ENABLED import com.android.settingslib.metadata.PreferenceHierarchy import com.android.settingslib.preference.CatalystScreenTestCase import com.google.common.truth.Truth.assertThat import org.junit.Test Loading @@ -28,11 +35,12 @@ import org.junit.runner.RunWith @Suppress("DEPRECATION") @RunWith(AndroidJUnit4::class) class AdaptiveConnectivityScreenTest : CatalystScreenTestCase() { class AdaptiveConnectivityScreenTest() : CatalystScreenTestCase() { override val preferenceScreenCreator = AdaptiveConnectivityScreen() override val flagName get() = Flags.FLAG_CATALYST_ADAPTIVE_CONNECTIVITY private lateinit var fragment: AdaptiveConnectivitySettings private val mContext: Context = ApplicationProvider.getApplicationContext() override fun migration() {} @Test Loading @@ -40,22 +48,122 @@ class AdaptiveConnectivityScreenTest : CatalystScreenTestCase() { assertThat(preferenceScreenCreator.key).isEqualTo(AdaptiveConnectivityScreen.KEY) } @Test fun getPreferenceHierarchy_returnsHierarchy() { val hierarchy: PreferenceHierarchy = preferenceScreenCreator.getPreferenceHierarchy(mContext) (appContext) assertThat(hierarchy.find(ADAPTIVE_CONNECTIVITY_ENABLED)).isNotNull() assertThat(hierarchy.find(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED)).isNull() assertThat(hierarchy.find(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED)).isNull() } @Test @EnableFlags(Flags.FLAG_ENABLE_NESTED_TOGGLE_SWITCHES) fun getPreferenceHierarchy_flagEnabled_returnsHierarchyWithNestedToggle() { val hierarchy: PreferenceHierarchy = preferenceScreenCreator.getPreferenceHierarchy(mContext) (appContext) assertThat(hierarchy.find(ADAPTIVE_CONNECTIVITY_ENABLED)).isNotNull() assertThat(hierarchy.find(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED)).isNotNull() assertThat(hierarchy.find(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED)).isNotNull() } @Test fun flagDefaultDisabled_noSwitchPreferenceCompatExists() { // create fragment val fragment: AdaptiveConnectivitySettings = preferenceScreenCreator.fragmentClass().newInstance() // check if switch preference exists assertSwitchPreferenceCompatIsNull(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED, fragment) assertSwitchPreferenceCompatIsNull(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED, fragment) val scenario = launchFragmentInContainer<AdaptiveConnectivitySettings>() scenario.onFragment { fragment -> this.fragment = fragment assertSwitchPreferenceCompatVisibility( ADAPTIVE_CONNECTIVITY_WIFI_ENABLED, fragment, false ) assertSwitchPreferenceCompatVisibility( ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED, fragment, false ) } } @Test @EnableFlags(Flags.FLAG_ENABLE_NESTED_TOGGLE_SWITCHES) fun flagEnabled_switchPreferenceCompatExists() { val scenario = launchFragmentInContainer<AdaptiveConnectivitySettings>() scenario.onFragment { fragment -> this.fragment = fragment assertSwitchPreferenceCompatVisibility( ADAPTIVE_CONNECTIVITY_WIFI_ENABLED, fragment, true ) assertSwitchPreferenceCompatVisibility( ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED, fragment, true ) } } @Test @EnableFlags(Flags.FLAG_ENABLE_NESTED_TOGGLE_SWITCHES) fun flagEnabled_onWifiScorerSwitchClick_shouldUpdateSetting() { val scenario = launchFragmentInContainer<AdaptiveConnectivitySettings>() scenario.onFragment { fragment: AdaptiveConnectivitySettings -> this.fragment = fragment val switchPreference = fragment.findPreference<SwitchPreferenceCompat>(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED) assertThat(switchPreference?.isChecked).isTrue() switchPreference?.performClick() assertThat(switchPreference?.isChecked).isFalse() assertThat(updateSetting(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED)).isFalse() switchPreference?.performClick() assertThat(switchPreference?.isChecked).isTrue() assertThat(updateSetting(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED)).isTrue() } } @Test @EnableFlags(Flags.FLAG_ENABLE_NESTED_TOGGLE_SWITCHES) fun flagEnabled_onAdaptiveMobileNetworkSwitchClick_shouldUpdateSetting() { val scenario = launchFragmentInContainer<AdaptiveConnectivitySettings>() scenario.onFragment { fragment: AdaptiveConnectivitySettings -> this.fragment = fragment val switchPreference = fragment.findPreference<SwitchPreferenceCompat>( ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED ) assertThat(switchPreference?.isChecked).isTrue() switchPreference?.performClick() assertThat(switchPreference?.isChecked).isFalse() assertThat(updateSetting(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED)).isFalse() switchPreference?.performClick() assertThat(switchPreference?.isChecked).isTrue() assertThat(updateSetting(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED)).isTrue() } } /** * Helper function to get the setting value from Settings.Secure. * * @param key the key of the setting to get. */ private fun updateSetting(key: String): Boolean { return (Settings.Secure.getInt( mContext.contentResolver, key, 0 ) == 1) } private fun assertSwitchPreferenceCompatIsNull( private fun assertSwitchPreferenceCompatVisibility( key: String, fragment: AdaptiveConnectivitySettings fragment: AdaptiveConnectivitySettings, isVisible: Boolean ) { val switchPreference = fragment.findPreference<SwitchPreferenceCompat>(key) assertThat(switchPreference).isNull() assertThat(switchPreference?.isVisible).isEqualTo(isVisible) } }