1 /* 2 * Copyright (C) 2020 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.content.Context 20 import android.net.ConnectivityManager.TYPE_MOBILE 21 import android.net.ConnectivityManager.TYPE_WIFI 22 import android.net.NetworkIdentity.OEM_NONE 23 import android.net.NetworkIdentity.OEM_PAID 24 import android.net.NetworkIdentity.OEM_PRIVATE 25 import android.net.NetworkIdentity.SUBTYPE_COMBINED 26 import android.net.NetworkIdentity.buildNetworkIdentity 27 import android.net.NetworkStats.DEFAULT_NETWORK_ALL 28 import android.net.NetworkStats.METERED_ALL 29 import android.net.NetworkStats.ROAMING_ALL 30 import android.net.NetworkTemplate.MATCH_MOBILE 31 import android.net.NetworkTemplate.MATCH_MOBILE_WILDCARD 32 import android.net.NetworkTemplate.MATCH_WIFI 33 import android.net.NetworkTemplate.MATCH_WIFI_WILDCARD 34 import android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA 35 import android.net.NetworkTemplate.NETWORK_TYPE_ALL 36 import android.net.NetworkTemplate.OEM_MANAGED_ALL 37 import android.net.NetworkTemplate.OEM_MANAGED_NO 38 import android.net.NetworkTemplate.OEM_MANAGED_YES 39 import android.net.NetworkTemplate.SUBSCRIBER_ID_MATCH_RULE_EXACT 40 import android.net.NetworkTemplate.WIFI_NETWORKID_ALL 41 import android.net.NetworkTemplate.buildTemplateCarrierMetered 42 import android.net.NetworkTemplate.buildTemplateMobileWithRatType 43 import android.net.NetworkTemplate.buildTemplateWifi 44 import android.net.NetworkTemplate.buildTemplateWifiWildcard 45 import android.os.Build 46 import android.telephony.TelephonyManager 47 import com.android.testutils.DevSdkIgnoreRule 48 import com.android.testutils.DevSdkIgnoreRunner 49 import com.android.testutils.assertParcelSane 50 import org.junit.Before 51 import org.junit.Test 52 import org.junit.runner.RunWith 53 import org.mockito.Mockito.mock 54 import org.mockito.MockitoAnnotations 55 import kotlin.test.assertEquals 56 import kotlin.test.assertFalse 57 import kotlin.test.assertNotEquals 58 import kotlin.test.assertTrue 59 60 private const val TEST_IMSI1 = "imsi1" 61 private const val TEST_IMSI2 = "imsi2" 62 private const val TEST_SSID1 = "ssid1" 63 private const val TEST_SSID2 = "ssid2" 64 65 @RunWith(DevSdkIgnoreRunner::class) 66 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) 67 class NetworkTemplateTest { 68 private val mockContext = mock(Context::class.java) 69 buildMobileNetworkStatenull70 private fun buildMobileNetworkState(subscriberId: String): NetworkStateSnapshot = 71 buildNetworkState(TYPE_MOBILE, subscriberId = subscriberId) 72 private fun buildWifiNetworkState(subscriberId: String?, ssid: String?): NetworkStateSnapshot = 73 buildNetworkState(TYPE_WIFI, subscriberId = subscriberId, ssid = ssid) 74 75 private fun buildNetworkState( 76 type: Int, 77 subscriberId: String? = null, 78 ssid: String? = null, 79 oemManaged: Int = OEM_NONE, 80 metered: Boolean = true 81 ): NetworkStateSnapshot { 82 val lp = LinkProperties() 83 val caps = NetworkCapabilities().apply { 84 setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, !metered) 85 setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true) 86 setSSID(ssid) 87 setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID, 88 (oemManaged and OEM_PAID) == OEM_PAID) 89 setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE, 90 (oemManaged and OEM_PRIVATE) == OEM_PRIVATE) 91 } 92 return NetworkStateSnapshot(mock(Network::class.java), caps, lp, subscriberId, type) 93 } 94 NetworkTemplatenull95 private fun NetworkTemplate.assertMatches(ident: NetworkIdentity) = 96 assertTrue(matches(ident), "$this does not match $ident") 97 98 private fun NetworkTemplate.assertDoesNotMatch(ident: NetworkIdentity) = 99 assertFalse(matches(ident), "$this should match $ident") 100 101 @Before 102 fun setup() { 103 MockitoAnnotations.initMocks(this) 104 } 105 106 @Test testWifiWildcardMatchesnull107 fun testWifiWildcardMatches() { 108 val templateWifiWildcard = buildTemplateWifiWildcard() 109 110 val identMobileImsi1 = buildNetworkIdentity(mockContext, 111 buildMobileNetworkState(TEST_IMSI1), 112 false, TelephonyManager.NETWORK_TYPE_UMTS) 113 val identWifiImsiNullSsid1 = buildNetworkIdentity( 114 mockContext, buildWifiNetworkState(null, TEST_SSID1), true, 0) 115 val identWifiImsi1Ssid1 = buildNetworkIdentity( 116 mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_SSID1), true, 0) 117 118 templateWifiWildcard.assertDoesNotMatch(identMobileImsi1) 119 templateWifiWildcard.assertMatches(identWifiImsiNullSsid1) 120 templateWifiWildcard.assertMatches(identWifiImsi1Ssid1) 121 } 122 123 @Test testWifiMatchesnull124 fun testWifiMatches() { 125 val templateWifiSsid1 = buildTemplateWifi(TEST_SSID1) 126 val templateWifiSsid1ImsiNull = buildTemplateWifi(TEST_SSID1, null) 127 val templateWifiSsid1Imsi1 = buildTemplateWifi(TEST_SSID1, TEST_IMSI1) 128 val templateWifiSsidAllImsi1 = buildTemplateWifi(WIFI_NETWORKID_ALL, TEST_IMSI1) 129 130 val identMobile1 = buildNetworkIdentity(mockContext, buildMobileNetworkState(TEST_IMSI1), 131 false, TelephonyManager.NETWORK_TYPE_UMTS) 132 val identWifiImsiNullSsid1 = buildNetworkIdentity( 133 mockContext, buildWifiNetworkState(null, TEST_SSID1), true, 0) 134 val identWifiImsi1Ssid1 = buildNetworkIdentity( 135 mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_SSID1), true, 0) 136 val identWifiImsi2Ssid1 = buildNetworkIdentity( 137 mockContext, buildWifiNetworkState(TEST_IMSI2, TEST_SSID1), true, 0) 138 val identWifiImsi1Ssid2 = buildNetworkIdentity( 139 mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_SSID2), true, 0) 140 141 // Verify that template with SSID only matches any subscriberId and specific SSID. 142 templateWifiSsid1.assertDoesNotMatch(identMobile1) 143 templateWifiSsid1.assertMatches(identWifiImsiNullSsid1) 144 templateWifiSsid1.assertMatches(identWifiImsi1Ssid1) 145 templateWifiSsid1.assertMatches(identWifiImsi2Ssid1) 146 templateWifiSsid1.assertDoesNotMatch(identWifiImsi1Ssid2) 147 148 // Verify that template with SSID1 and null imsi matches any network with 149 // SSID1 and null imsi. 150 templateWifiSsid1ImsiNull.assertDoesNotMatch(identMobile1) 151 templateWifiSsid1ImsiNull.assertMatches(identWifiImsiNullSsid1) 152 templateWifiSsid1ImsiNull.assertDoesNotMatch(identWifiImsi1Ssid1) 153 templateWifiSsid1ImsiNull.assertDoesNotMatch(identWifiImsi2Ssid1) 154 templateWifiSsid1ImsiNull.assertDoesNotMatch(identWifiImsi1Ssid2) 155 156 // Verify that template with SSID1 and imsi1 matches any network with 157 // SSID1 and imsi1. 158 templateWifiSsid1Imsi1.assertDoesNotMatch(identMobile1) 159 templateWifiSsid1Imsi1.assertDoesNotMatch(identWifiImsiNullSsid1) 160 templateWifiSsid1Imsi1.assertMatches(identWifiImsi1Ssid1) 161 templateWifiSsid1Imsi1.assertDoesNotMatch(identWifiImsi2Ssid1) 162 templateWifiSsid1Imsi1.assertDoesNotMatch(identWifiImsi1Ssid2) 163 164 // Verify that template with SSID all and imsi1 matches any network with 165 // any SSID and imsi1. 166 templateWifiSsidAllImsi1.assertDoesNotMatch(identMobile1) 167 templateWifiSsidAllImsi1.assertDoesNotMatch(identWifiImsiNullSsid1) 168 templateWifiSsidAllImsi1.assertMatches(identWifiImsi1Ssid1) 169 templateWifiSsidAllImsi1.assertDoesNotMatch(identWifiImsi2Ssid1) 170 templateWifiSsidAllImsi1.assertMatches(identWifiImsi1Ssid2) 171 } 172 173 @Test testCarrierMeteredMatchesnull174 fun testCarrierMeteredMatches() { 175 val templateCarrierImsi1Metered = buildTemplateCarrierMetered(TEST_IMSI1) 176 177 val mobileImsi1 = buildMobileNetworkState(TEST_IMSI1) 178 val mobileImsi1Unmetered = buildNetworkState(TYPE_MOBILE, TEST_IMSI1, null /* ssid */, 179 OEM_NONE, false /* metered */) 180 val mobileImsi2 = buildMobileNetworkState(TEST_IMSI2) 181 val wifiSsid1 = buildWifiNetworkState(null /* subscriberId */, TEST_SSID1) 182 val wifiImsi1Ssid1 = buildWifiNetworkState(TEST_IMSI1, TEST_SSID1) 183 val wifiImsi1Ssid1Unmetered = buildNetworkState(TYPE_WIFI, TEST_IMSI1, TEST_SSID1, 184 OEM_NONE, false /* metered */) 185 186 val identMobileImsi1Metered = buildNetworkIdentity(mockContext, 187 mobileImsi1, false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS) 188 val identMobileImsi1Unmetered = buildNetworkIdentity(mockContext, 189 mobileImsi1Unmetered, false /* defaultNetwork */, 190 TelephonyManager.NETWORK_TYPE_UMTS) 191 val identMobileImsi2Metered = buildNetworkIdentity(mockContext, 192 mobileImsi2, false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS) 193 val identWifiSsid1Metered = buildNetworkIdentity( 194 mockContext, wifiSsid1, true /* defaultNetwork */, 0 /* subType */) 195 val identCarrierWifiImsi1Metered = buildNetworkIdentity( 196 mockContext, wifiImsi1Ssid1, true /* defaultNetwork */, 0 /* subType */) 197 val identCarrierWifiImsi1NonMetered = buildNetworkIdentity(mockContext, 198 wifiImsi1Ssid1Unmetered, true /* defaultNetwork */, 0 /* subType */) 199 200 templateCarrierImsi1Metered.assertMatches(identMobileImsi1Metered) 201 templateCarrierImsi1Metered.assertDoesNotMatch(identMobileImsi1Unmetered) 202 templateCarrierImsi1Metered.assertDoesNotMatch(identMobileImsi2Metered) 203 templateCarrierImsi1Metered.assertDoesNotMatch(identWifiSsid1Metered) 204 templateCarrierImsi1Metered.assertMatches(identCarrierWifiImsi1Metered) 205 templateCarrierImsi1Metered.assertDoesNotMatch(identCarrierWifiImsi1NonMetered) 206 } 207 208 @Test testRatTypeGroupMatchesnull209 fun testRatTypeGroupMatches() { 210 val stateMobile = buildMobileNetworkState(TEST_IMSI1) 211 // Build UMTS template that matches mobile identities with RAT in the same 212 // group with any IMSI. See {@link NetworkTemplate#getCollapsedRatType}. 213 val templateUmts = buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UMTS) 214 // Build normal template that matches mobile identities with any RAT and IMSI. 215 val templateAll = buildTemplateMobileWithRatType(null, NETWORK_TYPE_ALL) 216 // Build template with UNKNOWN RAT that matches mobile identities with RAT that 217 // cannot be determined. 218 val templateUnknown = 219 buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UNKNOWN) 220 221 val identUmts = buildNetworkIdentity( 222 mockContext, stateMobile, false, TelephonyManager.NETWORK_TYPE_UMTS) 223 val identHsdpa = buildNetworkIdentity( 224 mockContext, stateMobile, false, TelephonyManager.NETWORK_TYPE_HSDPA) 225 val identLte = buildNetworkIdentity( 226 mockContext, stateMobile, false, TelephonyManager.NETWORK_TYPE_LTE) 227 val identCombined = buildNetworkIdentity( 228 mockContext, stateMobile, false, SUBTYPE_COMBINED) 229 val identImsi2 = buildNetworkIdentity(mockContext, buildMobileNetworkState(TEST_IMSI2), 230 false, TelephonyManager.NETWORK_TYPE_UMTS) 231 val identWifi = buildNetworkIdentity( 232 mockContext, buildWifiNetworkState(null, TEST_SSID1), true, 0) 233 234 // Assert that identity with the same RAT matches. 235 templateUmts.assertMatches(identUmts) 236 templateAll.assertMatches(identUmts) 237 templateUnknown.assertDoesNotMatch(identUmts) 238 // Assert that identity with the RAT within the same group matches. 239 templateUmts.assertMatches(identHsdpa) 240 templateAll.assertMatches(identHsdpa) 241 templateUnknown.assertDoesNotMatch(identHsdpa) 242 // Assert that identity with the RAT out of the same group only matches template with 243 // NETWORK_TYPE_ALL. 244 templateUmts.assertDoesNotMatch(identLte) 245 templateAll.assertMatches(identLte) 246 templateUnknown.assertDoesNotMatch(identLte) 247 // Assert that identity with combined RAT only matches with template with NETWORK_TYPE_ALL 248 // and NETWORK_TYPE_UNKNOWN. 249 templateUmts.assertDoesNotMatch(identCombined) 250 templateAll.assertMatches(identCombined) 251 templateUnknown.assertMatches(identCombined) 252 // Assert that identity with different IMSI matches. 253 templateUmts.assertMatches(identImsi2) 254 templateAll.assertMatches(identImsi2) 255 templateUnknown.assertDoesNotMatch(identImsi2) 256 // Assert that wifi identity does not match. 257 templateUmts.assertDoesNotMatch(identWifi) 258 templateAll.assertDoesNotMatch(identWifi) 259 templateUnknown.assertDoesNotMatch(identWifi) 260 } 261 262 @Test testParcelUnparcelnull263 fun testParcelUnparcel() { 264 val templateMobile = NetworkTemplate(MATCH_MOBILE, TEST_IMSI1, null, null, METERED_ALL, 265 ROAMING_ALL, DEFAULT_NETWORK_ALL, TelephonyManager.NETWORK_TYPE_LTE, 266 OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT) 267 val templateWifi = NetworkTemplate(MATCH_WIFI, null, null, TEST_SSID1, METERED_ALL, 268 ROAMING_ALL, DEFAULT_NETWORK_ALL, 0, OEM_MANAGED_ALL, 269 SUBSCRIBER_ID_MATCH_RULE_EXACT) 270 val templateOem = NetworkTemplate(MATCH_MOBILE, null, null, null, METERED_ALL, 271 ROAMING_ALL, DEFAULT_NETWORK_ALL, 0, OEM_MANAGED_YES, 272 SUBSCRIBER_ID_MATCH_RULE_EXACT) 273 assertParcelSane(templateMobile, 10) 274 assertParcelSane(templateWifi, 10) 275 assertParcelSane(templateOem, 10) 276 } 277 278 // Verify NETWORK_TYPE_* constants in NetworkTemplate do not conflict with 279 // TelephonyManager#NETWORK_TYPE_* constants. 280 @Test testNetworkTypeConstantsnull281 fun testNetworkTypeConstants() { 282 for (ratType in TelephonyManager.getAllNetworkTypes()) { 283 assertNotEquals(NETWORK_TYPE_ALL, ratType) 284 assertNotEquals(NETWORK_TYPE_5G_NSA, ratType) 285 } 286 } 287 288 @Test testOemNetworkConstantsnull289 fun testOemNetworkConstants() { 290 val constantValues = arrayOf(OEM_MANAGED_YES, OEM_MANAGED_ALL, OEM_MANAGED_NO, 291 OEM_PAID, OEM_PRIVATE, OEM_PAID or OEM_PRIVATE) 292 293 // Verify that "not OEM managed network" constants are equal. 294 assertEquals(OEM_MANAGED_NO, OEM_NONE) 295 296 // Verify the constants don't conflict. 297 assertEquals(constantValues.size, constantValues.distinct().count()) 298 } 299 300 /** 301 * Helper to enumerate and assert OEM managed wifi and mobile {@code NetworkTemplate}s match 302 * their the appropriate OEM managed {@code NetworkIdentity}s. 303 * 304 * @param networkType {@code TYPE_MOBILE} or {@code TYPE_WIFI} 305 * @param matchType A match rule from {@code NetworkTemplate.MATCH_*} corresponding to the 306 * networkType. 307 * @param subscriberId To be populated with {@code TEST_IMSI*} only if networkType is 308 * {@code TYPE_MOBILE}. May be left as null when matchType is 309 * {@link NetworkTemplate.MATCH_MOBILE_WILDCARD}. 310 * @param templateSsid Top be populated with {@code TEST_SSID*} only if networkType is 311 * {@code TYPE_WIFI}. May be left as null when matchType is 312 * {@link NetworkTemplate.MATCH_WIFI_WILDCARD}. 313 * @param identSsid If networkType is {@code TYPE_WIFI}, this value must *NOT* be null. Provide 314 * one of {@code TEST_SSID*}. 315 */ matchOemManagedIdentnull316 private fun matchOemManagedIdent( 317 networkType: Int, 318 matchType: Int, 319 subscriberId: String? = null, 320 templateSsid: String? = null, 321 identSsid: String? = null 322 ) { 323 val oemManagedStates = arrayOf(OEM_NONE, OEM_PAID, OEM_PRIVATE, OEM_PAID or OEM_PRIVATE) 324 val matchSubscriberIds = arrayOf(subscriberId) 325 326 val templateOemYes = NetworkTemplate(matchType, subscriberId, matchSubscriberIds, 327 templateSsid, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, 328 OEM_MANAGED_YES, SUBSCRIBER_ID_MATCH_RULE_EXACT) 329 val templateOemAll = NetworkTemplate(matchType, subscriberId, matchSubscriberIds, 330 templateSsid, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, 331 OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT) 332 333 for (identityOemManagedState in oemManagedStates) { 334 val ident = buildNetworkIdentity(mockContext, buildNetworkState(networkType, 335 subscriberId, identSsid, identityOemManagedState), /*defaultNetwork=*/false, 336 /*subType=*/0) 337 338 // Create a template with each OEM managed type and match it against the NetworkIdentity 339 for (templateOemManagedState in oemManagedStates) { 340 val template = NetworkTemplate(matchType, subscriberId, matchSubscriberIds, 341 templateSsid, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, 342 NETWORK_TYPE_ALL, templateOemManagedState, SUBSCRIBER_ID_MATCH_RULE_EXACT) 343 if (identityOemManagedState == templateOemManagedState) { 344 template.assertMatches(ident) 345 } else { 346 template.assertDoesNotMatch(ident) 347 } 348 } 349 // OEM_MANAGED_ALL ignores OEM state. 350 templateOemAll.assertMatches(ident) 351 if (identityOemManagedState == OEM_NONE) { 352 // OEM_MANAGED_YES matches everything except OEM_NONE. 353 templateOemYes.assertDoesNotMatch(ident) 354 } else { 355 templateOemYes.assertMatches(ident) 356 } 357 } 358 } 359 360 @Test testOemManagedMatchesIdentnull361 fun testOemManagedMatchesIdent() { 362 matchOemManagedIdent(TYPE_MOBILE, MATCH_MOBILE, subscriberId = TEST_IMSI1) 363 matchOemManagedIdent(TYPE_MOBILE, MATCH_MOBILE_WILDCARD) 364 matchOemManagedIdent(TYPE_WIFI, MATCH_WIFI, templateSsid = TEST_SSID1, 365 identSsid = TEST_SSID1) 366 matchOemManagedIdent(TYPE_WIFI, MATCH_WIFI_WILDCARD, identSsid = TEST_SSID1) 367 } 368 } 369