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.METERED_NO
30 import android.net.NetworkStats.METERED_YES
31 import android.net.NetworkStats.ROAMING_ALL
32 import android.net.NetworkTemplate.MATCH_MOBILE
33 import android.net.NetworkTemplate.MATCH_MOBILE_WILDCARD
34 import android.net.NetworkTemplate.MATCH_WIFI
35 import android.net.NetworkTemplate.MATCH_WIFI_WILDCARD
36 import android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA
37 import android.net.NetworkTemplate.NETWORK_TYPE_ALL
38 import android.net.NetworkTemplate.OEM_MANAGED_ALL
39 import android.net.NetworkTemplate.OEM_MANAGED_NO
40 import android.net.NetworkTemplate.OEM_MANAGED_YES
41 import android.net.NetworkTemplate.SUBSCRIBER_ID_MATCH_RULE_EXACT
42 import android.net.NetworkTemplate.WIFI_NETWORKID_ALL
43 import android.net.NetworkTemplate.buildTemplateCarrierMetered
44 import android.net.NetworkTemplate.buildTemplateMobileAll
45 import android.net.NetworkTemplate.buildTemplateMobileWildcard
46 import android.net.NetworkTemplate.buildTemplateMobileWithRatType
47 import android.net.NetworkTemplate.buildTemplateWifi
48 import android.net.NetworkTemplate.buildTemplateWifiWildcard
49 import android.net.NetworkTemplate.normalize
50 import android.os.Build
51 import android.telephony.TelephonyManager
52 import com.android.testutils.DevSdkIgnoreRule
53 import com.android.testutils.DevSdkIgnoreRunner
54 import com.android.testutils.assertParcelSane
55 import org.junit.Before
56 import org.junit.Test
57 import org.junit.runner.RunWith
58 import org.mockito.Mockito.mock
59 import org.mockito.MockitoAnnotations
60 import kotlin.test.assertEquals
61 import kotlin.test.assertFalse
62 import kotlin.test.assertNotEquals
63 import kotlin.test.assertTrue
64 
65 private const val TEST_IMSI1 = "imsi1"
66 private const val TEST_IMSI2 = "imsi2"
67 private const val TEST_IMSI3 = "imsi3"
68 private const val TEST_SSID1 = "ssid1"
69 private const val TEST_SSID2 = "ssid2"
70 
71 @RunWith(DevSdkIgnoreRunner::class)
72 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
73 class NetworkTemplateTest {
74     private val mockContext = mock(Context::class.java)
75 
76     private fun buildMobileNetworkState(subscriberId: String): NetworkStateSnapshot =
77             buildNetworkState(TYPE_MOBILE, subscriberId = subscriberId)
78     private fun buildWifiNetworkState(subscriberId: String?, ssid: String?): NetworkStateSnapshot =
79             buildNetworkState(TYPE_WIFI, subscriberId = subscriberId, ssid = ssid)
80 
81     private fun buildNetworkState(
82         type: Int,
83         subscriberId: String? = null,
84         ssid: String? = null,
85         oemManaged: Int = OEM_NONE,
86         metered: Boolean = true
87     ): NetworkStateSnapshot {
88         val lp = LinkProperties()
89         val caps = NetworkCapabilities().apply {
90             setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, !metered)
91             setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true)
92             setSSID(ssid)
93             setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID,
94                     (oemManaged and OEM_PAID) == OEM_PAID)
95             setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE,
96                     (oemManaged and OEM_PRIVATE) == OEM_PRIVATE)
97         }
98         return NetworkStateSnapshot(mock(Network::class.java), caps, lp, subscriberId, type)
99     }
100 
101     private fun NetworkTemplate.assertMatches(ident: NetworkIdentity) =
102             assertTrue(matches(ident), "$this does not match $ident")
103 
104     private fun NetworkTemplate.assertDoesNotMatch(ident: NetworkIdentity) =
105             assertFalse(matches(ident), "$this should match $ident")
106 
107     @Before
108     fun setup() {
109         MockitoAnnotations.initMocks(this)
110     }
111 
112     @Test
113     fun testWifiWildcardMatches() {
114         val templateWifiWildcard = buildTemplateWifiWildcard()
115 
116         val identMobileImsi1 = buildNetworkIdentity(mockContext,
117                 buildMobileNetworkState(TEST_IMSI1),
118                 false, TelephonyManager.NETWORK_TYPE_UMTS)
119         val identWifiImsiNullSsid1 = buildNetworkIdentity(
120                 mockContext, buildWifiNetworkState(null, TEST_SSID1), true, 0)
121         val identWifiImsi1Ssid1 = buildNetworkIdentity(
122                 mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_SSID1), true, 0)
123 
124         templateWifiWildcard.assertDoesNotMatch(identMobileImsi1)
125         templateWifiWildcard.assertMatches(identWifiImsiNullSsid1)
126         templateWifiWildcard.assertMatches(identWifiImsi1Ssid1)
127     }
128 
129     @Test
130     fun testWifiMatches() {
131         val templateWifiSsid1 = buildTemplateWifi(TEST_SSID1)
132         val templateWifiSsid1ImsiNull = buildTemplateWifi(TEST_SSID1, null)
133         val templateWifiSsid1Imsi1 = buildTemplateWifi(TEST_SSID1, TEST_IMSI1)
134         val templateWifiSsidAllImsi1 = buildTemplateWifi(WIFI_NETWORKID_ALL, TEST_IMSI1)
135 
136         val identMobile1 = buildNetworkIdentity(mockContext, buildMobileNetworkState(TEST_IMSI1),
137                 false, TelephonyManager.NETWORK_TYPE_UMTS)
138         val identWifiImsiNullSsid1 = buildNetworkIdentity(
139                 mockContext, buildWifiNetworkState(null, TEST_SSID1), true, 0)
140         val identWifiImsi1Ssid1 = buildNetworkIdentity(
141                 mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_SSID1), true, 0)
142         val identWifiImsi2Ssid1 = buildNetworkIdentity(
143                 mockContext, buildWifiNetworkState(TEST_IMSI2, TEST_SSID1), true, 0)
144         val identWifiImsi1Ssid2 = buildNetworkIdentity(
145                 mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_SSID2), true, 0)
146 
147         // Verify that template with SSID only matches any subscriberId and specific SSID.
148         templateWifiSsid1.assertDoesNotMatch(identMobile1)
149         templateWifiSsid1.assertMatches(identWifiImsiNullSsid1)
150         templateWifiSsid1.assertMatches(identWifiImsi1Ssid1)
151         templateWifiSsid1.assertMatches(identWifiImsi2Ssid1)
152         templateWifiSsid1.assertDoesNotMatch(identWifiImsi1Ssid2)
153 
154         // Verify that template with SSID1 and null imsi matches any network with
155         // SSID1 and null imsi.
156         templateWifiSsid1ImsiNull.assertDoesNotMatch(identMobile1)
157         templateWifiSsid1ImsiNull.assertMatches(identWifiImsiNullSsid1)
158         templateWifiSsid1ImsiNull.assertDoesNotMatch(identWifiImsi1Ssid1)
159         templateWifiSsid1ImsiNull.assertDoesNotMatch(identWifiImsi2Ssid1)
160         templateWifiSsid1ImsiNull.assertDoesNotMatch(identWifiImsi1Ssid2)
161 
162         // Verify that template with SSID1 and imsi1 matches any network with
163         // SSID1 and imsi1.
164         templateWifiSsid1Imsi1.assertDoesNotMatch(identMobile1)
165         templateWifiSsid1Imsi1.assertDoesNotMatch(identWifiImsiNullSsid1)
166         templateWifiSsid1Imsi1.assertMatches(identWifiImsi1Ssid1)
167         templateWifiSsid1Imsi1.assertDoesNotMatch(identWifiImsi2Ssid1)
168         templateWifiSsid1Imsi1.assertDoesNotMatch(identWifiImsi1Ssid2)
169 
170         // Verify that template with SSID all and imsi1 matches any network with
171         // any SSID and imsi1.
172         templateWifiSsidAllImsi1.assertDoesNotMatch(identMobile1)
173         templateWifiSsidAllImsi1.assertDoesNotMatch(identWifiImsiNullSsid1)
174         templateWifiSsidAllImsi1.assertMatches(identWifiImsi1Ssid1)
175         templateWifiSsidAllImsi1.assertDoesNotMatch(identWifiImsi2Ssid1)
176         templateWifiSsidAllImsi1.assertMatches(identWifiImsi1Ssid2)
177     }
178 
179     @Test
180     fun testMobileMatches() {
181         val templateMobileImsi1 = buildTemplateMobileAll(TEST_IMSI1)
182         val templateMobileImsi2WithRatType = buildTemplateMobileWithRatType(TEST_IMSI2,
183                 TelephonyManager.NETWORK_TYPE_UMTS, METERED_YES)
184 
185         val mobileImsi1 = buildNetworkState(TYPE_MOBILE, TEST_IMSI1, null /* ssid */,
186                 OEM_NONE, true /* metered */)
187         val identMobile1 = buildNetworkIdentity(mockContext, mobileImsi1,
188                 false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS)
189         val mobileImsi2 = buildMobileNetworkState(TEST_IMSI2)
190         val identMobile2Umts = buildNetworkIdentity(mockContext, mobileImsi2,
191                 false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS)
192 
193         val identWifiImsi1Ssid1 = buildNetworkIdentity(
194                 mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_SSID1), true, 0)
195 
196         // Verify that the template matches type and the subscriberId.
197         templateMobileImsi1.assertMatches(identMobile1)
198         templateMobileImsi2WithRatType.assertMatches(identMobile2Umts)
199 
200         // Verify that the template does not match the different subscriberId.
201         templateMobileImsi1.assertDoesNotMatch(identMobile2Umts)
202         templateMobileImsi2WithRatType.assertDoesNotMatch(identMobile1)
203 
204         // Verify that the different type does not match.
205         templateMobileImsi1.assertDoesNotMatch(identWifiImsi1Ssid1)
206     }
207 
208     @Test
209     fun testMobileWildcardMatches() {
210         val templateMobileWildcard = buildTemplateMobileWildcard()
211         val templateMobileNullImsiWithRatType = buildTemplateMobileWithRatType(null,
212                 TelephonyManager.NETWORK_TYPE_UMTS, METERED_ALL)
213 
214         val mobileImsi1 = buildMobileNetworkState(TEST_IMSI1)
215         val identMobile1 = buildNetworkIdentity(mockContext, mobileImsi1,
216                 false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS)
217 
218         // Verify that the template matches any subscriberId.
219         templateMobileWildcard.assertMatches(identMobile1)
220         templateMobileNullImsiWithRatType.assertMatches(identMobile1)
221 
222         val identWifiImsi1Ssid1 = buildNetworkIdentity(
223                 mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_SSID1), true, 0)
224 
225         // Verify that the different type does not match.
226         templateMobileWildcard.assertDoesNotMatch(identWifiImsi1Ssid1)
227         templateMobileNullImsiWithRatType.assertDoesNotMatch(identWifiImsi1Ssid1)
228     }
229 
230     @Test
231     fun testCarrierMeteredMatches() {
232         val templateCarrierImsi1Metered = buildTemplateCarrierMetered(TEST_IMSI1)
233 
234         val mobileImsi1 = buildMobileNetworkState(TEST_IMSI1)
235         val mobileImsi1Unmetered = buildNetworkState(TYPE_MOBILE, TEST_IMSI1, null /* ssid */,
236                 OEM_NONE, false /* metered */)
237         val mobileImsi2 = buildMobileNetworkState(TEST_IMSI2)
238         val wifiSsid1 = buildWifiNetworkState(null /* subscriberId */, TEST_SSID1)
239         val wifiImsi1Ssid1 = buildWifiNetworkState(TEST_IMSI1, TEST_SSID1)
240         val wifiImsi1Ssid1Unmetered = buildNetworkState(TYPE_WIFI, TEST_IMSI1, TEST_SSID1,
241                 OEM_NONE, false /* metered */)
242 
243         val identMobileImsi1Metered = buildNetworkIdentity(mockContext,
244                 mobileImsi1, false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS)
245         val identMobileImsi1Unmetered = buildNetworkIdentity(mockContext,
246                 mobileImsi1Unmetered, false /* defaultNetwork */,
247                 TelephonyManager.NETWORK_TYPE_UMTS)
248         val identMobileImsi2Metered = buildNetworkIdentity(mockContext,
249                 mobileImsi2, false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS)
250         val identWifiSsid1Metered = buildNetworkIdentity(
251                 mockContext, wifiSsid1, true /* defaultNetwork */, 0 /* subType */)
252         val identCarrierWifiImsi1Metered = buildNetworkIdentity(
253                 mockContext, wifiImsi1Ssid1, true /* defaultNetwork */, 0 /* subType */)
254         val identCarrierWifiImsi1NonMetered = buildNetworkIdentity(mockContext,
255                 wifiImsi1Ssid1Unmetered, true /* defaultNetwork */, 0 /* subType */)
256 
257         templateCarrierImsi1Metered.assertMatches(identMobileImsi1Metered)
258         templateCarrierImsi1Metered.assertDoesNotMatch(identMobileImsi1Unmetered)
259         templateCarrierImsi1Metered.assertDoesNotMatch(identMobileImsi2Metered)
260         templateCarrierImsi1Metered.assertDoesNotMatch(identWifiSsid1Metered)
261         templateCarrierImsi1Metered.assertMatches(identCarrierWifiImsi1Metered)
262         templateCarrierImsi1Metered.assertDoesNotMatch(identCarrierWifiImsi1NonMetered)
263     }
264 
265     // TODO: Refactor this test to reduce the line of codes.
266     @Test
267     fun testRatTypeGroupMatches() {
268         val stateMobileImsi1Metered = buildMobileNetworkState(TEST_IMSI1)
269         val stateMobileImsi1NonMetered = buildNetworkState(TYPE_MOBILE, TEST_IMSI1,
270                 null /* ssid */, OEM_NONE, false /* metered */)
271         val stateMobileImsi2NonMetered = buildNetworkState(TYPE_MOBILE, TEST_IMSI2,
272                 null /* ssid */, OEM_NONE, false /* metered */)
273 
274         // Build UMTS template that matches mobile identities with RAT in the same
275         // group with any IMSI. See {@link NetworkTemplate#getCollapsedRatType}.
276         val templateUmtsMetered = buildTemplateMobileWithRatType(null,
277                 TelephonyManager.NETWORK_TYPE_UMTS, METERED_YES)
278         // Build normal template that matches mobile identities with any RAT and IMSI.
279         val templateAllMetered = buildTemplateMobileWithRatType(null, NETWORK_TYPE_ALL,
280                 METERED_YES)
281         // Build template with UNKNOWN RAT that matches mobile identities with RAT that
282         // cannot be determined.
283         val templateUnknownMetered =
284                 buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UNKNOWN,
285                 METERED_YES)
286 
287         val templateUmtsNonMetered = buildTemplateMobileWithRatType(null,
288                 TelephonyManager.NETWORK_TYPE_UMTS, METERED_NO)
289         val templateAllNonMetered = buildTemplateMobileWithRatType(null, NETWORK_TYPE_ALL,
290                 METERED_NO)
291         val templateUnknownNonMetered =
292                 buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UNKNOWN,
293                 METERED_NO)
294 
295         val identUmtsMetered = buildNetworkIdentity(
296                 mockContext, stateMobileImsi1Metered, false, TelephonyManager.NETWORK_TYPE_UMTS)
297         val identHsdpaMetered = buildNetworkIdentity(
298                 mockContext, stateMobileImsi1Metered, false, TelephonyManager.NETWORK_TYPE_HSDPA)
299         val identLteMetered = buildNetworkIdentity(
300                 mockContext, stateMobileImsi1Metered, false, TelephonyManager.NETWORK_TYPE_LTE)
301         val identCombinedMetered = buildNetworkIdentity(
302                 mockContext, stateMobileImsi1Metered, false, SUBTYPE_COMBINED)
303         val identImsi2UmtsMetered = buildNetworkIdentity(mockContext,
304                 buildMobileNetworkState(TEST_IMSI2), false, TelephonyManager.NETWORK_TYPE_UMTS)
305         val identWifi = buildNetworkIdentity(
306                 mockContext, buildWifiNetworkState(null, TEST_SSID1), true, 0)
307 
308         val identUmtsNonMetered = buildNetworkIdentity(
309                 mockContext, stateMobileImsi1NonMetered, false, TelephonyManager.NETWORK_TYPE_UMTS)
310         val identHsdpaNonMetered = buildNetworkIdentity(
311                 mockContext, stateMobileImsi1NonMetered, false,
312                 TelephonyManager.NETWORK_TYPE_HSDPA)
313         val identLteNonMetered = buildNetworkIdentity(
314                 mockContext, stateMobileImsi1NonMetered, false, TelephonyManager.NETWORK_TYPE_LTE)
315         val identCombinedNonMetered = buildNetworkIdentity(
316                 mockContext, stateMobileImsi1NonMetered, false, SUBTYPE_COMBINED)
317         val identImsi2UmtsNonMetered = buildNetworkIdentity(mockContext,
318                 stateMobileImsi2NonMetered, false, TelephonyManager.NETWORK_TYPE_UMTS)
319 
320         // Assert that identity with the same RAT and meteredness matches.
321         // Verify metered template.
322         templateUmtsMetered.assertMatches(identUmtsMetered)
323         templateAllMetered.assertMatches(identUmtsMetered)
324         templateUnknownMetered.assertDoesNotMatch(identUmtsMetered)
325         // Verify non-metered template.
326         templateUmtsNonMetered.assertMatches(identUmtsNonMetered)
327         templateAllNonMetered.assertMatches(identUmtsNonMetered)
328         templateUnknownNonMetered.assertDoesNotMatch(identUmtsNonMetered)
329 
330         // Assert that identity with the same RAT but meteredness is different.
331         // Thus, it does not match.
332         templateUmtsNonMetered.assertDoesNotMatch(identUmtsMetered)
333         templateAllNonMetered.assertDoesNotMatch(identUmtsMetered)
334 
335         // Assert that identity with the RAT within the same group matches.
336         // Verify metered template.
337         templateUmtsMetered.assertMatches(identHsdpaMetered)
338         templateAllMetered.assertMatches(identHsdpaMetered)
339         templateUnknownMetered.assertDoesNotMatch(identHsdpaMetered)
340         // Verify non-metered template.
341         templateUmtsNonMetered.assertMatches(identHsdpaNonMetered)
342         templateAllNonMetered.assertMatches(identHsdpaNonMetered)
343         templateUnknownNonMetered.assertDoesNotMatch(identHsdpaNonMetered)
344 
345         // Assert that identity with the RAT out of the same group only matches template with
346         // NETWORK_TYPE_ALL.
347         // Verify metered template.
348         templateUmtsMetered.assertDoesNotMatch(identLteMetered)
349         templateAllMetered.assertMatches(identLteMetered)
350         templateUnknownMetered.assertDoesNotMatch(identLteMetered)
351         // Verify non-metered template.
352         templateUmtsNonMetered.assertDoesNotMatch(identLteNonMetered)
353         templateAllNonMetered.assertMatches(identLteNonMetered)
354         templateUnknownNonMetered.assertDoesNotMatch(identLteNonMetered)
355         // Verify non-metered template does not match identity with metered.
356         templateAllNonMetered.assertDoesNotMatch(identLteMetered)
357 
358         // Assert that identity with combined RAT only matches with template with NETWORK_TYPE_ALL
359         // and NETWORK_TYPE_UNKNOWN.
360         // Verify metered template.
361         templateUmtsMetered.assertDoesNotMatch(identCombinedMetered)
362         templateAllMetered.assertMatches(identCombinedMetered)
363         templateUnknownMetered.assertMatches(identCombinedMetered)
364         // Verify non-metered template.
365         templateUmtsNonMetered.assertDoesNotMatch(identCombinedNonMetered)
366         templateAllNonMetered.assertMatches(identCombinedNonMetered)
367         templateUnknownNonMetered.assertMatches(identCombinedNonMetered)
368         // Verify that identity with metered does not match non-metered template.
369         templateAllNonMetered.assertDoesNotMatch(identCombinedMetered)
370         templateUnknownNonMetered.assertDoesNotMatch(identCombinedMetered)
371 
372         // Assert that identity with different IMSI matches.
373         // Verify metered template.
374         templateUmtsMetered.assertMatches(identImsi2UmtsMetered)
375         templateAllMetered.assertMatches(identImsi2UmtsMetered)
376         templateUnknownMetered.assertDoesNotMatch(identImsi2UmtsMetered)
377         // Verify non-metered template.
378         templateUmtsNonMetered.assertMatches(identImsi2UmtsNonMetered)
379         templateAllNonMetered.assertMatches(identImsi2UmtsNonMetered)
380         templateUnknownNonMetered.assertDoesNotMatch(identImsi2UmtsNonMetered)
381         // Verify that the same RAT but different meteredness should not match.
382         templateUmtsNonMetered.assertDoesNotMatch(identImsi2UmtsMetered)
383         templateAllNonMetered.assertDoesNotMatch(identImsi2UmtsMetered)
384 
385         // Assert that wifi identity does not match.
386         templateUmtsMetered.assertDoesNotMatch(identWifi)
387         templateUnknownMetered.assertDoesNotMatch(identWifi)
388         templateUmtsNonMetered.assertDoesNotMatch(identWifi)
389         templateUnknownNonMetered.assertDoesNotMatch(identWifi)
390     }
391 
392     @Test
393     fun testParcelUnparcel() {
394         val templateMobile = NetworkTemplate(MATCH_MOBILE, TEST_IMSI1, null, null, METERED_ALL,
395                 ROAMING_ALL, DEFAULT_NETWORK_ALL, TelephonyManager.NETWORK_TYPE_LTE,
396                 OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT)
397         val templateWifi = NetworkTemplate(MATCH_WIFI, null, null, TEST_SSID1, METERED_ALL,
398                 ROAMING_ALL, DEFAULT_NETWORK_ALL, 0, OEM_MANAGED_ALL,
399                 SUBSCRIBER_ID_MATCH_RULE_EXACT)
400         val templateOem = NetworkTemplate(MATCH_MOBILE, null, null, null, METERED_ALL,
401                 ROAMING_ALL, DEFAULT_NETWORK_ALL, 0, OEM_MANAGED_YES,
402                 SUBSCRIBER_ID_MATCH_RULE_EXACT)
403         assertParcelSane(templateMobile, 10)
404         assertParcelSane(templateWifi, 10)
405         assertParcelSane(templateOem, 10)
406     }
407 
408     // Verify NETWORK_TYPE_* constants in NetworkTemplate do not conflict with
409     // TelephonyManager#NETWORK_TYPE_* constants.
410     @Test
411     fun testNetworkTypeConstants() {
412         for (ratType in TelephonyManager.getAllNetworkTypes()) {
413             assertNotEquals(NETWORK_TYPE_ALL, ratType)
414             assertNotEquals(NETWORK_TYPE_5G_NSA, ratType)
415         }
416     }
417 
418     @Test
419     fun testOemNetworkConstants() {
420         val constantValues = arrayOf(OEM_MANAGED_YES, OEM_MANAGED_ALL, OEM_MANAGED_NO,
421                 OEM_PAID, OEM_PRIVATE, OEM_PAID or OEM_PRIVATE)
422 
423         // Verify that "not OEM managed network" constants are equal.
424         assertEquals(OEM_MANAGED_NO, OEM_NONE)
425 
426         // Verify the constants don't conflict.
427         assertEquals(constantValues.size, constantValues.distinct().count())
428     }
429 
430     /**
431      * Helper to enumerate and assert OEM managed wifi and mobile {@code NetworkTemplate}s match
432      * their the appropriate OEM managed {@code NetworkIdentity}s.
433      *
434      * @param networkType {@code TYPE_MOBILE} or {@code TYPE_WIFI}
435      * @param matchType A match rule from {@code NetworkTemplate.MATCH_*} corresponding to the
436      *         networkType.
437      * @param subscriberId To be populated with {@code TEST_IMSI*} only if networkType is
438      *         {@code TYPE_MOBILE}. May be left as null when matchType is
439      *         {@link NetworkTemplate.MATCH_MOBILE_WILDCARD}.
440      * @param templateSsid Top be populated with {@code TEST_SSID*} only if networkType is
441      *         {@code TYPE_WIFI}. May be left as null when matchType is
442      *         {@link NetworkTemplate.MATCH_WIFI_WILDCARD}.
443      * @param identSsid If networkType is {@code TYPE_WIFI}, this value must *NOT* be null. Provide
444      *         one of {@code TEST_SSID*}.
445      */
446     private fun matchOemManagedIdent(
447         networkType: Int,
448         matchType: Int,
449         subscriberId: String? = null,
450         templateSsid: String? = null,
451         identSsid: String? = null
452     ) {
453         val oemManagedStates = arrayOf(OEM_NONE, OEM_PAID, OEM_PRIVATE, OEM_PAID or OEM_PRIVATE)
454         val matchSubscriberIds = arrayOf(subscriberId)
455 
456         val templateOemYes = NetworkTemplate(matchType, subscriberId, matchSubscriberIds,
457                 templateSsid, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
458                 OEM_MANAGED_YES, SUBSCRIBER_ID_MATCH_RULE_EXACT)
459         val templateOemAll = NetworkTemplate(matchType, subscriberId, matchSubscriberIds,
460                 templateSsid, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
461                 OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT)
462 
463         for (identityOemManagedState in oemManagedStates) {
464             val ident = buildNetworkIdentity(mockContext, buildNetworkState(networkType,
465                     subscriberId, identSsid, identityOemManagedState), /*defaultNetwork=*/false,
466                     /*subType=*/0)
467 
468             // Create a template with each OEM managed type and match it against the NetworkIdentity
469             for (templateOemManagedState in oemManagedStates) {
470                 val template = NetworkTemplate(matchType, subscriberId, matchSubscriberIds,
471                         templateSsid, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL,
472                         NETWORK_TYPE_ALL, templateOemManagedState, SUBSCRIBER_ID_MATCH_RULE_EXACT)
473                 if (identityOemManagedState == templateOemManagedState) {
474                     template.assertMatches(ident)
475                 } else {
476                     template.assertDoesNotMatch(ident)
477                 }
478             }
479             // OEM_MANAGED_ALL ignores OEM state.
480             templateOemAll.assertMatches(ident)
481             if (identityOemManagedState == OEM_NONE) {
482                 // OEM_MANAGED_YES matches everything except OEM_NONE.
483                 templateOemYes.assertDoesNotMatch(ident)
484             } else {
485                 templateOemYes.assertMatches(ident)
486             }
487         }
488     }
489 
490     @Test
491     fun testOemManagedMatchesIdent() {
492         matchOemManagedIdent(TYPE_MOBILE, MATCH_MOBILE, subscriberId = TEST_IMSI1)
493         matchOemManagedIdent(TYPE_MOBILE, MATCH_MOBILE_WILDCARD)
494         matchOemManagedIdent(TYPE_WIFI, MATCH_WIFI, templateSsid = TEST_SSID1,
495                 identSsid = TEST_SSID1)
496         matchOemManagedIdent(TYPE_WIFI, MATCH_WIFI_WILDCARD, identSsid = TEST_SSID1)
497     }
498 
499     @Test
500     fun testNormalize() {
501         var mergedImsiList = listOf(arrayOf(TEST_IMSI1, TEST_IMSI2))
502         val identMobileImsi1 = buildNetworkIdentity(mockContext,
503                 buildMobileNetworkState(TEST_IMSI1), false /* defaultNetwork */,
504                 TelephonyManager.NETWORK_TYPE_UMTS)
505         val identMobileImsi2 = buildNetworkIdentity(mockContext,
506                 buildMobileNetworkState(TEST_IMSI2), false /* defaultNetwork */,
507                 TelephonyManager.NETWORK_TYPE_UMTS)
508         val identMobileImsi3 = buildNetworkIdentity(mockContext,
509                 buildMobileNetworkState(TEST_IMSI3), false /* defaultNetwork */,
510                 TelephonyManager.NETWORK_TYPE_UMTS)
511         val identWifiImsi1Ssid1 = buildNetworkIdentity(
512                 mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_SSID1), true, 0)
513         val identWifiImsi2Ssid1 = buildNetworkIdentity(
514                 mockContext, buildWifiNetworkState(TEST_IMSI2, TEST_SSID1), true, 0)
515         val identWifiImsi3Ssid1 = buildNetworkIdentity(
516                 mockContext, buildWifiNetworkState(TEST_IMSI3, TEST_SSID1), true, 0)
517 
518         normalize(buildTemplateMobileAll(TEST_IMSI1), mergedImsiList).also {
519             it.assertMatches(identMobileImsi1)
520             it.assertMatches(identMobileImsi2)
521             it.assertDoesNotMatch(identMobileImsi3)
522         }
523         normalize(buildTemplateCarrierMetered(TEST_IMSI1), mergedImsiList).also {
524             it.assertMatches(identMobileImsi1)
525             it.assertMatches(identMobileImsi2)
526             it.assertDoesNotMatch(identMobileImsi3)
527         }
528         normalize(buildTemplateWifi(TEST_SSID1, TEST_IMSI1), mergedImsiList).also {
529             it.assertMatches(identWifiImsi1Ssid1)
530             it.assertMatches(identWifiImsi2Ssid1)
531             it.assertDoesNotMatch(identWifiImsi3Ssid1)
532         }
533         normalize(buildTemplateMobileWildcard(), mergedImsiList).also {
534             it.assertMatches(identMobileImsi1)
535             it.assertMatches(identMobileImsi2)
536             it.assertMatches(identMobileImsi3)
537         }
538     }
539 }
540