| /* | |
| * Copyright (C) 2021 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 android.net | |
| import android.net.ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE | |
| import android.net.ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_AVOID | |
| import android.net.ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_IGNORE | |
| import android.net.ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_PROMPT | |
| import android.net.ConnectivitySettingsManager.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS | |
| import android.net.ConnectivitySettingsManager.DATA_ACTIVITY_TIMEOUT_MOBILE | |
| import android.net.ConnectivitySettingsManager.DATA_ACTIVITY_TIMEOUT_WIFI | |
| import android.net.ConnectivitySettingsManager.DNS_RESOLVER_MAX_SAMPLES | |
| import android.net.ConnectivitySettingsManager.DNS_RESOLVER_MIN_SAMPLES | |
| import android.net.ConnectivitySettingsManager.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS | |
| import android.net.ConnectivitySettingsManager.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT | |
| import android.net.ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON | |
| import android.net.ConnectivitySettingsManager.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT | |
| import android.net.ConnectivitySettingsManager.NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS | |
| import android.net.ConnectivitySettingsManager.PRIVATE_DNS_DEFAULT_MODE | |
| import android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF | |
| import android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNISTIC | |
| import android.net.ConnectivitySettingsManager.WIFI_ALWAYS_REQUESTED | |
| import android.net.ConnectivitySettingsManager.getCaptivePortalMode | |
| import android.net.ConnectivitySettingsManager.getConnectivityKeepPendingIntentDuration | |
| import android.net.ConnectivitySettingsManager.getDnsResolverSampleRanges | |
| import android.net.ConnectivitySettingsManager.getDnsResolverSampleValidityDuration | |
| import android.net.ConnectivitySettingsManager.getDnsResolverSuccessThresholdPercent | |
| import android.net.ConnectivitySettingsManager.getIngressRateLimitInBytesPerSecond | |
| import android.net.ConnectivitySettingsManager.getMobileDataActivityTimeout | |
| import android.net.ConnectivitySettingsManager.getMobileDataAlwaysOn | |
| import android.net.ConnectivitySettingsManager.getNetworkSwitchNotificationMaximumDailyCount | |
| import android.net.ConnectivitySettingsManager.getNetworkSwitchNotificationRateDuration | |
| import android.net.ConnectivitySettingsManager.getPrivateDnsDefaultMode | |
| import android.net.ConnectivitySettingsManager.getWifiAlwaysRequested | |
| import android.net.ConnectivitySettingsManager.getWifiDataActivityTimeout | |
| import android.net.ConnectivitySettingsManager.setCaptivePortalMode | |
| import android.net.ConnectivitySettingsManager.setConnectivityKeepPendingIntentDuration | |
| import android.net.ConnectivitySettingsManager.setDnsResolverSampleRanges | |
| import android.net.ConnectivitySettingsManager.setDnsResolverSampleValidityDuration | |
| import android.net.ConnectivitySettingsManager.setDnsResolverSuccessThresholdPercent | |
| import android.net.ConnectivitySettingsManager.setIngressRateLimitInBytesPerSecond | |
| import android.net.ConnectivitySettingsManager.setMobileDataActivityTimeout | |
| import android.net.ConnectivitySettingsManager.setMobileDataAlwaysOn | |
| import android.net.ConnectivitySettingsManager.setNetworkSwitchNotificationMaximumDailyCount | |
| import android.net.ConnectivitySettingsManager.setNetworkSwitchNotificationRateDuration | |
| import android.net.ConnectivitySettingsManager.setPrivateDnsDefaultMode | |
| import android.net.ConnectivitySettingsManager.setWifiAlwaysRequested | |
| import android.net.ConnectivitySettingsManager.setWifiDataActivityTimeout | |
| import android.os.Build | |
| import android.platform.test.annotations.AppModeFull | |
| import android.provider.Settings | |
| import android.util.Range | |
| import androidx.test.InstrumentationRegistry | |
| import androidx.test.filters.SmallTest | |
| import com.android.net.module.util.ConnectivitySettingsUtils.getPrivateDnsModeAsString | |
| import com.android.testutils.ConnectivityModuleTest | |
| import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo | |
| import com.android.testutils.DevSdkIgnoreRunner | |
| import junit.framework.Assert.assertEquals | |
| import org.junit.Test | |
| import org.junit.runner.RunWith | |
| import java.time.Duration | |
| import java.util.Objects | |
| import kotlin.test.assertFailsWith | |
| /** | |
| * Tests for [ConnectivitySettingsManager]. | |
| * | |
| * Build, install and run with: | |
| * atest android.net.ConnectivitySettingsManagerTest | |
| */ | |
| @RunWith(DevSdkIgnoreRunner::class) | |
| @IgnoreUpTo(Build.VERSION_CODES.R) | |
| @SmallTest | |
| @AppModeFull(reason = "WRITE_SECURE_SETTINGS permission can't be granted to instant apps") | |
| class ConnectivitySettingsManagerTest { | |
| private val instrumentation = InstrumentationRegistry.getInstrumentation() | |
| private val context = instrumentation.context | |
| private val resolver = context.contentResolver | |
| private val defaultDuration = Duration.ofSeconds(0L) | |
| private val testTime1 = 5L | |
| private val testTime2 = 10L | |
| private val settingsTypeGlobal = "global" | |
| private val settingsTypeSecure = "secure" | |
| /*** Reset setting value or delete setting if the setting was not existed before testing. */ | |
| private fun resetSettings(names: Array<String>, type: String, values: Array<String?>) { | |
| for (i in names.indices) { | |
| if (Objects.equals(values[i], null)) { | |
| instrumentation.uiAutomation.executeShellCommand( | |
| "settings delete $type ${names[i]}") | |
| } else { | |
| if (settingsTypeSecure.equals(type)) { | |
| Settings.Secure.putString(resolver, names[i], values[i]) | |
| } else { | |
| Settings.Global.putString(resolver, names[i], values[i]) | |
| } | |
| } | |
| } | |
| } | |
| fun <T> testIntSetting( | |
| names: Array<String>, | |
| type: String, | |
| value1: T, | |
| value2: T, | |
| getter: () -> T, | |
| setter: (value: T) -> Unit, | |
| testIntValues: IntArray | |
| ) { | |
| val originals: Array<String?> = Array(names.size) { i -> | |
| if (settingsTypeSecure.equals(type)) { | |
| Settings.Secure.getString(resolver, names[i]) | |
| } else { | |
| Settings.Global.getString(resolver, names[i]) | |
| } | |
| } | |
| try { | |
| for (i in names.indices) { | |
| if (settingsTypeSecure.equals(type)) { | |
| Settings.Secure.putString(resolver, names[i], testIntValues[i].toString()) | |
| } else { | |
| Settings.Global.putString(resolver, names[i], testIntValues[i].toString()) | |
| } | |
| } | |
| assertEquals(value1, getter()) | |
| setter(value2) | |
| assertEquals(value2, getter()) | |
| } finally { | |
| resetSettings(names, type, originals) | |
| } | |
| } | |
| @Test | |
| fun testMobileDataActivityTimeout() { | |
| testIntSetting(names = arrayOf(DATA_ACTIVITY_TIMEOUT_MOBILE), type = settingsTypeGlobal, | |
| value1 = Duration.ofSeconds(testTime1), value2 = Duration.ofSeconds(testTime2), | |
| getter = { getMobileDataActivityTimeout(context, defaultDuration) }, | |
| setter = { setMobileDataActivityTimeout(context, it) }, | |
| testIntValues = intArrayOf(testTime1.toInt())) | |
| } | |
| @Test | |
| fun testWifiDataActivityTimeout() { | |
| testIntSetting(names = arrayOf(DATA_ACTIVITY_TIMEOUT_WIFI), type = settingsTypeGlobal, | |
| value1 = Duration.ofSeconds(testTime1), value2 = Duration.ofSeconds(testTime2), | |
| getter = { getWifiDataActivityTimeout(context, defaultDuration) }, | |
| setter = { setWifiDataActivityTimeout(context, it) }, | |
| testIntValues = intArrayOf(testTime1.toInt())) | |
| } | |
| @Test | |
| fun testDnsResolverSampleValidityDuration() { | |
| testIntSetting(names = arrayOf(DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS), | |
| type = settingsTypeGlobal, value1 = Duration.ofSeconds(testTime1), | |
| value2 = Duration.ofSeconds(testTime2), | |
| getter = { getDnsResolverSampleValidityDuration(context, defaultDuration) }, | |
| setter = { setDnsResolverSampleValidityDuration(context, it) }, | |
| testIntValues = intArrayOf(testTime1.toInt())) | |
| assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") { | |
| setDnsResolverSampleValidityDuration(context, Duration.ofSeconds(-1L)) } | |
| } | |
| @Test | |
| fun testDnsResolverSuccessThresholdPercent() { | |
| testIntSetting(names = arrayOf(DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT), | |
| type = settingsTypeGlobal, value1 = 5, value2 = 10, | |
| getter = { getDnsResolverSuccessThresholdPercent(context, 0 /* def */) }, | |
| setter = { setDnsResolverSuccessThresholdPercent(context, it) }, | |
| testIntValues = intArrayOf(5)) | |
| assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") { | |
| setDnsResolverSuccessThresholdPercent(context, -1) } | |
| assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") { | |
| setDnsResolverSuccessThresholdPercent(context, 120) } | |
| } | |
| @Test | |
| fun testDnsResolverSampleRanges() { | |
| testIntSetting(names = arrayOf(DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_MAX_SAMPLES), | |
| type = settingsTypeGlobal, value1 = Range(1, 63), value2 = Range(2, 62), | |
| getter = { getDnsResolverSampleRanges(context) }, | |
| setter = { setDnsResolverSampleRanges(context, it) }, | |
| testIntValues = intArrayOf(1, 63)) | |
| assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") { | |
| setDnsResolverSampleRanges(context, Range(-1, 62)) } | |
| assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") { | |
| setDnsResolverSampleRanges(context, Range(2, 65)) } | |
| } | |
| @Test | |
| fun testNetworkSwitchNotificationMaximumDailyCount() { | |
| testIntSetting(names = arrayOf(NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT), | |
| type = settingsTypeGlobal, value1 = 5, value2 = 15, | |
| getter = { getNetworkSwitchNotificationMaximumDailyCount(context, 0 /* def */) }, | |
| setter = { setNetworkSwitchNotificationMaximumDailyCount(context, it) }, | |
| testIntValues = intArrayOf(5)) | |
| assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") { | |
| setNetworkSwitchNotificationMaximumDailyCount(context, -1) } | |
| } | |
| @Test | |
| fun testNetworkSwitchNotificationRateDuration() { | |
| testIntSetting(names = arrayOf(NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS), | |
| type = settingsTypeGlobal, value1 = Duration.ofMillis(testTime1), | |
| value2 = Duration.ofMillis(testTime2), | |
| getter = { getNetworkSwitchNotificationRateDuration(context, defaultDuration) }, | |
| setter = { setNetworkSwitchNotificationRateDuration(context, it) }, | |
| testIntValues = intArrayOf(testTime1.toInt())) | |
| assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") { | |
| setNetworkSwitchNotificationRateDuration(context, Duration.ofMillis(-1L)) } | |
| } | |
| @Test | |
| fun testCaptivePortalMode() { | |
| testIntSetting(names = arrayOf(CAPTIVE_PORTAL_MODE), type = settingsTypeGlobal, | |
| value1 = CAPTIVE_PORTAL_MODE_AVOID, value2 = CAPTIVE_PORTAL_MODE_PROMPT, | |
| getter = { getCaptivePortalMode(context, CAPTIVE_PORTAL_MODE_IGNORE) }, | |
| setter = { setCaptivePortalMode(context, it) }, | |
| testIntValues = intArrayOf(CAPTIVE_PORTAL_MODE_AVOID)) | |
| assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") { | |
| setCaptivePortalMode(context, 5 /* mode */) } | |
| } | |
| @Test | |
| fun testPrivateDnsDefaultMode() { | |
| val original = Settings.Global.getString(resolver, PRIVATE_DNS_DEFAULT_MODE) | |
| try { | |
| val mode = getPrivateDnsModeAsString(PRIVATE_DNS_MODE_OPPORTUNISTIC) | |
| Settings.Global.putString(resolver, PRIVATE_DNS_DEFAULT_MODE, mode) | |
| assertEquals(mode, getPrivateDnsDefaultMode(context)) | |
| setPrivateDnsDefaultMode(context, PRIVATE_DNS_MODE_OFF) | |
| assertEquals(getPrivateDnsModeAsString(PRIVATE_DNS_MODE_OFF), | |
| getPrivateDnsDefaultMode(context)) | |
| } finally { | |
| resetSettings(names = arrayOf(PRIVATE_DNS_DEFAULT_MODE), type = settingsTypeGlobal, | |
| values = arrayOf(original)) | |
| } | |
| assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") { | |
| setPrivateDnsDefaultMode(context, -1) } | |
| } | |
| @Test | |
| fun testConnectivityKeepPendingIntentDuration() { | |
| testIntSetting(names = arrayOf(CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS), | |
| type = settingsTypeSecure, value1 = Duration.ofMillis(testTime1), | |
| value2 = Duration.ofMillis(testTime2), | |
| getter = { getConnectivityKeepPendingIntentDuration(context, defaultDuration) }, | |
| setter = { setConnectivityKeepPendingIntentDuration(context, it) }, | |
| testIntValues = intArrayOf(testTime1.toInt())) | |
| assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") { | |
| setConnectivityKeepPendingIntentDuration(context, Duration.ofMillis(-1L)) } | |
| } | |
| @Test | |
| fun testMobileDataAlwaysOn() { | |
| testIntSetting(names = arrayOf(MOBILE_DATA_ALWAYS_ON), type = settingsTypeGlobal, | |
| value1 = false, value2 = true, | |
| getter = { getMobileDataAlwaysOn(context, true /* def */) }, | |
| setter = { setMobileDataAlwaysOn(context, it) }, | |
| testIntValues = intArrayOf(0)) | |
| } | |
| @Test | |
| fun testWifiAlwaysRequested() { | |
| testIntSetting(names = arrayOf(WIFI_ALWAYS_REQUESTED), type = settingsTypeGlobal, | |
| value1 = false, value2 = true, | |
| getter = { getWifiAlwaysRequested(context, true /* def */) }, | |
| setter = { setWifiAlwaysRequested(context, it) }, | |
| testIntValues = intArrayOf(0)) | |
| } | |
| @ConnectivityModuleTest // get/setIngressRateLimitInBytesPerSecond was added via module update | |
| @Test | |
| fun testInternetNetworkRateLimitInBytesPerSecond() { | |
| val defaultRate = getIngressRateLimitInBytesPerSecond(context) | |
| val testRate = 1000L | |
| setIngressRateLimitInBytesPerSecond(context, testRate) | |
| assertEquals(testRate, getIngressRateLimitInBytesPerSecond(context)) | |
| setIngressRateLimitInBytesPerSecond(context, defaultRate) | |
| assertEquals(defaultRate, getIngressRateLimitInBytesPerSecond(context)) | |
| assertFailsWith<IllegalArgumentException>("Expected failure, but setting accepted") { | |
| setIngressRateLimitInBytesPerSecond(context, -10) | |
| } | |
| } | |
| } |