blob: cb39a0c819f2afdcaba6c1ba0be5a6ee8f868952 [file] [log] [blame]
/*
* Copyright (C) 2020 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.content.Context
import android.net.ConnectivityManager.TYPE_MOBILE
import android.net.ConnectivityManager.TYPE_WIFI
import android.net.NetworkIdentity.SUBTYPE_COMBINED
import android.net.NetworkIdentity.OEM_NONE
import android.net.NetworkIdentity.OEM_PAID
import android.net.NetworkIdentity.OEM_PRIVATE
import android.net.NetworkIdentity.buildNetworkIdentity
import android.net.NetworkStats.DEFAULT_NETWORK_ALL
import android.net.NetworkStats.METERED_ALL
import android.net.NetworkStats.ROAMING_ALL
import android.net.NetworkTemplate.MATCH_MOBILE
import android.net.NetworkTemplate.MATCH_MOBILE_WILDCARD
import android.net.NetworkTemplate.MATCH_WIFI
import android.net.NetworkTemplate.MATCH_WIFI_WILDCARD
import android.net.NetworkTemplate.WIFI_NETWORKID_ALL
import android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA
import android.net.NetworkTemplate.NETWORK_TYPE_ALL
import android.net.NetworkTemplate.OEM_MANAGED_ALL
import android.net.NetworkTemplate.OEM_MANAGED_NO
import android.net.NetworkTemplate.OEM_MANAGED_YES
import android.net.NetworkTemplate.SUBSCRIBER_ID_MATCH_RULE_EXACT
import android.net.NetworkTemplate.buildTemplateWifi
import android.net.NetworkTemplate.buildTemplateWifiWildcard
import android.net.NetworkTemplate.buildTemplateCarrierMetered
import android.net.NetworkTemplate.buildTemplateMobileWithRatType
import android.telephony.TelephonyManager
import com.android.testutils.assertParcelSane
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.Mockito.mock
import org.mockito.MockitoAnnotations
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertNotEquals
import kotlin.test.assertTrue
private const val TEST_IMSI1 = "imsi1"
private const val TEST_IMSI2 = "imsi2"
private const val TEST_SSID1 = "ssid1"
private const val TEST_SSID2 = "ssid2"
@RunWith(JUnit4::class)
class NetworkTemplateTest {
private val mockContext = mock(Context::class.java)
private fun buildMobileNetworkState(subscriberId: String): NetworkStateSnapshot =
buildNetworkState(TYPE_MOBILE, subscriberId = subscriberId)
private fun buildWifiNetworkState(subscriberId: String?, ssid: String?): NetworkStateSnapshot =
buildNetworkState(TYPE_WIFI, subscriberId = subscriberId, ssid = ssid)
private fun buildNetworkState(
type: Int,
subscriberId: String? = null,
ssid: String? = null,
oemManaged: Int = OEM_NONE,
metered: Boolean = true
): NetworkStateSnapshot {
val lp = LinkProperties()
val caps = NetworkCapabilities().apply {
setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, !metered)
setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true)
setSSID(ssid)
setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID,
(oemManaged and OEM_PAID) == OEM_PAID)
setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE,
(oemManaged and OEM_PRIVATE) == OEM_PRIVATE)
}
return NetworkStateSnapshot(mock(Network::class.java), caps, lp, subscriberId, type)
}
private fun NetworkTemplate.assertMatches(ident: NetworkIdentity) =
assertTrue(matches(ident), "$this does not match $ident")
private fun NetworkTemplate.assertDoesNotMatch(ident: NetworkIdentity) =
assertFalse(matches(ident), "$this should match $ident")
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
}
@Test
fun testWifiWildcardMatches() {
val templateWifiWildcard = buildTemplateWifiWildcard()
val identMobileImsi1 = buildNetworkIdentity(mockContext,
buildMobileNetworkState(TEST_IMSI1),
false, TelephonyManager.NETWORK_TYPE_UMTS)
val identWifiImsiNullSsid1 = buildNetworkIdentity(
mockContext, buildWifiNetworkState(null, TEST_SSID1), true, 0)
val identWifiImsi1Ssid1 = buildNetworkIdentity(
mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_SSID1), true, 0)
templateWifiWildcard.assertDoesNotMatch(identMobileImsi1)
templateWifiWildcard.assertMatches(identWifiImsiNullSsid1)
templateWifiWildcard.assertMatches(identWifiImsi1Ssid1)
}
@Test
fun testWifiMatches() {
val templateWifiSsid1 = buildTemplateWifi(TEST_SSID1)
val templateWifiSsid1ImsiNull = buildTemplateWifi(TEST_SSID1, null)
val templateWifiSsid1Imsi1 = buildTemplateWifi(TEST_SSID1, TEST_IMSI1)
val templateWifiSsidAllImsi1 = buildTemplateWifi(WIFI_NETWORKID_ALL, TEST_IMSI1)
val identMobile1 = buildNetworkIdentity(mockContext, buildMobileNetworkState(TEST_IMSI1),
false, TelephonyManager.NETWORK_TYPE_UMTS)
val identWifiImsiNullSsid1 = buildNetworkIdentity(
mockContext, buildWifiNetworkState(null, TEST_SSID1), true, 0)
val identWifiImsi1Ssid1 = buildNetworkIdentity(
mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_SSID1), true, 0)
val identWifiImsi2Ssid1 = buildNetworkIdentity(
mockContext, buildWifiNetworkState(TEST_IMSI2, TEST_SSID1), true, 0)
val identWifiImsi1Ssid2 = buildNetworkIdentity(
mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_SSID2), true, 0)
// Verify that template with SSID only matches any subscriberId and specific SSID.
templateWifiSsid1.assertDoesNotMatch(identMobile1)
templateWifiSsid1.assertMatches(identWifiImsiNullSsid1)
templateWifiSsid1.assertMatches(identWifiImsi1Ssid1)
templateWifiSsid1.assertMatches(identWifiImsi2Ssid1)
templateWifiSsid1.assertDoesNotMatch(identWifiImsi1Ssid2)
// Verify that template with SSID1 and null imsi matches any network with
// SSID1 and null imsi.
templateWifiSsid1ImsiNull.assertDoesNotMatch(identMobile1)
templateWifiSsid1ImsiNull.assertMatches(identWifiImsiNullSsid1)
templateWifiSsid1ImsiNull.assertDoesNotMatch(identWifiImsi1Ssid1)
templateWifiSsid1ImsiNull.assertDoesNotMatch(identWifiImsi2Ssid1)
templateWifiSsid1ImsiNull.assertDoesNotMatch(identWifiImsi1Ssid2)
// Verify that template with SSID1 and imsi1 matches any network with
// SSID1 and imsi1.
templateWifiSsid1Imsi1.assertDoesNotMatch(identMobile1)
templateWifiSsid1Imsi1.assertDoesNotMatch(identWifiImsiNullSsid1)
templateWifiSsid1Imsi1.assertMatches(identWifiImsi1Ssid1)
templateWifiSsid1Imsi1.assertDoesNotMatch(identWifiImsi2Ssid1)
templateWifiSsid1Imsi1.assertDoesNotMatch(identWifiImsi1Ssid2)
// Verify that template with SSID all and imsi1 matches any network with
// any SSID and imsi1.
templateWifiSsidAllImsi1.assertDoesNotMatch(identMobile1)
templateWifiSsidAllImsi1.assertDoesNotMatch(identWifiImsiNullSsid1)
templateWifiSsidAllImsi1.assertMatches(identWifiImsi1Ssid1)
templateWifiSsidAllImsi1.assertDoesNotMatch(identWifiImsi2Ssid1)
templateWifiSsidAllImsi1.assertMatches(identWifiImsi1Ssid2)
}
@Test
fun testCarrierMeteredMatches() {
val templateCarrierImsi1Metered = buildTemplateCarrierMetered(TEST_IMSI1)
val mobileImsi1 = buildMobileNetworkState(TEST_IMSI1)
val mobileImsi1Unmetered = buildNetworkState(TYPE_MOBILE, TEST_IMSI1, null /* ssid */,
OEM_NONE, false /* metered */)
val mobileImsi2 = buildMobileNetworkState(TEST_IMSI2)
val wifiSsid1 = buildWifiNetworkState(null /* subscriberId */, TEST_SSID1)
val wifiImsi1Ssid1 = buildWifiNetworkState(TEST_IMSI1, TEST_SSID1)
val wifiImsi1Ssid1Unmetered = buildNetworkState(TYPE_WIFI, TEST_IMSI1, TEST_SSID1,
OEM_NONE, false /* metered */)
val identMobileImsi1Metered = buildNetworkIdentity(mockContext,
mobileImsi1, false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS)
val identMobileImsi1Unmetered = buildNetworkIdentity(mockContext,
mobileImsi1Unmetered, false /* defaultNetwork */,
TelephonyManager.NETWORK_TYPE_UMTS)
val identMobileImsi2Metered = buildNetworkIdentity(mockContext,
mobileImsi2, false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS)
val identWifiSsid1Metered = buildNetworkIdentity(
mockContext, wifiSsid1, true /* defaultNetwork */, 0 /* subType */)
val identCarrierWifiImsi1Metered = buildNetworkIdentity(
mockContext, wifiImsi1Ssid1, true /* defaultNetwork */, 0 /* subType */)
val identCarrierWifiImsi1NonMetered = buildNetworkIdentity(mockContext,
wifiImsi1Ssid1Unmetered, true /* defaultNetwork */, 0 /* subType */)
templateCarrierImsi1Metered.assertMatches(identMobileImsi1Metered)
templateCarrierImsi1Metered.assertDoesNotMatch(identMobileImsi1Unmetered)
templateCarrierImsi1Metered.assertDoesNotMatch(identMobileImsi2Metered)
templateCarrierImsi1Metered.assertDoesNotMatch(identWifiSsid1Metered)
templateCarrierImsi1Metered.assertMatches(identCarrierWifiImsi1Metered)
templateCarrierImsi1Metered.assertDoesNotMatch(identCarrierWifiImsi1NonMetered)
}
@Test
fun testRatTypeGroupMatches() {
val stateMobile = buildMobileNetworkState(TEST_IMSI1)
// Build UMTS template that matches mobile identities with RAT in the same
// group with any IMSI. See {@link NetworkTemplate#getCollapsedRatType}.
val templateUmts = buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UMTS)
// Build normal template that matches mobile identities with any RAT and IMSI.
val templateAll = buildTemplateMobileWithRatType(null, NETWORK_TYPE_ALL)
// Build template with UNKNOWN RAT that matches mobile identities with RAT that
// cannot be determined.
val templateUnknown =
buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UNKNOWN)
val identUmts = buildNetworkIdentity(
mockContext, stateMobile, false, TelephonyManager.NETWORK_TYPE_UMTS)
val identHsdpa = buildNetworkIdentity(
mockContext, stateMobile, false, TelephonyManager.NETWORK_TYPE_HSDPA)
val identLte = buildNetworkIdentity(
mockContext, stateMobile, false, TelephonyManager.NETWORK_TYPE_LTE)
val identCombined = buildNetworkIdentity(
mockContext, stateMobile, false, SUBTYPE_COMBINED)
val identImsi2 = buildNetworkIdentity(mockContext, buildMobileNetworkState(TEST_IMSI2),
false, TelephonyManager.NETWORK_TYPE_UMTS)
val identWifi = buildNetworkIdentity(
mockContext, buildWifiNetworkState(null, TEST_SSID1), true, 0)
// Assert that identity with the same RAT matches.
templateUmts.assertMatches(identUmts)
templateAll.assertMatches(identUmts)
templateUnknown.assertDoesNotMatch(identUmts)
// Assert that identity with the RAT within the same group matches.
templateUmts.assertMatches(identHsdpa)
templateAll.assertMatches(identHsdpa)
templateUnknown.assertDoesNotMatch(identHsdpa)
// Assert that identity with the RAT out of the same group only matches template with
// NETWORK_TYPE_ALL.
templateUmts.assertDoesNotMatch(identLte)
templateAll.assertMatches(identLte)
templateUnknown.assertDoesNotMatch(identLte)
// Assert that identity with combined RAT only matches with template with NETWORK_TYPE_ALL
// and NETWORK_TYPE_UNKNOWN.
templateUmts.assertDoesNotMatch(identCombined)
templateAll.assertMatches(identCombined)
templateUnknown.assertMatches(identCombined)
// Assert that identity with different IMSI matches.
templateUmts.assertMatches(identImsi2)
templateAll.assertMatches(identImsi2)
templateUnknown.assertDoesNotMatch(identImsi2)
// Assert that wifi identity does not match.
templateUmts.assertDoesNotMatch(identWifi)
templateAll.assertDoesNotMatch(identWifi)
templateUnknown.assertDoesNotMatch(identWifi)
}
@Test
fun testParcelUnparcel() {
val templateMobile = NetworkTemplate(MATCH_MOBILE, TEST_IMSI1, null, null, METERED_ALL,
ROAMING_ALL, DEFAULT_NETWORK_ALL, TelephonyManager.NETWORK_TYPE_LTE,
OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT)
val templateWifi = NetworkTemplate(MATCH_WIFI, null, null, TEST_SSID1, METERED_ALL,
ROAMING_ALL, DEFAULT_NETWORK_ALL, 0, OEM_MANAGED_ALL,
SUBSCRIBER_ID_MATCH_RULE_EXACT)
val templateOem = NetworkTemplate(MATCH_MOBILE, null, null, null, METERED_ALL,
ROAMING_ALL, DEFAULT_NETWORK_ALL, 0, OEM_MANAGED_YES,
SUBSCRIBER_ID_MATCH_RULE_EXACT)
assertParcelSane(templateMobile, 10)
assertParcelSane(templateWifi, 10)
assertParcelSane(templateOem, 10)
}
// Verify NETWORK_TYPE_* constants in NetworkTemplate do not conflict with
// TelephonyManager#NETWORK_TYPE_* constants.
@Test
fun testNetworkTypeConstants() {
for (ratType in TelephonyManager.getAllNetworkTypes()) {
assertNotEquals(NETWORK_TYPE_ALL, ratType)
assertNotEquals(NETWORK_TYPE_5G_NSA, ratType)
}
}
@Test
fun testOemNetworkConstants() {
val constantValues = arrayOf(OEM_MANAGED_YES, OEM_MANAGED_ALL, OEM_MANAGED_NO,
OEM_PAID, OEM_PRIVATE, OEM_PAID or OEM_PRIVATE)
// Verify that "not OEM managed network" constants are equal.
assertEquals(OEM_MANAGED_NO, OEM_NONE)
// Verify the constants don't conflict.
assertEquals(constantValues.size, constantValues.distinct().count())
}
/**
* Helper to enumerate and assert OEM managed wifi and mobile {@code NetworkTemplate}s match
* their the appropriate OEM managed {@code NetworkIdentity}s.
*
* @param networkType {@code TYPE_MOBILE} or {@code TYPE_WIFI}
* @param matchType A match rule from {@code NetworkTemplate.MATCH_*} corresponding to the
* networkType.
* @param subscriberId To be populated with {@code TEST_IMSI*} only if networkType is
* {@code TYPE_MOBILE}. May be left as null when matchType is
* {@link NetworkTemplate.MATCH_MOBILE_WILDCARD}.
* @param templateSsid Top be populated with {@code TEST_SSID*} only if networkType is
* {@code TYPE_WIFI}. May be left as null when matchType is
* {@link NetworkTemplate.MATCH_WIFI_WILDCARD}.
* @param identSsid If networkType is {@code TYPE_WIFI}, this value must *NOT* be null. Provide
* one of {@code TEST_SSID*}.
*/
private fun matchOemManagedIdent(
networkType: Int,
matchType: Int,
subscriberId: String? = null,
templateSsid: String? = null,
identSsid: String? = null
) {
val oemManagedStates = arrayOf(OEM_NONE, OEM_PAID, OEM_PRIVATE, OEM_PAID or OEM_PRIVATE)
val matchSubscriberIds = arrayOf(subscriberId)
val templateOemYes = NetworkTemplate(matchType, subscriberId, matchSubscriberIds,
templateSsid, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
OEM_MANAGED_YES, SUBSCRIBER_ID_MATCH_RULE_EXACT)
val templateOemAll = NetworkTemplate(matchType, subscriberId, matchSubscriberIds,
templateSsid, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT)
for (identityOemManagedState in oemManagedStates) {
val ident = buildNetworkIdentity(mockContext, buildNetworkState(networkType,
subscriberId, identSsid, identityOemManagedState), /*defaultNetwork=*/false,
/*subType=*/0)
// Create a template with each OEM managed type and match it against the NetworkIdentity
for (templateOemManagedState in oemManagedStates) {
val template = NetworkTemplate(matchType, subscriberId, matchSubscriberIds,
templateSsid, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL,
NETWORK_TYPE_ALL, templateOemManagedState, SUBSCRIBER_ID_MATCH_RULE_EXACT)
if (identityOemManagedState == templateOemManagedState) {
template.assertMatches(ident)
} else {
template.assertDoesNotMatch(ident)
}
}
// OEM_MANAGED_ALL ignores OEM state.
templateOemAll.assertMatches(ident)
if (identityOemManagedState == OEM_NONE) {
// OEM_MANAGED_YES matches everything except OEM_NONE.
templateOemYes.assertDoesNotMatch(ident)
} else {
templateOemYes.assertMatches(ident)
}
}
}
@Test
fun testOemManagedMatchesIdent() {
matchOemManagedIdent(TYPE_MOBILE, MATCH_MOBILE, subscriberId = TEST_IMSI1)
matchOemManagedIdent(TYPE_MOBILE, MATCH_MOBILE_WILDCARD)
matchOemManagedIdent(TYPE_WIFI, MATCH_WIFI, templateSsid = TEST_SSID1,
identSsid = TEST_SSID1)
matchOemManagedIdent(TYPE_WIFI, MATCH_WIFI_WILDCARD, identSsid = TEST_SSID1)
}
}