1 /* 2 * Copyright (C) 2009 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.cts; 18 19 import static android.Manifest.permission.ACCESS_COARSE_LOCATION; 20 import static android.Manifest.permission.ACCESS_FINE_LOCATION; 21 import static android.Manifest.permission.ACCESS_NETWORK_STATE; 22 import static android.Manifest.permission.CONNECTIVITY_INTERNAL; 23 import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS; 24 import static android.Manifest.permission.NETWORK_FACTORY; 25 import static android.Manifest.permission.NETWORK_SETTINGS; 26 import static android.Manifest.permission.NETWORK_SETUP_WIZARD; 27 import static android.Manifest.permission.NETWORK_STACK; 28 import static android.Manifest.permission.READ_DEVICE_CONFIG; 29 import static android.Manifest.permission.TETHER_PRIVILEGED; 30 import static android.content.pm.PackageManager.FEATURE_BLUETOOTH; 31 import static android.content.pm.PackageManager.FEATURE_ETHERNET; 32 import static android.content.pm.PackageManager.FEATURE_TELEPHONY; 33 import static android.content.pm.PackageManager.FEATURE_USB_HOST; 34 import static android.content.pm.PackageManager.FEATURE_WATCH; 35 import static android.content.pm.PackageManager.FEATURE_WIFI; 36 import static android.content.pm.PackageManager.FEATURE_WIFI_DIRECT; 37 import static android.content.pm.PackageManager.GET_PERMISSIONS; 38 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 39 import static android.net.ConnectivityManager.EXTRA_NETWORK; 40 import static android.net.ConnectivityManager.EXTRA_NETWORK_REQUEST; 41 import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE; 42 import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY; 43 import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_1; 44 import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_2; 45 import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3; 46 import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE; 47 import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED; 48 import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY; 49 import static android.net.ConnectivityManager.FIREWALL_RULE_ALLOW; 50 import static android.net.ConnectivityManager.FIREWALL_RULE_DENY; 51 import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE; 52 import static android.net.ConnectivityManager.TYPE_BLUETOOTH; 53 import static android.net.ConnectivityManager.TYPE_ETHERNET; 54 import static android.net.ConnectivityManager.TYPE_MOBILE_CBS; 55 import static android.net.ConnectivityManager.TYPE_MOBILE_DUN; 56 import static android.net.ConnectivityManager.TYPE_MOBILE_EMERGENCY; 57 import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA; 58 import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI; 59 import static android.net.ConnectivityManager.TYPE_MOBILE_IA; 60 import static android.net.ConnectivityManager.TYPE_MOBILE_IMS; 61 import static android.net.ConnectivityManager.TYPE_MOBILE_MMS; 62 import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL; 63 import static android.net.ConnectivityManager.TYPE_PROXY; 64 import static android.net.ConnectivityManager.TYPE_VPN; 65 import static android.net.ConnectivityManager.TYPE_WIFI_P2P; 66 import static android.net.ConnectivitySettingsManager.setUidsAllowedOnRestrictedNetworks; 67 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND; 68 import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS; 69 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; 70 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; 71 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; 72 import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY; 73 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; 74 import static android.net.NetworkCapabilities.TRANSPORT_TEST; 75 import static android.net.NetworkCapabilities.TRANSPORT_VPN; 76 import static android.net.NetworkCapabilities.TRANSPORT_WIFI; 77 import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; 78 import static android.net.cts.util.CtsNetUtils.ConnectivityActionReceiver; 79 import static android.net.cts.util.CtsNetUtils.HTTP_PORT; 80 import static android.net.cts.util.CtsNetUtils.NETWORK_CALLBACK_ACTION; 81 import static android.net.cts.util.CtsNetUtils.TEST_HOST; 82 import static android.net.cts.util.CtsNetUtils.TestNetworkCallback; 83 import static android.net.cts.util.CtsTetheringUtils.TestTetheringEventCallback; 84 import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT; 85 import static android.os.Process.INVALID_UID; 86 import static android.provider.Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE; 87 import static android.system.OsConstants.AF_INET; 88 import static android.system.OsConstants.AF_INET6; 89 import static android.system.OsConstants.AF_UNSPEC; 90 91 import static com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity; 92 import static com.android.compatibility.common.util.SystemUtil.runShellCommand; 93 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; 94 import static com.android.modules.utils.build.SdkLevel.isAtLeastS; 95 import static com.android.net.module.util.NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTPS_URL; 96 import static com.android.net.module.util.NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTP_URL; 97 import static com.android.networkstack.apishim.ConstantsShim.BLOCKED_REASON_LOCKDOWN_VPN; 98 import static com.android.networkstack.apishim.ConstantsShim.BLOCKED_REASON_NONE; 99 import static com.android.networkstack.apishim.ConstantsShim.RECEIVER_EXPORTED; 100 import static com.android.testutils.Cleanup.testAndCleanup; 101 import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2; 102 import static com.android.testutils.MiscAsserts.assertThrows; 103 import static com.android.testutils.TestNetworkTrackerKt.initTestNetwork; 104 import static com.android.testutils.TestPermissionUtil.runAsShell; 105 106 import static org.junit.Assert.assertArrayEquals; 107 import static org.junit.Assert.assertEquals; 108 import static org.junit.Assert.assertFalse; 109 import static org.junit.Assert.assertNotEquals; 110 import static org.junit.Assert.assertNotNull; 111 import static org.junit.Assert.assertNotSame; 112 import static org.junit.Assert.assertNull; 113 import static org.junit.Assert.assertTrue; 114 import static org.junit.Assert.fail; 115 import static org.junit.Assume.assumeTrue; 116 117 import android.annotation.NonNull; 118 import android.app.Instrumentation; 119 import android.app.PendingIntent; 120 import android.app.UiAutomation; 121 import android.content.BroadcastReceiver; 122 import android.content.ContentResolver; 123 import android.content.Context; 124 import android.content.Intent; 125 import android.content.IntentFilter; 126 import android.content.pm.PackageInfo; 127 import android.content.pm.PackageManager; 128 import android.content.res.Resources; 129 import android.net.CaptivePortalData; 130 import android.net.ConnectivityManager; 131 import android.net.ConnectivityManager.NetworkCallback; 132 import android.net.ConnectivitySettingsManager; 133 import android.net.InetAddresses; 134 import android.net.IpSecManager; 135 import android.net.IpSecManager.UdpEncapsulationSocket; 136 import android.net.LinkAddress; 137 import android.net.LinkProperties; 138 import android.net.Network; 139 import android.net.NetworkAgent; 140 import android.net.NetworkAgentConfig; 141 import android.net.NetworkCapabilities; 142 import android.net.NetworkInfo; 143 import android.net.NetworkInfo.DetailedState; 144 import android.net.NetworkInfo.State; 145 import android.net.NetworkProvider; 146 import android.net.NetworkRequest; 147 import android.net.NetworkSpecifier; 148 import android.net.NetworkStateSnapshot; 149 import android.net.OemNetworkPreferences; 150 import android.net.ProxyInfo; 151 import android.net.SocketKeepalive; 152 import android.net.TelephonyNetworkSpecifier; 153 import android.net.TestNetworkInterface; 154 import android.net.TestNetworkManager; 155 import android.net.Uri; 156 import android.net.cts.util.CtsNetUtils; 157 import android.net.cts.util.CtsTetheringUtils; 158 import android.net.util.KeepaliveUtils; 159 import android.net.wifi.WifiInfo; 160 import android.net.wifi.WifiManager; 161 import android.os.Binder; 162 import android.os.Build; 163 import android.os.Handler; 164 import android.os.Looper; 165 import android.os.MessageQueue; 166 import android.os.Process; 167 import android.os.ServiceManager; 168 import android.os.SystemClock; 169 import android.os.UserHandle; 170 import android.os.VintfRuntimeInfo; 171 import android.platform.test.annotations.AppModeFull; 172 import android.provider.DeviceConfig; 173 import android.provider.Settings; 174 import android.telephony.SubscriptionManager; 175 import android.telephony.TelephonyManager; 176 import android.text.TextUtils; 177 import android.util.ArraySet; 178 import android.util.Log; 179 import android.util.Range; 180 181 import androidx.test.InstrumentationRegistry; 182 import androidx.test.filters.RequiresDevice; 183 import androidx.test.runner.AndroidJUnit4; 184 185 import com.android.internal.util.ArrayUtils; 186 import com.android.modules.utils.build.SdkLevel; 187 import com.android.net.module.util.CollectionUtils; 188 import com.android.networkstack.apishim.ConnectivityManagerShimImpl; 189 import com.android.networkstack.apishim.ConstantsShim; 190 import com.android.networkstack.apishim.NetworkInformationShimImpl; 191 import com.android.networkstack.apishim.common.ConnectivityManagerShim; 192 import com.android.testutils.CompatUtil; 193 import com.android.testutils.ConnectivityModuleTest; 194 import com.android.testutils.DevSdkIgnoreRule; 195 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; 196 import com.android.testutils.DeviceConfigRule; 197 import com.android.testutils.DeviceInfoUtils; 198 import com.android.testutils.DumpTestUtils; 199 import com.android.testutils.RecorderCallback.CallbackEntry; 200 import com.android.testutils.TestHttpServer; 201 import com.android.testutils.TestNetworkTracker; 202 import com.android.testutils.TestableNetworkCallback; 203 204 import junit.framework.AssertionFailedError; 205 206 import libcore.io.Streams; 207 208 import org.junit.After; 209 import org.junit.Before; 210 import org.junit.Rule; 211 import org.junit.Test; 212 import org.junit.runner.RunWith; 213 214 import java.io.FileDescriptor; 215 import java.io.IOException; 216 import java.io.InputStream; 217 import java.io.InputStreamReader; 218 import java.io.OutputStream; 219 import java.net.DatagramPacket; 220 import java.net.DatagramSocket; 221 import java.net.HttpURLConnection; 222 import java.net.Inet4Address; 223 import java.net.Inet6Address; 224 import java.net.InetAddress; 225 import java.net.InetSocketAddress; 226 import java.net.MalformedURLException; 227 import java.net.Socket; 228 import java.net.SocketException; 229 import java.net.URL; 230 import java.net.UnknownHostException; 231 import java.nio.charset.StandardCharsets; 232 import java.util.ArrayList; 233 import java.util.Collection; 234 import java.util.List; 235 import java.util.Objects; 236 import java.util.Random; 237 import java.util.Set; 238 import java.util.UUID; 239 import java.util.concurrent.CompletableFuture; 240 import java.util.concurrent.CountDownLatch; 241 import java.util.concurrent.Executor; 242 import java.util.concurrent.ExecutorService; 243 import java.util.concurrent.Executors; 244 import java.util.concurrent.LinkedBlockingQueue; 245 import java.util.concurrent.TimeUnit; 246 import java.util.concurrent.TimeoutException; 247 import java.util.concurrent.atomic.AtomicInteger; 248 import java.util.function.Supplier; 249 import java.util.regex.Matcher; 250 import java.util.regex.Pattern; 251 252 import fi.iki.elonen.NanoHTTPD.Method; 253 import fi.iki.elonen.NanoHTTPD.Response.IStatus; 254 import fi.iki.elonen.NanoHTTPD.Response.Status; 255 256 @RunWith(AndroidJUnit4.class) 257 public class ConnectivityManagerTest { 258 @Rule 259 public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule(); 260 261 @Rule 262 public final DeviceConfigRule mTestValidationConfigRule = new DeviceConfigRule( 263 5 /* retryCountBeforeSIfConfigChanged */); 264 265 private static final String TAG = ConnectivityManagerTest.class.getSimpleName(); 266 267 public static final int TYPE_MOBILE = ConnectivityManager.TYPE_MOBILE; 268 public static final int TYPE_WIFI = ConnectivityManager.TYPE_WIFI; 269 270 private static final int HOST_ADDRESS = 0x7f000001;// represent ip 127.0.0.1 271 private static final int KEEPALIVE_CALLBACK_TIMEOUT_MS = 2000; 272 private static final int INTERVAL_KEEPALIVE_RETRY_MS = 500; 273 private static final int MAX_KEEPALIVE_RETRY_COUNT = 3; 274 private static final int MIN_KEEPALIVE_INTERVAL = 10; 275 276 private static final int NETWORK_CALLBACK_TIMEOUT_MS = 30_000; 277 // Timeout for waiting network to be validated. Set the timeout to 30s, which is more than 278 // DNS timeout. 279 // TODO(b/252972908): reset the original timer when aosp/2188755 is ramped up. 280 private static final int LISTEN_ACTIVITY_TIMEOUT_MS = 30_000; 281 private static final int NO_CALLBACK_TIMEOUT_MS = 100; 282 private static final int NETWORK_REQUEST_TIMEOUT_MS = 3000; 283 private static final int SOCKET_TIMEOUT_MS = 100; 284 private static final int NUM_TRIES_MULTIPATH_PREF_CHECK = 20; 285 private static final long INTERVAL_MULTIPATH_PREF_CHECK_MS = 500; 286 // device could have only one interface: data, wifi. 287 private static final int MIN_NUM_NETWORK_TYPES = 1; 288 289 // Airplane Mode BroadcastReceiver Timeout 290 private static final long AIRPLANE_MODE_CHANGE_TIMEOUT_MS = 10_000L; 291 292 // Timeout for applying uids allowed on restricted networks 293 private static final long APPLYING_UIDS_ALLOWED_ON_RESTRICTED_NETWORKS_TIMEOUT_MS = 3_000L; 294 295 // Minimum supported keepalive counts for wifi and cellular. 296 public static final int MIN_SUPPORTED_CELLULAR_KEEPALIVE_COUNT = 1; 297 public static final int MIN_SUPPORTED_WIFI_KEEPALIVE_COUNT = 3; 298 299 private static final String NETWORK_METERED_MULTIPATH_PREFERENCE_RES_NAME = 300 "config_networkMeteredMultipathPreference"; 301 private static final String KEEPALIVE_ALLOWED_UNPRIVILEGED_RES_NAME = 302 "config_allowedUnprivilegedKeepalivePerUid"; 303 private static final String KEEPALIVE_RESERVED_PER_SLOT_RES_NAME = 304 "config_reservedPrivilegedKeepaliveSlots"; 305 private static final String TEST_RESTRICTED_NW_IFACE_NAME = "test-restricted-nw"; 306 307 private static final LinkAddress TEST_LINKADDR = new LinkAddress( 308 InetAddresses.parseNumericAddress("2001:db8::8"), 64); 309 310 private static final int AIRPLANE_MODE_OFF = 0; 311 private static final int AIRPLANE_MODE_ON = 1; 312 313 private static final String TEST_HTTPS_URL_PATH = "/https_path"; 314 private static final String TEST_HTTP_URL_PATH = "/http_path"; 315 private static final String LOCALHOST_HOSTNAME = "localhost"; 316 // Re-connecting to the AP, obtaining an IP address, revalidating can take a long time 317 private static final long WIFI_CONNECT_TIMEOUT_MS = 60_000L; 318 319 private Context mContext; 320 private Instrumentation mInstrumentation; 321 private ConnectivityManager mCm; 322 private ConnectivityManagerShim mCmShim; 323 private WifiManager mWifiManager; 324 private PackageManager mPackageManager; 325 private TelephonyManager mTm; 326 private final ArraySet<Integer> mNetworkTypes = new ArraySet<>(); 327 private UiAutomation mUiAutomation; 328 private CtsNetUtils mCtsNetUtils; 329 // The registered callbacks. 330 private List<NetworkCallback> mRegisteredCallbacks = new ArrayList<>(); 331 // Used for cleanup purposes. 332 private final List<Range<Integer>> mVpnRequiredUidRanges = new ArrayList<>(); 333 334 private final TestHttpServer mHttpServer = new TestHttpServer(LOCALHOST_HOSTNAME); 335 336 @Before setUp()337 public void setUp() throws Exception { 338 mInstrumentation = InstrumentationRegistry.getInstrumentation(); 339 mContext = mInstrumentation.getContext(); 340 mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 341 mCmShim = ConnectivityManagerShimImpl.newInstance(mContext); 342 mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); 343 mPackageManager = mContext.getPackageManager(); 344 mCtsNetUtils = new CtsNetUtils(mContext); 345 mTm = mContext.getSystemService(TelephonyManager.class); 346 347 if (isAtLeastS()) { 348 addSupportedNetworkTypes(); 349 } else { 350 addLegacySupportedNetworkTypes(); 351 } 352 353 mUiAutomation = mInstrumentation.getUiAutomation(); 354 355 assertNotNull("CTS requires a working Internet connection", mCm.getActiveNetwork()); 356 } 357 addLegacySupportedNetworkTypes()358 private void addLegacySupportedNetworkTypes() { 359 // Network type support as expected for android R- 360 // Get com.android.internal.R.array.networkAttributes 361 int resId = mContext.getResources().getIdentifier("networkAttributes", "array", "android"); 362 String[] naStrings = mContext.getResources().getStringArray(resId); 363 boolean wifiOnly = mPackageManager.hasSystemFeature(FEATURE_WIFI) 364 && !mPackageManager.hasSystemFeature(FEATURE_TELEPHONY); 365 for (String naString : naStrings) { 366 try { 367 final String[] splitConfig = naString.split(","); 368 // Format was name,type,radio,priority,restoreTime,dependencyMet 369 final int type = Integer.parseInt(splitConfig[1]); 370 if (wifiOnly && ConnectivityManager.isNetworkTypeMobile(type)) { 371 continue; 372 } 373 mNetworkTypes.add(type); 374 } catch (Exception e) {} 375 } 376 } 377 addSupportedNetworkTypes()378 private void addSupportedNetworkTypes() { 379 final PackageManager pm = mContext.getPackageManager(); 380 if (pm.hasSystemFeature(FEATURE_WIFI)) { 381 mNetworkTypes.add(TYPE_WIFI); 382 } 383 if (pm.hasSystemFeature(FEATURE_WIFI_DIRECT)) { 384 mNetworkTypes.add(TYPE_WIFI_P2P); 385 } 386 if (mContext.getSystemService(TelephonyManager.class).isDataCapable()) { 387 mNetworkTypes.add(TYPE_MOBILE); 388 mNetworkTypes.add(TYPE_MOBILE_MMS); 389 mNetworkTypes.add(TYPE_MOBILE_SUPL); 390 mNetworkTypes.add(TYPE_MOBILE_DUN); 391 mNetworkTypes.add(TYPE_MOBILE_HIPRI); 392 mNetworkTypes.add(TYPE_MOBILE_FOTA); 393 mNetworkTypes.add(TYPE_MOBILE_IMS); 394 mNetworkTypes.add(TYPE_MOBILE_CBS); 395 mNetworkTypes.add(TYPE_MOBILE_IA); 396 mNetworkTypes.add(TYPE_MOBILE_EMERGENCY); 397 } 398 if (pm.hasSystemFeature(FEATURE_BLUETOOTH)) { 399 mNetworkTypes.add(TYPE_BLUETOOTH); 400 } 401 if (pm.hasSystemFeature(FEATURE_WATCH)) { 402 mNetworkTypes.add(TYPE_PROXY); 403 } 404 if (mContext.getSystemService(Context.ETHERNET_SERVICE) != null) { 405 mNetworkTypes.add(TYPE_ETHERNET); 406 } 407 mNetworkTypes.add(TYPE_VPN); 408 } 409 410 @After tearDown()411 public void tearDown() throws Exception { 412 // Release any NetworkRequests filed to connect mobile data. 413 if (mCtsNetUtils.cellConnectAttempted()) { 414 mCtsNetUtils.disconnectFromCell(); 415 } 416 417 if (TestUtils.shouldTestSApis()) { 418 runWithShellPermissionIdentity( 419 () -> mCmShim.setRequireVpnForUids(false, mVpnRequiredUidRanges), 420 NETWORK_SETTINGS); 421 } 422 423 // All tests in this class require a working Internet connection as they start. Make 424 // sure there is still one as they end that's ready to use for the next test to use. 425 mTestValidationConfigRule.runAfterNextCleanup(() -> { 426 final TestNetworkCallback callback = new TestNetworkCallback(); 427 registerDefaultNetworkCallback(callback); 428 try { 429 assertNotNull("Couldn't restore Internet connectivity", 430 callback.waitForAvailable()); 431 } finally { 432 // Unregister all registered callbacks. 433 unregisterRegisteredCallbacks(); 434 } 435 }); 436 } 437 438 @Test testIsNetworkTypeValid()439 public void testIsNetworkTypeValid() { 440 assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE)); 441 assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_WIFI)); 442 assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_MMS)); 443 assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_SUPL)); 444 assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_DUN)); 445 assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_HIPRI)); 446 assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_WIMAX)); 447 assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_BLUETOOTH)); 448 assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_DUMMY)); 449 assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_ETHERNET)); 450 assertTrue(mCm.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_FOTA)); 451 assertTrue(mCm.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_IMS)); 452 assertTrue(mCm.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_CBS)); 453 assertTrue(mCm.isNetworkTypeValid(ConnectivityManager.TYPE_WIFI_P2P)); 454 assertTrue(mCm.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_IA)); 455 assertFalse(mCm.isNetworkTypeValid(-1)); 456 assertTrue(mCm.isNetworkTypeValid(0)); 457 assertTrue(mCm.isNetworkTypeValid(ConnectivityManager.MAX_NETWORK_TYPE)); 458 assertFalse(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.MAX_NETWORK_TYPE+1)); 459 460 NetworkInfo[] ni = mCm.getAllNetworkInfo(); 461 462 for (NetworkInfo n: ni) { 463 assertTrue(ConnectivityManager.isNetworkTypeValid(n.getType())); 464 } 465 466 } 467 468 @Test testSetNetworkPreference()469 public void testSetNetworkPreference() { 470 // getNetworkPreference() and setNetworkPreference() are both deprecated so they do 471 // not preform any action. Verify they are at least still callable. 472 mCm.setNetworkPreference(mCm.getNetworkPreference()); 473 } 474 475 @Test testGetActiveNetworkInfo()476 public void testGetActiveNetworkInfo() { 477 NetworkInfo ni = mCm.getActiveNetworkInfo(); 478 479 assertNotNull("You must have an active network connection to complete CTS", ni); 480 assertTrue(ConnectivityManager.isNetworkTypeValid(ni.getType())); 481 assertTrue(ni.getState() == State.CONNECTED); 482 } 483 484 @Test testGetActiveNetwork()485 public void testGetActiveNetwork() { 486 Network network = mCm.getActiveNetwork(); 487 assertNotNull("You must have an active network connection to complete CTS", network); 488 489 NetworkInfo ni = mCm.getNetworkInfo(network); 490 assertNotNull("Network returned from getActiveNetwork was invalid", ni); 491 492 // Similar to testGetActiveNetworkInfo above. 493 assertTrue(ConnectivityManager.isNetworkTypeValid(ni.getType())); 494 assertTrue(ni.getState() == State.CONNECTED); 495 } 496 497 @Test testGetNetworkInfo()498 public void testGetNetworkInfo() { 499 for (int type = -1; type <= ConnectivityManager.MAX_NETWORK_TYPE+1; type++) { 500 if (shouldBeSupported(type)) { 501 NetworkInfo ni = mCm.getNetworkInfo(type); 502 assertTrue("Info shouldn't be null for " + type, ni != null); 503 State state = ni.getState(); 504 assertTrue("Bad state for " + type, State.UNKNOWN.ordinal() >= state.ordinal() 505 && state.ordinal() >= State.CONNECTING.ordinal()); 506 DetailedState ds = ni.getDetailedState(); 507 assertTrue("Bad detailed state for " + type, 508 DetailedState.FAILED.ordinal() >= ds.ordinal() 509 && ds.ordinal() >= DetailedState.IDLE.ordinal()); 510 } else { 511 assertNull("Info should be null for " + type, mCm.getNetworkInfo(type)); 512 } 513 } 514 } 515 516 @Test testGetAllNetworkInfo()517 public void testGetAllNetworkInfo() { 518 NetworkInfo[] ni = mCm.getAllNetworkInfo(); 519 assertTrue(ni.length >= MIN_NUM_NETWORK_TYPES); 520 for (int type = 0; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) { 521 int desiredFoundCount = (shouldBeSupported(type) ? 1 : 0); 522 int foundCount = 0; 523 for (NetworkInfo i : ni) { 524 if (i.getType() == type) foundCount++; 525 } 526 if (foundCount != desiredFoundCount) { 527 Log.e(TAG, "failure in testGetAllNetworkInfo. Dump of returned NetworkInfos:"); 528 for (NetworkInfo networkInfo : ni) Log.e(TAG, " " + networkInfo); 529 } 530 assertTrue("Unexpected foundCount of " + foundCount + " for type " + type, 531 foundCount == desiredFoundCount); 532 } 533 } 534 getSubscriberIdForCellNetwork(Network cellNetwork)535 private String getSubscriberIdForCellNetwork(Network cellNetwork) { 536 final NetworkCapabilities cellCaps = mCm.getNetworkCapabilities(cellNetwork); 537 final NetworkSpecifier specifier = cellCaps.getNetworkSpecifier(); 538 assertTrue(specifier instanceof TelephonyNetworkSpecifier); 539 // Get subscription from Telephony network specifier. 540 final int subId = ((TelephonyNetworkSpecifier) specifier).getSubscriptionId(); 541 assertNotEquals(SubscriptionManager.INVALID_SUBSCRIPTION_ID, subId); 542 543 // Get subscriber Id from telephony manager. 544 final TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); 545 return runWithShellPermissionIdentity(() -> tm.getSubscriberId(subId), 546 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE); 547 } 548 549 @AppModeFull(reason = "Cannot request network in instant app mode") 550 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) 551 @Test testGetAllNetworkStateSnapshots()552 public void testGetAllNetworkStateSnapshots() 553 throws InterruptedException { 554 assumeTrue(mPackageManager.hasSystemFeature(FEATURE_TELEPHONY)); 555 // Make sure cell is active to retrieve IMSI for verification in later step. 556 final Network cellNetwork = mCtsNetUtils.connectToCell(); 557 final String subscriberId = getSubscriberIdForCellNetwork(cellNetwork); 558 assertFalse(TextUtils.isEmpty(subscriberId)); 559 560 // Verify the API cannot be called without proper permission. 561 assertThrows(SecurityException.class, () -> mCm.getAllNetworkStateSnapshots()); 562 563 // Get all networks, verify the result of getAllNetworkStateSnapshots matches the result 564 // got from other APIs. 565 final Network[] networks = mCm.getAllNetworks(); 566 assertGreaterOrEqual(networks.length, 1); 567 final TestableNetworkCallback allNetworkLinkPropertiesListener = 568 new TestableNetworkCallback(); 569 mCm.registerNetworkCallback(new NetworkRequest.Builder().clearCapabilities().build(), 570 allNetworkLinkPropertiesListener); 571 572 final List<NetworkStateSnapshot> snapshots = runWithShellPermissionIdentity( 573 () -> mCm.getAllNetworkStateSnapshots(), NETWORK_SETTINGS); 574 assertEquals(networks.length, snapshots.size()); 575 for (final Network network : networks) { 576 // Can't use a lambda because it will cause the test to crash on R with 577 // NoClassDefFoundError. 578 NetworkStateSnapshot snapshot = null; 579 for (NetworkStateSnapshot item : snapshots) { 580 if (item.getNetwork().equals(network)) { 581 snapshot = item; 582 break; 583 } 584 } 585 assertNotNull(snapshot); 586 final NetworkCapabilities caps = 587 Objects.requireNonNull(mCm.getNetworkCapabilities(network)); 588 // Redact specifier of the capabilities of the snapshot before comparing since 589 // the result returned from getNetworkCapabilities always get redacted. 590 final NetworkSpecifier snapshotCapSpecifier = 591 snapshot.getNetworkCapabilities().getNetworkSpecifier(); 592 final NetworkSpecifier redactedSnapshotCapSpecifier = 593 snapshotCapSpecifier == null ? null : snapshotCapSpecifier.redact(); 594 assertEquals("", caps.describeImmutableDifferences( 595 snapshot.getNetworkCapabilities() 596 .setNetworkSpecifier(redactedSnapshotCapSpecifier))); 597 598 // Don't check that the mutable fields are the same with synchronous calls, as 599 // the device may add or remove content of these fields in the middle of the test. 600 // Instead, search the target LinkProperties from received LinkPropertiesChanged 601 // callbacks. This is guaranteed to succeed because the callback is registered 602 // before getAllNetworkStateSnapshots is called. 603 final LinkProperties lpFromSnapshot = snapshot.getLinkProperties(); 604 allNetworkLinkPropertiesListener.eventuallyExpect(CallbackEntry.LINK_PROPERTIES_CHANGED, 605 NETWORK_CALLBACK_TIMEOUT_MS, 0 /* mark */, entry -> 606 entry.getNetwork().equals(network) 607 && entry.getLp().equals(lpFromSnapshot)); 608 609 assertEquals(mCm.getNetworkInfo(network).getType(), snapshot.getLegacyType()); 610 611 if (network.equals(cellNetwork)) { 612 assertEquals(subscriberId, snapshot.getSubscriberId()); 613 } 614 } 615 } 616 checkPermission(String perm, int uid)617 private boolean checkPermission(String perm, int uid) { 618 return mContext.checkPermission(perm, -1 /* pid */, uid) == PERMISSION_GRANTED; 619 } 620 findPackageByPermissions(@onNull List<String> requiredPermissions, @NonNull List<String> forbiddenPermissions)621 private String findPackageByPermissions(@NonNull List<String> requiredPermissions, 622 @NonNull List<String> forbiddenPermissions) throws Exception { 623 final List<PackageInfo> packageInfos = 624 mPackageManager.getInstalledPackages(GET_PERMISSIONS); 625 for (PackageInfo packageInfo : packageInfos) { 626 final int uid = mPackageManager.getPackageUid(packageInfo.packageName, 0 /* flags */); 627 if (!CollectionUtils.all(requiredPermissions, perm -> checkPermission(perm, uid))) { 628 continue; 629 } 630 if (CollectionUtils.any(forbiddenPermissions, perm -> checkPermission(perm, uid))) { 631 continue; 632 } 633 634 return packageInfo.packageName; 635 } 636 return null; 637 } 638 639 @DevSdkIgnoreRule.IgnoreUpTo(SC_V2) 640 @AppModeFull(reason = "Cannot get installed packages in instant app mode") 641 @Test testGetRedactedLinkPropertiesForPackage()642 public void testGetRedactedLinkPropertiesForPackage() throws Exception { 643 final String groundedPkg = findPackageByPermissions( 644 List.of(), /* requiredPermissions */ 645 List.of(ACCESS_NETWORK_STATE) /* forbiddenPermissions */); 646 assertNotNull("Couldn't find any package without ACCESS_NETWORK_STATE", groundedPkg); 647 final int groundedUid = mPackageManager.getPackageUid(groundedPkg, 0 /* flags */); 648 649 final String normalPkg = findPackageByPermissions( 650 List.of(ACCESS_NETWORK_STATE) /* requiredPermissions */, 651 List.of(NETWORK_SETTINGS, NETWORK_STACK, 652 PERMISSION_MAINLINE_NETWORK_STACK) /* forbiddenPermissions */); 653 assertNotNull("Couldn't find any package with ACCESS_NETWORK_STATE but" 654 + " without NETWORK_SETTINGS", normalPkg); 655 final int normalUid = mPackageManager.getPackageUid(normalPkg, 0 /* flags */); 656 657 // There are some privileged packages on the system, like the phone process, the network 658 // stack and the system server. 659 final String privilegedPkg = findPackageByPermissions( 660 List.of(ACCESS_NETWORK_STATE, NETWORK_SETTINGS), /* requiredPermissions */ 661 List.of() /* forbiddenPermissions */); 662 assertNotNull("Couldn't find a package with sufficient permissions", privilegedPkg); 663 final int privilegedUid = mPackageManager.getPackageUid(privilegedPkg, 0); 664 665 // Set parcelSensitiveFields to true to preserve CaptivePortalApiUrl & CaptivePortalData 666 // when parceling. 667 final LinkProperties lp = new LinkProperties(new LinkProperties(), 668 true /* parcelSensitiveFields */); 669 final Uri capportUrl = Uri.parse("https://capport.example.com/api"); 670 final CaptivePortalData capportData = new CaptivePortalData.Builder().build(); 671 final int mtu = 12345; 672 lp.setMtu(mtu); 673 lp.setCaptivePortalApiUrl(capportUrl); 674 lp.setCaptivePortalData(capportData); 675 676 // No matter what the given uid is, a SecurityException will be thrown if the caller 677 // doesn't hold the NETWORK_SETTINGS permission. 678 assertThrows(SecurityException.class, 679 () -> mCm.getRedactedLinkPropertiesForPackage(lp, groundedUid, groundedPkg)); 680 assertThrows(SecurityException.class, 681 () -> mCm.getRedactedLinkPropertiesForPackage(lp, normalUid, normalPkg)); 682 assertThrows(SecurityException.class, 683 () -> mCm.getRedactedLinkPropertiesForPackage(lp, privilegedUid, privilegedPkg)); 684 685 runAsShell(NETWORK_SETTINGS, () -> { 686 // No matter what the given uid is, if the given LinkProperties is null, then 687 // NullPointerException will be thrown. 688 assertThrows(NullPointerException.class, 689 () -> mCm.getRedactedLinkPropertiesForPackage(null, groundedUid, groundedPkg)); 690 assertThrows(NullPointerException.class, 691 () -> mCm.getRedactedLinkPropertiesForPackage(null, normalUid, normalPkg)); 692 assertThrows(NullPointerException.class, 693 () -> mCm.getRedactedLinkPropertiesForPackage( 694 null, privilegedUid, privilegedPkg)); 695 696 // Make sure null is returned for a UID without ACCESS_NETWORK_STATE. 697 assertNull(mCm.getRedactedLinkPropertiesForPackage(lp, groundedUid, groundedPkg)); 698 699 // CaptivePortalApiUrl & CaptivePortalData will be set to null if given uid doesn't hold 700 // the NETWORK_SETTINGS permission. 701 assertNull(mCm.getRedactedLinkPropertiesForPackage(lp, normalUid, normalPkg) 702 .getCaptivePortalApiUrl()); 703 assertNull(mCm.getRedactedLinkPropertiesForPackage(lp, normalUid, normalPkg) 704 .getCaptivePortalData()); 705 // MTU is not sensitive and is not redacted. 706 assertEquals(mtu, mCm.getRedactedLinkPropertiesForPackage(lp, normalUid, normalPkg) 707 .getMtu()); 708 709 // CaptivePortalApiUrl & CaptivePortalData will be preserved if the given uid holds the 710 // NETWORK_SETTINGS permission. 711 assertNotNull(lp.getCaptivePortalApiUrl()); 712 assertNotNull(lp.getCaptivePortalData()); 713 assertEquals(lp.getCaptivePortalApiUrl(), 714 mCm.getRedactedLinkPropertiesForPackage(lp, privilegedUid, privilegedPkg) 715 .getCaptivePortalApiUrl()); 716 assertEquals(lp.getCaptivePortalData(), 717 mCm.getRedactedLinkPropertiesForPackage(lp, privilegedUid, privilegedPkg) 718 .getCaptivePortalData()); 719 }); 720 } 721 redactNc(@onNull final NetworkCapabilities nc, int uid, @NonNull String packageName)722 private NetworkCapabilities redactNc(@NonNull final NetworkCapabilities nc, int uid, 723 @NonNull String packageName) { 724 return mCm.getRedactedNetworkCapabilitiesForPackage(nc, uid, packageName); 725 } 726 727 @DevSdkIgnoreRule.IgnoreUpTo(SC_V2) 728 @AppModeFull(reason = "Cannot get installed packages in instant app mode") 729 @Test testGetRedactedNetworkCapabilitiesForPackage()730 public void testGetRedactedNetworkCapabilitiesForPackage() throws Exception { 731 final String groundedPkg = findPackageByPermissions( 732 List.of(), /* requiredPermissions */ 733 List.of(ACCESS_NETWORK_STATE) /* forbiddenPermissions */); 734 assertNotNull("Couldn't find any package without ACCESS_NETWORK_STATE", groundedPkg); 735 final int groundedUid = mPackageManager.getPackageUid(groundedPkg, 0 /* flags */); 736 737 // A package which doesn't have any of the permissions below, but has NETWORK_STATE. 738 // There should be a number of packages like this on the device; AOSP has many, 739 // including contacts, webview, the keyboard, pacprocessor, messaging. 740 final String normalPkg = findPackageByPermissions( 741 List.of(ACCESS_NETWORK_STATE) /* requiredPermissions */, 742 List.of(NETWORK_SETTINGS, NETWORK_FACTORY, NETWORK_SETUP_WIZARD, 743 NETWORK_STACK, PERMISSION_MAINLINE_NETWORK_STACK, 744 ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION) /* forbiddenPermissions */); 745 assertNotNull("Can't find a package with ACCESS_NETWORK_STATE but without any of" 746 + " the forbidden permissions", normalPkg); 747 final int normalUid = mPackageManager.getPackageUid(normalPkg, 0 /* flags */); 748 749 // There are some privileged packages on the system, like the phone process, the network 750 // stack and the system server. 751 final String privilegedPkg = findPackageByPermissions( 752 List.of(ACCESS_NETWORK_STATE, NETWORK_SETTINGS, NETWORK_FACTORY, 753 ACCESS_FINE_LOCATION), /* requiredPermissions */ 754 List.of() /* forbiddenPermissions */); 755 assertNotNull("Couldn't find a package with sufficient permissions", privilegedPkg); 756 final int privilegedUid = mPackageManager.getPackageUid(privilegedPkg, 0); 757 758 final Set<Range<Integer>> uids = new ArraySet<>(); 759 uids.add(new Range<>(10000, 10100)); 760 uids.add(new Range<>(10200, 10300)); 761 final String ssid = "My-WiFi"; 762 // This test will set underlying networks in the capabilities to redact to see if they 763 // are appropriately redacted, so fetch the default network to put in there as an example. 764 final Network defaultNetwork = mCm.getActiveNetwork(); 765 assertNotNull("CTS requires a working Internet connection", defaultNetwork); 766 final int subId1 = 1; 767 final int subId2 = 2; 768 final int[] administratorUids = {normalUid}; 769 final String bssid = "location sensitive"; 770 final int rssi = 43; // not location sensitive 771 final WifiInfo wifiInfo = new WifiInfo.Builder() 772 .setBssid(bssid) 773 .setRssi(rssi) 774 .build(); 775 final NetworkCapabilities nc = new NetworkCapabilities.Builder() 776 .setUids(uids) 777 .setSsid(ssid) 778 .setUnderlyingNetworks(List.of(defaultNetwork)) 779 .setSubscriptionIds(Set.of(subId1, subId2)) 780 .setAdministratorUids(administratorUids) 781 .setOwnerUid(normalUid) 782 .setTransportInfo(wifiInfo) 783 .build(); 784 785 // No matter what the given uid is, a SecurityException will be thrown if the caller 786 // doesn't hold the NETWORK_SETTINGS permission. 787 assertThrows(SecurityException.class, () -> redactNc(nc, groundedUid, groundedPkg)); 788 assertThrows(SecurityException.class, () -> redactNc(nc, normalUid, normalPkg)); 789 assertThrows(SecurityException.class, () -> redactNc(nc, privilegedUid, privilegedPkg)); 790 791 runAsShell(NETWORK_SETTINGS, () -> { 792 // Make sure that the NC is null if the package doesn't hold ACCESS_NETWORK_STATE. 793 assertNull(redactNc(nc, groundedUid, groundedPkg)); 794 795 // Uids, ssid, underlying networks & subscriptionIds will be redacted if the given uid 796 // doesn't hold the associated permissions. The wifi transport info is also suitably 797 // redacted. 798 final NetworkCapabilities redactedNormal = redactNc(nc, normalUid, normalPkg); 799 assertNull(redactedNormal.getUids()); 800 assertNull(redactedNormal.getSsid()); 801 assertNull(redactedNormal.getUnderlyingNetworks()); 802 assertEquals(0, redactedNormal.getSubscriptionIds().size()); 803 assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, 804 ((WifiInfo) redactedNormal.getTransportInfo()).getBSSID()); 805 assertEquals(rssi, ((WifiInfo) redactedNormal.getTransportInfo()).getRssi()); 806 807 // Uids, ssid, underlying networks & subscriptionIds will be preserved if the given uid 808 // holds the associated permissions. 809 final NetworkCapabilities redactedPrivileged = 810 redactNc(nc, privilegedUid, privilegedPkg); 811 assertEquals(uids, redactedPrivileged.getUids()); 812 assertEquals(ssid, redactedPrivileged.getSsid()); 813 assertEquals(List.of(defaultNetwork), redactedPrivileged.getUnderlyingNetworks()); 814 assertEquals(Set.of(subId1, subId2), redactedPrivileged.getSubscriptionIds()); 815 assertEquals(bssid, ((WifiInfo) redactedPrivileged.getTransportInfo()).getBSSID()); 816 assertEquals(rssi, ((WifiInfo) redactedPrivileged.getTransportInfo()).getRssi()); 817 818 // The owner uid is only preserved when the network is a VPN and the uid is the 819 // same as the owner uid. 820 nc.addTransportType(TRANSPORT_VPN); 821 assertEquals(normalUid, redactNc(nc, normalUid, normalPkg).getOwnerUid()); 822 assertEquals(INVALID_UID, redactNc(nc, privilegedUid, privilegedPkg).getOwnerUid()); 823 nc.removeTransportType(TRANSPORT_VPN); 824 825 // If the given uid doesn't hold location permissions, the owner uid will be set to 826 // INVALID_UID even when sent to that UID (this avoids a wifi suggestor knowing where 827 // the device is by virtue of the device connecting to its own network). 828 assertEquals(INVALID_UID, redactNc(nc, normalUid, normalPkg).getOwnerUid()); 829 830 // If the given uid holds location permissions, the owner uid is preserved. This works 831 // because the shell holds ACCESS_FINE_LOCATION. 832 final int[] administratorUids2 = { privilegedUid }; 833 nc.setAdministratorUids(administratorUids2); 834 nc.setOwnerUid(privilegedUid); 835 assertEquals(privilegedUid, redactNc(nc, privilegedUid, privilegedPkg).getOwnerUid()); 836 }); 837 } 838 839 /** 840 * Tests that connections can be opened on WiFi and cellphone networks, 841 * and that they are made from different IP addresses. 842 */ 843 @AppModeFull(reason = "Cannot get WifiManager in instant app mode") 844 @Test 845 @RequiresDevice // Virtual devices use a single internet connection for all networks testOpenConnection()846 public void testOpenConnection() throws Exception { 847 assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI)); 848 assumeTrue(mPackageManager.hasSystemFeature(FEATURE_TELEPHONY)); 849 850 Network wifiNetwork = mCtsNetUtils.connectToWifi(); 851 Network cellNetwork = mCtsNetUtils.connectToCell(); 852 // This server returns the requestor's IP address as the response body. 853 URL url = new URL("http://google-ipv6test.appspot.com/ip.js?fmt=text"); 854 String wifiAddressString = httpGet(wifiNetwork, url); 855 String cellAddressString = httpGet(cellNetwork, url); 856 857 assertFalse(String.format("Same address '%s' on two different networks (%s, %s)", 858 wifiAddressString, wifiNetwork, cellNetwork), 859 wifiAddressString.equals(cellAddressString)); 860 861 // Verify that the IP addresses that the requests appeared to come from are actually on the 862 // respective networks. 863 assertOnNetwork(wifiAddressString, wifiNetwork); 864 assertOnNetwork(cellAddressString, cellNetwork); 865 866 assertFalse("Unexpectedly equal: " + wifiNetwork, wifiNetwork.equals(cellNetwork)); 867 } 868 869 /** 870 * Performs a HTTP GET to the specified URL on the specified Network, and returns 871 * the response body decoded as UTF-8. 872 */ httpGet(Network network, URL httpUrl)873 private static String httpGet(Network network, URL httpUrl) throws IOException { 874 HttpURLConnection connection = (HttpURLConnection) network.openConnection(httpUrl); 875 try { 876 InputStream inputStream = connection.getInputStream(); 877 return Streams.readFully(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); 878 } finally { 879 connection.disconnect(); 880 } 881 } 882 assertOnNetwork(String adressString, Network network)883 private void assertOnNetwork(String adressString, Network network) throws UnknownHostException { 884 InetAddress address = InetAddress.getByName(adressString); 885 LinkProperties linkProperties = mCm.getLinkProperties(network); 886 // To make sure that the request went out on the right network, check that 887 // the IP address seen by the server is assigned to the expected network. 888 // We can only do this for IPv6 addresses, because in IPv4 we will likely 889 // have a private IPv4 address, and that won't match what the server sees. 890 if (address instanceof Inet6Address) { 891 assertContains(linkProperties.getAddresses(), address); 892 } 893 } 894 assertContains(Collection<T> collection, T element)895 private static<T> void assertContains(Collection<T> collection, T element) { 896 assertTrue(element + " not found in " + collection, collection.contains(element)); 897 } 898 assertStartUsingNetworkFeatureUnsupported(int networkType, String feature)899 private void assertStartUsingNetworkFeatureUnsupported(int networkType, String feature) { 900 try { 901 mCm.startUsingNetworkFeature(networkType, feature); 902 fail("startUsingNetworkFeature is no longer supported in the current API version"); 903 } catch (UnsupportedOperationException expected) {} 904 } 905 assertStopUsingNetworkFeatureUnsupported(int networkType, String feature)906 private void assertStopUsingNetworkFeatureUnsupported(int networkType, String feature) { 907 try { 908 mCm.startUsingNetworkFeature(networkType, feature); 909 fail("stopUsingNetworkFeature is no longer supported in the current API version"); 910 } catch (UnsupportedOperationException expected) {} 911 } 912 assertRequestRouteToHostUnsupported(int networkType, int hostAddress)913 private void assertRequestRouteToHostUnsupported(int networkType, int hostAddress) { 914 try { 915 mCm.requestRouteToHost(networkType, hostAddress); 916 fail("requestRouteToHost is no longer supported in the current API version"); 917 } catch (UnsupportedOperationException expected) {} 918 } 919 920 @Test testStartUsingNetworkFeature()921 public void testStartUsingNetworkFeature() { 922 923 final String invalidateFeature = "invalidateFeature"; 924 final String mmsFeature = "enableMMS"; 925 926 assertStartUsingNetworkFeatureUnsupported(TYPE_MOBILE, invalidateFeature); 927 assertStopUsingNetworkFeatureUnsupported(TYPE_MOBILE, invalidateFeature); 928 assertStartUsingNetworkFeatureUnsupported(TYPE_WIFI, mmsFeature); 929 } 930 shouldEthernetBeSupported()931 private boolean shouldEthernetBeSupported() { 932 // Instant mode apps aren't allowed to query the Ethernet service due to selinux policies. 933 // When in instant mode, don't fail if the Ethernet service is available. Instead, rely on 934 // the fact that Ethernet should be supported if the device has a hardware Ethernet port, or 935 // if the device can be a USB host and thus can use USB Ethernet adapters. 936 // 937 // Note that this test this will still fail in instant mode if a device supports Ethernet 938 // via other hardware means. We are not currently aware of any such device. 939 return hasEthernetService() 940 || mPackageManager.hasSystemFeature(FEATURE_ETHERNET) 941 || mPackageManager.hasSystemFeature(FEATURE_USB_HOST); 942 } 943 hasEthernetService()944 private boolean hasEthernetService() { 945 // On Q creating EthernetManager from a thread that does not have a looper (like the test 946 // thread) crashes because it tried to use Looper.myLooper() through the default Handler 947 // constructor to run onAvailabilityChanged callbacks. Use ServiceManager to check whether 948 // the service exists instead. 949 // TODO: remove once Q is no longer supported in MTS, as ServiceManager is hidden API 950 if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) { 951 return ServiceManager.getService(Context.ETHERNET_SERVICE) != null; 952 } 953 return mContext.getSystemService(Context.ETHERNET_SERVICE) != null; 954 } 955 shouldBeSupported(int networkType)956 private boolean shouldBeSupported(int networkType) { 957 return mNetworkTypes.contains(networkType) 958 || (networkType == ConnectivityManager.TYPE_VPN) 959 || (networkType == ConnectivityManager.TYPE_ETHERNET && shouldEthernetBeSupported()); 960 } 961 962 @Test testIsNetworkSupported()963 public void testIsNetworkSupported() { 964 for (int type = -1; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) { 965 boolean supported = mCm.isNetworkSupported(type); 966 if (shouldBeSupported(type)) { 967 assertTrue("Network type " + type + " should be supported", supported); 968 } else { 969 assertFalse("Network type " + type + " should not be supported", supported); 970 } 971 } 972 } 973 974 @Test testRequestRouteToHost()975 public void testRequestRouteToHost() { 976 for (int type = -1 ; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) { 977 assertRequestRouteToHostUnsupported(type, HOST_ADDRESS); 978 } 979 } 980 981 @Test testTest()982 public void testTest() { 983 mCm.getBackgroundDataSetting(); 984 } 985 makeDefaultRequest()986 private NetworkRequest makeDefaultRequest() { 987 // Make a request that is similar to the way framework tracks the system 988 // default network. 989 return new NetworkRequest.Builder() 990 .clearCapabilities() 991 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) 992 .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) 993 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) 994 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) 995 .build(); 996 } 997 makeWifiNetworkRequest()998 private NetworkRequest makeWifiNetworkRequest() { 999 return new NetworkRequest.Builder() 1000 .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) 1001 .addCapability(NET_CAPABILITY_INTERNET) 1002 .build(); 1003 } 1004 makeCellNetworkRequest()1005 private NetworkRequest makeCellNetworkRequest() { 1006 return new NetworkRequest.Builder() 1007 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) 1008 .addCapability(NET_CAPABILITY_INTERNET) 1009 .build(); 1010 } 1011 hasPrivateDnsValidated(CallbackEntry entry, Network networkForPrivateDns)1012 private boolean hasPrivateDnsValidated(CallbackEntry entry, Network networkForPrivateDns) { 1013 if (!networkForPrivateDns.equals(entry.getNetwork())) return false; 1014 final NetworkCapabilities nc = ((CallbackEntry.CapabilitiesChanged) entry).getCaps(); 1015 return !nc.isPrivateDnsBroken() && nc.hasCapability(NET_CAPABILITY_VALIDATED); 1016 } 1017 1018 @AppModeFull(reason = "WRITE_SECURE_SETTINGS permission can't be granted to instant apps") 1019 @Test @IgnoreUpTo(Build.VERSION_CODES.Q) testIsPrivateDnsBroken()1020 public void testIsPrivateDnsBroken() throws InterruptedException { 1021 final String invalidPrivateDnsServer = "invalidhostname.example.com"; 1022 final String goodPrivateDnsServer = "dns.google"; 1023 mCtsNetUtils.storePrivateDnsSetting(); 1024 final TestableNetworkCallback cb = new TestableNetworkCallback(); 1025 registerNetworkCallback(makeWifiNetworkRequest(), cb); 1026 try { 1027 // Verifying the good private DNS sever 1028 mCtsNetUtils.setPrivateDnsStrictMode(goodPrivateDnsServer); 1029 final Network networkForPrivateDns = mCtsNetUtils.ensureWifiConnected(); 1030 cb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED, NETWORK_CALLBACK_TIMEOUT_MS, 1031 entry -> hasPrivateDnsValidated(entry, networkForPrivateDns)); 1032 1033 // Verifying the broken private DNS sever 1034 mCtsNetUtils.setPrivateDnsStrictMode(invalidPrivateDnsServer); 1035 cb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED, NETWORK_CALLBACK_TIMEOUT_MS, 1036 entry -> (((CallbackEntry.CapabilitiesChanged) entry).getCaps() 1037 .isPrivateDnsBroken()) && networkForPrivateDns.equals(entry.getNetwork())); 1038 } finally { 1039 mCtsNetUtils.restorePrivateDnsSetting(); 1040 // Toggle wifi to make sure it is re-validated 1041 reconnectWifi(); 1042 } 1043 } 1044 1045 /** 1046 * Exercises both registerNetworkCallback and unregisterNetworkCallback. This checks to 1047 * see if we get a callback for the TRANSPORT_WIFI transport type being available. 1048 * 1049 * <p>In order to test that a NetworkCallback occurs, we need some change in the network 1050 * state (either a transport or capability is now available). The most straightforward is 1051 * WiFi. We could add a version that uses the telephony data connection but it's not clear 1052 * that it would increase test coverage by much (how many devices have 3G radio but not Wifi?). 1053 */ 1054 @AppModeFull(reason = "Cannot get WifiManager in instant app mode") 1055 @Test testRegisterNetworkCallback()1056 public void testRegisterNetworkCallback() throws Exception { 1057 assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI)); 1058 1059 // We will register for a WIFI network being available or lost. 1060 final TestNetworkCallback callback = new TestNetworkCallback(); 1061 registerNetworkCallback(makeWifiNetworkRequest(), callback); 1062 1063 final TestNetworkCallback defaultTrackingCallback = new TestNetworkCallback(); 1064 registerDefaultNetworkCallback(defaultTrackingCallback); 1065 1066 final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback(); 1067 final TestNetworkCallback perUidCallback = new TestNetworkCallback(); 1068 final TestNetworkCallback bestMatchingCallback = new TestNetworkCallback(); 1069 final Handler h = new Handler(Looper.getMainLooper()); 1070 if (TestUtils.shouldTestSApis()) { 1071 assertThrows(SecurityException.class, () -> 1072 registerSystemDefaultNetworkCallback(systemDefaultCallback, h)); 1073 runWithShellPermissionIdentity(() -> { 1074 registerSystemDefaultNetworkCallback(systemDefaultCallback, h); 1075 registerDefaultNetworkCallbackForUid(Process.myUid(), perUidCallback, h); 1076 }, NETWORK_SETTINGS); 1077 registerBestMatchingNetworkCallback(makeDefaultRequest(), bestMatchingCallback, h); 1078 } 1079 1080 Network wifiNetwork = null; 1081 mCtsNetUtils.ensureWifiConnected(); 1082 1083 // Now we should expect to get a network callback about availability of the wifi 1084 // network even if it was already connected as a state-based action when the callback 1085 // is registered. 1086 wifiNetwork = callback.waitForAvailable(); 1087 assertNotNull("Did not receive onAvailable for TRANSPORT_WIFI request", 1088 wifiNetwork); 1089 1090 final Network defaultNetwork = defaultTrackingCallback.waitForAvailable(); 1091 assertNotNull("Did not receive onAvailable on default network callback", 1092 defaultNetwork); 1093 1094 if (TestUtils.shouldTestSApis()) { 1095 assertNotNull("Did not receive onAvailable on system default network callback", 1096 systemDefaultCallback.waitForAvailable()); 1097 final Network perUidNetwork = perUidCallback.waitForAvailable(); 1098 assertNotNull("Did not receive onAvailable on per-UID default network callback", 1099 perUidNetwork); 1100 assertEquals(defaultNetwork, perUidNetwork); 1101 final Network bestMatchingNetwork = bestMatchingCallback.waitForAvailable(); 1102 assertNotNull("Did not receive onAvailable on best matching network callback", 1103 bestMatchingNetwork); 1104 assertEquals(defaultNetwork, bestMatchingNetwork); 1105 } 1106 } 1107 1108 @ConnectivityModuleTest 1109 @IgnoreUpTo(Build.VERSION_CODES.R) 1110 @Test testRegisterSystemDefaultNetworkCallbackPermission()1111 public void testRegisterSystemDefaultNetworkCallbackPermission() { 1112 final Handler h = new Handler(Looper.getMainLooper()); 1113 // Verify registerSystemDefaultNetworkCallback can be accessed via 1114 // CONNECTIVITY_USE_RESTRICTED_NETWORKS permission. 1115 runWithShellPermissionIdentity(() -> 1116 registerSystemDefaultNetworkCallback(new TestNetworkCallback(), h), 1117 CONNECTIVITY_USE_RESTRICTED_NETWORKS); 1118 } 1119 1120 /** 1121 * Tests both registerNetworkCallback and unregisterNetworkCallback similarly to 1122 * {@link #testRegisterNetworkCallback} except that a {@code PendingIntent} is used instead 1123 * of a {@code NetworkCallback}. 1124 */ 1125 @AppModeFull(reason = "Cannot get WifiManager in instant app mode") 1126 @Test testRegisterNetworkCallback_withPendingIntent()1127 public void testRegisterNetworkCallback_withPendingIntent() { 1128 assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI)); 1129 1130 // Create a ConnectivityActionReceiver that has an IntentFilter for our locally defined 1131 // action, NETWORK_CALLBACK_ACTION. 1132 final IntentFilter filter = new IntentFilter(); 1133 filter.addAction(NETWORK_CALLBACK_ACTION); 1134 1135 final ConnectivityActionReceiver receiver = new ConnectivityActionReceiver( 1136 mCm, ConnectivityManager.TYPE_WIFI, NetworkInfo.State.CONNECTED); 1137 final int flags = SdkLevel.isAtLeastT() ? RECEIVER_EXPORTED : 0; 1138 mContext.registerReceiver(receiver, filter, flags); 1139 1140 // Create a broadcast PendingIntent for NETWORK_CALLBACK_ACTION. 1141 final Intent intent = new Intent(NETWORK_CALLBACK_ACTION) 1142 .setPackage(mContext.getPackageName()); 1143 // While ConnectivityService would put extra info such as network or request id before 1144 // broadcasting the inner intent. The MUTABLE flag needs to be added accordingly. 1145 final PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0 /*requestCode*/, 1146 intent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE); 1147 1148 // We will register for a WIFI network being available or lost. 1149 mCm.registerNetworkCallback(makeWifiNetworkRequest(), pendingIntent); 1150 1151 try { 1152 mCtsNetUtils.ensureWifiConnected(); 1153 1154 // Now we expect to get the Intent delivered notifying of the availability of the wifi 1155 // network even if it was already connected as a state-based action when the callback 1156 // is registered. 1157 assertTrue("Did not receive expected Intent " + intent + " for TRANSPORT_WIFI", 1158 receiver.waitForState()); 1159 } catch (InterruptedException e) { 1160 fail("Broadcast receiver or NetworkCallback wait was interrupted."); 1161 } finally { 1162 mCm.unregisterNetworkCallback(pendingIntent); 1163 pendingIntent.cancel(); 1164 mContext.unregisterReceiver(receiver); 1165 } 1166 } 1167 runIdenticalPendingIntentsRequestTest(boolean useListen)1168 private void runIdenticalPendingIntentsRequestTest(boolean useListen) throws Exception { 1169 assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI)); 1170 1171 // Disconnect before registering callbacks, reconnect later to fire them 1172 mCtsNetUtils.ensureWifiDisconnected(null); 1173 1174 final NetworkRequest firstRequest = makeWifiNetworkRequest(); 1175 final NetworkRequest secondRequest = new NetworkRequest(firstRequest); 1176 // Will match wifi or test, since transports are ORed; but there should only be wifi 1177 secondRequest.networkCapabilities.addTransportType(TRANSPORT_TEST); 1178 1179 PendingIntent firstIntent = null; 1180 PendingIntent secondIntent = null; 1181 BroadcastReceiver receiver = null; 1182 1183 // Avoid receiving broadcasts from other runs by appending a timestamp 1184 final String broadcastAction = NETWORK_CALLBACK_ACTION + System.currentTimeMillis(); 1185 try { 1186 // Intent is mutable to receive EXTRA_NETWORK_REQUEST from ConnectivityService 1187 final String extraBoolKey = "extra_bool"; 1188 firstIntent = PendingIntent.getBroadcast(mContext, 1189 0 /* requestCode */, 1190 new Intent(broadcastAction).putExtra(extraBoolKey, false) 1191 .setPackage(mContext.getPackageName()), 1192 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE); 1193 1194 if (useListen) { 1195 mCm.registerNetworkCallback(firstRequest, firstIntent); 1196 } else { 1197 mCm.requestNetwork(firstRequest, firstIntent); 1198 } 1199 1200 // Second intent equals the first as per filterEquals (extras don't count), so first 1201 // intent will be updated with the new extras 1202 secondIntent = PendingIntent.getBroadcast(mContext, 1203 0 /* requestCode */, 1204 new Intent(broadcastAction).putExtra(extraBoolKey, true) 1205 .setPackage(mContext.getPackageName()), 1206 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE); 1207 1208 // Because secondIntent.intentFilterEquals the first, the request should be replaced 1209 if (useListen) { 1210 mCm.registerNetworkCallback(secondRequest, secondIntent); 1211 } else { 1212 mCm.requestNetwork(secondRequest, secondIntent); 1213 } 1214 1215 final IntentFilter filter = new IntentFilter(); 1216 filter.addAction(broadcastAction); 1217 1218 final CompletableFuture<Network> networkFuture = new CompletableFuture<>(); 1219 final AtomicInteger receivedCount = new AtomicInteger(0); 1220 receiver = new BroadcastReceiver() { 1221 @Override 1222 public void onReceive(Context context, Intent intent) { 1223 final NetworkRequest request = intent.getParcelableExtra(EXTRA_NETWORK_REQUEST); 1224 assertPendingIntentRequestMatches(request, secondRequest, useListen); 1225 receivedCount.incrementAndGet(); 1226 networkFuture.complete(intent.getParcelableExtra(EXTRA_NETWORK)); 1227 } 1228 }; 1229 final int flags = SdkLevel.isAtLeastT() ? RECEIVER_EXPORTED : 0; 1230 mContext.registerReceiver(receiver, filter, flags); 1231 1232 final Network wifiNetwork = mCtsNetUtils.ensureWifiConnected(); 1233 try { 1234 assertEquals(wifiNetwork, networkFuture.get( 1235 NETWORK_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS)); 1236 } catch (TimeoutException e) { 1237 throw new AssertionError("PendingIntent not received for " + secondRequest, e); 1238 } 1239 1240 // Sleep for a small amount of time to try to check that only one callback is ever 1241 // received (so the first callback was really unregistered). This does not guarantee 1242 // that the test will fail if it runs very slowly, but it should at least be very 1243 // noticeably flaky. 1244 Thread.sleep(NO_CALLBACK_TIMEOUT_MS); 1245 1246 // For R- frameworks, listens will receive duplicated callbacks. See b/189868426. 1247 if (isAtLeastS() || !useListen) { 1248 assertEquals("PendingIntent should only be received once", 1, receivedCount.get()); 1249 } 1250 } finally { 1251 if (firstIntent != null) mCm.unregisterNetworkCallback(firstIntent); 1252 if (secondIntent != null) mCm.unregisterNetworkCallback(secondIntent); 1253 if (receiver != null) mContext.unregisterReceiver(receiver); 1254 mCtsNetUtils.ensureWifiConnected(); 1255 } 1256 } 1257 assertPendingIntentRequestMatches(NetworkRequest broadcasted, NetworkRequest filed, boolean useListen)1258 private void assertPendingIntentRequestMatches(NetworkRequest broadcasted, NetworkRequest filed, 1259 boolean useListen) { 1260 assertArrayEquals(filed.networkCapabilities.getCapabilities(), 1261 broadcasted.networkCapabilities.getCapabilities()); 1262 // For R- frameworks, listens will receive duplicated callbacks. See b/189868426. 1263 if (!isAtLeastS() && useListen) return; 1264 assertArrayEquals(filed.networkCapabilities.getTransportTypes(), 1265 broadcasted.networkCapabilities.getTransportTypes()); 1266 } 1267 1268 @AppModeFull(reason = "Cannot get WifiManager in instant app mode") 1269 @Test testRegisterNetworkRequest_identicalPendingIntents()1270 public void testRegisterNetworkRequest_identicalPendingIntents() throws Exception { 1271 runIdenticalPendingIntentsRequestTest(false /* useListen */); 1272 } 1273 1274 @AppModeFull(reason = "Cannot get WifiManager in instant app mode") 1275 @Test testRegisterNetworkCallback_identicalPendingIntents()1276 public void testRegisterNetworkCallback_identicalPendingIntents() throws Exception { 1277 runIdenticalPendingIntentsRequestTest(true /* useListen */); 1278 } 1279 1280 /** 1281 * Exercises the requestNetwork with NetworkCallback API. This checks to 1282 * see if we get a callback for an INTERNET request. 1283 */ 1284 @AppModeFull(reason = "CHANGE_NETWORK_STATE permission can't be granted to instant apps") 1285 @Test testRequestNetworkCallback()1286 public void testRequestNetworkCallback() throws Exception { 1287 final TestNetworkCallback callback = new TestNetworkCallback(); 1288 requestNetwork(new NetworkRequest.Builder() 1289 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) 1290 .build(), callback); 1291 1292 // Wait to get callback for availability of internet 1293 Network internetNetwork = callback.waitForAvailable(); 1294 assertNotNull("Did not receive NetworkCallback#onAvailable for INTERNET", internetNetwork); 1295 } 1296 1297 /** 1298 * Exercises the requestNetwork with NetworkCallback API with timeout - expected to 1299 * fail. Use WIFI and switch Wi-Fi off. 1300 */ 1301 @AppModeFull(reason = "Cannot get WifiManager in instant app mode") 1302 @Test testRequestNetworkCallback_onUnavailable()1303 public void testRequestNetworkCallback_onUnavailable() { 1304 final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled(); 1305 if (previousWifiEnabledState) { 1306 mCtsNetUtils.ensureWifiDisconnected(null); 1307 } 1308 1309 final TestNetworkCallback callback = new TestNetworkCallback(); 1310 requestNetwork(new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build(), 1311 callback, 100); 1312 1313 try { 1314 // Wait to get callback for unavailability of requested network 1315 assertTrue("Did not receive NetworkCallback#onUnavailable", 1316 callback.waitForUnavailable()); 1317 } catch (InterruptedException e) { 1318 fail("NetworkCallback wait was interrupted."); 1319 } finally { 1320 if (previousWifiEnabledState) { 1321 mCtsNetUtils.connectToWifi(); 1322 } 1323 } 1324 } 1325 getFirstV4Address(Network network)1326 private InetAddress getFirstV4Address(Network network) { 1327 LinkProperties linkProperties = mCm.getLinkProperties(network); 1328 for (InetAddress address : linkProperties.getAddresses()) { 1329 if (address instanceof Inet4Address) { 1330 return address; 1331 } 1332 } 1333 return null; 1334 } 1335 1336 /** 1337 * Checks that enabling/disabling wifi causes CONNECTIVITY_ACTION broadcasts. 1338 */ 1339 @AppModeFull(reason = "Cannot get WifiManager in instant app mode") 1340 @Test testToggleWifiConnectivityAction()1341 public void testToggleWifiConnectivityAction() throws Exception { 1342 // toggleWifi calls connectToWifi and disconnectFromWifi, which both wait for 1343 // CONNECTIVITY_ACTION broadcasts. 1344 mCtsNetUtils.toggleWifi(); 1345 } 1346 1347 /** Verify restricted networks cannot be requested. */ 1348 @AppModeFull(reason = "CHANGE_NETWORK_STATE permission can't be granted to instant apps") 1349 @Test testRestrictedNetworks()1350 public void testRestrictedNetworks() { 1351 // Verify we can request unrestricted networks: 1352 NetworkRequest request = new NetworkRequest.Builder() 1353 .addCapability(NET_CAPABILITY_INTERNET).build(); 1354 NetworkCallback callback = new NetworkCallback(); 1355 mCm.requestNetwork(request, callback); 1356 mCm.unregisterNetworkCallback(callback); 1357 // Verify we cannot request restricted networks: 1358 request = new NetworkRequest.Builder().addCapability(NET_CAPABILITY_IMS).build(); 1359 callback = new NetworkCallback(); 1360 try { 1361 mCm.requestNetwork(request, callback); 1362 fail("No exception thrown when restricted network requested."); 1363 } catch (SecurityException expected) {} 1364 } 1365 1366 // Returns "true", "false" or "none" getWifiMeteredStatus(String ssid)1367 private String getWifiMeteredStatus(String ssid) throws Exception { 1368 // Interestingly giving the SSID as an argument to list wifi-networks 1369 // only works iff the network in question has the "false" policy. 1370 // Also unfortunately runShellCommand does not pass the command to the interpreter 1371 // so it's not possible to | grep the ssid. 1372 final String command = "cmd netpolicy list wifi-networks"; 1373 final String policyString = runShellCommand(mInstrumentation, command); 1374 1375 final Matcher m = Pattern.compile("^" + ssid + ";(true|false|none)$", 1376 Pattern.MULTILINE | Pattern.UNIX_LINES).matcher(policyString); 1377 if (!m.find()) { 1378 fail("Unexpected format from cmd netpolicy, policyString = " + policyString); 1379 } 1380 return m.group(1); 1381 } 1382 1383 // metered should be "true", "false" or "none" setWifiMeteredStatus(String ssid, String metered)1384 private void setWifiMeteredStatus(String ssid, String metered) throws Exception { 1385 final String setCommand = "cmd netpolicy set metered-network " + ssid + " " + metered; 1386 runShellCommand(mInstrumentation, setCommand); 1387 assertEquals(getWifiMeteredStatus(ssid), metered); 1388 } 1389 unquoteSSID(String ssid)1390 private String unquoteSSID(String ssid) { 1391 // SSID is returned surrounded by quotes if it can be decoded as UTF-8. 1392 // Otherwise it's guaranteed not to start with a quote. 1393 if (ssid.charAt(0) == '"') { 1394 return ssid.substring(1, ssid.length() - 1); 1395 } else { 1396 return ssid; 1397 } 1398 } 1399 waitForActiveNetworkMetered(final int targetTransportType, final boolean requestedMeteredness, final boolean waitForValidation, final boolean useSystemDefault)1400 private Network waitForActiveNetworkMetered(final int targetTransportType, 1401 final boolean requestedMeteredness, final boolean waitForValidation, 1402 final boolean useSystemDefault) 1403 throws Exception { 1404 final CompletableFuture<Network> networkFuture = new CompletableFuture<>(); 1405 final NetworkCallback networkCallback = new NetworkCallback() { 1406 @Override 1407 public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) { 1408 if (!nc.hasTransport(targetTransportType)) return; 1409 1410 final boolean metered = !nc.hasCapability(NET_CAPABILITY_NOT_METERED); 1411 final boolean validated = nc.hasCapability(NET_CAPABILITY_VALIDATED); 1412 if (metered == requestedMeteredness && (!waitForValidation || validated)) { 1413 networkFuture.complete(network); 1414 } 1415 } 1416 }; 1417 1418 try { 1419 // Registering a callback here guarantees onCapabilitiesChanged is called immediately 1420 // with the current setting. Therefore, if the setting has already been changed, 1421 // this method will return right away, and if not, it'll wait for the setting to change. 1422 if (useSystemDefault) { 1423 runWithShellPermissionIdentity(() -> 1424 registerSystemDefaultNetworkCallback(networkCallback, 1425 new Handler(Looper.getMainLooper())), 1426 NETWORK_SETTINGS); 1427 } else { 1428 registerDefaultNetworkCallback(networkCallback); 1429 } 1430 1431 // Changing meteredness on wifi involves reconnecting, which can take several seconds 1432 // (involves re-associating, DHCP...). 1433 return networkFuture.get(NETWORK_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS); 1434 } catch (TimeoutException e) { 1435 throw new AssertionError("Timed out waiting for active network metered status to " 1436 + "change to " + requestedMeteredness + " ; network = " 1437 + mCm.getActiveNetwork(), e); 1438 } 1439 } 1440 setWifiMeteredStatusAndWait(String ssid, boolean isMetered, boolean waitForValidation)1441 private Network setWifiMeteredStatusAndWait(String ssid, boolean isMetered, 1442 boolean waitForValidation) throws Exception { 1443 setWifiMeteredStatus(ssid, Boolean.toString(isMetered) /* metered */); 1444 mCtsNetUtils.ensureWifiConnected(); 1445 return waitForActiveNetworkMetered(TRANSPORT_WIFI, 1446 isMetered /* requestedMeteredness */, 1447 waitForValidation, 1448 true /* useSystemDefault */); 1449 } 1450 assertMultipathPreferenceIsEventually(Network network, int oldValue, int expectedValue)1451 private void assertMultipathPreferenceIsEventually(Network network, int oldValue, 1452 int expectedValue) { 1453 // Quick check : if oldValue == expectedValue, there is no way to guarantee the test 1454 // is not flaky. 1455 assertNotSame(oldValue, expectedValue); 1456 1457 for (int i = 0; i < NUM_TRIES_MULTIPATH_PREF_CHECK; ++i) { 1458 final int actualValue = mCm.getMultipathPreference(network); 1459 if (actualValue == expectedValue) { 1460 return; 1461 } 1462 if (actualValue != oldValue) { 1463 fail("Multipath preference is neither previous (" + oldValue 1464 + ") nor expected (" + expectedValue + ")"); 1465 } 1466 SystemClock.sleep(INTERVAL_MULTIPATH_PREF_CHECK_MS); 1467 } 1468 fail("Timed out waiting for multipath preference to change. expected = " 1469 + expectedValue + " ; actual = " + mCm.getMultipathPreference(network)); 1470 } 1471 getCurrentMeteredMultipathPreference(ContentResolver resolver)1472 private int getCurrentMeteredMultipathPreference(ContentResolver resolver) { 1473 final String rawMeteredPref = Settings.Global.getString(resolver, 1474 NETWORK_METERED_MULTIPATH_PREFERENCE); 1475 return TextUtils.isEmpty(rawMeteredPref) 1476 ? getIntResourceForName(NETWORK_METERED_MULTIPATH_PREFERENCE_RES_NAME) 1477 : Integer.parseInt(rawMeteredPref); 1478 } 1479 findNextPrefValue(ContentResolver resolver)1480 private int findNextPrefValue(ContentResolver resolver) { 1481 // A bit of a nuclear hammer, but race conditions in CTS are bad. To be able to 1482 // detect a correct setting value without race conditions, the next pref must 1483 // be a valid value (range 0..3) that is different from the old setting of the 1484 // metered preference and from the unmetered preference. 1485 final int meteredPref = getCurrentMeteredMultipathPreference(resolver); 1486 final int unmeteredPref = ConnectivityManager.MULTIPATH_PREFERENCE_UNMETERED; 1487 if (0 != meteredPref && 0 != unmeteredPref) return 0; 1488 if (1 != meteredPref && 1 != unmeteredPref) return 1; 1489 return 2; 1490 } 1491 1492 /** 1493 * Verify that getMultipathPreference does return appropriate values 1494 * for metered and unmetered networks. 1495 */ 1496 @AppModeFull(reason = "Cannot get WifiManager in instant app mode") 1497 @Test testGetMultipathPreference()1498 public void testGetMultipathPreference() throws Exception { 1499 assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI)); 1500 final ContentResolver resolver = mContext.getContentResolver(); 1501 mCtsNetUtils.ensureWifiConnected(); 1502 final String ssid = unquoteSSID(mWifiManager.getConnectionInfo().getSSID()); 1503 final String oldMeteredSetting = getWifiMeteredStatus(ssid); 1504 final String oldMeteredMultipathPreference = Settings.Global.getString( 1505 resolver, NETWORK_METERED_MULTIPATH_PREFERENCE); 1506 try { 1507 final int initialMeteredPreference = getCurrentMeteredMultipathPreference(resolver); 1508 int newMeteredPreference = findNextPrefValue(resolver); 1509 Settings.Global.putString(resolver, NETWORK_METERED_MULTIPATH_PREFERENCE, 1510 Integer.toString(newMeteredPreference)); 1511 // Wifi meteredness changes from unmetered to metered will disconnect and reconnect 1512 // since R. 1513 final Network network = setWifiMeteredStatusAndWait(ssid, true /* isMetered */, 1514 false /* waitForValidation */); 1515 assertEquals(ssid, unquoteSSID(mWifiManager.getConnectionInfo().getSSID())); 1516 assertEquals(mCm.getNetworkCapabilities(network).hasCapability( 1517 NET_CAPABILITY_NOT_METERED), false); 1518 assertMultipathPreferenceIsEventually(network, initialMeteredPreference, 1519 newMeteredPreference); 1520 1521 final int oldMeteredPreference = newMeteredPreference; 1522 newMeteredPreference = findNextPrefValue(resolver); 1523 Settings.Global.putString(resolver, NETWORK_METERED_MULTIPATH_PREFERENCE, 1524 Integer.toString(newMeteredPreference)); 1525 assertEquals(mCm.getNetworkCapabilities(network).hasCapability( 1526 NET_CAPABILITY_NOT_METERED), false); 1527 assertMultipathPreferenceIsEventually(network, 1528 oldMeteredPreference, newMeteredPreference); 1529 1530 // No disconnect from unmetered to metered. 1531 setWifiMeteredStatusAndWait(ssid, false /* isMetered */, false /* waitForValidation */); 1532 assertEquals(mCm.getNetworkCapabilities(network).hasCapability( 1533 NET_CAPABILITY_NOT_METERED), true); 1534 assertMultipathPreferenceIsEventually(network, newMeteredPreference, 1535 ConnectivityManager.MULTIPATH_PREFERENCE_UNMETERED); 1536 } finally { 1537 Settings.Global.putString(resolver, NETWORK_METERED_MULTIPATH_PREFERENCE, 1538 oldMeteredMultipathPreference); 1539 setWifiMeteredStatus(ssid, oldMeteredSetting); 1540 } 1541 } 1542 1543 // TODO: move the following socket keep alive test to dedicated test class. 1544 /** 1545 * Callback used in tcp keepalive offload that allows caller to wait callback fires. 1546 */ 1547 private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback { 1548 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }; 1549 1550 public static class CallbackValue { 1551 public final CallbackType callbackType; 1552 public final int error; 1553 CallbackValue(final CallbackType type, final int error)1554 private CallbackValue(final CallbackType type, final int error) { 1555 this.callbackType = type; 1556 this.error = error; 1557 } 1558 1559 public static class OnStartedCallback extends CallbackValue { OnStartedCallback()1560 OnStartedCallback() { super(CallbackType.ON_STARTED, 0); } 1561 } 1562 1563 public static class OnStoppedCallback extends CallbackValue { OnStoppedCallback()1564 OnStoppedCallback() { super(CallbackType.ON_STOPPED, 0); } 1565 } 1566 1567 public static class OnErrorCallback extends CallbackValue { OnErrorCallback(final int error)1568 OnErrorCallback(final int error) { super(CallbackType.ON_ERROR, error); } 1569 } 1570 1571 @Override equals(Object o)1572 public boolean equals(Object o) { 1573 return o.getClass() == this.getClass() 1574 && this.callbackType == ((CallbackValue) o).callbackType 1575 && this.error == ((CallbackValue) o).error; 1576 } 1577 1578 @Override toString()1579 public String toString() { 1580 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error); 1581 } 1582 } 1583 1584 private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>(); 1585 1586 @Override onStarted()1587 public void onStarted() { 1588 mCallbacks.add(new CallbackValue.OnStartedCallback()); 1589 } 1590 1591 @Override onStopped()1592 public void onStopped() { 1593 mCallbacks.add(new CallbackValue.OnStoppedCallback()); 1594 } 1595 1596 @Override onError(final int error)1597 public void onError(final int error) { 1598 mCallbacks.add(new CallbackValue.OnErrorCallback(error)); 1599 } 1600 pollCallback()1601 public CallbackValue pollCallback() { 1602 try { 1603 return mCallbacks.poll(KEEPALIVE_CALLBACK_TIMEOUT_MS, 1604 TimeUnit.MILLISECONDS); 1605 } catch (InterruptedException e) { 1606 fail("Callback not seen after " + KEEPALIVE_CALLBACK_TIMEOUT_MS + " ms"); 1607 } 1608 return null; 1609 } expectCallback(CallbackValue expectedCallback)1610 private void expectCallback(CallbackValue expectedCallback) { 1611 final CallbackValue actualCallback = pollCallback(); 1612 assertEquals(expectedCallback, actualCallback); 1613 } 1614 expectStarted()1615 public void expectStarted() { 1616 expectCallback(new CallbackValue.OnStartedCallback()); 1617 } 1618 expectStopped()1619 public void expectStopped() { 1620 expectCallback(new CallbackValue.OnStoppedCallback()); 1621 } 1622 expectError(int error)1623 public void expectError(int error) { 1624 expectCallback(new CallbackValue.OnErrorCallback(error)); 1625 } 1626 } 1627 getAddrByName(final String hostname, final int family)1628 private InetAddress getAddrByName(final String hostname, final int family) throws Exception { 1629 final InetAddress[] allAddrs = InetAddress.getAllByName(hostname); 1630 for (InetAddress addr : allAddrs) { 1631 if (family == AF_INET && addr instanceof Inet4Address) return addr; 1632 1633 if (family == AF_INET6 && addr instanceof Inet6Address) return addr; 1634 1635 if (family == AF_UNSPEC) return addr; 1636 } 1637 return null; 1638 } 1639 getConnectedSocket(final Network network, final String host, final int port, final int family)1640 private Socket getConnectedSocket(final Network network, final String host, final int port, 1641 final int family) throws Exception { 1642 final Socket s = network.getSocketFactory().createSocket(); 1643 try { 1644 final InetAddress addr = getAddrByName(host, family); 1645 if (addr == null) fail("Fail to get destination address for " + family); 1646 1647 final InetSocketAddress sockAddr = new InetSocketAddress(addr, port); 1648 s.connect(sockAddr); 1649 } catch (Exception e) { 1650 s.close(); 1651 throw e; 1652 } 1653 return s; 1654 } 1655 getSupportedKeepalivesForNet(@onNull Network network)1656 private int getSupportedKeepalivesForNet(@NonNull Network network) throws Exception { 1657 final NetworkCapabilities nc = mCm.getNetworkCapabilities(network); 1658 1659 // Get number of supported concurrent keepalives for testing network. 1660 final int[] keepalivesPerTransport = runAsShell(NETWORK_SETTINGS, 1661 () -> mCm.getSupportedKeepalives()); 1662 return KeepaliveUtils.getSupportedKeepalivesForNetworkCapabilities( 1663 keepalivesPerTransport, nc); 1664 } 1665 isTcpKeepaliveSupportedByKernel()1666 private static boolean isTcpKeepaliveSupportedByKernel() { 1667 final String kVersionString = VintfRuntimeInfo.getKernelVersion(); 1668 return DeviceInfoUtils.compareMajorMinorVersion(kVersionString, "4.8") >= 0; 1669 } 1670 1671 /** 1672 * Verifies that the keepalive API cannot create any keepalive when the maximum number of 1673 * keepalives is set to 0. 1674 */ 1675 @AppModeFull(reason = "Cannot get WifiManager in instant app mode") 1676 // getSupportedKeepalives is available in updatable ConnectivityManager (S+) 1677 // Also, this feature is not mainlined before S, and it's fine to skip on R- devices. 1678 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) @ConnectivityModuleTest 1679 @Test testKeepaliveWifiUnsupported()1680 public void testKeepaliveWifiUnsupported() throws Exception { 1681 assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI)); 1682 1683 final Network network = mCtsNetUtils.ensureWifiConnected(); 1684 if (getSupportedKeepalivesForNet(network) != 0) return; 1685 final InetAddress srcAddr = getFirstV4Address(network); 1686 assumeTrue("This test requires native IPv4", srcAddr != null); 1687 1688 runWithShellPermissionIdentity(() -> { 1689 assertEquals(0, createConcurrentSocketKeepalives(network, srcAddr, 1, 0)); 1690 assertEquals(0, createConcurrentSocketKeepalives(network, srcAddr, 0, 1)); 1691 }); 1692 } 1693 1694 @AppModeFull(reason = "Cannot get WifiManager in instant app mode") 1695 // getSupportedKeepalives is available in updatable ConnectivityManager (S+) 1696 // Also, this feature is not mainlined before S, and it's fine to skip on R- devices. 1697 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) @ConnectivityModuleTest 1698 @Test 1699 @RequiresDevice // Keepalive is not supported on virtual hardware testCreateTcpKeepalive()1700 public void testCreateTcpKeepalive() throws Exception { 1701 assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI)); 1702 1703 final Network network = mCtsNetUtils.ensureWifiConnected(); 1704 if (getSupportedKeepalivesForNet(network) == 0) return; 1705 final InetAddress srcAddr = getFirstV4Address(network); 1706 assumeTrue("This test requires native IPv4", srcAddr != null); 1707 1708 // If kernel < 4.8 then it doesn't support TCP keepalive, but it might still support 1709 // NAT-T keepalive. If keepalive limits from resource overlay is not zero, TCP keepalive 1710 // needs to be supported except if the kernel doesn't support it. 1711 if (!isTcpKeepaliveSupportedByKernel()) { 1712 // Verify that the callback result is expected. 1713 runWithShellPermissionIdentity(() -> { 1714 assertEquals(0, createConcurrentSocketKeepalives(network, srcAddr, 0, 1)); 1715 }); 1716 Log.i(TAG, "testCreateTcpKeepalive is skipped for kernel " 1717 + VintfRuntimeInfo.getKernelVersion()); 1718 return; 1719 } 1720 1721 final byte[] requestBytes = CtsNetUtils.HTTP_REQUEST.getBytes("UTF-8"); 1722 // So far only ipv4 tcp keepalive offload is supported. 1723 // TODO: add test case for ipv6 tcp keepalive offload when it is supported. 1724 try (Socket s = getConnectedSocket(network, TEST_HOST, HTTP_PORT, AF_INET)) { 1725 1726 // Should able to start keep alive offload when socket is idle. 1727 final Executor executor = mContext.getMainExecutor(); 1728 final TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(); 1729 1730 mUiAutomation.adoptShellPermissionIdentity(); 1731 try (SocketKeepalive sk = mCm.createSocketKeepalive(network, s, executor, callback)) { 1732 sk.start(MIN_KEEPALIVE_INTERVAL); 1733 callback.expectStarted(); 1734 1735 // App should not able to write during keepalive offload. 1736 final OutputStream out = s.getOutputStream(); 1737 try { 1738 out.write(requestBytes); 1739 fail("Should not able to write"); 1740 } catch (IOException e) { } 1741 // App should not able to read during keepalive offload. 1742 final InputStream in = s.getInputStream(); 1743 byte[] responseBytes = new byte[4096]; 1744 try { 1745 in.read(responseBytes); 1746 fail("Should not able to read"); 1747 } catch (IOException e) { } 1748 1749 // Stop. 1750 sk.stop(); 1751 callback.expectStopped(); 1752 } finally { 1753 mUiAutomation.dropShellPermissionIdentity(); 1754 } 1755 1756 // Ensure socket is still connected. 1757 assertTrue(s.isConnected()); 1758 assertFalse(s.isClosed()); 1759 1760 // Let socket be not idle. 1761 try { 1762 final OutputStream out = s.getOutputStream(); 1763 out.write(requestBytes); 1764 } catch (IOException e) { 1765 fail("Failed to write data " + e); 1766 } 1767 // Make sure response data arrives. 1768 final MessageQueue fdHandlerQueue = Looper.getMainLooper().getQueue(); 1769 final FileDescriptor fd = s.getFileDescriptor$(); 1770 final CountDownLatch mOnReceiveLatch = new CountDownLatch(1); 1771 fdHandlerQueue.addOnFileDescriptorEventListener(fd, EVENT_INPUT, (readyFd, events) -> { 1772 mOnReceiveLatch.countDown(); 1773 return 0; // Unregister listener. 1774 }); 1775 if (!mOnReceiveLatch.await(2, TimeUnit.SECONDS)) { 1776 fdHandlerQueue.removeOnFileDescriptorEventListener(fd); 1777 fail("Timeout: no response data"); 1778 } 1779 1780 // Should get ERROR_SOCKET_NOT_IDLE because there is still data in the receive queue 1781 // that has not been read. 1782 mUiAutomation.adoptShellPermissionIdentity(); 1783 try (SocketKeepalive sk = mCm.createSocketKeepalive(network, s, executor, callback)) { 1784 sk.start(MIN_KEEPALIVE_INTERVAL); 1785 callback.expectError(SocketKeepalive.ERROR_SOCKET_NOT_IDLE); 1786 } finally { 1787 mUiAutomation.dropShellPermissionIdentity(); 1788 } 1789 } 1790 } 1791 createConcurrentKeepalivesOfType( int requestCount, @NonNull TestSocketKeepaliveCallback callback, Supplier<SocketKeepalive> kaFactory)1792 private ArrayList<SocketKeepalive> createConcurrentKeepalivesOfType( 1793 int requestCount, @NonNull TestSocketKeepaliveCallback callback, 1794 Supplier<SocketKeepalive> kaFactory) { 1795 final ArrayList<SocketKeepalive> kalist = new ArrayList<>(); 1796 1797 int remainingRetries = MAX_KEEPALIVE_RETRY_COUNT; 1798 1799 // Test concurrent keepalives with the given supplier. 1800 while (kalist.size() < requestCount) { 1801 final SocketKeepalive ka = kaFactory.get(); 1802 ka.start(MIN_KEEPALIVE_INTERVAL); 1803 TestSocketKeepaliveCallback.CallbackValue cv = callback.pollCallback(); 1804 assertNotNull(cv); 1805 if (cv.callbackType == TestSocketKeepaliveCallback.CallbackType.ON_ERROR) { 1806 if (kalist.size() == 0 && cv.error == SocketKeepalive.ERROR_UNSUPPORTED) { 1807 // Unsupported. 1808 break; 1809 } else if (cv.error == SocketKeepalive.ERROR_INSUFFICIENT_RESOURCES) { 1810 // Limit reached or temporary unavailable due to stopped slot is not yet 1811 // released. 1812 if (remainingRetries > 0) { 1813 SystemClock.sleep(INTERVAL_KEEPALIVE_RETRY_MS); 1814 remainingRetries--; 1815 continue; 1816 } 1817 break; 1818 } 1819 } 1820 if (cv.callbackType == TestSocketKeepaliveCallback.CallbackType.ON_STARTED) { 1821 kalist.add(ka); 1822 } else { 1823 fail("Unexpected error when creating " + (kalist.size() + 1) + " " 1824 + ka.getClass().getSimpleName() + ": " + cv); 1825 } 1826 } 1827 1828 return kalist; 1829 } 1830 createConcurrentNattSocketKeepalives( @onNull Network network, @NonNull InetAddress srcAddr, int requestCount, @NonNull TestSocketKeepaliveCallback callback)1831 private @NonNull ArrayList<SocketKeepalive> createConcurrentNattSocketKeepalives( 1832 @NonNull Network network, @NonNull InetAddress srcAddr, int requestCount, 1833 @NonNull TestSocketKeepaliveCallback callback) throws Exception { 1834 1835 final Executor executor = mContext.getMainExecutor(); 1836 1837 // Initialize a real NaT-T socket. 1838 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE); 1839 final UdpEncapsulationSocket nattSocket = mIpSec.openUdpEncapsulationSocket(); 1840 final InetAddress dstAddr = getAddrByName(TEST_HOST, AF_INET); 1841 assertNotNull(srcAddr); 1842 assertNotNull(dstAddr); 1843 1844 // Test concurrent Nat-T keepalives. 1845 final ArrayList<SocketKeepalive> result = createConcurrentKeepalivesOfType(requestCount, 1846 callback, () -> mCm.createSocketKeepalive(network, nattSocket, 1847 srcAddr, dstAddr, executor, callback)); 1848 1849 nattSocket.close(); 1850 return result; 1851 } 1852 createConcurrentTcpSocketKeepalives( @onNull Network network, int requestCount, @NonNull TestSocketKeepaliveCallback callback)1853 private @NonNull ArrayList<SocketKeepalive> createConcurrentTcpSocketKeepalives( 1854 @NonNull Network network, int requestCount, 1855 @NonNull TestSocketKeepaliveCallback callback) { 1856 final Executor executor = mContext.getMainExecutor(); 1857 1858 // Create concurrent TCP keepalives. 1859 return createConcurrentKeepalivesOfType(requestCount, callback, () -> { 1860 // Assert that TCP connections can be established. The file descriptor of tcp 1861 // sockets will be duplicated and kept valid in service side if the keepalives are 1862 // successfully started. 1863 try (Socket tcpSocket = getConnectedSocket(network, TEST_HOST, HTTP_PORT, 1864 AF_INET)) { 1865 return mCm.createSocketKeepalive(network, tcpSocket, executor, callback); 1866 } catch (Exception e) { 1867 fail("Unexpected error when creating TCP socket: " + e); 1868 } 1869 return null; 1870 }); 1871 } 1872 1873 /** 1874 * Creates concurrent keepalives until the specified counts of each type of keepalives are 1875 * reached or the expected error callbacks are received for each type of keepalives. 1876 * 1877 * @return the total number of keepalives created. 1878 */ 1879 private int createConcurrentSocketKeepalives( 1880 @NonNull Network network, @NonNull InetAddress srcAddr, int nattCount, int tcpCount) 1881 throws Exception { 1882 final ArrayList<SocketKeepalive> kalist = new ArrayList<>(); 1883 final TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(); 1884 1885 kalist.addAll(createConcurrentNattSocketKeepalives(network, srcAddr, nattCount, callback)); 1886 kalist.addAll(createConcurrentTcpSocketKeepalives(network, tcpCount, callback)); 1887 1888 final int ret = kalist.size(); 1889 1890 // Clean up. 1891 for (final SocketKeepalive ka : kalist) { 1892 ka.stop(); 1893 callback.expectStopped(); 1894 } 1895 kalist.clear(); 1896 1897 return ret; 1898 } 1899 1900 /** 1901 * Verifies that the concurrent keepalive slots meet the minimum requirement, and don't 1902 * get leaked after iterations. 1903 */ 1904 @AppModeFull(reason = "Cannot get WifiManager in instant app mode") 1905 @Test 1906 // getSupportedKeepalives is available in updatable ConnectivityManager (S+) 1907 // Also, this feature is not mainlined before S, and it's fine to skip on R- devices. 1908 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) @ConnectivityModuleTest 1909 @RequiresDevice // Keepalive is not supported on virtual hardware 1910 public void testSocketKeepaliveLimitWifi() throws Exception { 1911 assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI)); 1912 1913 final Network network = mCtsNetUtils.ensureWifiConnected(); 1914 final int supported = getSupportedKeepalivesForNet(network); 1915 if (supported == 0) { 1916 return; 1917 } 1918 final InetAddress srcAddr = getFirstV4Address(network); 1919 assumeTrue("This test requires native IPv4", srcAddr != null); 1920 1921 runWithShellPermissionIdentity(() -> { 1922 // Verifies that the supported keepalive slots meet MIN_SUPPORTED_KEEPALIVE_COUNT. 1923 assertGreaterOrEqual(supported, MIN_SUPPORTED_WIFI_KEEPALIVE_COUNT); 1924 1925 // Verifies that Nat-T keepalives can be established. 1926 assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr, 1927 supported + 1, 0)); 1928 // Verifies that keepalives don't get leaked in second round. 1929 assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr, supported, 1930 0)); 1931 }); 1932 1933 // If kernel < 4.8 then it doesn't support TCP keepalive, but it might still support 1934 // NAT-T keepalive. Test below cases only if TCP keepalive is supported by kernel. 1935 if (!isTcpKeepaliveSupportedByKernel()) return; 1936 1937 runWithShellPermissionIdentity(() -> { 1938 assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr, 0, 1939 supported + 1)); 1940 1941 // Verifies that different types can be established at the same time. 1942 assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr, 1943 supported / 2, supported - supported / 2)); 1944 1945 // Verifies that keepalives don't get leaked in second round. 1946 assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr, 0, 1947 supported)); 1948 assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr, 1949 supported / 2, supported - supported / 2)); 1950 }); 1951 } 1952 1953 /** 1954 * Verifies that the concurrent keepalive slots meet the minimum telephony requirement, and 1955 * don't get leaked after iterations. 1956 */ 1957 @AppModeFull(reason = "Cannot request network in instant app mode") 1958 @Test 1959 // getSupportedKeepalives is available in updatable ConnectivityManager (S+) 1960 // Also, this feature is not mainlined before S, and it's fine to skip on R- devices. 1961 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) @ConnectivityModuleTest 1962 @RequiresDevice // Keepalive is not supported on virtual hardware 1963 public void testSocketKeepaliveLimitTelephony() throws Exception { 1964 if (!mPackageManager.hasSystemFeature(FEATURE_TELEPHONY)) { 1965 Log.i(TAG, "testSocketKeepaliveLimitTelephony cannot execute unless device" 1966 + " supports telephony"); 1967 return; 1968 } 1969 1970 final int firstSdk = SdkLevel.isAtLeastS() 1971 ? Build.VERSION.DEVICE_INITIAL_SDK_INT 1972 // FIRST_SDK_INT was a @TestApi field renamed to DEVICE_INITIAL_SDK_INT in S 1973 : Build.VERSION.class.getField("FIRST_SDK_INT").getInt(null); 1974 if (firstSdk < Build.VERSION_CODES.Q) { 1975 Log.i(TAG, "testSocketKeepaliveLimitTelephony: skip test for devices launching" 1976 + " before Q: " + firstSdk); 1977 return; 1978 } 1979 1980 final Network network = mCtsNetUtils.connectToCell(); 1981 final int supported = getSupportedKeepalivesForNet(network); 1982 final InetAddress srcAddr = getFirstV4Address(network); 1983 assumeTrue("This test requires native IPv4", srcAddr != null); 1984 1985 runWithShellPermissionIdentity(() -> { 1986 // Verifies that the supported keepalive slots meet minimum requirement. 1987 assertGreaterOrEqual(supported, MIN_SUPPORTED_CELLULAR_KEEPALIVE_COUNT); 1988 // Verifies that Nat-T keepalives can be established. 1989 assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr, 1990 supported + 1, 0)); 1991 // Verifies that keepalives don't get leaked in second round. 1992 assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr, supported, 1993 0)); 1994 }); 1995 } 1996 1997 private int getIntResourceForName(@NonNull String resName) { 1998 final Resources r = mContext.getResources(); 1999 final int resId = r.getIdentifier(resName, "integer", "android"); 2000 return r.getInteger(resId); 2001 } 2002 2003 /** 2004 * Verifies that the keepalive slots are limited as customized for unprivileged requests. 2005 */ 2006 @AppModeFull(reason = "Cannot get WifiManager in instant app mode") 2007 @Test 2008 // getSupportedKeepalives is available in updatable ConnectivityManager (S+) 2009 // Also, this feature is not mainlined before S, and it's fine to skip on R- devices. 2010 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) @ConnectivityModuleTest 2011 @RequiresDevice // Keepalive is not supported on virtual hardware 2012 public void testSocketKeepaliveUnprivileged() throws Exception { 2013 assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI)); 2014 2015 final Network network = mCtsNetUtils.ensureWifiConnected(); 2016 final int supported = getSupportedKeepalivesForNet(network); 2017 if (supported == 0) { 2018 return; 2019 } 2020 final InetAddress srcAddr = getFirstV4Address(network); 2021 assumeTrue("This test requires native IPv4", srcAddr != null); 2022 2023 // Resource ID might be shifted on devices that compiled with different symbols. 2024 // Thus, resolve ID at runtime is needed. 2025 final int allowedUnprivilegedPerUid = 2026 getIntResourceForName(KEEPALIVE_ALLOWED_UNPRIVILEGED_RES_NAME); 2027 final int reservedPrivilegedSlots = 2028 getIntResourceForName(KEEPALIVE_RESERVED_PER_SLOT_RES_NAME); 2029 // Verifies that unprivileged request per uid cannot exceed the limit customized in the 2030 // resource. Currently, unprivileged keepalive slots are limited to Nat-T only, this test 2031 // does not apply to TCP. 2032 assertGreaterOrEqual(supported, reservedPrivilegedSlots); 2033 assertGreaterOrEqual(supported, allowedUnprivilegedPerUid); 2034 final int expectedUnprivileged = 2035 Math.min(allowedUnprivilegedPerUid, supported - reservedPrivilegedSlots); 2036 assertEquals(expectedUnprivileged, 2037 createConcurrentSocketKeepalives(network, srcAddr, supported + 1, 0)); 2038 } 2039 2040 private static void assertGreaterOrEqual(long greater, long lesser) { 2041 assertTrue("" + greater + " expected to be greater than or equal to " + lesser, 2042 greater >= lesser); 2043 } 2044 2045 private void verifyBindSocketToRestrictedNetworkDisallowed() throws Exception { 2046 final TestableNetworkCallback testNetworkCb = new TestableNetworkCallback(); 2047 final NetworkRequest testRequest = new NetworkRequest.Builder() 2048 .addTransportType(NetworkCapabilities.TRANSPORT_TEST) 2049 .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) 2050 .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) 2051 .setNetworkSpecifier(CompatUtil.makeTestNetworkSpecifier( 2052 TEST_RESTRICTED_NW_IFACE_NAME)) 2053 .build(); 2054 runWithShellPermissionIdentity(() -> requestNetwork(testRequest, testNetworkCb), 2055 CONNECTIVITY_USE_RESTRICTED_NETWORKS, 2056 // CONNECTIVITY_INTERNAL is for requesting restricted network because shell does not 2057 // have CONNECTIVITY_USE_RESTRICTED_NETWORKS on R. 2058 CONNECTIVITY_INTERNAL); 2059 2060 // Create a restricted network and ensure this package cannot bind to that network either. 2061 final NetworkAgent agent = createRestrictedNetworkAgent(mContext); 2062 final Network network = agent.getNetwork(); 2063 2064 try (Socket socket = new Socket()) { 2065 // Verify that the network is restricted. 2066 testNetworkCb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED, 2067 NETWORK_CALLBACK_TIMEOUT_MS, 2068 entry -> network.equals(entry.getNetwork()) 2069 && (!((CallbackEntry.CapabilitiesChanged) entry).getCaps() 2070 .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED))); 2071 // CtsNetTestCases package doesn't hold CONNECTIVITY_USE_RESTRICTED_NETWORKS, so it 2072 // does not allow to bind socket to restricted network. 2073 assertThrows(IOException.class, () -> network.bindSocket(socket)); 2074 } finally { 2075 agent.unregister(); 2076 } 2077 } 2078 2079 /** 2080 * Verifies that apps are not allowed to access restricted networks even if they declare the 2081 * CONNECTIVITY_USE_RESTRICTED_NETWORKS permission in their manifests. 2082 * See. b/144679405. 2083 */ 2084 @AppModeFull(reason = "Cannot get WifiManager in instant app mode") 2085 @Test 2086 @IgnoreUpTo(Build.VERSION_CODES.Q) 2087 public void testRestrictedNetworkPermission() throws Exception { 2088 // Ensure that CONNECTIVITY_USE_RESTRICTED_NETWORKS isn't granted to this package. 2089 final PackageInfo app = mPackageManager.getPackageInfo(mContext.getPackageName(), 2090 GET_PERMISSIONS); 2091 final int index = ArrayUtils.indexOf( 2092 app.requestedPermissions, CONNECTIVITY_USE_RESTRICTED_NETWORKS); 2093 assertTrue(index >= 0); 2094 assertTrue(app.requestedPermissionsFlags[index] != PERMISSION_GRANTED); 2095 2096 if (mPackageManager.hasSystemFeature(FEATURE_WIFI)) { 2097 // Expect binding to the wifi network to succeed. 2098 final Network wifiNetwork = mCtsNetUtils.ensureWifiConnected(); 2099 try (Socket socket = new Socket()) { 2100 wifiNetwork.bindSocket(socket); 2101 } 2102 } 2103 2104 // Ensure that this package cannot bind to any restricted network that's currently 2105 // connected. 2106 Network[] networks = mCm.getAllNetworks(); 2107 for (Network network : networks) { 2108 final NetworkCapabilities nc = mCm.getNetworkCapabilities(network); 2109 if (nc == null) { 2110 continue; 2111 } 2112 2113 try (Socket socket = new Socket()) { 2114 if (nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) { 2115 network.bindSocket(socket); // binding should succeed 2116 } else { 2117 assertThrows(IOException.class, () -> network.bindSocket(socket)); 2118 } 2119 } 2120 } 2121 2122 verifyBindSocketToRestrictedNetworkDisallowed(); 2123 } 2124 2125 /** 2126 * Verifies that apps are allowed to call setAirplaneMode if they declare 2127 * NETWORK_AIRPLANE_MODE permission in their manifests. 2128 * See b/145164696. 2129 */ 2130 @AppModeFull(reason = "NETWORK_AIRPLANE_MODE permission can't be granted to instant apps") 2131 @Test 2132 public void testSetAirplaneMode() throws Exception{ 2133 // Starting from T, wifi supports airplane mode enhancement which may not disconnect wifi 2134 // when airplane mode is on. The actual behavior that the device will have could only be 2135 // checked with hidden wifi APIs(see Settings.Secure.WIFI_APM_STATE). Thus, stop verifying 2136 // wifi on T+ device. 2137 final boolean verifyWifi = mPackageManager.hasSystemFeature(FEATURE_WIFI) 2138 && !SdkLevel.isAtLeastT(); 2139 final boolean supportTelephony = mPackageManager.hasSystemFeature(FEATURE_TELEPHONY); 2140 // store the current state of airplane mode 2141 final boolean isAirplaneModeEnabled = isAirplaneModeEnabled(); 2142 final TestableNetworkCallback wifiCb = new TestableNetworkCallback(); 2143 final TestableNetworkCallback telephonyCb = new TestableNetworkCallback(); 2144 // disable airplane mode to reach a known state 2145 runShellCommand("cmd connectivity airplane-mode disable"); 2146 // Verify that networks are available as expected if wifi or cell is supported. Continue the 2147 // test if none of them are supported since test should still able to verify the permission 2148 // mechanism. 2149 if (verifyWifi) { 2150 mCtsNetUtils.ensureWifiConnected(); 2151 registerCallbackAndWaitForAvailable(makeWifiNetworkRequest(), wifiCb); 2152 } 2153 if (supportTelephony) { 2154 // connectToCell needs to be followed by disconnectFromCell, which is called in tearDown 2155 mCtsNetUtils.connectToCell(); 2156 registerCallbackAndWaitForAvailable(makeCellNetworkRequest(), telephonyCb); 2157 } 2158 2159 try { 2160 // Verify we cannot set Airplane Mode without correct permission: 2161 assertThrows(SecurityException.class, () -> setAndVerifyAirplaneMode(true)); 2162 2163 // disable airplane mode again to reach a known state 2164 runShellCommand("cmd connectivity airplane-mode disable"); 2165 2166 // Verify we can enable Airplane Mode with correct permission. 2167 // TODO: test that NETWORK_AIRPLANE_MODE works as well, once the shell has it. 2168 runAsShell(NETWORK_SETTINGS, () -> setAndVerifyAirplaneMode(true)); 2169 2170 // Verify that the enabling airplane mode takes effect as expected to prevent flakiness 2171 // caused by fast airplane mode switches. Ensure network lost before turning off 2172 // airplane mode. 2173 if (verifyWifi) waitForLost(wifiCb); 2174 if (supportTelephony) waitForLost(telephonyCb); 2175 2176 // Verify we can disable Airplane Mode with correct permission: 2177 runAsShell(NETWORK_SETTINGS, () -> setAndVerifyAirplaneMode(false)); 2178 2179 // Verify that turning airplane mode off takes effect as expected. 2180 // connectToCell only registers a request, it cannot / does not need to be called twice 2181 mCtsNetUtils.ensureWifiConnected(); 2182 if (verifyWifi) waitForAvailable(wifiCb); 2183 if (supportTelephony) waitForAvailable(telephonyCb); 2184 } finally { 2185 // Restore the previous state of airplane mode and permissions: 2186 runShellCommand("cmd connectivity airplane-mode " 2187 + (isAirplaneModeEnabled ? "enable" : "disable")); 2188 } 2189 } 2190 2191 private void registerCallbackAndWaitForAvailable(@NonNull final NetworkRequest request, 2192 @NonNull final TestableNetworkCallback cb) { 2193 registerNetworkCallback(request, cb); 2194 waitForAvailable(cb); 2195 } 2196 2197 private void waitForAvailable(@NonNull final TestableNetworkCallback cb) { 2198 cb.eventuallyExpect(CallbackEntry.AVAILABLE, NETWORK_CALLBACK_TIMEOUT_MS, 2199 c -> c instanceof CallbackEntry.Available); 2200 } 2201 2202 private void waitForTransport( 2203 @NonNull final TestableNetworkCallback cb, final int expectedTransport) { 2204 cb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED, 2205 NETWORK_CALLBACK_TIMEOUT_MS, 2206 entry -> ((CallbackEntry.CapabilitiesChanged) entry).getCaps() 2207 .hasTransport(expectedTransport)); 2208 } 2209 2210 private void waitForAvailable( 2211 @NonNull final TestableNetworkCallback cb, @NonNull final Network expectedNetwork) { 2212 cb.expectAvailableCallbacks(expectedNetwork, false /* suspended */, 2213 null /* validated */, 2214 false /* blocked */, NETWORK_CALLBACK_TIMEOUT_MS); 2215 } 2216 2217 private void waitForLost(@NonNull final TestableNetworkCallback cb) { 2218 cb.eventuallyExpect(CallbackEntry.LOST, NETWORK_CALLBACK_TIMEOUT_MS, 2219 c -> c instanceof CallbackEntry.Lost); 2220 } 2221 2222 private void setAndVerifyAirplaneMode(Boolean expectedResult) 2223 throws Exception { 2224 final CompletableFuture<Boolean> actualResult = new CompletableFuture(); 2225 BroadcastReceiver receiver = new BroadcastReceiver() { 2226 @Override 2227 public void onReceive(Context context, Intent intent) { 2228 // The defaultValue of getExtraBoolean should be the opposite of what is 2229 // expected, thus ensuring a test failure if the extra is absent. 2230 actualResult.complete(intent.getBooleanExtra("state", !expectedResult)); 2231 } 2232 }; 2233 try { 2234 mContext.registerReceiver(receiver, 2235 new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED)); 2236 mCm.setAirplaneMode(expectedResult); 2237 final String msg = "Setting Airplane Mode failed,"; 2238 assertEquals(msg, expectedResult, actualResult.get(AIRPLANE_MODE_CHANGE_TIMEOUT_MS, 2239 TimeUnit.MILLISECONDS)); 2240 } finally { 2241 mContext.unregisterReceiver(receiver); 2242 } 2243 } 2244 2245 private static boolean isAirplaneModeEnabled() { 2246 return runShellCommand("cmd connectivity airplane-mode") 2247 .trim().equals("enabled"); 2248 } 2249 2250 @Test 2251 public void testGetCaptivePortalServerUrl() { 2252 final String permission = Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q 2253 ? CONNECTIVITY_INTERNAL 2254 : NETWORK_SETTINGS; 2255 final String url = runAsShell(permission, mCm::getCaptivePortalServerUrl); 2256 assertNotNull("getCaptivePortalServerUrl must not be null", url); 2257 try { 2258 final URL parsedUrl = new URL(url); 2259 // As per the javadoc, the URL must be HTTP 2260 assertEquals("Invalid captive portal URL protocol", "http", parsedUrl.getProtocol()); 2261 } catch (MalformedURLException e) { 2262 throw new AssertionFailedError("Captive portal server URL is invalid: " + e); 2263 } 2264 } 2265 2266 /** 2267 * Verifies that apps are forbidden from getting ssid information from 2268 * {@Code NetworkCapabilities} if they do not hold NETWORK_SETTINGS permission. 2269 * See b/161370134. 2270 */ 2271 @AppModeFull(reason = "Cannot get WifiManager in instant app mode") 2272 @Test 2273 public void testSsidInNetworkCapabilities() throws Exception { 2274 assumeTrue("testSsidInNetworkCapabilities cannot execute unless device supports WiFi", 2275 mPackageManager.hasSystemFeature(FEATURE_WIFI)); 2276 2277 final Network network = mCtsNetUtils.ensureWifiConnected(); 2278 final String ssid = unquoteSSID(mWifiManager.getConnectionInfo().getSSID()); 2279 assertNotNull("Ssid getting from WifiManager is null", ssid); 2280 // This package should have no NETWORK_SETTINGS permission. Verify that no ssid is contained 2281 // in the NetworkCapabilities. 2282 verifySsidFromQueriedNetworkCapabilities(network, ssid, false /* hasSsid */); 2283 verifySsidFromCallbackNetworkCapabilities(ssid, false /* hasSsid */); 2284 // Adopt shell permission to allow to get ssid information. 2285 runWithShellPermissionIdentity(() -> { 2286 verifySsidFromQueriedNetworkCapabilities(network, ssid, true /* hasSsid */); 2287 verifySsidFromCallbackNetworkCapabilities(ssid, true /* hasSsid */); 2288 }); 2289 } 2290 2291 private void verifySsidFromQueriedNetworkCapabilities(@NonNull Network network, 2292 @NonNull String ssid, boolean hasSsid) throws Exception { 2293 // Verify if ssid is contained in NetworkCapabilities queried from ConnectivityManager. 2294 final NetworkCapabilities nc = mCm.getNetworkCapabilities(network); 2295 assertNotNull("NetworkCapabilities of the network is null", nc); 2296 assertEquals(hasSsid, Pattern.compile(ssid).matcher(nc.toString()).find()); 2297 } 2298 2299 private void verifySsidFromCallbackNetworkCapabilities(@NonNull String ssid, boolean hasSsid) 2300 throws Exception { 2301 final CompletableFuture<NetworkCapabilities> foundNc = new CompletableFuture(); 2302 final NetworkCallback callback = new NetworkCallback() { 2303 @Override 2304 public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) { 2305 foundNc.complete(nc); 2306 } 2307 }; 2308 2309 registerNetworkCallback(makeWifiNetworkRequest(), callback); 2310 // Registering a callback here guarantees onCapabilitiesChanged is called immediately 2311 // because WiFi network should be connected. 2312 final NetworkCapabilities nc = 2313 foundNc.get(NETWORK_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS); 2314 // Verify if ssid is contained in the NetworkCapabilities received from callback. 2315 assertNotNull("NetworkCapabilities of the network is null", nc); 2316 assertEquals(hasSsid, Pattern.compile(ssid).matcher(nc.toString()).find()); 2317 } 2318 2319 /** 2320 * Verify background request can only be requested when acquiring 2321 * {@link android.Manifest.permission.NETWORK_SETTINGS}. 2322 */ 2323 @AppModeFull(reason = "Instant apps cannot create test networks") 2324 @Test 2325 public void testRequestBackgroundNetwork() { 2326 // Cannot use @IgnoreUpTo(Build.VERSION_CODES.R) because this test also requires API 31 2327 // shims, and @IgnoreUpTo does not check that. 2328 assumeTrue(TestUtils.shouldTestSApis()); 2329 2330 // Create a tun interface. Use the returned interface name as the specifier to create 2331 // a test network request. 2332 final TestNetworkManager tnm = runWithShellPermissionIdentity(() -> 2333 mContext.getSystemService(TestNetworkManager.class), 2334 android.Manifest.permission.MANAGE_TEST_NETWORKS); 2335 final TestNetworkInterface testNetworkInterface = runWithShellPermissionIdentity(() -> 2336 tnm.createTunInterface(new LinkAddress[]{TEST_LINKADDR}), 2337 android.Manifest.permission.MANAGE_TEST_NETWORKS, 2338 android.Manifest.permission.NETWORK_SETTINGS); 2339 assertNotNull(testNetworkInterface); 2340 2341 final NetworkRequest testRequest = new NetworkRequest.Builder() 2342 .addTransportType(TRANSPORT_TEST) 2343 // Test networks do not have NOT_VPN or TRUSTED capabilities by default 2344 .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) 2345 .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) 2346 .setNetworkSpecifier(CompatUtil.makeTestNetworkSpecifier( 2347 testNetworkInterface.getInterfaceName())) 2348 .build(); 2349 2350 // Verify background network cannot be requested without NETWORK_SETTINGS permission. 2351 final TestableNetworkCallback callback = new TestableNetworkCallback(); 2352 final Handler handler = new Handler(Looper.getMainLooper()); 2353 assertThrows(SecurityException.class, 2354 () -> requestBackgroundNetwork(testRequest, callback, handler)); 2355 2356 Network testNetwork = null; 2357 try { 2358 // Request background test network via Shell identity which has NETWORK_SETTINGS 2359 // permission granted. 2360 runWithShellPermissionIdentity( 2361 () -> requestBackgroundNetwork(testRequest, callback, handler), 2362 new String[] { android.Manifest.permission.NETWORK_SETTINGS }); 2363 2364 // Register the test network agent which has no foreground request associated to it. 2365 // And verify it can satisfy the background network request just fired. 2366 final Binder binder = new Binder(); 2367 runWithShellPermissionIdentity(() -> 2368 tnm.setupTestNetwork(testNetworkInterface.getInterfaceName(), binder), 2369 new String[] { android.Manifest.permission.MANAGE_TEST_NETWORKS, 2370 android.Manifest.permission.NETWORK_SETTINGS }); 2371 waitForAvailable(callback); 2372 testNetwork = callback.getLastAvailableNetwork(); 2373 assertNotNull(testNetwork); 2374 2375 // The test network that has just connected is a foreground network, 2376 // non-listen requests will get available callback before it can be put into 2377 // background if no foreground request can be satisfied. Thus, wait for a short 2378 // period is needed to let foreground capability go away. 2379 callback.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED, 2380 NETWORK_CALLBACK_TIMEOUT_MS, 2381 c -> c instanceof CallbackEntry.CapabilitiesChanged 2382 && !((CallbackEntry.CapabilitiesChanged) c).getCaps() 2383 .hasCapability(NET_CAPABILITY_FOREGROUND)); 2384 final NetworkCapabilities nc = mCm.getNetworkCapabilities(testNetwork); 2385 assertFalse("expected background network, but got " + nc, 2386 nc.hasCapability(NET_CAPABILITY_FOREGROUND)); 2387 } finally { 2388 final Network n = testNetwork; 2389 runWithShellPermissionIdentity(() -> { 2390 if (null != n) { 2391 tnm.teardownTestNetwork(n); 2392 callback.eventuallyExpect(CallbackEntry.LOST, 2393 NETWORK_CALLBACK_TIMEOUT_MS, 2394 lost -> n.equals(lost.getNetwork())); 2395 } 2396 testNetworkInterface.getFileDescriptor().close(); 2397 }, new String[] { android.Manifest.permission.MANAGE_TEST_NETWORKS }); 2398 } 2399 } 2400 2401 private class DetailedBlockedStatusCallback extends TestableNetworkCallback { 2402 public void expectAvailableCallbacksWithBlockedReasonNone(Network network) { 2403 super.expectAvailableCallbacks(network, false /* suspended */, true /* validated */, 2404 BLOCKED_REASON_NONE, NETWORK_CALLBACK_TIMEOUT_MS); 2405 } 2406 public void eventuallyExpectBlockedStatusCallback(Network network, int blockedStatus) { 2407 super.eventuallyExpect(CallbackEntry.BLOCKED_STATUS_INT, NETWORK_CALLBACK_TIMEOUT_MS, 2408 (it) -> it.getNetwork().equals(network) && it.getReason() == blockedStatus); 2409 } 2410 public void onBlockedStatusChanged(Network network, int blockedReasons) { 2411 Log.v(TAG, "onBlockedStatusChanged " + network + " " + blockedReasons); 2412 getHistory().add(new CallbackEntry.BlockedStatusInt(network, blockedReasons)); 2413 } 2414 private void assertNoBlockedStatusCallback() { 2415 super.assertNoCallback(NO_CALLBACK_TIMEOUT_MS, 2416 c -> c instanceof CallbackEntry.BlockedStatus); 2417 } 2418 } 2419 2420 private void setRequireVpnForUids(boolean requireVpn, Collection<Range<Integer>> ranges) 2421 throws Exception { 2422 mCmShim.setRequireVpnForUids(requireVpn, ranges); 2423 for (Range<Integer> range : ranges) { 2424 if (requireVpn) { 2425 mVpnRequiredUidRanges.add(range); 2426 } else { 2427 assertTrue(mVpnRequiredUidRanges.remove(range)); 2428 } 2429 } 2430 } 2431 2432 @AppModeFull(reason = "Cannot get WifiManager in instant app mode") 2433 @Test 2434 public void testBlockedStatusCallback() throws Exception { 2435 // Cannot use @IgnoreUpTo(Build.VERSION_CODES.R) because this test also requires API 31 2436 // shims, and @IgnoreUpTo does not check that. 2437 assumeTrue(TestUtils.shouldTestSApis()); 2438 // The test will need a stable active network that is persistent during the test. 2439 // Try to connect to a wifi network and wait for it becomes the default network before 2440 // starting the test to prevent from sudden active network change caused by previous 2441 // executed tests. 2442 if (mPackageManager.hasSystemFeature(FEATURE_WIFI)) { 2443 final Network expectedDefaultNetwork = mCtsNetUtils.ensureWifiConnected(); 2444 mCtsNetUtils.expectNetworkIsSystemDefault(expectedDefaultNetwork); 2445 } 2446 2447 final DetailedBlockedStatusCallback myUidCallback = new DetailedBlockedStatusCallback(); 2448 final DetailedBlockedStatusCallback otherUidCallback = new DetailedBlockedStatusCallback(); 2449 2450 final int myUid = Process.myUid(); 2451 final int otherUid = UserHandle.getUid(5, Process.FIRST_APPLICATION_UID); 2452 final Handler handler = new Handler(Looper.getMainLooper()); 2453 2454 registerDefaultNetworkCallback(myUidCallback, handler); 2455 runWithShellPermissionIdentity(() -> registerDefaultNetworkCallbackForUid( 2456 otherUid, otherUidCallback, handler), NETWORK_SETTINGS); 2457 2458 final Network defaultNetwork = myUidCallback.expect(CallbackEntry.AVAILABLE).getNetwork(); 2459 final List<DetailedBlockedStatusCallback> allCallbacks = 2460 List.of(myUidCallback, otherUidCallback); 2461 for (DetailedBlockedStatusCallback callback : allCallbacks) { 2462 callback.eventuallyExpectBlockedStatusCallback(defaultNetwork, BLOCKED_REASON_NONE); 2463 } 2464 2465 final Range<Integer> myUidRange = new Range<>(myUid, myUid); 2466 final Range<Integer> otherUidRange = new Range<>(otherUid, otherUid); 2467 2468 runWithShellPermissionIdentity(() -> setRequireVpnForUids( 2469 true, List.of(myUidRange)), NETWORK_SETTINGS); 2470 myUidCallback.eventuallyExpectBlockedStatusCallback(defaultNetwork, 2471 BLOCKED_REASON_LOCKDOWN_VPN); 2472 otherUidCallback.assertNoBlockedStatusCallback(); 2473 2474 runWithShellPermissionIdentity(() -> setRequireVpnForUids( 2475 true, List.of(myUidRange, otherUidRange)), NETWORK_SETTINGS); 2476 myUidCallback.assertNoBlockedStatusCallback(); 2477 otherUidCallback.eventuallyExpectBlockedStatusCallback(defaultNetwork, 2478 BLOCKED_REASON_LOCKDOWN_VPN); 2479 2480 // setRequireVpnForUids does no deduplication or refcounting. Removing myUidRange does not 2481 // unblock myUid because it was added to the blocked ranges twice. 2482 runWithShellPermissionIdentity(() -> 2483 setRequireVpnForUids(false, List.of(myUidRange)), NETWORK_SETTINGS); 2484 myUidCallback.assertNoBlockedStatusCallback(); 2485 otherUidCallback.assertNoBlockedStatusCallback(); 2486 2487 runWithShellPermissionIdentity(() -> setRequireVpnForUids( 2488 false, List.of(myUidRange, otherUidRange)), NETWORK_SETTINGS); 2489 myUidCallback.eventuallyExpectBlockedStatusCallback(defaultNetwork, BLOCKED_REASON_NONE); 2490 otherUidCallback.eventuallyExpectBlockedStatusCallback(defaultNetwork, BLOCKED_REASON_NONE); 2491 2492 myUidCallback.assertNoBlockedStatusCallback(); 2493 otherUidCallback.assertNoBlockedStatusCallback(); 2494 } 2495 2496 @Test 2497 public void testSetVpnDefaultForUids() { 2498 assumeTrue(TestUtils.shouldTestUApis()); 2499 final String session = UUID.randomUUID().toString(); 2500 assertThrows(NullPointerException.class, () -> mCm.setVpnDefaultForUids(session, null)); 2501 assertThrows(SecurityException.class, 2502 () -> mCm.setVpnDefaultForUids(session, new ArraySet<>())); 2503 // For testing the complete behavior of setVpnDefaultForUids(), please refer to 2504 // HostsideVpnTests. 2505 } 2506 2507 private void doTestLegacyLockdownEnabled() throws Exception { 2508 NetworkInfo info = mCm.getActiveNetworkInfo(); 2509 assertNotNull(info); 2510 assertEquals(DetailedState.CONNECTED, info.getDetailedState()); 2511 2512 final TestableNetworkCallback callback = new TestableNetworkCallback(); 2513 try { 2514 mCmShim.setLegacyLockdownVpnEnabled(true); 2515 2516 // setLegacyLockdownVpnEnabled is asynchronous and only takes effect when the 2517 // ConnectivityService handler thread processes it. Ensure it has taken effect by doing 2518 // something that blocks until the handler thread is idle. 2519 registerDefaultNetworkCallback(callback); 2520 waitForAvailable(callback); 2521 2522 // Test one of the effects of setLegacyLockdownVpnEnabled: the fact that any NetworkInfo 2523 // in state CONNECTED is degraded to CONNECTING if the legacy VPN is not connected. 2524 info = mCm.getActiveNetworkInfo(); 2525 assertNotNull(info); 2526 assertEquals(DetailedState.CONNECTING, info.getDetailedState()); 2527 } finally { 2528 mCmShim.setLegacyLockdownVpnEnabled(false); 2529 } 2530 } 2531 2532 @Test 2533 public void testLegacyLockdownEnabled() { 2534 // Cannot use @IgnoreUpTo(Build.VERSION_CODES.R) because this test also requires API 31 2535 // shims, and @IgnoreUpTo does not check that. 2536 assumeTrue(TestUtils.shouldTestSApis()); 2537 runWithShellPermissionIdentity(() -> doTestLegacyLockdownEnabled(), NETWORK_SETTINGS); 2538 } 2539 2540 @Test 2541 public void testGetCapabilityCarrierName() { 2542 assumeTrue(TestUtils.shouldTestSApis()); 2543 assertEquals("ENTERPRISE", NetworkInformationShimImpl.newInstance() 2544 .getCapabilityCarrierName(ConstantsShim.NET_CAPABILITY_ENTERPRISE)); 2545 assertNull(NetworkInformationShimImpl.newInstance() 2546 .getCapabilityCarrierName(ConstantsShim.NET_CAPABILITY_NOT_VCN_MANAGED)); 2547 } 2548 2549 @Test 2550 public void testSetGlobalProxy() { 2551 assumeTrue(TestUtils.shouldTestSApis()); 2552 // Behavior is verified in gts. Verify exception thrown w/o permission. 2553 assertThrows(SecurityException.class, () -> mCm.setGlobalProxy( 2554 ProxyInfo.buildDirectProxy("example.com" /* host */, 8080 /* port */))); 2555 } 2556 2557 @Test 2558 public void testFactoryResetWithoutPermission() { 2559 assumeTrue(TestUtils.shouldTestSApis()); 2560 assertThrows(SecurityException.class, () -> mCm.factoryReset()); 2561 } 2562 2563 @AppModeFull(reason = "Cannot get WifiManager in instant app mode") 2564 @Test 2565 public void testFactoryReset() throws Exception { 2566 assumeTrue(TestUtils.shouldTestSApis()); 2567 2568 // Store current settings. 2569 final int curAvoidBadWifi = 2570 ConnectivitySettingsManager.getNetworkAvoidBadWifi(mContext); 2571 final int curPrivateDnsMode = ConnectivitySettingsManager.getPrivateDnsMode(mContext); 2572 2573 final CtsTetheringUtils tetherUtils = new CtsTetheringUtils(mContext); 2574 final TestTetheringEventCallback tetherEventCallback = 2575 tetherUtils.registerTetheringEventCallback(); 2576 try { 2577 tetherEventCallback.assumeWifiTetheringSupported(mContext); 2578 // To prevent WiFi-to-WiFi interruption while entering APM: 2579 // - If WiFi is retained while entering APM, hotspot will also remain enabled. 2580 // - If WiFi is off before APM or disabled while entering APM, hotspot will be 2581 // disabled. 2582 // 2583 // To ensure hotspot always be disabled after enabling APM, disable wifi before 2584 // enabling the hotspot. 2585 mCtsNetUtils.disableWifi(); 2586 2587 tetherUtils.startWifiTethering(tetherEventCallback); 2588 // Update setting to verify the behavior. 2589 setAirplaneMode(true); 2590 // Verify softap lost to make sure airplane mode takes effect. This could 2591 // prevent the race condition between airplane mode enabled and the followed 2592 // up wifi tethering enabled. 2593 tetherEventCallback.expectNoTetheringActive(); 2594 2595 // start wifi tethering 2596 tetherUtils.startWifiTethering(tetherEventCallback); 2597 2598 ConnectivitySettingsManager.setPrivateDnsMode(mContext, 2599 ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF); 2600 ConnectivitySettingsManager.setNetworkAvoidBadWifi(mContext, 2601 ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI_IGNORE); 2602 assertEquals(AIRPLANE_MODE_ON, Settings.Global.getInt( 2603 mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON)); 2604 // Verify factoryReset 2605 runAsShell(NETWORK_SETTINGS, TETHER_PRIVILEGED, () -> { 2606 mCm.factoryReset(); 2607 tetherEventCallback.expectNoTetheringActive(); 2608 }); 2609 verifySettings(AIRPLANE_MODE_OFF, 2610 ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNISTIC, 2611 ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI_PROMPT); 2612 } finally { 2613 // Restore settings. 2614 setAirplaneMode(false); 2615 ConnectivitySettingsManager.setNetworkAvoidBadWifi(mContext, curAvoidBadWifi); 2616 ConnectivitySettingsManager.setPrivateDnsMode(mContext, curPrivateDnsMode); 2617 tetherUtils.unregisterTetheringEventCallback(tetherEventCallback); 2618 tetherUtils.stopAllTethering(); 2619 mCtsNetUtils.ensureWifiConnected(); 2620 } 2621 } 2622 2623 private void setAirplaneMode(boolean enable) { 2624 runAsShell(NETWORK_SETTINGS, () -> mCm.setAirplaneMode(enable)); 2625 } 2626 2627 /** 2628 * Verify that {@link ConnectivityManager#setProfileNetworkPreference} cannot be called 2629 * without required NETWORK_STACK permissions. 2630 */ 2631 @Test 2632 public void testSetProfileNetworkPreference_NoPermission() { 2633 // Cannot use @IgnoreUpTo(Build.VERSION_CODES.R) because this test also requires API 31 2634 // shims, and @IgnoreUpTo does not check that. 2635 assumeTrue(TestUtils.shouldTestSApis()); 2636 assertThrows(SecurityException.class, () -> mCm.setProfileNetworkPreference( 2637 UserHandle.of(0), PROFILE_NETWORK_PREFERENCE_ENTERPRISE, null /* executor */, 2638 null /* listener */)); 2639 } 2640 2641 @Test 2642 public void testSystemReady() { 2643 assumeTrue(TestUtils.shouldTestSApis()); 2644 assertThrows(SecurityException.class, () -> mCm.systemReady()); 2645 } 2646 2647 @Test 2648 public void testGetIpSecNetIdRange() { 2649 assumeTrue(TestUtils.shouldTestSApis()); 2650 // The lower refers to ConnectivityManager.TUN_INTF_NETID_START. 2651 final long lower = 64512; 2652 // The upper refers to ConnectivityManager.TUN_INTF_NETID_START 2653 // + ConnectivityManager.TUN_INTF_NETID_RANGE - 1 2654 final long upper = 65535; 2655 assertEquals(lower, (long) ConnectivityManager.getIpSecNetIdRange().getLower()); 2656 assertEquals(upper, (long) ConnectivityManager.getIpSecNetIdRange().getUpper()); 2657 } 2658 2659 private void verifySettings(int expectedAirplaneMode, int expectedPrivateDnsMode, 2660 int expectedAvoidBadWifi) throws Exception { 2661 assertEquals(expectedAirplaneMode, Settings.Global.getInt( 2662 mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON)); 2663 assertEquals(expectedPrivateDnsMode, 2664 ConnectivitySettingsManager.getPrivateDnsMode(mContext)); 2665 assertEquals(expectedAvoidBadWifi, 2666 ConnectivitySettingsManager.getNetworkAvoidBadWifi(mContext)); 2667 } 2668 2669 /** 2670 * Verify that per-app OEM network preference functions as expected for network preference TEST. 2671 * For specified apps, validate networks are prioritized in order: unmetered, TEST transport, 2672 * default network. 2673 */ 2674 @AppModeFull(reason = "Instant apps cannot create test networks") 2675 @Test 2676 public void testSetOemNetworkPreferenceForTestPref() throws Exception { 2677 // Cannot use @IgnoreUpTo(Build.VERSION_CODES.R) because this test also requires API 31 2678 // shims, and @IgnoreUpTo does not check that. 2679 assumeTrue(TestUtils.shouldTestSApis()); 2680 assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI)); 2681 2682 final TestNetworkTracker tnt = callWithShellPermissionIdentity( 2683 () -> initTestNetwork(mContext, TEST_LINKADDR, NETWORK_CALLBACK_TIMEOUT_MS)); 2684 final TestableNetworkCallback defaultCallback = new TestableNetworkCallback(); 2685 final TestableNetworkCallback systemDefaultCallback = new TestableNetworkCallback(); 2686 2687 final Network wifiNetwork = mCtsNetUtils.ensureWifiConnected(); 2688 final NetworkCapabilities wifiNetworkCapabilities = callWithShellPermissionIdentity( 2689 () -> mCm.getNetworkCapabilities(wifiNetwork)); 2690 final String ssid = unquoteSSID(wifiNetworkCapabilities.getSsid()); 2691 final boolean oldMeteredValue = wifiNetworkCapabilities.isMetered(); 2692 2693 testAndCleanup(() -> { 2694 // This network will be used for unmetered. Wait for it to be validated because 2695 // OEM_NETWORK_PREFERENCE_TEST only prefers NOT_METERED&VALIDATED to a network with 2696 // TRANSPORT_TEST, like OEM_NETWORK_PREFERENCE_OEM_PAID. 2697 setWifiMeteredStatusAndWait(ssid, false /* isMetered */, true /* waitForValidation */); 2698 2699 setOemNetworkPreferenceForMyPackage(OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST); 2700 registerTestOemNetworkPreferenceCallbacks(defaultCallback, systemDefaultCallback); 2701 2702 // Validate that an unmetered network is used over other networks. 2703 waitForAvailable(defaultCallback, wifiNetwork); 2704 systemDefaultCallback.eventuallyExpect(CallbackEntry.AVAILABLE, 2705 NETWORK_CALLBACK_TIMEOUT_MS, cb -> wifiNetwork.equals(cb.getNetwork())); 2706 2707 // Validate that when setting unmetered to metered, unmetered is lost and replaced by 2708 // the network with the TEST transport. Also wait for validation here, in case there 2709 // is a bug that's only visible when the network is validated. 2710 setWifiMeteredStatusAndWait(ssid, true /* isMetered */, true /* waitForValidation */); 2711 defaultCallback.expect(CallbackEntry.LOST, wifiNetwork, NETWORK_CALLBACK_TIMEOUT_MS); 2712 waitForAvailable(defaultCallback, tnt.getNetwork()); 2713 // Depending on if this device has cellular connectivity or not, multiple available 2714 // callbacks may be received. Eventually, metered Wi-Fi should be the final available 2715 // callback in any case therefore confirm its receipt before continuing to assure the 2716 // system is in the expected state. 2717 waitForTransport(systemDefaultCallback, TRANSPORT_WIFI); 2718 }, /* cleanup */ () -> { 2719 // Validate that removing the test network will fallback to the default network. 2720 runWithShellPermissionIdentity(tnt::teardown); 2721 // The other callbacks (LP or NC changes) would receive before LOST callback. Use 2722 // eventuallyExpect to check callback for avoiding test flake. 2723 defaultCallback.eventuallyExpect(CallbackEntry.LOST, NETWORK_CALLBACK_TIMEOUT_MS, 2724 lost -> tnt.getNetwork().equals(lost.getNetwork())); 2725 waitForAvailable(defaultCallback); 2726 }, /* cleanup */ () -> { 2727 setWifiMeteredStatusAndWait(ssid, oldMeteredValue, false /* waitForValidation */); 2728 }, /* cleanup */ () -> { 2729 // Cleanup any prior test state from setOemNetworkPreference 2730 clearOemNetworkPreference(); 2731 }); 2732 } 2733 2734 /** 2735 * Verify that per-app OEM network preference functions as expected for network pref TEST_ONLY. 2736 * For specified apps, validate that only TEST transport type networks are used. 2737 */ 2738 @AppModeFull(reason = "Instant apps cannot create test networks") 2739 @Test 2740 public void testSetOemNetworkPreferenceForTestOnlyPref() throws Exception { 2741 // Cannot use @IgnoreUpTo(Build.VERSION_CODES.R) because this test also requires API 31 2742 // shims, and @IgnoreUpTo does not check that. 2743 assumeTrue(TestUtils.shouldTestSApis()); 2744 assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI)); 2745 2746 final TestNetworkTracker tnt = callWithShellPermissionIdentity( 2747 () -> initTestNetwork(mContext, TEST_LINKADDR, NETWORK_CALLBACK_TIMEOUT_MS)); 2748 final TestableNetworkCallback defaultCallback = new TestableNetworkCallback(); 2749 final TestableNetworkCallback systemDefaultCallback = new TestableNetworkCallback(); 2750 2751 final Network wifiNetwork = mCtsNetUtils.ensureWifiConnected(); 2752 2753 testAndCleanup(() -> { 2754 setOemNetworkPreferenceForMyPackage( 2755 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST_ONLY); 2756 registerTestOemNetworkPreferenceCallbacks(defaultCallback, systemDefaultCallback); 2757 waitForAvailable(defaultCallback, tnt.getNetwork()); 2758 systemDefaultCallback.eventuallyExpect(CallbackEntry.AVAILABLE, 2759 NETWORK_CALLBACK_TIMEOUT_MS, cb -> wifiNetwork.equals(cb.getNetwork())); 2760 }, /* cleanup */ () -> { 2761 runWithShellPermissionIdentity(tnt::teardown); 2762 defaultCallback.expect(CallbackEntry.LOST, tnt, NETWORK_CALLBACK_TIMEOUT_MS); 2763 2764 // This network preference should only ever use the test network therefore available 2765 // should not trigger when the test network goes down (e.g. switch to cellular). 2766 defaultCallback.assertNoCallback(); 2767 // The system default should still be connected to Wi-fi 2768 assertEquals(wifiNetwork, systemDefaultCallback.getLastAvailableNetwork()); 2769 }, /* cleanup */ () -> { 2770 // Cleanup any prior test state from setOemNetworkPreference 2771 clearOemNetworkPreference(); 2772 2773 // The default (non-test) network should be available as the network pref was 2774 // cleared. 2775 waitForAvailable(defaultCallback); 2776 }); 2777 } 2778 2779 private void registerTestOemNetworkPreferenceCallbacks( 2780 @NonNull final TestableNetworkCallback defaultCallback, 2781 @NonNull final TestableNetworkCallback systemDefaultCallback) { 2782 registerDefaultNetworkCallback(defaultCallback); 2783 runWithShellPermissionIdentity(() -> 2784 registerSystemDefaultNetworkCallback(systemDefaultCallback, 2785 new Handler(Looper.getMainLooper())), NETWORK_SETTINGS); 2786 } 2787 2788 private static final class OnCompleteListenerCallback { 2789 final CompletableFuture<Object> mDone = new CompletableFuture<>(); 2790 2791 public void onComplete() { 2792 mDone.complete(new Object()); 2793 } 2794 2795 void expectOnComplete() throws Exception { 2796 try { 2797 mDone.get(NETWORK_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS); 2798 } catch (TimeoutException e) { 2799 fail("Expected onComplete() not received after " 2800 + NETWORK_CALLBACK_TIMEOUT_MS + " ms"); 2801 } 2802 } 2803 } 2804 2805 private void setOemNetworkPreferenceForMyPackage(final int networkPref) throws Exception { 2806 final OemNetworkPreferences pref = new OemNetworkPreferences.Builder() 2807 .addNetworkPreference(mContext.getPackageName(), networkPref) 2808 .build(); 2809 final OnCompleteListenerCallback oemPrefListener = new OnCompleteListenerCallback(); 2810 mUiAutomation.adoptShellPermissionIdentity(); 2811 try { 2812 mCm.setOemNetworkPreference( 2813 pref, mContext.getMainExecutor(), oemPrefListener::onComplete); 2814 } finally { 2815 mUiAutomation.dropShellPermissionIdentity(); 2816 } 2817 oemPrefListener.expectOnComplete(); 2818 } 2819 2820 /** 2821 * This will clear the OEM network preference on the device. As there is currently no way of 2822 * getting the existing preference, if this is executed while an existing preference is in 2823 * place, that preference will need to be reapplied after executing this test. 2824 * @throws Exception 2825 */ 2826 private void clearOemNetworkPreference() throws Exception { 2827 final OemNetworkPreferences clearPref = new OemNetworkPreferences.Builder().build(); 2828 final OnCompleteListenerCallback oemPrefListener = new OnCompleteListenerCallback(); 2829 mUiAutomation.adoptShellPermissionIdentity(); 2830 try { 2831 mCm.setOemNetworkPreference( 2832 clearPref, mContext.getMainExecutor(), oemPrefListener::onComplete); 2833 } finally { 2834 mUiAutomation.dropShellPermissionIdentity(); 2835 } 2836 oemPrefListener.expectOnComplete(); 2837 } 2838 2839 @Test 2840 public void testSetAcceptPartialConnectivity_NoPermission_GetException() { 2841 assumeTrue(TestUtils.shouldTestSApis()); 2842 assertThrows(SecurityException.class, () -> mCm.setAcceptPartialConnectivity( 2843 mCm.getActiveNetwork(), false /* accept */ , false /* always */)); 2844 } 2845 2846 private void ensureCellIsValidatedBeforeMockingValidationUrls() { 2847 // Verify that current supported network is validated so that the mock http server will not 2848 // apply to unexpected networks. Also see aosp/2208680. 2849 // 2850 // This may also apply to wifi in principle, but in practice methods that mock validation 2851 // URL all disconnect wifi forcefully anyway, so don't wait for wifi to validate. 2852 if (mPackageManager.hasSystemFeature(FEATURE_TELEPHONY)) { 2853 ensureValidatedNetwork(makeCellNetworkRequest()); 2854 } 2855 } 2856 2857 private void ensureValidatedNetwork(NetworkRequest request) { 2858 final TestableNetworkCallback cb = new TestableNetworkCallback(); 2859 mCm.registerNetworkCallback(request, cb); 2860 cb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED, 2861 NETWORK_CALLBACK_TIMEOUT_MS, 2862 entry -> ((CallbackEntry.CapabilitiesChanged) entry).getCaps() 2863 .hasCapability(NET_CAPABILITY_VALIDATED)); 2864 mCm.unregisterNetworkCallback(cb); 2865 } 2866 2867 @AppModeFull(reason = "WRITE_DEVICE_CONFIG permission can't be granted to instant apps") 2868 @Test 2869 public void testAcceptPartialConnectivity_validatedNetwork() throws Exception { 2870 assumeTrue(TestUtils.shouldTestSApis()); 2871 assumeTrue("testAcceptPartialConnectivity_validatedNetwork cannot execute" 2872 + " unless device supports WiFi", 2873 mPackageManager.hasSystemFeature(FEATURE_WIFI)); 2874 2875 try { 2876 // Wait for partial connectivity to be detected on the network 2877 final Network network = preparePartialConnectivity(); 2878 2879 runAsShell(NETWORK_SETTINGS, () -> { 2880 // The always bit is verified in NetworkAgentTest 2881 mCm.setAcceptPartialConnectivity(network, true /* accept */, false /* always */); 2882 }); 2883 2884 // Accept partial connectivity network should result in a validated network 2885 expectNetworkHasCapability(network, NET_CAPABILITY_VALIDATED, WIFI_CONNECT_TIMEOUT_MS); 2886 } finally { 2887 mHttpServer.stop(); 2888 mTestValidationConfigRule.runAfterNextCleanup(this::reconnectWifi); 2889 } 2890 } 2891 2892 @AppModeFull(reason = "WRITE_DEVICE_CONFIG permission can't be granted to instant apps") 2893 @Test 2894 public void testRejectPartialConnectivity_TearDownNetwork() throws Exception { 2895 assumeTrue(TestUtils.shouldTestSApis()); 2896 assumeTrue("testAcceptPartialConnectivity_validatedNetwork cannot execute" 2897 + " unless device supports WiFi", 2898 mPackageManager.hasSystemFeature(FEATURE_WIFI)); 2899 2900 final TestNetworkCallback cb = new TestNetworkCallback(); 2901 try { 2902 // Wait for partial connectivity to be detected on the network 2903 final Network network = preparePartialConnectivity(); 2904 2905 requestNetwork(makeWifiNetworkRequest(), cb); 2906 runAsShell(NETWORK_SETTINGS, () -> { 2907 // The always bit is verified in NetworkAgentTest 2908 mCm.setAcceptPartialConnectivity(network, false /* accept */, false /* always */); 2909 }); 2910 // Reject partial connectivity network should cause the network being torn down 2911 assertEquals(network, cb.waitForLost()); 2912 } finally { 2913 mHttpServer.stop(); 2914 // Wifi will not automatically reconnect to the network. ensureWifiDisconnected cannot 2915 // apply here. Thus, turn off wifi first and restart to restore. 2916 mTestValidationConfigRule.runAfterNextCleanup(() -> { 2917 mCtsNetUtils.disableWifi(); 2918 mCtsNetUtils.ensureWifiConnected(); 2919 }); 2920 } 2921 } 2922 2923 @Test 2924 public void testSetAcceptUnvalidated_NoPermission_GetException() { 2925 assumeTrue(TestUtils.shouldTestSApis()); 2926 assertThrows(SecurityException.class, () -> mCm.setAcceptUnvalidated( 2927 mCm.getActiveNetwork(), false /* accept */ , false /* always */)); 2928 } 2929 2930 @AppModeFull(reason = "WRITE_DEVICE_CONFIG permission can't be granted to instant apps") 2931 @Test 2932 public void testRejectUnvalidated_TearDownNetwork() throws Exception { 2933 assumeTrue(TestUtils.shouldTestSApis()); 2934 final boolean canRunTest = mPackageManager.hasSystemFeature(FEATURE_WIFI) 2935 && mPackageManager.hasSystemFeature(FEATURE_TELEPHONY); 2936 assumeTrue("testAcceptPartialConnectivity_validatedNetwork cannot execute" 2937 + " unless device supports WiFi and telephony", canRunTest); 2938 2939 final TestableNetworkCallback wifiCb = new TestableNetworkCallback(); 2940 try { 2941 // Ensure at least one default network candidate connected. 2942 mCtsNetUtils.connectToCell(); 2943 2944 final Network wifiNetwork = prepareUnvalidatedNetwork(); 2945 // Default network should not be wifi ,but checking that wifi is not the default doesn't 2946 // guarantee that it won't become the default in the future. 2947 assertNotEquals(wifiNetwork, mCm.getActiveNetwork()); 2948 2949 registerNetworkCallback(makeWifiNetworkRequest(), wifiCb); 2950 runAsShell(NETWORK_SETTINGS, () -> { 2951 mCm.setAcceptUnvalidated(wifiNetwork, false /* accept */, false /* always */); 2952 }); 2953 waitForLost(wifiCb); 2954 } finally { 2955 mHttpServer.stop(); 2956 /// Wifi will not automatically reconnect to the network. ensureWifiDisconnected cannot 2957 // apply here. Thus, turn off wifi first and restart to restore. 2958 mTestValidationConfigRule.runAfterNextCleanup(() -> { 2959 mCtsNetUtils.disableWifi(); 2960 mCtsNetUtils.ensureWifiConnected(); 2961 }); 2962 } 2963 } 2964 2965 @AppModeFull(reason = "WRITE_DEVICE_CONFIG permission can't be granted to instant apps") 2966 @Test 2967 public void testSetAvoidUnvalidated() throws Exception { 2968 assumeTrue(TestUtils.shouldTestSApis()); 2969 // TODO: Allow in debuggable ROM only. To be replaced by FabricatedOverlay 2970 assumeTrue(Build.isDebuggable()); 2971 final boolean canRunTest = mPackageManager.hasSystemFeature(FEATURE_WIFI) 2972 && mPackageManager.hasSystemFeature(FEATURE_TELEPHONY); 2973 assumeTrue("testSetAvoidUnvalidated cannot execute" 2974 + " unless device supports WiFi and telephony", canRunTest); 2975 2976 final TestableNetworkCallback wifiCb = new TestableNetworkCallback(); 2977 final TestableNetworkCallback defaultCb = new TestableNetworkCallback(); 2978 final int previousAvoidBadWifi = 2979 ConnectivitySettingsManager.getNetworkAvoidBadWifi(mContext); 2980 2981 allowBadWifi(); 2982 2983 final Network cellNetwork = mCtsNetUtils.connectToCell(); 2984 final Network wifiNetwork = prepareValidatedNetwork(); 2985 2986 registerDefaultNetworkCallback(defaultCb); 2987 registerNetworkCallback(makeWifiNetworkRequest(), wifiCb); 2988 2989 try { 2990 // Verify wifi is the default network. 2991 defaultCb.eventuallyExpect(CallbackEntry.AVAILABLE, NETWORK_CALLBACK_TIMEOUT_MS, 2992 entry -> wifiNetwork.equals(entry.getNetwork())); 2993 wifiCb.eventuallyExpect(CallbackEntry.AVAILABLE, NETWORK_CALLBACK_TIMEOUT_MS, 2994 entry -> wifiNetwork.equals(entry.getNetwork())); 2995 assertTrue(mCm.getNetworkCapabilities(wifiNetwork).hasCapability( 2996 NET_CAPABILITY_VALIDATED)); 2997 2998 // The cell network has already been checked to be validated. 2999 // Configure response code for unvalidated network. 3000 configTestServer(Status.INTERNAL_ERROR, Status.INTERNAL_ERROR); 3001 mCm.reportNetworkConnectivity(wifiNetwork, false); 3002 // Default network should stay on unvalidated wifi because avoid bad wifi is disabled. 3003 defaultCb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED, 3004 NETWORK_CALLBACK_TIMEOUT_MS, 3005 entry -> !((CallbackEntry.CapabilitiesChanged) entry).getCaps() 3006 .hasCapability(NET_CAPABILITY_VALIDATED)); 3007 wifiCb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED, 3008 NETWORK_CALLBACK_TIMEOUT_MS, 3009 entry -> !((CallbackEntry.CapabilitiesChanged) entry).getCaps() 3010 .hasCapability(NET_CAPABILITY_VALIDATED)); 3011 3012 runAsShell(NETWORK_SETTINGS, () -> { 3013 mCm.setAvoidUnvalidated(wifiNetwork); 3014 }); 3015 // Default network should be updated to validated cellular network. 3016 defaultCb.eventuallyExpect(CallbackEntry.AVAILABLE, NETWORK_CALLBACK_TIMEOUT_MS, 3017 entry -> cellNetwork.equals(entry.getNetwork())); 3018 // The network should not validate again. 3019 wifiCb.assertNoCallback(NO_CALLBACK_TIMEOUT_MS, c -> isValidatedCaps(c)); 3020 } finally { 3021 resetAvoidBadWifi(previousAvoidBadWifi); 3022 mHttpServer.stop(); 3023 mTestValidationConfigRule.runAfterNextCleanup(this::reconnectWifi); 3024 } 3025 } 3026 3027 private boolean isValidatedCaps(CallbackEntry c) { 3028 if (!(c instanceof CallbackEntry.CapabilitiesChanged)) return false; 3029 final CallbackEntry.CapabilitiesChanged capsChanged = (CallbackEntry.CapabilitiesChanged) c; 3030 return capsChanged.getCaps().hasCapability(NET_CAPABILITY_VALIDATED); 3031 } 3032 3033 private void resetAvoidBadWifi(int settingValue) { 3034 setTestAllowBadWifiResource(0 /* timeMs */); 3035 ConnectivitySettingsManager.setNetworkAvoidBadWifi(mContext, settingValue); 3036 } 3037 3038 private void allowBadWifi() { 3039 setTestAllowBadWifiResource( 3040 System.currentTimeMillis() + WIFI_CONNECT_TIMEOUT_MS /* timeMs */); 3041 ConnectivitySettingsManager.setNetworkAvoidBadWifi(mContext, 3042 ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI_IGNORE); 3043 } 3044 3045 private void setTestAllowBadWifiResource(long timeMs) { 3046 runAsShell(NETWORK_SETTINGS, () -> { 3047 mCm.setTestAllowBadWifiUntil(timeMs); 3048 }); 3049 } 3050 3051 private Network expectNetworkHasCapability(Network network, int expectedNetCap, long timeout) 3052 throws Exception { 3053 final CompletableFuture<Network> future = new CompletableFuture(); 3054 final NetworkCallback cb = new NetworkCallback() { 3055 @Override 3056 public void onCapabilitiesChanged(Network n, NetworkCapabilities nc) { 3057 if (n.equals(network) && nc.hasCapability(expectedNetCap)) { 3058 future.complete(network); 3059 } 3060 } 3061 }; 3062 3063 registerNetworkCallback(new NetworkRequest.Builder().build(), cb); 3064 return future.get(timeout, TimeUnit.MILLISECONDS); 3065 } 3066 3067 private void prepareHttpServer() throws Exception { 3068 runAsShell(READ_DEVICE_CONFIG, () -> { 3069 // Verify that the test URLs are not normally set on the device, but do not fail if the 3070 // test URLs are set to what this test uses (URLs on localhost), in case the test was 3071 // interrupted manually and rerun. 3072 assertEmptyOrLocalhostUrl(TEST_CAPTIVE_PORTAL_HTTPS_URL); 3073 assertEmptyOrLocalhostUrl(TEST_CAPTIVE_PORTAL_HTTP_URL); 3074 }); 3075 3076 NetworkValidationTestUtil.clearValidationTestUrlsDeviceConfig(); 3077 3078 mHttpServer.start(); 3079 } 3080 3081 private Network reconnectWifi() { 3082 mCtsNetUtils.ensureWifiDisconnected(null /* wifiNetworkToCheck */); 3083 return mCtsNetUtils.ensureWifiConnected(); 3084 } 3085 3086 private Network prepareValidatedNetwork() throws Exception { 3087 ensureCellIsValidatedBeforeMockingValidationUrls(); 3088 3089 prepareHttpServer(); 3090 configTestServer(Status.NO_CONTENT, Status.NO_CONTENT); 3091 // Disconnect wifi first then start wifi network with configuration. 3092 final Network wifiNetwork = reconnectWifi(); 3093 3094 return expectNetworkHasCapability(wifiNetwork, NET_CAPABILITY_VALIDATED, 3095 WIFI_CONNECT_TIMEOUT_MS); 3096 } 3097 3098 private Network preparePartialConnectivity() throws Exception { 3099 ensureCellIsValidatedBeforeMockingValidationUrls(); 3100 3101 prepareHttpServer(); 3102 // Configure response code for partial connectivity 3103 configTestServer(Status.INTERNAL_ERROR /* httpsStatusCode */, 3104 Status.NO_CONTENT /* httpStatusCode */); 3105 // Disconnect wifi first then start wifi network with configuration. 3106 mCtsNetUtils.ensureWifiDisconnected(null /* wifiNetworkToCheck */); 3107 final Network network = mCtsNetUtils.ensureWifiConnected(); 3108 3109 return expectNetworkHasCapability(network, NET_CAPABILITY_PARTIAL_CONNECTIVITY, 3110 WIFI_CONNECT_TIMEOUT_MS); 3111 } 3112 3113 private Network prepareUnvalidatedNetwork() throws Exception { 3114 ensureCellIsValidatedBeforeMockingValidationUrls(); 3115 3116 prepareHttpServer(); 3117 // Configure response code for unvalidated network 3118 configTestServer(Status.INTERNAL_ERROR /* httpsStatusCode */, 3119 Status.INTERNAL_ERROR /* httpStatusCode */); 3120 3121 // Disconnect wifi first then start wifi network with configuration. 3122 mCtsNetUtils.ensureWifiDisconnected(null /* wifiNetworkToCheck */); 3123 final Network wifiNetwork = mCtsNetUtils.ensureWifiConnected(); 3124 return expectNetworkHasCapability(wifiNetwork, NET_CAPABILITY_INTERNET, 3125 WIFI_CONNECT_TIMEOUT_MS); 3126 } 3127 3128 private String makeUrl(String path) { 3129 return "http://localhost:" + mHttpServer.getListeningPort() + path; 3130 } 3131 3132 private void assertEmptyOrLocalhostUrl(String urlKey) { 3133 final String url = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_CONNECTIVITY, urlKey); 3134 assertTrue(urlKey + " must not be set in production scenarios, current value= " + url, 3135 TextUtils.isEmpty(url) || LOCALHOST_HOSTNAME.equals(Uri.parse(url).getHost())); 3136 } 3137 3138 private void configTestServer(IStatus httpsStatusCode, IStatus httpStatusCode) { 3139 mHttpServer.addResponse(new TestHttpServer.Request( 3140 TEST_HTTPS_URL_PATH, Method.GET, "" /* queryParameters */), 3141 httpsStatusCode, null /* locationHeader */, "" /* content */); 3142 mHttpServer.addResponse(new TestHttpServer.Request( 3143 TEST_HTTP_URL_PATH, Method.GET, "" /* queryParameters */), 3144 httpStatusCode, null /* locationHeader */, "" /* content */); 3145 NetworkValidationTestUtil.setHttpsUrlDeviceConfig(mTestValidationConfigRule, 3146 makeUrl(TEST_HTTPS_URL_PATH)); 3147 NetworkValidationTestUtil.setHttpUrlDeviceConfig(mTestValidationConfigRule, 3148 makeUrl(TEST_HTTP_URL_PATH)); 3149 NetworkValidationTestUtil.setUrlExpirationDeviceConfig(mTestValidationConfigRule, 3150 System.currentTimeMillis() + WIFI_CONNECT_TIMEOUT_MS); 3151 } 3152 3153 @AppModeFull(reason = "Need WiFi support to test the default active network") 3154 @Test 3155 public void testDefaultNetworkActiveListener() throws Exception { 3156 final boolean supportWifi = mPackageManager.hasSystemFeature(FEATURE_WIFI); 3157 final boolean supportTelephony = mPackageManager.hasSystemFeature(FEATURE_TELEPHONY); 3158 assumeTrue("testDefaultNetworkActiveListener cannot execute" 3159 + " unless device supports WiFi or telephony", (supportWifi || supportTelephony)); 3160 3161 if (supportWifi) { 3162 mCtsNetUtils.ensureWifiDisconnected(null /* wifiNetworkToCheck */); 3163 } else { 3164 mCtsNetUtils.disconnectFromCell(); 3165 } 3166 3167 final CompletableFuture<Boolean> future = new CompletableFuture<>(); 3168 final ConnectivityManager.OnNetworkActiveListener listener = () -> future.complete(true); 3169 mCm.addDefaultNetworkActiveListener(listener); 3170 testAndCleanup(() -> { 3171 // New default network connected will trigger a network activity notification. 3172 if (supportWifi) { 3173 mCtsNetUtils.ensureWifiConnected(); 3174 } else { 3175 mCtsNetUtils.connectToCell(); 3176 } 3177 assertTrue(future.get(LISTEN_ACTIVITY_TIMEOUT_MS, TimeUnit.MILLISECONDS)); 3178 }, () -> { 3179 mCm.removeDefaultNetworkActiveListener(listener); 3180 }); 3181 } 3182 3183 /** 3184 * The networks used in this test are real networks and as such they can see seemingly random 3185 * updates of their capabilities or link properties as conditions change, e.g. the network 3186 * loses validation or IPv4 shows up. Many tests should simply treat these callbacks as 3187 * spurious. 3188 */ 3189 private void assertNoCallbackExceptCapOrLpChange( 3190 @NonNull final TestableNetworkCallback cb) { 3191 cb.assertNoCallback(NO_CALLBACK_TIMEOUT_MS, 3192 c -> !(c instanceof CallbackEntry.CapabilitiesChanged 3193 || c instanceof CallbackEntry.LinkPropertiesChanged)); 3194 } 3195 3196 @AppModeFull(reason = "Cannot get WifiManager in instant app mode") 3197 @Test 3198 public void testMobileDataPreferredUids() throws Exception { 3199 assumeTrue(TestUtils.shouldTestSApis()); 3200 final boolean canRunTest = mPackageManager.hasSystemFeature(FEATURE_WIFI) 3201 && mPackageManager.hasSystemFeature(FEATURE_TELEPHONY); 3202 assumeTrue("testMobileDataPreferredUidsWithCallback cannot execute" 3203 + " unless device supports both WiFi and telephony", canRunTest); 3204 3205 final int uid = mPackageManager.getPackageUid(mContext.getPackageName(), 0 /* flag */); 3206 final Set<Integer> mobileDataPreferredUids = 3207 ConnectivitySettingsManager.getMobileDataPreferredUids(mContext); 3208 // CtsNetTestCases uid should not list in MOBILE_DATA_PREFERRED_UIDS setting because it just 3209 // installs to device. In case the uid is existed in setting mistakenly, try to remove the 3210 // uid and set correct uids to setting. 3211 mobileDataPreferredUids.remove(uid); 3212 ConnectivitySettingsManager.setMobileDataPreferredUids(mContext, mobileDataPreferredUids); 3213 3214 // For testing mobile data preferred uids feature, it needs both wifi and cell network. 3215 final Network wifiNetwork = mCtsNetUtils.ensureWifiConnected(); 3216 final Network cellNetwork = mCtsNetUtils.connectToCell(); 3217 final TestableNetworkCallback defaultTrackingCb = new TestableNetworkCallback(); 3218 final TestableNetworkCallback systemDefaultCb = new TestableNetworkCallback(); 3219 final Handler h = new Handler(Looper.getMainLooper()); 3220 runWithShellPermissionIdentity(() -> registerSystemDefaultNetworkCallback( 3221 systemDefaultCb, h), NETWORK_SETTINGS); 3222 registerDefaultNetworkCallback(defaultTrackingCb); 3223 3224 try { 3225 // CtsNetTestCases uid is not listed in MOBILE_DATA_PREFERRED_UIDS setting, so the 3226 // per-app default network should be same as system default network. 3227 waitForAvailable(systemDefaultCb, wifiNetwork); 3228 waitForAvailable(defaultTrackingCb, wifiNetwork); 3229 // Active network for CtsNetTestCases uid should be wifi now. 3230 assertEquals(wifiNetwork, mCm.getActiveNetwork()); 3231 3232 // Add CtsNetTestCases uid to MOBILE_DATA_PREFERRED_UIDS setting, then available per-app 3233 // default network callback should be received with cell network. 3234 final Set<Integer> newMobileDataPreferredUids = new ArraySet<>(mobileDataPreferredUids); 3235 newMobileDataPreferredUids.add(uid); 3236 ConnectivitySettingsManager.setMobileDataPreferredUids( 3237 mContext, newMobileDataPreferredUids); 3238 waitForAvailable(defaultTrackingCb, cellNetwork); 3239 // No change for system default network. Expect no callback except CapabilitiesChanged 3240 // or LinkPropertiesChanged which may be triggered randomly from wifi network. 3241 assertNoCallbackExceptCapOrLpChange(systemDefaultCb); 3242 // Active network for CtsNetTestCases uid should change to cell, too. 3243 assertEquals(cellNetwork, mCm.getActiveNetwork()); 3244 3245 // Remove CtsNetTestCases uid from MOBILE_DATA_PREFERRED_UIDS setting, then available 3246 // per-app default network callback should be received again with system default network 3247 newMobileDataPreferredUids.remove(uid); 3248 ConnectivitySettingsManager.setMobileDataPreferredUids( 3249 mContext, newMobileDataPreferredUids); 3250 waitForAvailable(defaultTrackingCb, wifiNetwork); 3251 // No change for system default network. Expect no callback except CapabilitiesChanged 3252 // or LinkPropertiesChanged which may be triggered randomly from wifi network. 3253 assertNoCallbackExceptCapOrLpChange(systemDefaultCb); 3254 // Active network for CtsNetTestCases uid should change back to wifi. 3255 assertEquals(wifiNetwork, mCm.getActiveNetwork()); 3256 } finally { 3257 // Restore setting. 3258 ConnectivitySettingsManager.setMobileDataPreferredUids( 3259 mContext, mobileDataPreferredUids); 3260 } 3261 } 3262 3263 private void assertBindSocketToNetworkSuccess(final Network network) throws Exception { 3264 final CompletableFuture<Boolean> future = new CompletableFuture<>(); 3265 final ExecutorService executor = Executors.newSingleThreadExecutor(); 3266 try { 3267 executor.execute(() -> { 3268 for (int i = 0; i < 300; i++) { 3269 SystemClock.sleep(10); 3270 3271 try (Socket socket = new Socket()) { 3272 network.bindSocket(socket); 3273 future.complete(true); 3274 return; 3275 } catch (IOException e) { } 3276 } 3277 }); 3278 assertTrue(future.get(APPLYING_UIDS_ALLOWED_ON_RESTRICTED_NETWORKS_TIMEOUT_MS, 3279 TimeUnit.MILLISECONDS)); 3280 } finally { 3281 executor.shutdown(); 3282 } 3283 } 3284 3285 private static NetworkAgent createRestrictedNetworkAgent(final Context context) { 3286 // Create test network agent with restricted network. 3287 final NetworkCapabilities nc = new NetworkCapabilities.Builder() 3288 .addTransportType(NetworkCapabilities.TRANSPORT_TEST) 3289 .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) 3290 .setNetworkSpecifier(CompatUtil.makeTestNetworkSpecifier( 3291 TEST_RESTRICTED_NW_IFACE_NAME)) 3292 .build(); 3293 final NetworkAgent agent = new NetworkAgent(context, Looper.getMainLooper(), TAG, nc, 3294 new LinkProperties(), 10 /* score */, new NetworkAgentConfig.Builder().build(), 3295 new NetworkProvider(context, Looper.getMainLooper(), TAG)) {}; 3296 runWithShellPermissionIdentity(() -> agent.register(), 3297 android.Manifest.permission.MANAGE_TEST_NETWORKS); 3298 agent.markConnected(); 3299 3300 return agent; 3301 } 3302 3303 @AppModeFull(reason = "WRITE_SECURE_SETTINGS permission can't be granted to instant apps") 3304 @Test 3305 public void testUidsAllowedOnRestrictedNetworks() throws Exception { 3306 assumeTestSApis(); 3307 3308 // TODO (b/175199465): figure out a reasonable permission check for 3309 // setUidsAllowedOnRestrictedNetworks that allows tests but not system-external callers. 3310 assumeTrue(Build.isDebuggable()); 3311 3312 final int uid = mPackageManager.getPackageUid(mContext.getPackageName(), 0 /* flag */); 3313 final Set<Integer> originalUidsAllowedOnRestrictedNetworks = 3314 ConnectivitySettingsManager.getUidsAllowedOnRestrictedNetworks(mContext); 3315 // CtsNetTestCases uid should not list in UIDS_ALLOWED_ON_RESTRICTED_NETWORKS setting 3316 // because it has been just installed to device. In case the uid is existed in setting 3317 // mistakenly, try to remove the uid and set correct uids to setting. 3318 originalUidsAllowedOnRestrictedNetworks.remove(uid); 3319 runWithShellPermissionIdentity(() -> setUidsAllowedOnRestrictedNetworks( 3320 mContext, originalUidsAllowedOnRestrictedNetworks), NETWORK_SETTINGS); 3321 3322 // File a restricted network request with permission first to hold the connection. 3323 final TestableNetworkCallback testNetworkCb = new TestableNetworkCallback(); 3324 final NetworkRequest testRequest = new NetworkRequest.Builder() 3325 .addTransportType(NetworkCapabilities.TRANSPORT_TEST) 3326 .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) 3327 .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) 3328 .setNetworkSpecifier(CompatUtil.makeTestNetworkSpecifier( 3329 TEST_RESTRICTED_NW_IFACE_NAME)) 3330 .build(); 3331 runWithShellPermissionIdentity(() -> requestNetwork(testRequest, testNetworkCb), 3332 CONNECTIVITY_USE_RESTRICTED_NETWORKS); 3333 3334 // File another restricted network request without permission. 3335 final TestableNetworkCallback restrictedNetworkCb = new TestableNetworkCallback(); 3336 final NetworkRequest restrictedRequest = new NetworkRequest.Builder() 3337 .addTransportType(NetworkCapabilities.TRANSPORT_TEST) 3338 .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) 3339 .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) 3340 .setNetworkSpecifier(CompatUtil.makeTestNetworkSpecifier( 3341 TEST_RESTRICTED_NW_IFACE_NAME)) 3342 .build(); 3343 // Uid is not in allowed list and no permissions. Expect that SecurityException will throw. 3344 assertThrows(SecurityException.class, 3345 () -> mCm.requestNetwork(restrictedRequest, restrictedNetworkCb)); 3346 3347 final NetworkAgent agent = createRestrictedNetworkAgent(mContext); 3348 final Network network = agent.getNetwork(); 3349 3350 try (Socket socket = new Socket()) { 3351 // Verify that the network is restricted. 3352 testNetworkCb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED, 3353 NETWORK_CALLBACK_TIMEOUT_MS, 3354 entry -> network.equals(entry.getNetwork()) 3355 && (!((CallbackEntry.CapabilitiesChanged) entry).getCaps() 3356 .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED))); 3357 // CtsNetTestCases package doesn't hold CONNECTIVITY_USE_RESTRICTED_NETWORKS, so it 3358 // does not allow to bind socket to restricted network. 3359 assertThrows(IOException.class, () -> network.bindSocket(socket)); 3360 3361 // Add CtsNetTestCases uid to UIDS_ALLOWED_ON_RESTRICTED_NETWORKS setting, then it can 3362 // bind socket to restricted network normally. 3363 final Set<Integer> newUidsAllowedOnRestrictedNetworks = 3364 new ArraySet<>(originalUidsAllowedOnRestrictedNetworks); 3365 newUidsAllowedOnRestrictedNetworks.add(uid); 3366 runWithShellPermissionIdentity(() -> setUidsAllowedOnRestrictedNetworks( 3367 mContext, newUidsAllowedOnRestrictedNetworks), NETWORK_SETTINGS); 3368 // Wait a while for sending allowed uids on the restricted network to netd. 3369 // TODD: Have a significant signal to know the uids has been sent to netd. 3370 assertBindSocketToNetworkSuccess(network); 3371 3372 if (TestUtils.shouldTestTApis()) { 3373 // Uid is in allowed list. Try file network request again. 3374 requestNetwork(restrictedRequest, restrictedNetworkCb); 3375 // Verify that the network is restricted. 3376 restrictedNetworkCb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED, 3377 NETWORK_CALLBACK_TIMEOUT_MS, 3378 entry -> network.equals(entry.getNetwork()) 3379 && (!((CallbackEntry.CapabilitiesChanged) entry).getCaps() 3380 .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED))); 3381 } 3382 } finally { 3383 agent.unregister(); 3384 3385 // Restore setting. 3386 runWithShellPermissionIdentity(() -> setUidsAllowedOnRestrictedNetworks( 3387 mContext, originalUidsAllowedOnRestrictedNetworks), NETWORK_SETTINGS); 3388 } 3389 } 3390 3391 @Test 3392 public void testDump() throws Exception { 3393 final String dumpOutput = DumpTestUtils.dumpServiceWithShellPermission( 3394 Context.CONNECTIVITY_SERVICE, "--short"); 3395 assertTrue(dumpOutput, dumpOutput.contains("Active default network")); 3396 } 3397 3398 @Test @IgnoreUpTo(SC_V2) 3399 public void testDumpBpfNetMaps() throws Exception { 3400 final String[] args = new String[] {"--short", "trafficcontroller"}; 3401 String dumpOutput = DumpTestUtils.dumpServiceWithShellPermission( 3402 Context.CONNECTIVITY_SERVICE, args); 3403 assertTrue(dumpOutput, dumpOutput.contains("TrafficController")); 3404 assertFalse(dumpOutput, dumpOutput.contains("BPF map content")); 3405 3406 dumpOutput = DumpTestUtils.dumpServiceWithShellPermission( 3407 Context.CONNECTIVITY_SERVICE, args[1]); 3408 assertTrue(dumpOutput, dumpOutput.contains("BPF map content")); 3409 } 3410 3411 private void checkFirewallBlocking(final DatagramSocket srcSock, final DatagramSocket dstSock, 3412 final boolean expectBlock, final int chain) throws Exception { 3413 final Random random = new Random(); 3414 final byte[] sendData = new byte[100]; 3415 random.nextBytes(sendData); 3416 3417 final DatagramPacket pkt = new DatagramPacket(sendData, sendData.length, 3418 InetAddresses.parseNumericAddress("::1"), dstSock.getLocalPort()); 3419 try { 3420 srcSock.send(pkt); 3421 } catch (IOException e) { 3422 if (expectBlock) { 3423 return; 3424 } 3425 fail("Expect not to be blocked by firewall but sending packet was blocked:" 3426 + " chain=" + chain 3427 + " chainEnabled=" + mCm.getFirewallChainEnabled(chain) 3428 + " uidFirewallRule=" + mCm.getUidFirewallRule(chain, Process.myUid())); 3429 } 3430 3431 dstSock.receive(pkt); 3432 assertArrayEquals(sendData, pkt.getData()); 3433 3434 if (expectBlock) { 3435 fail("Expect to be blocked by firewall but sending packet was not blocked:" 3436 + " chain=" + chain 3437 + " chainEnabled=" + mCm.getFirewallChainEnabled(chain) 3438 + " uidFirewallRule=" + mCm.getUidFirewallRule(chain, Process.myUid())); 3439 } 3440 } 3441 3442 private static final boolean EXPECT_PASS = false; 3443 private static final boolean EXPECT_BLOCK = true; 3444 3445 // ALLOWLIST means the firewall denies all by default, uids must be explicitly allowed 3446 // DENYLIST means the firewall allows all by default, uids must be explicitly denyed 3447 private static final boolean ALLOWLIST = true; 3448 private static final boolean DENYLIST = false; 3449 3450 private void doTestFirewallBlocking(final int chain, final boolean isAllowList) { 3451 final int myUid = Process.myUid(); 3452 final int ruleToAddMatch = isAllowList ? FIREWALL_RULE_ALLOW : FIREWALL_RULE_DENY; 3453 final int ruleToRemoveMatch = isAllowList ? FIREWALL_RULE_DENY : FIREWALL_RULE_ALLOW; 3454 3455 runWithShellPermissionIdentity(() -> { 3456 // Firewall chain status will be restored after the test. 3457 final boolean wasChainEnabled = mCm.getFirewallChainEnabled(chain); 3458 final int previousUidFirewallRule = mCm.getUidFirewallRule(chain, myUid); 3459 final DatagramSocket srcSock = new DatagramSocket(); 3460 final DatagramSocket dstSock = new DatagramSocket(); 3461 testAndCleanup(() -> { 3462 if (wasChainEnabled) { 3463 mCm.setFirewallChainEnabled(chain, false /* enable */); 3464 } 3465 if (previousUidFirewallRule == ruleToAddMatch) { 3466 mCm.setUidFirewallRule(chain, myUid, ruleToRemoveMatch); 3467 } 3468 dstSock.setSoTimeout(SOCKET_TIMEOUT_MS); 3469 3470 // Chain disabled, UID not on chain. 3471 checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS, chain); 3472 3473 // Chain enabled, UID not on chain. 3474 mCm.setFirewallChainEnabled(chain, true /* enable */); 3475 assertTrue(mCm.getFirewallChainEnabled(chain)); 3476 checkFirewallBlocking( 3477 srcSock, dstSock, isAllowList ? EXPECT_BLOCK : EXPECT_PASS, chain); 3478 3479 // Chain enabled, UID on chain. 3480 mCm.setUidFirewallRule(chain, myUid, ruleToAddMatch); 3481 checkFirewallBlocking( 3482 srcSock, dstSock, isAllowList ? EXPECT_PASS : EXPECT_BLOCK, chain); 3483 3484 // Chain disabled, UID on chain. 3485 mCm.setFirewallChainEnabled(chain, false /* enable */); 3486 assertFalse(mCm.getFirewallChainEnabled(chain)); 3487 checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS, chain); 3488 3489 // Chain disabled, UID not on chain. 3490 mCm.setUidFirewallRule(chain, myUid, ruleToRemoveMatch); 3491 checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS, chain); 3492 }, /* cleanup */ () -> { 3493 srcSock.close(); 3494 dstSock.close(); 3495 }, /* cleanup */ () -> { 3496 // Restore the global chain status 3497 mCm.setFirewallChainEnabled(chain, wasChainEnabled); 3498 }, /* cleanup */ () -> { 3499 // Restore the uid firewall rule status 3500 try { 3501 mCm.setUidFirewallRule(chain, myUid, previousUidFirewallRule); 3502 } catch (IllegalStateException ignored) { 3503 // Removing match causes an exception when the rule entry for the uid does 3504 // not exist. But this is fine and can be ignored. 3505 } 3506 }); 3507 }, NETWORK_SETTINGS); 3508 } 3509 3510 @Test @IgnoreUpTo(SC_V2) @ConnectivityModuleTest 3511 @AppModeFull(reason = "Socket cannot bind in instant app mode") 3512 public void testFirewallBlockingDozable() { 3513 doTestFirewallBlocking(FIREWALL_CHAIN_DOZABLE, ALLOWLIST); 3514 } 3515 3516 @Test @IgnoreUpTo(SC_V2) @ConnectivityModuleTest 3517 @AppModeFull(reason = "Socket cannot bind in instant app mode") 3518 public void testFirewallBlockingPowersave() { 3519 doTestFirewallBlocking(FIREWALL_CHAIN_POWERSAVE, ALLOWLIST); 3520 } 3521 3522 @Test @IgnoreUpTo(SC_V2) @ConnectivityModuleTest 3523 @AppModeFull(reason = "Socket cannot bind in instant app mode") 3524 public void testFirewallBlockingRestricted() { 3525 doTestFirewallBlocking(FIREWALL_CHAIN_RESTRICTED, ALLOWLIST); 3526 } 3527 3528 @Test @IgnoreUpTo(SC_V2) @ConnectivityModuleTest 3529 @AppModeFull(reason = "Socket cannot bind in instant app mode") 3530 public void testFirewallBlockingLowPowerStandby() { 3531 doTestFirewallBlocking(FIREWALL_CHAIN_LOW_POWER_STANDBY, ALLOWLIST); 3532 } 3533 3534 @Test @IgnoreUpTo(SC_V2) @ConnectivityModuleTest 3535 @AppModeFull(reason = "Socket cannot bind in instant app mode") 3536 public void testFirewallBlockingStandby() { 3537 doTestFirewallBlocking(FIREWALL_CHAIN_STANDBY, DENYLIST); 3538 } 3539 3540 @Test @IgnoreUpTo(SC_V2) @ConnectivityModuleTest 3541 @AppModeFull(reason = "Socket cannot bind in instant app mode") 3542 public void testFirewallBlockingOemDeny1() { 3543 doTestFirewallBlocking(FIREWALL_CHAIN_OEM_DENY_1, DENYLIST); 3544 } 3545 3546 @Test @IgnoreUpTo(SC_V2) @ConnectivityModuleTest 3547 @AppModeFull(reason = "Socket cannot bind in instant app mode") 3548 public void testFirewallBlockingOemDeny2() { 3549 doTestFirewallBlocking(FIREWALL_CHAIN_OEM_DENY_2, DENYLIST); 3550 } 3551 3552 @Test @IgnoreUpTo(SC_V2) @ConnectivityModuleTest 3553 @AppModeFull(reason = "Socket cannot bind in instant app mode") 3554 public void testFirewallBlockingOemDeny3() { 3555 doTestFirewallBlocking(FIREWALL_CHAIN_OEM_DENY_3, DENYLIST); 3556 } 3557 3558 private void assertSocketOpen(final Socket socket) throws Exception { 3559 mCtsNetUtils.testHttpRequest(socket); 3560 } 3561 3562 private void assertSocketClosed(final Socket socket) throws Exception { 3563 try { 3564 mCtsNetUtils.testHttpRequest(socket); 3565 fail("Socket is expected to be closed"); 3566 } catch (SocketException expected) { 3567 } 3568 } 3569 3570 private static final boolean EXPECT_OPEN = false; 3571 private static final boolean EXPECT_CLOSE = true; 3572 3573 private void doTestFirewallCloseSocket(final int chain, final int rule, final int targetUid, 3574 final boolean expectClose) { 3575 runWithShellPermissionIdentity(() -> { 3576 // Firewall chain status will be restored after the test. 3577 final boolean wasChainEnabled = mCm.getFirewallChainEnabled(chain); 3578 final int previousUidFirewallRule = mCm.getUidFirewallRule(chain, targetUid); 3579 final Socket socket = new Socket(TEST_HOST, HTTP_PORT); 3580 socket.setSoTimeout(NETWORK_REQUEST_TIMEOUT_MS); 3581 testAndCleanup(() -> { 3582 mCm.setFirewallChainEnabled(chain, false /* enable */); 3583 assertSocketOpen(socket); 3584 3585 try { 3586 mCm.setUidFirewallRule(chain, targetUid, rule); 3587 } catch (IllegalStateException ignored) { 3588 // Removing match causes an exception when the rule entry for the uid does 3589 // not exist. But this is fine and can be ignored. 3590 } 3591 mCm.setFirewallChainEnabled(chain, true /* enable */); 3592 3593 if (expectClose) { 3594 assertSocketClosed(socket); 3595 } else { 3596 assertSocketOpen(socket); 3597 } 3598 }, /* cleanup */ () -> { 3599 // Restore the global chain status 3600 mCm.setFirewallChainEnabled(chain, wasChainEnabled); 3601 }, /* cleanup */ () -> { 3602 // Restore the uid firewall rule status 3603 try { 3604 mCm.setUidFirewallRule(chain, targetUid, previousUidFirewallRule); 3605 } catch (IllegalStateException ignored) { 3606 // Removing match causes an exception when the rule entry for the uid does 3607 // not exist. But this is fine and can be ignored. 3608 } 3609 }, /* cleanup */ () -> { 3610 socket.close(); 3611 }); 3612 }, NETWORK_SETTINGS); 3613 } 3614 3615 @Test @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) @ConnectivityModuleTest 3616 public void testFirewallCloseSocketAllowlistChainAllow() { 3617 doTestFirewallCloseSocket(FIREWALL_CHAIN_DOZABLE, FIREWALL_RULE_ALLOW, 3618 Process.myUid(), EXPECT_OPEN); 3619 } 3620 3621 @Test @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) @ConnectivityModuleTest 3622 public void testFirewallCloseSocketAllowlistChainDeny() { 3623 doTestFirewallCloseSocket(FIREWALL_CHAIN_DOZABLE, FIREWALL_RULE_DENY, 3624 Process.myUid(), EXPECT_CLOSE); 3625 } 3626 3627 @Test @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) @ConnectivityModuleTest 3628 public void testFirewallCloseSocketAllowlistChainOtherUid() { 3629 doTestFirewallCloseSocket(FIREWALL_CHAIN_DOZABLE, FIREWALL_RULE_ALLOW, 3630 Process.myUid() + 1, EXPECT_CLOSE); 3631 doTestFirewallCloseSocket(FIREWALL_CHAIN_DOZABLE, FIREWALL_RULE_DENY, 3632 Process.myUid() + 1, EXPECT_CLOSE); 3633 } 3634 3635 @Test @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) @ConnectivityModuleTest 3636 public void testFirewallCloseSocketDenylistChainAllow() { 3637 doTestFirewallCloseSocket(FIREWALL_CHAIN_STANDBY, FIREWALL_RULE_ALLOW, 3638 Process.myUid(), EXPECT_OPEN); 3639 } 3640 3641 @Test @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) @ConnectivityModuleTest 3642 public void testFirewallCloseSocketDenylistChainDeny() { 3643 doTestFirewallCloseSocket(FIREWALL_CHAIN_STANDBY, FIREWALL_RULE_DENY, 3644 Process.myUid(), EXPECT_CLOSE); 3645 } 3646 3647 @Test @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) @ConnectivityModuleTest 3648 public void testFirewallCloseSocketDenylistChainOtherUid() { 3649 doTestFirewallCloseSocket(FIREWALL_CHAIN_STANDBY, FIREWALL_RULE_ALLOW, 3650 Process.myUid() + 1, EXPECT_OPEN); 3651 doTestFirewallCloseSocket(FIREWALL_CHAIN_STANDBY, FIREWALL_RULE_DENY, 3652 Process.myUid() + 1, EXPECT_OPEN); 3653 } 3654 3655 private void assumeTestSApis() { 3656 // Cannot use @IgnoreUpTo(Build.VERSION_CODES.R) because this test also requires API 31 3657 // shims, and @IgnoreUpTo does not check that. 3658 assumeTrue(TestUtils.shouldTestSApis()); 3659 } 3660 3661 private void unregisterRegisteredCallbacks() { 3662 for (NetworkCallback callback: mRegisteredCallbacks) { 3663 mCm.unregisterNetworkCallback(callback); 3664 } 3665 } 3666 3667 private void registerDefaultNetworkCallback(NetworkCallback callback) { 3668 mCm.registerDefaultNetworkCallback(callback); 3669 mRegisteredCallbacks.add(callback); 3670 } 3671 3672 private void registerDefaultNetworkCallback(NetworkCallback callback, Handler handler) { 3673 mCm.registerDefaultNetworkCallback(callback, handler); 3674 mRegisteredCallbacks.add(callback); 3675 } 3676 3677 private void registerNetworkCallback(NetworkRequest request, NetworkCallback callback) { 3678 mCm.registerNetworkCallback(request, callback); 3679 mRegisteredCallbacks.add(callback); 3680 } 3681 3682 private void registerSystemDefaultNetworkCallback(NetworkCallback callback, Handler handler) { 3683 mCmShim.registerSystemDefaultNetworkCallback(callback, handler); 3684 mRegisteredCallbacks.add(callback); 3685 } 3686 3687 private void registerDefaultNetworkCallbackForUid(int uid, NetworkCallback callback, 3688 Handler handler) throws Exception { 3689 mCmShim.registerDefaultNetworkCallbackForUid(uid, callback, handler); 3690 mRegisteredCallbacks.add(callback); 3691 } 3692 3693 private void requestNetwork(NetworkRequest request, NetworkCallback callback) { 3694 mCm.requestNetwork(request, callback); 3695 mRegisteredCallbacks.add(callback); 3696 } 3697 3698 private void requestNetwork(NetworkRequest request, NetworkCallback callback, int timeoutSec) { 3699 mCm.requestNetwork(request, callback, timeoutSec); 3700 mRegisteredCallbacks.add(callback); 3701 } 3702 3703 private void registerBestMatchingNetworkCallback(NetworkRequest request, 3704 NetworkCallback callback, Handler handler) { 3705 mCm.registerBestMatchingNetworkCallback(request, callback, handler); 3706 mRegisteredCallbacks.add(callback); 3707 } 3708 3709 private void requestBackgroundNetwork(NetworkRequest request, NetworkCallback callback, 3710 Handler handler) throws Exception { 3711 mCmShim.requestBackgroundNetwork(request, callback, handler); 3712 mRegisteredCallbacks.add(callback); 3713 } 3714 } 3715