1 /*
2  * Copyright (C) 2023 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 com.android.server
18 
19 import android.net.IpPrefix
20 import android.net.INetd
21 import android.net.LinkAddress
22 import android.net.LinkProperties
23 import android.net.NativeNetworkConfig
24 import android.net.NativeNetworkType
25 import android.net.NetworkCapabilities
26 import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
27 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED
28 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED
29 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING
30 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED
31 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED
32 import android.net.NetworkScore
33 import android.net.NetworkCapabilities.TRANSPORT_SATELLITE
34 import android.net.NetworkScore.KEEP_CONNECTED_FOR_TEST
35 import android.net.RouteInfo
36 import android.net.UidRange
37 import android.net.UidRangeParcel
38 import android.net.VpnManager
39 import android.net.netd.aidl.NativeUidRangeConfig
40 import android.os.Build
41 import android.os.UserHandle
42 import android.util.ArraySet
43 import com.android.net.module.util.CollectionUtils
44 import com.android.server.ConnectivityService.PREFERENCE_ORDER_SATELLITE_FALLBACK
45 import com.android.testutils.DevSdkIgnoreRule
46 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
47 import com.android.testutils.DevSdkIgnoreRunner
48 import com.android.testutils.TestableNetworkCallback
49 import com.android.testutils.visibleOnHandlerThread
50 import org.junit.Assert
51 import org.junit.Rule
52 import org.junit.Test
53 import org.junit.runner.RunWith
54 import org.mockito.ArgumentMatchers.any
55 import org.mockito.Mockito.inOrder
56 import org.mockito.Mockito.never
57 import kotlin.test.assertEquals
58 import kotlin.test.assertTrue
59 
60 private const val SECONDARY_USER = 10
61 private val SECONDARY_USER_HANDLE = UserHandle(SECONDARY_USER)
62 private const val TEST_PACKAGE_UID = 123
63 private const val TEST_PACKAGE_UID2 = 321
64 
65 @DevSdkIgnoreRunner.MonitorThreadLeak
66 @RunWith(DevSdkIgnoreRunner::class)
67 @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
68 class CSSatelliteNetworkTest : CSTest() {
69     @get:Rule
70     val ignoreRule = DevSdkIgnoreRule()
71 
72     /**
73      * Test createMultiLayerNrisFromSatelliteNetworkPreferredUids returns correct
74      * NetworkRequestInfo.
75      */
76     @Test
testCreateMultiLayerNrisFromSatelliteNetworkPreferredUidsnull77     fun testCreateMultiLayerNrisFromSatelliteNetworkPreferredUids() {
78         // Verify that empty uid set should not create any NRI for it.
79         val nrisNoUid = service.createMultiLayerNrisFromSatelliteNetworkFallbackUids(emptySet())
80         Assert.assertEquals(0, nrisNoUid.size.toLong())
81         val uid1 = PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID)
82         val uid2 = PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID2)
83         val uid3 = SECONDARY_USER_HANDLE.getUid(TEST_PACKAGE_UID)
84         assertCreateMultiLayerNrisFromSatelliteNetworkPreferredUids(mutableSetOf(uid1))
85         assertCreateMultiLayerNrisFromSatelliteNetworkPreferredUids(mutableSetOf(uid1, uid3))
86         assertCreateMultiLayerNrisFromSatelliteNetworkPreferredUids(mutableSetOf(uid1, uid2))
87     }
88 
89     /**
90      * Test that satellite network satisfies satellite fallback per-app default network request and
91      * send correct net id and uid ranges to netd.
92      */
doTestSatelliteNetworkFallbackUidsnull93     private fun doTestSatelliteNetworkFallbackUids(restricted: Boolean) {
94         val netdInOrder = inOrder(netd)
95 
96         val satelliteAgent = createSatelliteAgent("satellite0", restricted)
97         satelliteAgent.connect()
98 
99         val satelliteNetId = satelliteAgent.network.netId
100         val permission = if (restricted) {INetd.PERMISSION_SYSTEM} else {INetd.PERMISSION_NONE}
101         netdInOrder.verify(netd).networkCreate(
102             nativeNetworkConfigPhysical(satelliteNetId, permission))
103 
104         val uid1 = PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID)
105         val uid2 = PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID2)
106         val uid3 = SECONDARY_USER_HANDLE.getUid(TEST_PACKAGE_UID)
107 
108         // Initial satellite network fallback uids status.
109         updateSatelliteNetworkFallbackUids(setOf())
110         netdInOrder.verify(netd, never()).networkAddUidRangesParcel(any())
111         netdInOrder.verify(netd, never()).networkRemoveUidRangesParcel(any())
112 
113         // Update satellite network fallback uids and verify that net id and uid ranges send to netd
114         var uids = mutableSetOf(uid1, uid2, uid3)
115         val uidRanges1 = toUidRangeStableParcels(uidRangesForUids(uids))
116         val config1 = NativeUidRangeConfig(
117             satelliteNetId, uidRanges1,
118             PREFERENCE_ORDER_SATELLITE_FALLBACK
119         )
120         updateSatelliteNetworkFallbackUids(uids)
121         netdInOrder.verify(netd).networkAddUidRangesParcel(config1)
122         netdInOrder.verify(netd, never()).networkRemoveUidRangesParcel(any())
123 
124         // Update satellite network fallback uids and verify that net id and uid ranges send to netd
125         uids = mutableSetOf(uid1)
126         val uidRanges2: Array<UidRangeParcel?> = toUidRangeStableParcels(uidRangesForUids(uids))
127         val config2 = NativeUidRangeConfig(
128             satelliteNetId, uidRanges2,
129             PREFERENCE_ORDER_SATELLITE_FALLBACK
130         )
131         updateSatelliteNetworkFallbackUids(uids)
132         netdInOrder.verify(netd).networkRemoveUidRangesParcel(config1)
133         netdInOrder.verify(netd).networkAddUidRangesParcel(config2)
134     }
135 
136     @Test
testSatelliteNetworkFallbackUids_restrictednull137     fun testSatelliteNetworkFallbackUids_restricted() {
138         doTestSatelliteNetworkFallbackUids(restricted = true)
139     }
140 
141     @Test @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
testSatelliteNetworkFallbackUids_nonRestrictednull142     fun testSatelliteNetworkFallbackUids_nonRestricted() {
143         doTestSatelliteNetworkFallbackUids(restricted = false)
144     }
145 
doTestSatelliteNeverBecomeDefaultNetworknull146     private fun doTestSatelliteNeverBecomeDefaultNetwork(restricted: Boolean) {
147         val agent = createSatelliteAgent("satellite0", restricted)
148         agent.connect()
149         val defaultCb = TestableNetworkCallback()
150         cm.registerDefaultNetworkCallback(defaultCb)
151         // Satellite network must not become the default network
152         defaultCb.assertNoCallback()
153     }
154 
155     @Test
testSatelliteNeverBecomeDefaultNetwork_restrictednull156     fun testSatelliteNeverBecomeDefaultNetwork_restricted() {
157         doTestSatelliteNeverBecomeDefaultNetwork(restricted = true)
158     }
159 
160     @Test @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
testSatelliteNeverBecomeDefaultNetwork_notRestrictednull161     fun testSatelliteNeverBecomeDefaultNetwork_notRestricted() {
162         doTestSatelliteNeverBecomeDefaultNetwork(restricted = false)
163     }
164 
assertCreateMultiLayerNrisFromSatelliteNetworkPreferredUidsnull165     private fun assertCreateMultiLayerNrisFromSatelliteNetworkPreferredUids(uids: Set<Int>) {
166         val nris: Set<ConnectivityService.NetworkRequestInfo> =
167             service.createMultiLayerNrisFromSatelliteNetworkFallbackUids(uids)
168         val nri = nris.iterator().next()
169         // Verify that one NRI is created with multilayer requests. Because one NRI can contain
170         // multiple uid ranges, so it only need create one NRI here.
171         assertEquals(1, nris.size.toLong())
172         assertTrue(nri.isMultilayerRequest)
173         assertEquals(nri.uids, uidRangesForUids(uids))
174         assertEquals(PREFERENCE_ORDER_SATELLITE_FALLBACK, nri.mPreferenceOrder)
175     }
176 
updateSatelliteNetworkFallbackUidsnull177     private fun updateSatelliteNetworkFallbackUids(uids: Set<Int>) {
178         visibleOnHandlerThread(csHandler) {
179             deps.satelliteNetworkFallbackUidUpdate!!.accept(uids)
180         }
181     }
182 
nativeNetworkConfigPhysicalnull183     private fun nativeNetworkConfigPhysical(netId: Int, permission: Int) =
184         NativeNetworkConfig(netId, NativeNetworkType.PHYSICAL, permission,
185             false /* secure */, VpnManager.TYPE_VPN_NONE, false /* excludeLocalRoutes */)
186 
187     private fun createSatelliteAgent(name: String, restricted: Boolean = true): CSAgentWrapper {
188         return Agent(score = keepScore(), lp = lp(name),
189             nc = satelliteNc(restricted)
190         )
191     }
192 
toUidRangeStableParcelsnull193     private fun toUidRangeStableParcels(ranges: Set<UidRange>): Array<UidRangeParcel?> {
194         val stableRanges = arrayOfNulls<UidRangeParcel>(ranges.size)
195         for ((index, range) in ranges.withIndex()) {
196             stableRanges[index] = UidRangeParcel(range.start, range.stop)
197         }
198         return stableRanges
199     }
200 
uidRangesForUidsnull201     private fun uidRangesForUids(vararg uids: Int): Set<UidRange> {
202         val ranges = ArraySet<UidRange>()
203         for (uid in uids) {
204             ranges.add(UidRange(uid, uid))
205         }
206         return ranges
207     }
208 
uidRangesForUidsnull209     private fun uidRangesForUids(uids: Collection<Int>): Set<UidRange> {
210         return uidRangesForUids(*CollectionUtils.toIntArray(uids))
211     }
212 
satelliteNcnull213     private fun satelliteNc(restricted: Boolean) =
214             NetworkCapabilities.Builder().apply {
215                 addTransportType(TRANSPORT_SATELLITE)
216 
217                 addCapability(NET_CAPABILITY_INTERNET)
218                 addCapability(NET_CAPABILITY_NOT_SUSPENDED)
219                 addCapability(NET_CAPABILITY_NOT_ROAMING)
220                 addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
221                 if (restricted) {
222                     removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
223                 }
224                 removeCapability(NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED)
225             }.build()
226 
<lambda>null227     private fun lp(iface: String) = LinkProperties().apply {
228         interfaceName = iface
229         addLinkAddress(LinkAddress(LOCAL_IPV4_ADDRESS, 32))
230         addRoute(RouteInfo(IpPrefix("0.0.0.0/0"), null, null))
231     }
232 
233     // This allows keeping all the networks connected without having to file individual requests
234     // for them.
keepScorenull235     private fun keepScore() = FromS(
236         NetworkScore.Builder().setKeepConnectedReason(KEEP_CONNECTED_FOR_TEST).build()
237     )
238 }
239