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 org.mockito.Mockito.verify 58 import kotlin.test.assertEquals 59 import kotlin.test.assertTrue 60 61 private const val SECONDARY_USER = 10 62 private val SECONDARY_USER_HANDLE = UserHandle(SECONDARY_USER) 63 private const val TEST_PACKAGE_UID = 123 64 private const val TEST_PACKAGE_UID2 = 321 65 66 @DevSdkIgnoreRunner.MonitorThreadLeak 67 @RunWith(DevSdkIgnoreRunner::class) 68 @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) 69 class CSSatelliteNetworkTest : CSTest() { 70 @get:Rule 71 val ignoreRule = DevSdkIgnoreRule() 72 73 /** 74 * Test createMultiLayerNrisFromSatelliteNetworkPreferredUids returns correct 75 * NetworkRequestInfo. 76 */ 77 @Test testCreateMultiLayerNrisFromSatelliteNetworkPreferredUidsnull78 fun testCreateMultiLayerNrisFromSatelliteNetworkPreferredUids() { 79 // Verify that empty uid set should not create any NRI for it. 80 val nrisNoUid = service.createMultiLayerNrisFromSatelliteNetworkFallbackUids(emptySet()) 81 Assert.assertEquals(0, nrisNoUid.size.toLong()) 82 val uid1 = PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID) 83 val uid2 = PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID2) 84 val uid3 = SECONDARY_USER_HANDLE.getUid(TEST_PACKAGE_UID) 85 assertCreateMultiLayerNrisFromSatelliteNetworkPreferredUids(mutableSetOf(uid1)) 86 assertCreateMultiLayerNrisFromSatelliteNetworkPreferredUids(mutableSetOf(uid1, uid3)) 87 assertCreateMultiLayerNrisFromSatelliteNetworkPreferredUids(mutableSetOf(uid1, uid2)) 88 } 89 90 /** 91 * Test that satellite network satisfies satellite fallback per-app default network request and 92 * send correct net id and uid ranges to netd. 93 */ doTestSatelliteNetworkFallbackUidsnull94 private fun doTestSatelliteNetworkFallbackUids(restricted: Boolean) { 95 val netdInOrder = inOrder(netd) 96 97 val satelliteAgent = createSatelliteAgent("satellite0", restricted) 98 satelliteAgent.connect() 99 100 val satelliteNetId = satelliteAgent.network.netId 101 val permission = if (restricted) {INetd.PERMISSION_SYSTEM} else {INetd.PERMISSION_NONE} 102 netdInOrder.verify(netd).networkCreate( 103 nativeNetworkConfigPhysical(satelliteNetId, permission)) 104 105 val uid1 = PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID) 106 val uid2 = PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID2) 107 val uid3 = SECONDARY_USER_HANDLE.getUid(TEST_PACKAGE_UID) 108 109 // Initial satellite network fallback uids status. 110 updateSatelliteNetworkFallbackUids(setOf()) 111 netdInOrder.verify(netd, never()).networkAddUidRangesParcel(any()) 112 netdInOrder.verify(netd, never()).networkRemoveUidRangesParcel(any()) 113 114 // Update satellite network fallback uids and verify that net id and uid ranges send to netd 115 var uids = mutableSetOf(uid1, uid2, uid3) 116 val uidRanges1 = toUidRangeStableParcels(uidRangesForUids(uids)) 117 val config1 = NativeUidRangeConfig( 118 satelliteNetId, uidRanges1, 119 PREFERENCE_ORDER_SATELLITE_FALLBACK 120 ) 121 updateSatelliteNetworkFallbackUids(uids) 122 netdInOrder.verify(netd).networkAddUidRangesParcel(config1) 123 netdInOrder.verify(netd, never()).networkRemoveUidRangesParcel(any()) 124 125 // Update satellite network fallback uids and verify that net id and uid ranges send to netd 126 uids = mutableSetOf(uid1) 127 val uidRanges2: Array<UidRangeParcel?> = toUidRangeStableParcels(uidRangesForUids(uids)) 128 val config2 = NativeUidRangeConfig( 129 satelliteNetId, uidRanges2, 130 PREFERENCE_ORDER_SATELLITE_FALLBACK 131 ) 132 updateSatelliteNetworkFallbackUids(uids) 133 netdInOrder.verify(netd).networkRemoveUidRangesParcel(config1) 134 netdInOrder.verify(netd).networkAddUidRangesParcel(config2) 135 } 136 137 @Test testSatelliteNetworkFallbackUids_restrictednull138 fun testSatelliteNetworkFallbackUids_restricted() { 139 doTestSatelliteNetworkFallbackUids(restricted = true) 140 } 141 142 @Test @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) testSatelliteNetworkFallbackUids_nonRestrictednull143 fun testSatelliteNetworkFallbackUids_nonRestricted() { 144 doTestSatelliteNetworkFallbackUids(restricted = false) 145 } 146 doTestSatelliteNeverBecomeDefaultNetworknull147 private fun doTestSatelliteNeverBecomeDefaultNetwork(restricted: Boolean) { 148 val agent = createSatelliteAgent("satellite0", restricted) 149 agent.connect() 150 val defaultCb = TestableNetworkCallback() 151 cm.registerDefaultNetworkCallback(defaultCb) 152 // Satellite network must not become the default network 153 defaultCb.assertNoCallback() 154 } 155 156 @Test testSatelliteNeverBecomeDefaultNetwork_restrictednull157 fun testSatelliteNeverBecomeDefaultNetwork_restricted() { 158 doTestSatelliteNeverBecomeDefaultNetwork(restricted = true) 159 } 160 161 @Test @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) testSatelliteNeverBecomeDefaultNetwork_notRestrictednull162 fun testSatelliteNeverBecomeDefaultNetwork_notRestricted() { 163 doTestSatelliteNeverBecomeDefaultNetwork(restricted = false) 164 } 165 doTestUnregisterAfterReplacementSatisfiernull166 private fun doTestUnregisterAfterReplacementSatisfier(destroyBeforeRequest: Boolean = false, 167 destroyAfterRequest: Boolean = false) { 168 val satelliteAgent = createSatelliteAgent("satellite0") 169 satelliteAgent.connect() 170 171 if (destroyBeforeRequest) { 172 satelliteAgent.unregisterAfterReplacement(timeoutMs = 5000) 173 } 174 175 val uids = setOf(TEST_PACKAGE_UID) 176 updateSatelliteNetworkFallbackUids(uids) 177 178 if (destroyBeforeRequest) { 179 verify(netd, never()).networkAddUidRangesParcel(any()) 180 } else { 181 verify(netd).networkAddUidRangesParcel( 182 NativeUidRangeConfig( 183 satelliteAgent.network.netId, 184 toUidRangeStableParcels(uidRangesForUids(uids)), 185 PREFERENCE_ORDER_SATELLITE_FALLBACK 186 ) 187 ) 188 } 189 190 if (destroyAfterRequest) { 191 satelliteAgent.unregisterAfterReplacement(timeoutMs = 5000) 192 } 193 194 updateSatelliteNetworkFallbackUids(setOf()) 195 if (destroyBeforeRequest || destroyAfterRequest) { 196 // If the network is already destroyed, networkRemoveUidRangesParcel should not be 197 // called. 198 verify(netd, never()).networkRemoveUidRangesParcel(any()) 199 } else { 200 verify(netd).networkRemoveUidRangesParcel( 201 NativeUidRangeConfig( 202 satelliteAgent.network.netId, 203 toUidRangeStableParcels(uidRangesForUids(uids)), 204 PREFERENCE_ORDER_SATELLITE_FALLBACK 205 ) 206 ) 207 } 208 } 209 210 @Test testUnregisterAfterReplacementSatisfier_destroyBeforeRequestnull211 fun testUnregisterAfterReplacementSatisfier_destroyBeforeRequest() { 212 doTestUnregisterAfterReplacementSatisfier(destroyBeforeRequest = true) 213 } 214 215 @Test testUnregisterAfterReplacementSatisfier_destroyAfterRequestnull216 fun testUnregisterAfterReplacementSatisfier_destroyAfterRequest() { 217 doTestUnregisterAfterReplacementSatisfier(destroyAfterRequest = true) 218 } 219 220 @Test testUnregisterAfterReplacementSatisfier_notDestroyednull221 fun testUnregisterAfterReplacementSatisfier_notDestroyed() { 222 doTestUnregisterAfterReplacementSatisfier() 223 } 224 assertCreateMultiLayerNrisFromSatelliteNetworkPreferredUidsnull225 private fun assertCreateMultiLayerNrisFromSatelliteNetworkPreferredUids(uids: Set<Int>) { 226 val nris: Set<ConnectivityService.NetworkRequestInfo> = 227 service.createMultiLayerNrisFromSatelliteNetworkFallbackUids(uids) 228 val nri = nris.iterator().next() 229 // Verify that one NRI is created with multilayer requests. Because one NRI can contain 230 // multiple uid ranges, so it only need create one NRI here. 231 assertEquals(1, nris.size.toLong()) 232 assertTrue(nri.isMultilayerRequest) 233 assertEquals(nri.uids, uidRangesForUids(uids)) 234 assertEquals(PREFERENCE_ORDER_SATELLITE_FALLBACK, nri.mPreferenceOrder) 235 } 236 updateSatelliteNetworkFallbackUidsnull237 private fun updateSatelliteNetworkFallbackUids(uids: Set<Int>) { 238 visibleOnHandlerThread(csHandler) { 239 deps.satelliteNetworkFallbackUidUpdate!!.accept(uids) 240 } 241 } 242 nativeNetworkConfigPhysicalnull243 private fun nativeNetworkConfigPhysical(netId: Int, permission: Int) = 244 NativeNetworkConfig(netId, NativeNetworkType.PHYSICAL, permission, 245 false /* secure */, VpnManager.TYPE_VPN_NONE, false /* excludeLocalRoutes */) 246 247 private fun createSatelliteAgent(name: String, restricted: Boolean = true): CSAgentWrapper { 248 return Agent(score = keepScore(), lp = lp(name), 249 nc = satelliteNc(restricted) 250 ) 251 } 252 toUidRangeStableParcelsnull253 private fun toUidRangeStableParcels(ranges: Set<UidRange>): Array<UidRangeParcel?> { 254 val stableRanges = arrayOfNulls<UidRangeParcel>(ranges.size) 255 for ((index, range) in ranges.withIndex()) { 256 stableRanges[index] = UidRangeParcel(range.start, range.stop) 257 } 258 return stableRanges 259 } 260 uidRangesForUidsnull261 private fun uidRangesForUids(vararg uids: Int): Set<UidRange> { 262 val ranges = ArraySet<UidRange>() 263 for (uid in uids) { 264 ranges.add(UidRange(uid, uid)) 265 } 266 return ranges 267 } 268 uidRangesForUidsnull269 private fun uidRangesForUids(uids: Collection<Int>): Set<UidRange> { 270 return uidRangesForUids(*CollectionUtils.toIntArray(uids)) 271 } 272 satelliteNcnull273 private fun satelliteNc(restricted: Boolean) = 274 NetworkCapabilities.Builder().apply { 275 addTransportType(TRANSPORT_SATELLITE) 276 277 addCapability(NET_CAPABILITY_INTERNET) 278 addCapability(NET_CAPABILITY_NOT_SUSPENDED) 279 addCapability(NET_CAPABILITY_NOT_ROAMING) 280 addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) 281 if (restricted) { 282 removeCapability(NET_CAPABILITY_NOT_RESTRICTED) 283 } 284 removeCapability(NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED) 285 }.build() 286 <lambda>null287 private fun lp(iface: String) = LinkProperties().apply { 288 interfaceName = iface 289 addLinkAddress(LinkAddress(LOCAL_IPV4_ADDRESS, 32)) 290 addRoute(RouteInfo(IpPrefix("0.0.0.0/0"), null, null)) 291 } 292 293 // This allows keeping all the networks connected without having to file individual requests 294 // for them. keepScorenull295 private fun keepScore() = FromS( 296 NetworkScore.Builder().setKeepConnectedReason(KEEP_CONNECTED_FOR_TEST).build() 297 ) 298 } 299