paulhu | 236a992 | 2021-03-29 10:50:36 +0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2021 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package android.net |
| 18 | |
| 19 | import android.net.ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE |
| 20 | import android.net.ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_AVOID |
| 21 | import android.net.ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_IGNORE |
| 22 | import android.net.ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_PROMPT |
| 23 | import android.net.ConnectivitySettingsManager.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS |
| 24 | import android.net.ConnectivitySettingsManager.DATA_ACTIVITY_TIMEOUT_MOBILE |
| 25 | import android.net.ConnectivitySettingsManager.DATA_ACTIVITY_TIMEOUT_WIFI |
| 26 | import android.net.ConnectivitySettingsManager.DNS_RESOLVER_MAX_SAMPLES |
| 27 | import android.net.ConnectivitySettingsManager.DNS_RESOLVER_MIN_SAMPLES |
| 28 | import android.net.ConnectivitySettingsManager.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS |
| 29 | import android.net.ConnectivitySettingsManager.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT |
| 30 | import android.net.ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON |
| 31 | import android.net.ConnectivitySettingsManager.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT |
| 32 | import android.net.ConnectivitySettingsManager.NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS |
| 33 | import android.net.ConnectivitySettingsManager.PRIVATE_DNS_DEFAULT_MODE |
| 34 | import android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF |
| 35 | import android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNISTIC |
| 36 | import android.net.ConnectivitySettingsManager.WIFI_ALWAYS_REQUESTED |
| 37 | import android.net.ConnectivitySettingsManager.getCaptivePortalMode |
| 38 | import android.net.ConnectivitySettingsManager.getConnectivityKeepPendingIntentDuration |
| 39 | import android.net.ConnectivitySettingsManager.getDnsResolverSampleRanges |
| 40 | import android.net.ConnectivitySettingsManager.getDnsResolverSampleValidityDuration |
| 41 | import android.net.ConnectivitySettingsManager.getDnsResolverSuccessThresholdPercent |
Patrick Rohr | a208436 | 2022-01-03 15:55:52 +0100 | [diff] [blame] | 42 | import android.net.ConnectivitySettingsManager.getIngressRateLimitInBytesPerSecond |
paulhu | 236a992 | 2021-03-29 10:50:36 +0800 | [diff] [blame] | 43 | import android.net.ConnectivitySettingsManager.getMobileDataActivityTimeout |
| 44 | import android.net.ConnectivitySettingsManager.getMobileDataAlwaysOn |
| 45 | import android.net.ConnectivitySettingsManager.getNetworkSwitchNotificationMaximumDailyCount |
| 46 | import android.net.ConnectivitySettingsManager.getNetworkSwitchNotificationRateDuration |
| 47 | import android.net.ConnectivitySettingsManager.getPrivateDnsDefaultMode |
| 48 | import android.net.ConnectivitySettingsManager.getWifiAlwaysRequested |
| 49 | import android.net.ConnectivitySettingsManager.getWifiDataActivityTimeout |
| 50 | import android.net.ConnectivitySettingsManager.setCaptivePortalMode |
| 51 | import android.net.ConnectivitySettingsManager.setConnectivityKeepPendingIntentDuration |
| 52 | import android.net.ConnectivitySettingsManager.setDnsResolverSampleRanges |
| 53 | import android.net.ConnectivitySettingsManager.setDnsResolverSampleValidityDuration |
| 54 | import android.net.ConnectivitySettingsManager.setDnsResolverSuccessThresholdPercent |
Patrick Rohr | a208436 | 2022-01-03 15:55:52 +0100 | [diff] [blame] | 55 | import android.net.ConnectivitySettingsManager.setIngressRateLimitInBytesPerSecond |
paulhu | 236a992 | 2021-03-29 10:50:36 +0800 | [diff] [blame] | 56 | import android.net.ConnectivitySettingsManager.setMobileDataActivityTimeout |
| 57 | import android.net.ConnectivitySettingsManager.setMobileDataAlwaysOn |
| 58 | import android.net.ConnectivitySettingsManager.setNetworkSwitchNotificationMaximumDailyCount |
| 59 | import android.net.ConnectivitySettingsManager.setNetworkSwitchNotificationRateDuration |
| 60 | import android.net.ConnectivitySettingsManager.setPrivateDnsDefaultMode |
| 61 | import android.net.ConnectivitySettingsManager.setWifiAlwaysRequested |
| 62 | import android.net.ConnectivitySettingsManager.setWifiDataActivityTimeout |
| 63 | import android.os.Build |
| 64 | import android.platform.test.annotations.AppModeFull |
| 65 | import android.provider.Settings |
| 66 | import android.util.Range |
| 67 | import androidx.test.InstrumentationRegistry |
| 68 | import androidx.test.filters.SmallTest |
| 69 | import com.android.net.module.util.ConnectivitySettingsUtils.getPrivateDnsModeAsString |
| 70 | import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo |
| 71 | import com.android.testutils.DevSdkIgnoreRunner |
| 72 | import junit.framework.Assert.assertEquals |
| 73 | import org.junit.Test |
| 74 | import org.junit.runner.RunWith |
| 75 | import java.time.Duration |
| 76 | import java.util.Objects |
| 77 | import kotlin.test.assertFailsWith |
| 78 | |
| 79 | /** |
| 80 | * Tests for [ConnectivitySettingsManager]. |
| 81 | * |
| 82 | * Build, install and run with: |
| 83 | * atest android.net.ConnectivitySettingsManagerTest |
| 84 | */ |
| 85 | @RunWith(DevSdkIgnoreRunner::class) |
| 86 | @IgnoreUpTo(Build.VERSION_CODES.R) |
| 87 | @SmallTest |
| 88 | @AppModeFull(reason = "WRITE_SECURE_SETTINGS permission can't be granted to instant apps") |
| 89 | class ConnectivitySettingsManagerTest { |
| 90 | private val instrumentation = InstrumentationRegistry.getInstrumentation() |
| 91 | private val context = instrumentation.context |
| 92 | private val resolver = context.contentResolver |
| 93 | |
| 94 | private val defaultDuration = Duration.ofSeconds(0L) |
| 95 | private val testTime1 = 5L |
| 96 | private val testTime2 = 10L |
| 97 | private val settingsTypeGlobal = "global" |
| 98 | private val settingsTypeSecure = "secure" |
| 99 | |
| 100 | /*** Reset setting value or delete setting if the setting was not existed before testing. */ |
| 101 | private fun resetSettings(names: Array<String>, type: String, values: Array<String?>) { |
| 102 | for (i in names.indices) { |
| 103 | if (Objects.equals(values[i], null)) { |
| 104 | instrumentation.uiAutomation.executeShellCommand( |
| 105 | "settings delete $type ${names[i]}") |
| 106 | } else { |
| 107 | if (settingsTypeSecure.equals(type)) { |
| 108 | Settings.Secure.putString(resolver, names[i], values[i]) |
| 109 | } else { |
| 110 | Settings.Global.putString(resolver, names[i], values[i]) |
| 111 | } |
| 112 | } |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | fun <T> testIntSetting( |
| 117 | names: Array<String>, |
| 118 | type: String, |
| 119 | value1: T, |
| 120 | value2: T, |
| 121 | getter: () -> T, |
| 122 | setter: (value: T) -> Unit, |
| 123 | testIntValues: IntArray |
| 124 | ) { |
| 125 | val originals: Array<String?> = Array(names.size) { i -> |
| 126 | if (settingsTypeSecure.equals(type)) { |
| 127 | Settings.Secure.getString(resolver, names[i]) |
| 128 | } else { |
| 129 | Settings.Global.getString(resolver, names[i]) |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | try { |
| 134 | for (i in names.indices) { |
| 135 | if (settingsTypeSecure.equals(type)) { |
| 136 | Settings.Secure.putString(resolver, names[i], testIntValues[i].toString()) |
| 137 | } else { |
| 138 | Settings.Global.putString(resolver, names[i], testIntValues[i].toString()) |
| 139 | } |
| 140 | } |
| 141 | assertEquals(value1, getter()) |
| 142 | |
| 143 | setter(value2) |
| 144 | assertEquals(value2, getter()) |
| 145 | } finally { |
| 146 | resetSettings(names, type, originals) |
| 147 | } |
| 148 | } |
| 149 | |
| 150 | @Test |
| 151 | fun testMobileDataActivityTimeout() { |
| 152 | testIntSetting(names = arrayOf(DATA_ACTIVITY_TIMEOUT_MOBILE), type = settingsTypeGlobal, |
| 153 | value1 = Duration.ofSeconds(testTime1), value2 = Duration.ofSeconds(testTime2), |
| 154 | getter = { getMobileDataActivityTimeout(context, defaultDuration) }, |
| 155 | setter = { setMobileDataActivityTimeout(context, it) }, |
| 156 | testIntValues = intArrayOf(testTime1.toInt())) |
| 157 | } |
| 158 | |
| 159 | @Test |
| 160 | fun testWifiDataActivityTimeout() { |
| 161 | testIntSetting(names = arrayOf(DATA_ACTIVITY_TIMEOUT_WIFI), type = settingsTypeGlobal, |
| 162 | value1 = Duration.ofSeconds(testTime1), value2 = Duration.ofSeconds(testTime2), |
| 163 | getter = { getWifiDataActivityTimeout(context, defaultDuration) }, |
| 164 | setter = { setWifiDataActivityTimeout(context, it) }, |
| 165 | testIntValues = intArrayOf(testTime1.toInt())) |
| 166 | } |
| 167 | |
| 168 | @Test |
| 169 | fun testDnsResolverSampleValidityDuration() { |
| 170 | testIntSetting(names = arrayOf(DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS), |
| 171 | type = settingsTypeGlobal, value1 = Duration.ofSeconds(testTime1), |
| 172 | value2 = Duration.ofSeconds(testTime2), |
| 173 | getter = { getDnsResolverSampleValidityDuration(context, defaultDuration) }, |
| 174 | setter = { setDnsResolverSampleValidityDuration(context, it) }, |
| 175 | testIntValues = intArrayOf(testTime1.toInt())) |
| 176 | |
| 177 | assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") { |
| 178 | setDnsResolverSampleValidityDuration(context, Duration.ofSeconds(-1L)) } |
| 179 | } |
| 180 | |
| 181 | @Test |
| 182 | fun testDnsResolverSuccessThresholdPercent() { |
| 183 | testIntSetting(names = arrayOf(DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT), |
| 184 | type = settingsTypeGlobal, value1 = 5, value2 = 10, |
| 185 | getter = { getDnsResolverSuccessThresholdPercent(context, 0 /* def */) }, |
| 186 | setter = { setDnsResolverSuccessThresholdPercent(context, it) }, |
| 187 | testIntValues = intArrayOf(5)) |
| 188 | |
| 189 | assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") { |
| 190 | setDnsResolverSuccessThresholdPercent(context, -1) } |
| 191 | assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") { |
| 192 | setDnsResolverSuccessThresholdPercent(context, 120) } |
| 193 | } |
| 194 | |
| 195 | @Test |
| 196 | fun testDnsResolverSampleRanges() { |
| 197 | testIntSetting(names = arrayOf(DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_MAX_SAMPLES), |
| 198 | type = settingsTypeGlobal, value1 = Range(1, 63), value2 = Range(2, 62), |
| 199 | getter = { getDnsResolverSampleRanges(context) }, |
| 200 | setter = { setDnsResolverSampleRanges(context, it) }, |
| 201 | testIntValues = intArrayOf(1, 63)) |
| 202 | |
| 203 | assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") { |
| 204 | setDnsResolverSampleRanges(context, Range(-1, 62)) } |
| 205 | assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") { |
| 206 | setDnsResolverSampleRanges(context, Range(2, 65)) } |
| 207 | } |
| 208 | |
| 209 | @Test |
| 210 | fun testNetworkSwitchNotificationMaximumDailyCount() { |
| 211 | testIntSetting(names = arrayOf(NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT), |
| 212 | type = settingsTypeGlobal, value1 = 5, value2 = 15, |
| 213 | getter = { getNetworkSwitchNotificationMaximumDailyCount(context, 0 /* def */) }, |
| 214 | setter = { setNetworkSwitchNotificationMaximumDailyCount(context, it) }, |
| 215 | testIntValues = intArrayOf(5)) |
| 216 | |
| 217 | assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") { |
| 218 | setNetworkSwitchNotificationMaximumDailyCount(context, -1) } |
| 219 | } |
| 220 | |
| 221 | @Test |
| 222 | fun testNetworkSwitchNotificationRateDuration() { |
| 223 | testIntSetting(names = arrayOf(NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS), |
| 224 | type = settingsTypeGlobal, value1 = Duration.ofMillis(testTime1), |
| 225 | value2 = Duration.ofMillis(testTime2), |
| 226 | getter = { getNetworkSwitchNotificationRateDuration(context, defaultDuration) }, |
| 227 | setter = { setNetworkSwitchNotificationRateDuration(context, it) }, |
| 228 | testIntValues = intArrayOf(testTime1.toInt())) |
| 229 | |
| 230 | assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") { |
| 231 | setNetworkSwitchNotificationRateDuration(context, Duration.ofMillis(-1L)) } |
| 232 | } |
| 233 | |
| 234 | @Test |
| 235 | fun testCaptivePortalMode() { |
| 236 | testIntSetting(names = arrayOf(CAPTIVE_PORTAL_MODE), type = settingsTypeGlobal, |
| 237 | value1 = CAPTIVE_PORTAL_MODE_AVOID, value2 = CAPTIVE_PORTAL_MODE_PROMPT, |
| 238 | getter = { getCaptivePortalMode(context, CAPTIVE_PORTAL_MODE_IGNORE) }, |
| 239 | setter = { setCaptivePortalMode(context, it) }, |
| 240 | testIntValues = intArrayOf(CAPTIVE_PORTAL_MODE_AVOID)) |
| 241 | |
| 242 | assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") { |
| 243 | setCaptivePortalMode(context, 5 /* mode */) } |
| 244 | } |
| 245 | |
| 246 | @Test |
| 247 | fun testPrivateDnsDefaultMode() { |
| 248 | val original = Settings.Global.getString(resolver, PRIVATE_DNS_DEFAULT_MODE) |
| 249 | |
| 250 | try { |
| 251 | val mode = getPrivateDnsModeAsString(PRIVATE_DNS_MODE_OPPORTUNISTIC) |
| 252 | Settings.Global.putString(resolver, PRIVATE_DNS_DEFAULT_MODE, mode) |
| 253 | assertEquals(mode, getPrivateDnsDefaultMode(context)) |
| 254 | |
| 255 | setPrivateDnsDefaultMode(context, PRIVATE_DNS_MODE_OFF) |
| 256 | assertEquals(getPrivateDnsModeAsString(PRIVATE_DNS_MODE_OFF), |
| 257 | getPrivateDnsDefaultMode(context)) |
| 258 | } finally { |
| 259 | resetSettings(names = arrayOf(PRIVATE_DNS_DEFAULT_MODE), type = settingsTypeGlobal, |
| 260 | values = arrayOf(original)) |
| 261 | } |
| 262 | |
| 263 | assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") { |
| 264 | setPrivateDnsDefaultMode(context, -1) } |
| 265 | } |
| 266 | |
| 267 | @Test |
| 268 | fun testConnectivityKeepPendingIntentDuration() { |
| 269 | testIntSetting(names = arrayOf(CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS), |
| 270 | type = settingsTypeSecure, value1 = Duration.ofMillis(testTime1), |
| 271 | value2 = Duration.ofMillis(testTime2), |
| 272 | getter = { getConnectivityKeepPendingIntentDuration(context, defaultDuration) }, |
| 273 | setter = { setConnectivityKeepPendingIntentDuration(context, it) }, |
| 274 | testIntValues = intArrayOf(testTime1.toInt())) |
| 275 | |
| 276 | assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") { |
| 277 | setConnectivityKeepPendingIntentDuration(context, Duration.ofMillis(-1L)) } |
| 278 | } |
| 279 | |
| 280 | @Test |
| 281 | fun testMobileDataAlwaysOn() { |
| 282 | testIntSetting(names = arrayOf(MOBILE_DATA_ALWAYS_ON), type = settingsTypeGlobal, |
| 283 | value1 = false, value2 = true, |
| 284 | getter = { getMobileDataAlwaysOn(context, true /* def */) }, |
| 285 | setter = { setMobileDataAlwaysOn(context, it) }, |
| 286 | testIntValues = intArrayOf(0)) |
| 287 | } |
| 288 | |
| 289 | @Test |
| 290 | fun testWifiAlwaysRequested() { |
| 291 | testIntSetting(names = arrayOf(WIFI_ALWAYS_REQUESTED), type = settingsTypeGlobal, |
| 292 | value1 = false, value2 = true, |
| 293 | getter = { getWifiAlwaysRequested(context, true /* def */) }, |
| 294 | setter = { setWifiAlwaysRequested(context, it) }, |
| 295 | testIntValues = intArrayOf(0)) |
| 296 | } |
Patrick Rohr | a208436 | 2022-01-03 15:55:52 +0100 | [diff] [blame] | 297 | |
| 298 | @Test |
| 299 | fun testInternetNetworkRateLimitInBytesPerSecond() { |
| 300 | val defaultRate = getIngressRateLimitInBytesPerSecond(context) |
| 301 | val testRate = 1000L |
| 302 | setIngressRateLimitInBytesPerSecond(context, testRate) |
| 303 | assertEquals(testRate, getIngressRateLimitInBytesPerSecond(context)) |
| 304 | |
| 305 | setIngressRateLimitInBytesPerSecond(context, defaultRate) |
| 306 | assertEquals(defaultRate, getIngressRateLimitInBytesPerSecond(context)) |
| 307 | |
| 308 | assertFailsWith<IllegalArgumentException>("Expected failure, but setting accepted") { |
| 309 | setIngressRateLimitInBytesPerSecond(context, -10) |
| 310 | } |
| 311 | } |
paulhu | 236a992 | 2021-03-29 10:50:36 +0800 | [diff] [blame] | 312 | } |