1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server; 18 19 import static android.Manifest.permission.CHANGE_NETWORK_STATE; 20 import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS; 21 import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; 22 import static android.content.pm.PackageManager.GET_PERMISSIONS; 23 import static android.content.pm.PackageManager.MATCH_ANY_USER; 24 import static android.content.pm.PackageManager.PERMISSION_DENIED; 25 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 26 import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN; 27 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; 28 import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO; 29 import static android.net.ConnectivityManager.EXTRA_NETWORK_TYPE; 30 import static android.net.ConnectivityManager.NETID_UNSET; 31 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF; 32 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC; 33 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; 34 import static android.net.ConnectivityManager.TYPE_ETHERNET; 35 import static android.net.ConnectivityManager.TYPE_MOBILE; 36 import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA; 37 import static android.net.ConnectivityManager.TYPE_MOBILE_MMS; 38 import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL; 39 import static android.net.ConnectivityManager.TYPE_WIFI; 40 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS; 41 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK; 42 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP; 43 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS; 44 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS; 45 import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL; 46 import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID; 47 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL; 48 import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS; 49 import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; 50 import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS; 51 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND; 52 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA; 53 import static android.net.NetworkCapabilities.NET_CAPABILITY_IA; 54 import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS; 55 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; 56 import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS; 57 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; 58 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; 59 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; 60 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; 61 import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY; 62 import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS; 63 import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL; 64 import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; 65 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; 66 import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P; 67 import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP; 68 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; 69 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; 70 import static android.net.NetworkCapabilities.TRANSPORT_VPN; 71 import static android.net.NetworkCapabilities.TRANSPORT_WIFI; 72 import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE; 73 import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED; 74 import static android.net.NetworkPolicyManager.RULE_NONE; 75 import static android.net.NetworkPolicyManager.RULE_REJECT_ALL; 76 import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; 77 import static android.net.RouteInfo.RTN_UNREACHABLE; 78 import static android.os.Process.INVALID_UID; 79 import static android.system.OsConstants.IPPROTO_TCP; 80 81 import static com.android.server.ConnectivityServiceTestUtilsKt.transportToLegacyType; 82 import static com.android.testutils.ConcurrentUtilsKt.await; 83 import static com.android.testutils.ConcurrentUtilsKt.durationOf; 84 import static com.android.testutils.ExceptionUtils.ignoreExceptions; 85 import static com.android.testutils.HandlerUtilsKt.waitForIdleSerialExecutor; 86 import static com.android.testutils.MiscAssertsKt.assertContainsExactly; 87 import static com.android.testutils.MiscAssertsKt.assertEmpty; 88 import static com.android.testutils.MiscAssertsKt.assertLength; 89 import static com.android.testutils.MiscAssertsKt.assertRunsInAtMost; 90 import static com.android.testutils.MiscAssertsKt.assertThrows; 91 92 import static org.junit.Assert.assertEquals; 93 import static org.junit.Assert.assertFalse; 94 import static org.junit.Assert.assertNotEquals; 95 import static org.junit.Assert.assertNotNull; 96 import static org.junit.Assert.assertNull; 97 import static org.junit.Assert.assertTrue; 98 import static org.junit.Assert.fail; 99 import static org.mockito.ArgumentMatchers.anyLong; 100 import static org.mockito.ArgumentMatchers.anyString; 101 import static org.mockito.ArgumentMatchers.argThat; 102 import static org.mockito.ArgumentMatchers.eq; 103 import static org.mockito.ArgumentMatchers.isNull; 104 import static org.mockito.ArgumentMatchers.startsWith; 105 import static org.mockito.Matchers.anyInt; 106 import static org.mockito.Mockito.any; 107 import static org.mockito.Mockito.atLeastOnce; 108 import static org.mockito.Mockito.doAnswer; 109 import static org.mockito.Mockito.doNothing; 110 import static org.mockito.Mockito.doReturn; 111 import static org.mockito.Mockito.doThrow; 112 import static org.mockito.Mockito.inOrder; 113 import static org.mockito.Mockito.mock; 114 import static org.mockito.Mockito.never; 115 import static org.mockito.Mockito.reset; 116 import static org.mockito.Mockito.spy; 117 import static org.mockito.Mockito.timeout; 118 import static org.mockito.Mockito.times; 119 import static org.mockito.Mockito.verify; 120 import static org.mockito.Mockito.verifyNoMoreInteractions; 121 import static org.mockito.Mockito.when; 122 123 import android.Manifest; 124 import android.annotation.NonNull; 125 import android.app.AlarmManager; 126 import android.app.AppOpsManager; 127 import android.app.NotificationManager; 128 import android.app.PendingIntent; 129 import android.content.BroadcastReceiver; 130 import android.content.ContentProvider; 131 import android.content.ContentResolver; 132 import android.content.Context; 133 import android.content.Intent; 134 import android.content.IntentFilter; 135 import android.content.pm.ApplicationInfo; 136 import android.content.pm.PackageInfo; 137 import android.content.pm.PackageManager; 138 import android.content.pm.UserInfo; 139 import android.content.res.Resources; 140 import android.location.LocationManager; 141 import android.net.CaptivePortalData; 142 import android.net.ConnectionInfo; 143 import android.net.ConnectivityManager; 144 import android.net.ConnectivityManager.NetworkCallback; 145 import android.net.ConnectivityManager.PacketKeepalive; 146 import android.net.ConnectivityManager.PacketKeepaliveCallback; 147 import android.net.ConnectivityManager.TooManyRequestsException; 148 import android.net.ConnectivityThread; 149 import android.net.DataStallReportParcelable; 150 import android.net.IConnectivityDiagnosticsCallback; 151 import android.net.IDnsResolver; 152 import android.net.IIpConnectivityMetrics; 153 import android.net.INetd; 154 import android.net.INetworkMonitor; 155 import android.net.INetworkMonitorCallbacks; 156 import android.net.INetworkPolicyListener; 157 import android.net.INetworkPolicyManager; 158 import android.net.INetworkStatsService; 159 import android.net.InetAddresses; 160 import android.net.InterfaceConfiguration; 161 import android.net.IpPrefix; 162 import android.net.IpSecManager; 163 import android.net.IpSecManager.UdpEncapsulationSocket; 164 import android.net.LinkAddress; 165 import android.net.LinkProperties; 166 import android.net.MatchAllNetworkSpecifier; 167 import android.net.Network; 168 import android.net.NetworkAgent; 169 import android.net.NetworkAgentConfig; 170 import android.net.NetworkCapabilities; 171 import android.net.NetworkFactory; 172 import android.net.NetworkInfo; 173 import android.net.NetworkRequest; 174 import android.net.NetworkSpecifier; 175 import android.net.NetworkStack; 176 import android.net.NetworkStackClient; 177 import android.net.NetworkState; 178 import android.net.NetworkTestResultParcelable; 179 import android.net.NetworkUtils; 180 import android.net.ProxyInfo; 181 import android.net.ResolverParamsParcel; 182 import android.net.RouteInfo; 183 import android.net.RouteInfoParcel; 184 import android.net.SocketKeepalive; 185 import android.net.UidRange; 186 import android.net.Uri; 187 import android.net.VpnManager; 188 import android.net.metrics.IpConnectivityLog; 189 import android.net.shared.NetworkMonitorUtils; 190 import android.net.shared.PrivateDnsConfig; 191 import android.net.util.MultinetworkPolicyTracker; 192 import android.os.BadParcelableException; 193 import android.os.Binder; 194 import android.os.Build; 195 import android.os.Bundle; 196 import android.os.ConditionVariable; 197 import android.os.Handler; 198 import android.os.HandlerThread; 199 import android.os.IBinder; 200 import android.os.INetworkManagementService; 201 import android.os.Looper; 202 import android.os.Parcel; 203 import android.os.ParcelFileDescriptor; 204 import android.os.Parcelable; 205 import android.os.Process; 206 import android.os.RemoteException; 207 import android.os.SystemClock; 208 import android.os.UserHandle; 209 import android.os.UserManager; 210 import android.provider.Settings; 211 import android.security.KeyStore; 212 import android.system.Os; 213 import android.telephony.TelephonyManager; 214 import android.test.mock.MockContentResolver; 215 import android.text.TextUtils; 216 import android.util.ArraySet; 217 import android.util.Log; 218 import android.util.SparseArray; 219 220 import androidx.test.InstrumentationRegistry; 221 import androidx.test.filters.FlakyTest; 222 import androidx.test.filters.SmallTest; 223 import androidx.test.runner.AndroidJUnit4; 224 225 import com.android.internal.app.IBatteryStats; 226 import com.android.internal.net.VpnConfig; 227 import com.android.internal.net.VpnInfo; 228 import com.android.internal.util.ArrayUtils; 229 import com.android.internal.util.WakeupMessage; 230 import com.android.internal.util.test.BroadcastInterceptingContext; 231 import com.android.internal.util.test.FakeSettingsProvider; 232 import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo; 233 import com.android.server.connectivity.ConnectivityConstants; 234 import com.android.server.connectivity.DefaultNetworkMetrics; 235 import com.android.server.connectivity.IpConnectivityMetrics; 236 import com.android.server.connectivity.MockableSystemProperties; 237 import com.android.server.connectivity.Nat464Xlat; 238 import com.android.server.connectivity.NetworkAgentInfo; 239 import com.android.server.connectivity.NetworkNotificationManager.NotificationType; 240 import com.android.server.connectivity.ProxyTracker; 241 import com.android.server.connectivity.Vpn; 242 import com.android.server.net.NetworkPinner; 243 import com.android.server.net.NetworkPolicyManagerInternal; 244 import com.android.testutils.ExceptionUtils; 245 import com.android.testutils.HandlerUtilsKt; 246 import com.android.testutils.RecorderCallback.CallbackEntry; 247 import com.android.testutils.TestableNetworkCallback; 248 249 import org.junit.After; 250 import org.junit.Before; 251 import org.junit.Ignore; 252 import org.junit.Test; 253 import org.junit.runner.RunWith; 254 import org.mockito.ArgumentCaptor; 255 import org.mockito.InOrder; 256 import org.mockito.Mock; 257 import org.mockito.MockitoAnnotations; 258 import org.mockito.Spy; 259 import org.mockito.stubbing.Answer; 260 261 import java.io.IOException; 262 import java.net.DatagramSocket; 263 import java.net.Inet4Address; 264 import java.net.Inet6Address; 265 import java.net.InetAddress; 266 import java.net.InetSocketAddress; 267 import java.net.Socket; 268 import java.util.ArrayList; 269 import java.util.Arrays; 270 import java.util.Collection; 271 import java.util.Collections; 272 import java.util.HashMap; 273 import java.util.HashSet; 274 import java.util.List; 275 import java.util.Objects; 276 import java.util.Set; 277 import java.util.concurrent.CountDownLatch; 278 import java.util.concurrent.Executor; 279 import java.util.concurrent.ExecutorService; 280 import java.util.concurrent.Executors; 281 import java.util.concurrent.LinkedBlockingQueue; 282 import java.util.concurrent.TimeUnit; 283 import java.util.concurrent.atomic.AtomicBoolean; 284 import java.util.function.Predicate; 285 import java.util.function.Supplier; 286 287 import kotlin.reflect.KClass; 288 289 /** 290 * Tests for {@link ConnectivityService}. 291 * 292 * Build, install and run with: 293 * runtest frameworks-net -c com.android.server.ConnectivityServiceTest 294 */ 295 @RunWith(AndroidJUnit4.class) 296 @SmallTest 297 public class ConnectivityServiceTest { 298 private static final String TAG = "ConnectivityServiceTest"; 299 300 private static final int TIMEOUT_MS = 500; 301 private static final int TEST_LINGER_DELAY_MS = 300; 302 // Chosen to be less than the linger timeout. This ensures that we can distinguish between a 303 // LOST callback that arrives immediately and a LOST callback that arrives after the linger 304 // timeout. For this, our assertions should run fast enough to leave less than 305 // (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are 306 // supposedly fired, and the time we call expectCallback. 307 private static final int TEST_CALLBACK_TIMEOUT_MS = 250; 308 // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to 309 // complete before callbacks are verified. 310 private static final int TEST_REQUEST_TIMEOUT_MS = 150; 311 312 private static final int UNREASONABLY_LONG_ALARM_WAIT_MS = 1000; 313 314 private static final long TIMESTAMP = 1234L; 315 316 private static final int NET_ID = 110; 317 318 private static final String CLAT_PREFIX = "v4-"; 319 private static final String MOBILE_IFNAME = "test_rmnet_data0"; 320 private static final String WIFI_IFNAME = "test_wlan0"; 321 private static final String WIFI_WOL_IFNAME = "test_wlan_wol"; 322 private static final String TEST_PACKAGE_NAME = "com.android.test.package"; 323 private static final String[] EMPTY_STRING_ARRAY = new String[0]; 324 325 private static final String INTERFACE_NAME = "interface"; 326 327 private MockContext mServiceContext; 328 private HandlerThread mCsHandlerThread; 329 private ConnectivityService mService; 330 private WrappedConnectivityManager mCm; 331 private TestNetworkAgentWrapper mWiFiNetworkAgent; 332 private TestNetworkAgentWrapper mCellNetworkAgent; 333 private TestNetworkAgentWrapper mEthernetNetworkAgent; 334 private MockVpn mMockVpn; 335 private Context mContext; 336 private INetworkPolicyListener mPolicyListener; 337 private WrappedMultinetworkPolicyTracker mPolicyTracker; 338 private HandlerThread mAlarmManagerThread; 339 340 @Mock IIpConnectivityMetrics mIpConnectivityMetrics; 341 @Mock IpConnectivityMetrics.Logger mMetricsService; 342 @Mock DefaultNetworkMetrics mDefaultNetworkMetrics; 343 @Mock INetworkManagementService mNetworkManagementService; 344 @Mock INetworkStatsService mStatsService; 345 @Mock IBatteryStats mBatteryStatsService; 346 @Mock INetworkPolicyManager mNpm; 347 @Mock IDnsResolver mMockDnsResolver; 348 @Mock INetd mMockNetd; 349 @Mock NetworkStackClient mNetworkStack; 350 @Mock PackageManager mPackageManager; 351 @Mock UserManager mUserManager; 352 @Mock NotificationManager mNotificationManager; 353 @Mock AlarmManager mAlarmManager; 354 @Mock IConnectivityDiagnosticsCallback mConnectivityDiagnosticsCallback; 355 @Mock IBinder mIBinder; 356 @Mock LocationManager mLocationManager; 357 @Mock AppOpsManager mAppOpsManager; 358 @Mock TelephonyManager mTelephonyManager; 359 360 private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor = 361 ArgumentCaptor.forClass(ResolverParamsParcel.class); 362 363 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods 364 // do not go through ConnectivityService but talk to netd directly, so they don't automatically 365 // reflect the state of our test ConnectivityService. 366 private class WrappedConnectivityManager extends ConnectivityManager { 367 private Network mFakeBoundNetwork; 368 bindProcessToNetwork(Network network)369 public synchronized boolean bindProcessToNetwork(Network network) { 370 mFakeBoundNetwork = network; 371 return true; 372 } 373 getBoundNetworkForProcess()374 public synchronized Network getBoundNetworkForProcess() { 375 return mFakeBoundNetwork; 376 } 377 WrappedConnectivityManager(Context context, ConnectivityService service)378 public WrappedConnectivityManager(Context context, ConnectivityService service) { 379 super(context, service); 380 } 381 } 382 383 private class MockContext extends BroadcastInterceptingContext { 384 private final MockContentResolver mContentResolver; 385 // Contains all registered receivers since this object was created. Useful to clear 386 // them when needed, as BroadcastInterceptingContext does not provide this facility. 387 private final List<BroadcastReceiver> mRegisteredReceivers = new ArrayList<>(); 388 389 @Spy private Resources mResources; 390 private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>(); 391 // Map of permission name -> PermissionManager.Permission_{GRANTED|DENIED} constant 392 private final HashMap<String, Integer> mMockedPermissions = new HashMap<>(); 393 MockContext(Context base, ContentProvider settingsProvider)394 MockContext(Context base, ContentProvider settingsProvider) { 395 super(base); 396 397 mResources = spy(base.getResources()); 398 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)). 399 thenReturn(new String[] { 400 "wifi,1,1,1,-1,true", 401 "mobile,0,0,0,-1,true", 402 "mobile_mms,2,0,2,60000,true", 403 "mobile_supl,3,0,2,60000,true", 404 }); 405 406 when(mResources.getStringArray( 407 com.android.internal.R.array.config_wakeonlan_supported_interfaces)) 408 .thenReturn(new String[]{ 409 WIFI_WOL_IFNAME, 410 }); 411 412 mContentResolver = new MockContentResolver(); 413 mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider); 414 } 415 416 @Override startActivityAsUser(Intent intent, UserHandle handle)417 public void startActivityAsUser(Intent intent, UserHandle handle) { 418 mStartedActivities.offer(intent); 419 } 420 expectStartActivityIntent(int timeoutMs)421 public Intent expectStartActivityIntent(int timeoutMs) { 422 Intent intent = null; 423 try { 424 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS); 425 } catch (InterruptedException e) {} 426 assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent); 427 return intent; 428 } 429 expectNoStartActivityIntent(int timeoutMs)430 public void expectNoStartActivityIntent(int timeoutMs) { 431 try { 432 assertNull("Received unexpected Intent to start activity", 433 mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS)); 434 } catch (InterruptedException e) {} 435 } 436 437 @Override getSystemService(String name)438 public Object getSystemService(String name) { 439 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm; 440 if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager; 441 if (Context.USER_SERVICE.equals(name)) return mUserManager; 442 if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager; 443 if (Context.LOCATION_SERVICE.equals(name)) return mLocationManager; 444 if (Context.APP_OPS_SERVICE.equals(name)) return mAppOpsManager; 445 if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager; 446 return super.getSystemService(name); 447 } 448 449 @Override getContentResolver()450 public ContentResolver getContentResolver() { 451 return mContentResolver; 452 } 453 454 @Override getResources()455 public Resources getResources() { 456 return mResources; 457 } 458 459 @Override getPackageManager()460 public PackageManager getPackageManager() { 461 return mPackageManager; 462 } 463 checkMockedPermission(String permission, Supplier<Integer> ifAbsent)464 private int checkMockedPermission(String permission, Supplier<Integer> ifAbsent) { 465 final Integer granted = mMockedPermissions.get(permission); 466 return granted != null ? granted : ifAbsent.get(); 467 } 468 469 @Override checkPermission(String permission, int pid, int uid)470 public int checkPermission(String permission, int pid, int uid) { 471 return checkMockedPermission( 472 permission, () -> super.checkPermission(permission, pid, uid)); 473 } 474 475 @Override checkCallingOrSelfPermission(String permission)476 public int checkCallingOrSelfPermission(String permission) { 477 return checkMockedPermission( 478 permission, () -> super.checkCallingOrSelfPermission(permission)); 479 } 480 481 @Override enforceCallingOrSelfPermission(String permission, String message)482 public void enforceCallingOrSelfPermission(String permission, String message) { 483 final Integer granted = mMockedPermissions.get(permission); 484 if (granted == null) { 485 super.enforceCallingOrSelfPermission(permission, message); 486 return; 487 } 488 489 if (!granted.equals(PERMISSION_GRANTED)) { 490 throw new SecurityException("[Test] permission denied: " + permission); 491 } 492 } 493 494 /** 495 * Mock checks for the specified permission, and have them behave as per {@code granted}. 496 * 497 * <p>Passing null reverts to default behavior, which does a real permission check on the 498 * test package. 499 * @param granted One of {@link PackageManager#PERMISSION_GRANTED} or 500 * {@link PackageManager#PERMISSION_DENIED}. 501 */ setPermission(String permission, Integer granted)502 public void setPermission(String permission, Integer granted) { 503 mMockedPermissions.put(permission, granted); 504 } 505 506 @Override registerReceiver(BroadcastReceiver receiver, IntentFilter filter)507 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { 508 mRegisteredReceivers.add(receiver); 509 return super.registerReceiver(receiver, filter); 510 } 511 clearRegisteredReceivers()512 public void clearRegisteredReceivers() { 513 // super.unregisterReceiver is a no-op for receivers that are not registered (because 514 // they haven't been registered or because they have already been unregistered). 515 // For the same reason, don't bother clearing mRegisteredReceivers. 516 for (final BroadcastReceiver rcv : mRegisteredReceivers) unregisterReceiver(rcv); 517 } 518 } 519 waitForIdle()520 private void waitForIdle() { 521 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); 522 waitForIdle(mCellNetworkAgent, TIMEOUT_MS); 523 waitForIdle(mWiFiNetworkAgent, TIMEOUT_MS); 524 waitForIdle(mEthernetNetworkAgent, TIMEOUT_MS); 525 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); 526 HandlerUtilsKt.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS); 527 } 528 waitForIdle(TestNetworkAgentWrapper agent, long timeoutMs)529 private void waitForIdle(TestNetworkAgentWrapper agent, long timeoutMs) { 530 if (agent == null) { 531 return; 532 } 533 agent.waitForIdle(timeoutMs); 534 } 535 536 @Test testWaitForIdle()537 public void testWaitForIdle() throws Exception { 538 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng. 539 540 // Tests that waitForIdle returns immediately if the service is already idle. 541 for (int i = 0; i < attempts; i++) { 542 waitForIdle(); 543 } 544 545 // Bring up a network that we can use to send messages to ConnectivityService. 546 ConditionVariable cv = registerConnectivityBroadcast(1); 547 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 548 mWiFiNetworkAgent.connect(false); 549 waitFor(cv); 550 Network n = mWiFiNetworkAgent.getNetwork(); 551 assertNotNull(n); 552 553 // Tests that calling waitForIdle waits for messages to be processed. 554 for (int i = 0; i < attempts; i++) { 555 mWiFiNetworkAgent.setSignalStrength(i); 556 waitForIdle(); 557 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength()); 558 } 559 } 560 561 // This test has an inherent race condition in it, and cannot be enabled for continuous testing 562 // or presubmit tests. It is kept for manual runs and documentation purposes. 563 @Ignore verifyThatNotWaitingForIdleCausesRaceConditions()564 public void verifyThatNotWaitingForIdleCausesRaceConditions() throws Exception { 565 // Bring up a network that we can use to send messages to ConnectivityService. 566 ConditionVariable cv = registerConnectivityBroadcast(1); 567 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 568 mWiFiNetworkAgent.connect(false); 569 waitFor(cv); 570 Network n = mWiFiNetworkAgent.getNetwork(); 571 assertNotNull(n); 572 573 // Ensure that not calling waitForIdle causes a race condition. 574 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng. 575 for (int i = 0; i < attempts; i++) { 576 mWiFiNetworkAgent.setSignalStrength(i); 577 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) { 578 // We hit a race condition, as expected. Pass the test. 579 return; 580 } 581 } 582 583 // No race? There is a bug in this test. 584 fail("expected race condition at least once in " + attempts + " attempts"); 585 } 586 587 private class TestNetworkAgentWrapper extends NetworkAgentWrapper { 588 private static final int VALIDATION_RESULT_INVALID = 0; 589 590 private static final long DATA_STALL_TIMESTAMP = 10L; 591 private static final int DATA_STALL_DETECTION_METHOD = 1; 592 593 private INetworkMonitor mNetworkMonitor; 594 private INetworkMonitorCallbacks mNmCallbacks; 595 private int mNmValidationResult = VALIDATION_RESULT_INVALID; 596 private int mProbesCompleted; 597 private int mProbesSucceeded; 598 private String mNmValidationRedirectUrl = null; 599 private boolean mNmProvNotificationRequested = false; 600 601 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable(); 602 // Contains the redirectUrl from networkStatus(). Before reading, wait for 603 // mNetworkStatusReceived. 604 private String mRedirectUrl; 605 TestNetworkAgentWrapper(int transport)606 TestNetworkAgentWrapper(int transport) throws Exception { 607 this(transport, new LinkProperties()); 608 } 609 TestNetworkAgentWrapper(int transport, LinkProperties linkProperties)610 TestNetworkAgentWrapper(int transport, LinkProperties linkProperties) 611 throws Exception { 612 super(transport, linkProperties, mServiceContext); 613 614 // Waits for the NetworkAgent to be registered, which includes the creation of the 615 // NetworkMonitor. 616 waitForIdle(TIMEOUT_MS); 617 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); 618 HandlerUtilsKt.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS); 619 } 620 621 @Override makeNetworkAgent(LinkProperties linkProperties)622 protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties) 623 throws Exception { 624 mNetworkMonitor = mock(INetworkMonitor.class); 625 626 final Answer validateAnswer = inv -> { 627 new Thread(ignoreExceptions(this::onValidationRequested)).start(); 628 return null; 629 }; 630 631 doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any()); 632 doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt()); 633 634 final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class); 635 final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor = 636 ArgumentCaptor.forClass(INetworkMonitorCallbacks.class); 637 doNothing().when(mNetworkStack).makeNetworkMonitor( 638 nmNetworkCaptor.capture(), 639 any() /* name */, 640 nmCbCaptor.capture()); 641 642 final InstrumentedNetworkAgent na = new InstrumentedNetworkAgent(this, linkProperties) { 643 @Override 644 public void networkStatus(int status, String redirectUrl) { 645 mRedirectUrl = redirectUrl; 646 mNetworkStatusReceived.open(); 647 } 648 }; 649 650 assertEquals(na.getNetwork().netId, nmNetworkCaptor.getValue().netId); 651 mNmCallbacks = nmCbCaptor.getValue(); 652 653 mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor); 654 655 return na; 656 } 657 onValidationRequested()658 private void onValidationRequested() throws Exception { 659 if (mNmProvNotificationRequested 660 && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) { 661 mNmCallbacks.hideProvisioningNotification(); 662 mNmProvNotificationRequested = false; 663 } 664 665 mNmCallbacks.notifyProbeStatusChanged(mProbesCompleted, mProbesSucceeded); 666 final NetworkTestResultParcelable p = new NetworkTestResultParcelable(); 667 p.result = mNmValidationResult; 668 p.probesAttempted = mProbesCompleted; 669 p.probesSucceeded = mProbesSucceeded; 670 p.redirectUrl = mNmValidationRedirectUrl; 671 p.timestampMillis = TIMESTAMP; 672 mNmCallbacks.notifyNetworkTestedWithExtras(p); 673 674 if (mNmValidationRedirectUrl != null) { 675 mNmCallbacks.showProvisioningNotification( 676 "test_provisioning_notif_action", TEST_PACKAGE_NAME); 677 mNmProvNotificationRequested = true; 678 } 679 } 680 681 /** 682 * Connect without adding any internet capability. 683 */ connectWithoutInternet()684 public void connectWithoutInternet() { 685 super.connect(); 686 } 687 688 /** 689 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET. 690 * @param validated Indicate if network should pretend to be validated. 691 */ connect(boolean validated)692 public void connect(boolean validated) { 693 connect(validated, true, false /* isStrictMode */); 694 } 695 696 /** 697 * Transition this NetworkAgent to CONNECTED state. 698 * @param validated Indicate if network should pretend to be validated. 699 * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET. 700 */ connect(boolean validated, boolean hasInternet, boolean isStrictMode)701 public void connect(boolean validated, boolean hasInternet, boolean isStrictMode) { 702 assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_INTERNET)); 703 704 ConnectivityManager.NetworkCallback callback = null; 705 final ConditionVariable validatedCv = new ConditionVariable(); 706 if (validated) { 707 setNetworkValid(isStrictMode); 708 NetworkRequest request = new NetworkRequest.Builder() 709 .addTransportType(getNetworkCapabilities().getTransportTypes()[0]) 710 .clearCapabilities() 711 .build(); 712 callback = new ConnectivityManager.NetworkCallback() { 713 public void onCapabilitiesChanged(Network network, 714 NetworkCapabilities networkCapabilities) { 715 if (network.equals(getNetwork()) && 716 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) { 717 validatedCv.open(); 718 } 719 } 720 }; 721 mCm.registerNetworkCallback(request, callback); 722 } 723 if (hasInternet) { 724 addCapability(NET_CAPABILITY_INTERNET); 725 } 726 727 connectWithoutInternet(); 728 729 if (validated) { 730 // Wait for network to validate. 731 waitFor(validatedCv); 732 setNetworkInvalid(isStrictMode); 733 } 734 735 if (callback != null) mCm.unregisterNetworkCallback(callback); 736 } 737 connectWithCaptivePortal(String redirectUrl, boolean isStrictMode)738 public void connectWithCaptivePortal(String redirectUrl, boolean isStrictMode) { 739 setNetworkPortal(redirectUrl, isStrictMode); 740 connect(false, true /* hasInternet */, isStrictMode); 741 } 742 connectWithPartialConnectivity()743 public void connectWithPartialConnectivity() { 744 setNetworkPartial(); 745 connect(false); 746 } 747 connectWithPartialValidConnectivity(boolean isStrictMode)748 public void connectWithPartialValidConnectivity(boolean isStrictMode) { 749 setNetworkPartialValid(isStrictMode); 750 connect(false, true /* hasInternet */, isStrictMode); 751 } 752 setNetworkValid(boolean isStrictMode)753 void setNetworkValid(boolean isStrictMode) { 754 mNmValidationResult = NETWORK_VALIDATION_RESULT_VALID; 755 mNmValidationRedirectUrl = null; 756 int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS; 757 if (isStrictMode) { 758 probesSucceeded |= NETWORK_VALIDATION_PROBE_PRIVDNS; 759 } 760 // The probesCompleted equals to probesSucceeded for the case of valid network, so put 761 // the same value into two different parameter of the method. 762 setProbesStatus(probesSucceeded, probesSucceeded); 763 } 764 setNetworkInvalid(boolean isStrictMode)765 void setNetworkInvalid(boolean isStrictMode) { 766 mNmValidationResult = VALIDATION_RESULT_INVALID; 767 mNmValidationRedirectUrl = null; 768 int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS 769 | NETWORK_VALIDATION_PROBE_HTTP; 770 int probesSucceeded = 0; 771 // If the isStrictMode is true, it means the network is invalid when NetworkMonitor 772 // tried to validate the private DNS but failed. 773 if (isStrictMode) { 774 probesCompleted &= ~NETWORK_VALIDATION_PROBE_HTTP; 775 probesSucceeded = probesCompleted; 776 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS; 777 } 778 setProbesStatus(probesCompleted, probesSucceeded); 779 } 780 setNetworkPortal(String redirectUrl, boolean isStrictMode)781 void setNetworkPortal(String redirectUrl, boolean isStrictMode) { 782 setNetworkInvalid(isStrictMode); 783 mNmValidationRedirectUrl = redirectUrl; 784 // Suppose the portal is found when NetworkMonitor probes NETWORK_VALIDATION_PROBE_HTTP 785 // in the beginning, so the NETWORK_VALIDATION_PROBE_HTTPS hasn't probed yet. 786 int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP; 787 int probesSucceeded = VALIDATION_RESULT_INVALID; 788 if (isStrictMode) { 789 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS; 790 } 791 setProbesStatus(probesCompleted, probesSucceeded); 792 } 793 setNetworkPartial()794 void setNetworkPartial() { 795 mNmValidationResult = NETWORK_VALIDATION_RESULT_PARTIAL; 796 mNmValidationRedirectUrl = null; 797 int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS 798 | NETWORK_VALIDATION_PROBE_FALLBACK; 799 int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_FALLBACK; 800 setProbesStatus(probesCompleted, probesSucceeded); 801 } 802 setNetworkPartialValid(boolean isStrictMode)803 void setNetworkPartialValid(boolean isStrictMode) { 804 setNetworkPartial(); 805 mNmValidationResult |= NETWORK_VALIDATION_RESULT_VALID; 806 int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS 807 | NETWORK_VALIDATION_PROBE_HTTP; 808 int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP; 809 // Suppose the partial network cannot pass the private DNS validation as well, so only 810 // add NETWORK_VALIDATION_PROBE_DNS in probesCompleted but not probesSucceeded. 811 if (isStrictMode) { 812 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS; 813 } 814 setProbesStatus(probesCompleted, probesSucceeded); 815 } 816 setProbesStatus(int probesCompleted, int probesSucceeded)817 void setProbesStatus(int probesCompleted, int probesSucceeded) { 818 mProbesCompleted = probesCompleted; 819 mProbesSucceeded = probesSucceeded; 820 } 821 notifyCaptivePortalDataChanged(CaptivePortalData data)822 void notifyCaptivePortalDataChanged(CaptivePortalData data) { 823 try { 824 mNmCallbacks.notifyCaptivePortalDataChanged(data); 825 } catch (RemoteException e) { 826 throw new AssertionError("This cannot happen", e); 827 } 828 } 829 waitForRedirectUrl()830 public String waitForRedirectUrl() { 831 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS)); 832 return mRedirectUrl; 833 } 834 expectDisconnected()835 public void expectDisconnected() { 836 expectDisconnected(TIMEOUT_MS); 837 } 838 expectPreventReconnectReceived()839 public void expectPreventReconnectReceived() { 840 expectPreventReconnectReceived(TIMEOUT_MS); 841 } 842 notifyDataStallSuspected()843 void notifyDataStallSuspected() throws Exception { 844 final DataStallReportParcelable p = new DataStallReportParcelable(); 845 p.detectionMethod = DATA_STALL_DETECTION_METHOD; 846 p.timestampMillis = DATA_STALL_TIMESTAMP; 847 mNmCallbacks.notifyDataStallSuspected(p); 848 } 849 } 850 851 /** 852 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove 853 * operations have been processed. Before ConnectivityService can add or remove any requests, 854 * the factory must be told to expect those operations by calling expectAddRequestsWithScores or 855 * expectRemoveRequests. 856 */ 857 private static class MockNetworkFactory extends NetworkFactory { 858 private final ConditionVariable mNetworkStartedCV = new ConditionVariable(); 859 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable(); 860 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false); 861 862 // Used to expect that requests be removed or added on a separate thread, without sleeping. 863 // Callers can call either expectAddRequestsWithScores() or expectRemoveRequests() exactly 864 // once, then cause some other thread to add or remove requests, then call 865 // waitForRequests(). 866 // It is not possible to wait for both add and remove requests. When adding, the queue 867 // contains the expected score. When removing, the value is unused, all matters is the 868 // number of objects in the queue. 869 private final LinkedBlockingQueue<Integer> mExpectations; 870 871 // Whether we are currently expecting requests to be added or removed. Valid only if 872 // mExpectations is non-empty. 873 private boolean mExpectingAdditions; 874 875 // Used to collect the networks requests managed by this factory. This is a duplicate of 876 // the internal information stored in the NetworkFactory (which is private). 877 private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>(); 878 MockNetworkFactory(Looper looper, Context context, String logTag, NetworkCapabilities filter)879 public MockNetworkFactory(Looper looper, Context context, String logTag, 880 NetworkCapabilities filter) { 881 super(looper, context, logTag, filter); 882 mExpectations = new LinkedBlockingQueue<>(); 883 } 884 getMyRequestCount()885 public int getMyRequestCount() { 886 return getRequestCount(); 887 } 888 startNetwork()889 protected void startNetwork() { 890 mNetworkStarted.set(true); 891 mNetworkStartedCV.open(); 892 } 893 stopNetwork()894 protected void stopNetwork() { 895 mNetworkStarted.set(false); 896 mNetworkStoppedCV.open(); 897 } 898 getMyStartRequested()899 public boolean getMyStartRequested() { 900 return mNetworkStarted.get(); 901 } 902 getNetworkStartedCV()903 public ConditionVariable getNetworkStartedCV() { 904 mNetworkStartedCV.close(); 905 return mNetworkStartedCV; 906 } 907 getNetworkStoppedCV()908 public ConditionVariable getNetworkStoppedCV() { 909 mNetworkStoppedCV.close(); 910 return mNetworkStoppedCV; 911 } 912 913 @Override handleAddRequest(NetworkRequest request, int score, int factorySerialNumber)914 protected void handleAddRequest(NetworkRequest request, int score, 915 int factorySerialNumber) { 916 synchronized (mExpectations) { 917 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty 918 919 assertNotNull("Added more requests than expected (" + request + " score : " 920 + score + ")", expectedScore); 921 // If we're expecting anything, we must be expecting additions. 922 if (!mExpectingAdditions) { 923 fail("Can't add requests while expecting requests to be removed"); 924 } 925 if (expectedScore != score) { 926 fail("Expected score was " + expectedScore + " but actual was " + score 927 + " in added request"); 928 } 929 930 // Add the request. 931 mNetworkRequests.put(request.requestId, request); 932 super.handleAddRequest(request, score, factorySerialNumber); 933 mExpectations.notify(); 934 } 935 } 936 937 @Override handleRemoveRequest(NetworkRequest request)938 protected void handleRemoveRequest(NetworkRequest request) { 939 synchronized (mExpectations) { 940 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty 941 942 assertTrue("Removed more requests than expected", expectedScore != null); 943 // If we're expecting anything, we must be expecting removals. 944 if (mExpectingAdditions) { 945 fail("Can't remove requests while expecting requests to be added"); 946 } 947 948 // Remove the request. 949 mNetworkRequests.remove(request.requestId); 950 super.handleRemoveRequest(request); 951 mExpectations.notify(); 952 } 953 } 954 955 // Trigger releasing the request as unfulfillable triggerUnfulfillable(NetworkRequest r)956 public void triggerUnfulfillable(NetworkRequest r) { 957 super.releaseRequestAsUnfulfillableByAnyFactory(r); 958 } 959 assertNoExpectations()960 private void assertNoExpectations() { 961 if (mExpectations.size() != 0) { 962 fail("Can't add expectation, " + mExpectations.size() + " already pending"); 963 } 964 } 965 966 // Expects that requests with the specified scores will be added. expectAddRequestsWithScores(final int... scores)967 public void expectAddRequestsWithScores(final int... scores) { 968 assertNoExpectations(); 969 mExpectingAdditions = true; 970 for (int score : scores) { 971 mExpectations.add(score); 972 } 973 } 974 975 // Expects that count requests will be removed. expectRemoveRequests(final int count)976 public void expectRemoveRequests(final int count) { 977 assertNoExpectations(); 978 mExpectingAdditions = false; 979 for (int i = 0; i < count; ++i) { 980 mExpectations.add(0); // For removals the score is ignored so any value will do. 981 } 982 } 983 984 // Waits for the expected request additions or removals to happen within a timeout. waitForRequests()985 public void waitForRequests() throws InterruptedException { 986 final long deadline = SystemClock.elapsedRealtime() + TIMEOUT_MS; 987 synchronized (mExpectations) { 988 while (mExpectations.size() > 0 && SystemClock.elapsedRealtime() < deadline) { 989 mExpectations.wait(deadline - SystemClock.elapsedRealtime()); 990 } 991 } 992 final long count = mExpectations.size(); 993 final String msg = count + " requests still not " + 994 (mExpectingAdditions ? "added" : "removed") + 995 " after " + TIMEOUT_MS + " ms"; 996 assertEquals(msg, 0, count); 997 } 998 waitForNetworkRequests(final int count)999 public SparseArray<NetworkRequest> waitForNetworkRequests(final int count) 1000 throws InterruptedException { 1001 waitForRequests(); 1002 assertEquals(count, getMyRequestCount()); 1003 return mNetworkRequests; 1004 } 1005 } 1006 startHandlerThreadAndReturnLooper()1007 private static Looper startHandlerThreadAndReturnLooper() { 1008 final HandlerThread handlerThread = new HandlerThread("MockVpnThread"); 1009 handlerThread.start(); 1010 return handlerThread.getLooper(); 1011 } 1012 1013 private class MockVpn extends Vpn { 1014 // TODO : the interactions between this mock and the mock network agent are too 1015 // hard to get right at this moment, because it's unclear in which case which 1016 // target needs to get a method call or both, and in what order. It's because 1017 // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn 1018 // parent class of MockVpn agent wants that responsibility. 1019 // That being said inside the test it should be possible to make the interactions 1020 // harder to get wrong with precise speccing, judicious comments, helper methods 1021 // and a few sprinkled assertions. 1022 1023 private boolean mConnected = false; 1024 // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does 1025 // not inherit from NetworkAgent. 1026 private TestNetworkAgentWrapper mMockNetworkAgent; 1027 private int mVpnType = VpnManager.TYPE_VPN_SERVICE; 1028 1029 private VpnInfo mVpnInfo; 1030 private Network[] mUnderlyingNetworks; 1031 MockVpn(int userId)1032 public MockVpn(int userId) { 1033 super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService, 1034 userId, mock(KeyStore.class)); 1035 } 1036 setNetworkAgent(TestNetworkAgentWrapper agent)1037 public void setNetworkAgent(TestNetworkAgentWrapper agent) { 1038 agent.waitForIdle(TIMEOUT_MS); 1039 mMockNetworkAgent = agent; 1040 mNetworkAgent = agent.getNetworkAgent(); 1041 mNetworkCapabilities.set(agent.getNetworkCapabilities()); 1042 } 1043 setUids(Set<UidRange> uids)1044 public void setUids(Set<UidRange> uids) { 1045 mNetworkCapabilities.setUids(uids); 1046 updateCapabilities(null /* defaultNetwork */); 1047 } 1048 setVpnType(int vpnType)1049 public void setVpnType(int vpnType) { 1050 mVpnType = vpnType; 1051 } 1052 1053 @Override getNetId()1054 public int getNetId() { 1055 if (mMockNetworkAgent == null) { 1056 return NETID_UNSET; 1057 } 1058 return mMockNetworkAgent.getNetwork().netId; 1059 } 1060 1061 @Override appliesToUid(int uid)1062 public boolean appliesToUid(int uid) { 1063 return mConnected; // Trickery to simplify testing. 1064 } 1065 1066 @Override isCallerEstablishedOwnerLocked()1067 protected boolean isCallerEstablishedOwnerLocked() { 1068 return mConnected; // Similar trickery 1069 } 1070 1071 @Override getActiveAppVpnType()1072 public int getActiveAppVpnType() { 1073 return mVpnType; 1074 } 1075 connect(boolean isAlwaysMetered)1076 private void connect(boolean isAlwaysMetered) { 1077 mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities()); 1078 mConnected = true; 1079 mConfig = new VpnConfig(); 1080 mConfig.isMetered = isAlwaysMetered; 1081 } 1082 connectAsAlwaysMetered()1083 public void connectAsAlwaysMetered() { 1084 connect(true /* isAlwaysMetered */); 1085 } 1086 connect()1087 public void connect() { 1088 connect(false /* isAlwaysMetered */); 1089 } 1090 1091 @Override updateCapabilities(Network defaultNetwork)1092 public NetworkCapabilities updateCapabilities(Network defaultNetwork) { 1093 if (!mConnected) return null; 1094 super.updateCapabilities(defaultNetwork); 1095 // Because super.updateCapabilities will update the capabilities of the agent but 1096 // not the mock agent, the mock agent needs to know about them. 1097 copyCapabilitiesToNetworkAgent(); 1098 return new NetworkCapabilities(mNetworkCapabilities); 1099 } 1100 copyCapabilitiesToNetworkAgent()1101 private void copyCapabilitiesToNetworkAgent() { 1102 if (null != mMockNetworkAgent) { 1103 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities, 1104 false /* sendToConnectivityService */); 1105 } 1106 } 1107 disconnect()1108 public void disconnect() { 1109 mConnected = false; 1110 mConfig = null; 1111 } 1112 1113 @Override getVpnInfo()1114 public synchronized VpnInfo getVpnInfo() { 1115 if (mVpnInfo != null) return mVpnInfo; 1116 1117 return super.getVpnInfo(); 1118 } 1119 setVpnInfo(VpnInfo vpnInfo)1120 private synchronized void setVpnInfo(VpnInfo vpnInfo) { 1121 mVpnInfo = vpnInfo; 1122 } 1123 1124 @Override getUnderlyingNetworks()1125 public synchronized Network[] getUnderlyingNetworks() { 1126 if (mUnderlyingNetworks != null) return mUnderlyingNetworks; 1127 1128 return super.getUnderlyingNetworks(); 1129 } 1130 1131 /** Don't override behavior for {@link Vpn#setUnderlyingNetworks}. */ overrideUnderlyingNetworks(Network[] underlyingNetworks)1132 private synchronized void overrideUnderlyingNetworks(Network[] underlyingNetworks) { 1133 mUnderlyingNetworks = underlyingNetworks; 1134 } 1135 } 1136 mockVpn(int uid)1137 private void mockVpn(int uid) { 1138 synchronized (mService.mVpns) { 1139 int userId = UserHandle.getUserId(uid); 1140 mMockVpn = new MockVpn(userId); 1141 // This has no effect unless the VPN is actually connected, because things like 1142 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN 1143 // netId, and check if that network is actually connected. 1144 mService.mVpns.put(userId, mMockVpn); 1145 } 1146 } 1147 setUidRulesChanged(int uidRules)1148 private void setUidRulesChanged(int uidRules) throws RemoteException { 1149 mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules); 1150 } 1151 setRestrictBackgroundChanged(boolean restrictBackground)1152 private void setRestrictBackgroundChanged(boolean restrictBackground) throws RemoteException { 1153 mPolicyListener.onRestrictBackgroundChanged(restrictBackground); 1154 } 1155 getNat464Xlat(NetworkAgentWrapper mna)1156 private Nat464Xlat getNat464Xlat(NetworkAgentWrapper mna) { 1157 return mService.getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd; 1158 } 1159 1160 private static class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker { 1161 volatile boolean mConfigRestrictsAvoidBadWifi; 1162 volatile int mConfigMeteredMultipathPreference; 1163 WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r)1164 WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) { 1165 super(c, h, r); 1166 } 1167 1168 @Override configRestrictsAvoidBadWifi()1169 public boolean configRestrictsAvoidBadWifi() { 1170 return mConfigRestrictsAvoidBadWifi; 1171 } 1172 1173 @Override configMeteredMultipathPreference()1174 public int configMeteredMultipathPreference() { 1175 return mConfigMeteredMultipathPreference; 1176 } 1177 } 1178 1179 /** 1180 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open. 1181 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens. 1182 */ waitFor(ConditionVariable conditionVariable)1183 static private void waitFor(ConditionVariable conditionVariable) { 1184 if (conditionVariable.block(TIMEOUT_MS)) { 1185 return; 1186 } 1187 fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms"); 1188 } 1189 1190 private static final int VPN_USER = 0; 1191 private static final int APP1_UID = UserHandle.getUid(VPN_USER, 10100); 1192 private static final int APP2_UID = UserHandle.getUid(VPN_USER, 10101); 1193 private static final int VPN_UID = UserHandle.getUid(VPN_USER, 10043); 1194 1195 @Before setUp()1196 public void setUp() throws Exception { 1197 mContext = InstrumentationRegistry.getContext(); 1198 1199 MockitoAnnotations.initMocks(this); 1200 when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics); 1201 1202 when(mUserManager.getUsers(eq(true))).thenReturn( 1203 Arrays.asList(new UserInfo[] { 1204 new UserInfo(VPN_USER, "", 0), 1205 })); 1206 final ApplicationInfo applicationInfo = new ApplicationInfo(); 1207 applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q; 1208 when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any())) 1209 .thenReturn(applicationInfo); 1210 1211 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not. 1212 // http://b/25897652 . 1213 if (Looper.myLooper() == null) { 1214 Looper.prepare(); 1215 } 1216 mockDefaultPackages(); 1217 1218 FakeSettingsProvider.clearSettingsProvider(); 1219 mServiceContext = new MockContext(InstrumentationRegistry.getContext(), 1220 new FakeSettingsProvider()); 1221 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class); 1222 LocalServices.addService( 1223 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class)); 1224 1225 mAlarmManagerThread = new HandlerThread("TestAlarmManager"); 1226 mAlarmManagerThread.start(); 1227 initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler()); 1228 1229 mCsHandlerThread = new HandlerThread("TestConnectivityService"); 1230 final ConnectivityService.Dependencies deps = makeDependencies(); 1231 mService = new ConnectivityService(mServiceContext, 1232 mNetworkManagementService, 1233 mStatsService, 1234 mNpm, 1235 mMockDnsResolver, 1236 mock(IpConnectivityLog.class), 1237 mMockNetd, 1238 deps); 1239 mService.mLingerDelayMs = TEST_LINGER_DELAY_MS; 1240 verify(deps).makeMultinetworkPolicyTracker(any(), any(), any()); 1241 1242 final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor = 1243 ArgumentCaptor.forClass(INetworkPolicyListener.class); 1244 verify(mNpm).registerListener(policyListenerCaptor.capture()); 1245 mPolicyListener = policyListenerCaptor.getValue(); 1246 1247 // Create local CM before sending system ready so that we can answer 1248 // getSystemService() correctly. 1249 mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService); 1250 mService.systemReady(); 1251 mockVpn(Process.myUid()); 1252 mCm.bindProcessToNetwork(null); 1253 1254 // Ensure that the default setting for Captive Portals is used for most tests 1255 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT); 1256 setAlwaysOnNetworks(false); 1257 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com"); 1258 } 1259 makeDependencies()1260 private ConnectivityService.Dependencies makeDependencies() { 1261 final MockableSystemProperties systemProperties = spy(new MockableSystemProperties()); 1262 when(systemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0); 1263 when(systemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false); 1264 1265 final ConnectivityService.Dependencies deps = mock(ConnectivityService.Dependencies.class); 1266 doReturn(mCsHandlerThread).when(deps).makeHandlerThread(); 1267 doReturn(new TestNetIdManager()).when(deps).makeNetIdManager(); 1268 doReturn(mNetworkStack).when(deps).getNetworkStack(); 1269 doReturn(systemProperties).when(deps).getSystemProperties(); 1270 doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any()); 1271 doReturn(mMetricsService).when(deps).getMetricsLogger(); 1272 doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt()); 1273 doReturn(mIpConnectivityMetrics).when(deps).getIpConnectivityMetrics(); 1274 doReturn(mBatteryStatsService).when(deps).getBatteryStatsService(); 1275 doReturn(true).when(deps).hasService(Context.ETHERNET_SERVICE); 1276 doAnswer(inv -> { 1277 mPolicyTracker = new WrappedMultinetworkPolicyTracker( 1278 inv.getArgument(0), inv.getArgument(1), inv.getArgument(2)); 1279 return mPolicyTracker; 1280 }).when(deps).makeMultinetworkPolicyTracker(any(), any(), any()); 1281 1282 return deps; 1283 } 1284 initAlarmManager(final AlarmManager am, final Handler alarmHandler)1285 private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) { 1286 doAnswer(inv -> { 1287 final long when = inv.getArgument(1); 1288 final WakeupMessage wakeupMsg = inv.getArgument(3); 1289 final Handler handler = inv.getArgument(4); 1290 1291 long delayMs = when - SystemClock.elapsedRealtime(); 1292 if (delayMs < 0) delayMs = 0; 1293 if (delayMs > UNREASONABLY_LONG_ALARM_WAIT_MS) { 1294 fail("Attempting to send msg more than " + UNREASONABLY_LONG_ALARM_WAIT_MS 1295 + "ms into the future: " + delayMs); 1296 } 1297 alarmHandler.postDelayed(() -> handler.post(wakeupMsg::onAlarm), wakeupMsg /* token */, 1298 delayMs); 1299 1300 return null; 1301 }).when(am).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), anyLong(), anyString(), 1302 any(WakeupMessage.class), any()); 1303 1304 doAnswer(inv -> { 1305 final WakeupMessage wakeupMsg = inv.getArgument(0); 1306 alarmHandler.removeCallbacksAndMessages(wakeupMsg /* token */); 1307 return null; 1308 }).when(am).cancel(any(WakeupMessage.class)); 1309 } 1310 1311 @After tearDown()1312 public void tearDown() throws Exception { 1313 setAlwaysOnNetworks(false); 1314 if (mCellNetworkAgent != null) { 1315 mCellNetworkAgent.disconnect(); 1316 mCellNetworkAgent = null; 1317 } 1318 if (mWiFiNetworkAgent != null) { 1319 mWiFiNetworkAgent.disconnect(); 1320 mWiFiNetworkAgent = null; 1321 } 1322 if (mEthernetNetworkAgent != null) { 1323 mEthernetNetworkAgent.disconnect(); 1324 mEthernetNetworkAgent = null; 1325 } 1326 FakeSettingsProvider.clearSettingsProvider(); 1327 1328 mCsHandlerThread.quitSafely(); 1329 mAlarmManagerThread.quitSafely(); 1330 } 1331 mockDefaultPackages()1332 private void mockDefaultPackages() throws Exception { 1333 final String testPackageName = mContext.getPackageName(); 1334 final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo( 1335 testPackageName, PackageManager.GET_PERMISSIONS); 1336 when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn( 1337 new String[] {testPackageName}); 1338 when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(), 1339 eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo); 1340 1341 when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn( 1342 Arrays.asList(new PackageInfo[] { 1343 buildPackageInfo(/* SYSTEM */ false, APP1_UID), 1344 buildPackageInfo(/* SYSTEM */ false, APP2_UID), 1345 buildPackageInfo(/* SYSTEM */ false, VPN_UID) 1346 })); 1347 } 1348 verifyActiveNetwork(int transport)1349 private void verifyActiveNetwork(int transport) { 1350 // Test getActiveNetworkInfo() 1351 assertNotNull(mCm.getActiveNetworkInfo()); 1352 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType()); 1353 // Test getActiveNetwork() 1354 assertNotNull(mCm.getActiveNetwork()); 1355 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid())); 1356 if (!NetworkCapabilities.isValidTransport(transport)) { 1357 throw new IllegalStateException("Unknown transport " + transport); 1358 } 1359 switch (transport) { 1360 case TRANSPORT_WIFI: 1361 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork()); 1362 break; 1363 case TRANSPORT_CELLULAR: 1364 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork()); 1365 break; 1366 default: 1367 break; 1368 } 1369 // Test getNetworkInfo(Network) 1370 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork())); 1371 assertEquals(transportToLegacyType(transport), 1372 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType()); 1373 // Test getNetworkCapabilities(Network) 1374 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork())); 1375 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport)); 1376 } 1377 verifyNoNetwork()1378 private void verifyNoNetwork() { 1379 waitForIdle(); 1380 // Test getActiveNetworkInfo() 1381 assertNull(mCm.getActiveNetworkInfo()); 1382 // Test getActiveNetwork() 1383 assertNull(mCm.getActiveNetwork()); 1384 assertNull(mCm.getActiveNetworkForUid(Process.myUid())); 1385 // Test getAllNetworks() 1386 assertEmpty(mCm.getAllNetworks()); 1387 } 1388 1389 /** 1390 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION 1391 * broadcasts are received. 1392 */ registerConnectivityBroadcast(final int count)1393 private ConditionVariable registerConnectivityBroadcast(final int count) { 1394 return registerConnectivityBroadcastThat(count, intent -> true); 1395 } 1396 registerConnectivityBroadcastThat(final int count, @NonNull final Predicate<Intent> filter)1397 private ConditionVariable registerConnectivityBroadcastThat(final int count, 1398 @NonNull final Predicate<Intent> filter) { 1399 final ConditionVariable cv = new ConditionVariable(); 1400 final IntentFilter intentFilter = new IntentFilter(CONNECTIVITY_ACTION); 1401 final BroadcastReceiver receiver = new BroadcastReceiver() { 1402 private int remaining = count; 1403 public void onReceive(Context context, Intent intent) { 1404 if (!filter.test(intent)) return; 1405 if (--remaining == 0) { 1406 cv.open(); 1407 mServiceContext.unregisterReceiver(this); 1408 } 1409 } 1410 }; 1411 mServiceContext.registerReceiver(receiver, intentFilter); 1412 return cv; 1413 } 1414 1415 @Test testNetworkTypes()1416 public void testNetworkTypes() { 1417 // Ensure that our mocks for the networkAttributes config variable work as expected. If they 1418 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types 1419 // will fail. Failing here is much easier to debug. 1420 assertTrue(mCm.isNetworkSupported(TYPE_WIFI)); 1421 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE)); 1422 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS)); 1423 assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA)); 1424 1425 // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our 1426 // mocks, this assert exercises the ConnectivityService code path that ensures that 1427 // TYPE_ETHERNET is supported if the ethernet service is running. 1428 assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET)); 1429 } 1430 1431 @Test testNetworkFeature()1432 public void testNetworkFeature() throws Exception { 1433 // Connect the cell agent and wait for the connected broadcast. 1434 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 1435 mCellNetworkAgent.addCapability(NET_CAPABILITY_SUPL); 1436 final ConditionVariable cv1 = registerConnectivityBroadcastThat(1, 1437 intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE); 1438 mCellNetworkAgent.connect(true); 1439 waitFor(cv1); 1440 1441 // Build legacy request for SUPL. 1442 final NetworkCapabilities legacyCaps = new NetworkCapabilities(); 1443 legacyCaps.addTransportType(TRANSPORT_CELLULAR); 1444 legacyCaps.addCapability(NET_CAPABILITY_SUPL); 1445 final NetworkRequest legacyRequest = new NetworkRequest(legacyCaps, TYPE_MOBILE_SUPL, 1446 ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST); 1447 1448 // File request, withdraw it and make sure no broadcast is sent 1449 final ConditionVariable cv2 = registerConnectivityBroadcast(1); 1450 final TestNetworkCallback callback = new TestNetworkCallback(); 1451 mCm.requestNetwork(legacyRequest, callback); 1452 callback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent); 1453 mCm.unregisterNetworkCallback(callback); 1454 assertFalse(cv2.block(800)); // 800ms long enough to at least flake if this is sent 1455 // As the broadcast did not fire, the receiver was not unregistered. Do this now. 1456 mServiceContext.clearRegisteredReceivers(); 1457 1458 // Disconnect the network and expect mobile disconnected broadcast. Use a small hack to 1459 // check that has been sent. 1460 final AtomicBoolean vanillaAction = new AtomicBoolean(false); 1461 final ConditionVariable cv3 = registerConnectivityBroadcastThat(1, intent -> { 1462 if (intent.getAction().equals(CONNECTIVITY_ACTION)) { 1463 vanillaAction.set(true); 1464 } 1465 return !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected(); 1466 }); 1467 mCellNetworkAgent.disconnect(); 1468 waitFor(cv3); 1469 assertTrue(vanillaAction.get()); 1470 } 1471 1472 @Test testLingering()1473 public void testLingering() throws Exception { 1474 verifyNoNetwork(); 1475 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 1476 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 1477 assertNull(mCm.getActiveNetworkInfo()); 1478 assertNull(mCm.getActiveNetwork()); 1479 // Test bringing up validated cellular. 1480 ConditionVariable cv = registerConnectivityBroadcast(1); 1481 mCellNetworkAgent.connect(true); 1482 waitFor(cv); 1483 verifyActiveNetwork(TRANSPORT_CELLULAR); 1484 assertLength(2, mCm.getAllNetworks()); 1485 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) || 1486 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork())); 1487 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) || 1488 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork())); 1489 // Test bringing up validated WiFi. 1490 cv = registerConnectivityBroadcast(2); 1491 mWiFiNetworkAgent.connect(true); 1492 waitFor(cv); 1493 verifyActiveNetwork(TRANSPORT_WIFI); 1494 assertLength(2, mCm.getAllNetworks()); 1495 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) || 1496 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork())); 1497 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) || 1498 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork())); 1499 // Test cellular linger timeout. 1500 mCellNetworkAgent.expectDisconnected(); 1501 waitForIdle(); 1502 assertLength(1, mCm.getAllNetworks()); 1503 verifyActiveNetwork(TRANSPORT_WIFI); 1504 assertLength(1, mCm.getAllNetworks()); 1505 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork()); 1506 // Test WiFi disconnect. 1507 cv = registerConnectivityBroadcast(1); 1508 mWiFiNetworkAgent.disconnect(); 1509 waitFor(cv); 1510 verifyNoNetwork(); 1511 } 1512 1513 @Test testValidatedCellularOutscoresUnvalidatedWiFi()1514 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception { 1515 // Test bringing up unvalidated WiFi 1516 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 1517 ConditionVariable cv = registerConnectivityBroadcast(1); 1518 mWiFiNetworkAgent.connect(false); 1519 waitFor(cv); 1520 verifyActiveNetwork(TRANSPORT_WIFI); 1521 // Test bringing up unvalidated cellular 1522 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 1523 mCellNetworkAgent.connect(false); 1524 waitForIdle(); 1525 verifyActiveNetwork(TRANSPORT_WIFI); 1526 // Test cellular disconnect. 1527 mCellNetworkAgent.disconnect(); 1528 waitForIdle(); 1529 verifyActiveNetwork(TRANSPORT_WIFI); 1530 // Test bringing up validated cellular 1531 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 1532 cv = registerConnectivityBroadcast(2); 1533 mCellNetworkAgent.connect(true); 1534 waitFor(cv); 1535 verifyActiveNetwork(TRANSPORT_CELLULAR); 1536 // Test cellular disconnect. 1537 cv = registerConnectivityBroadcast(2); 1538 mCellNetworkAgent.disconnect(); 1539 waitFor(cv); 1540 verifyActiveNetwork(TRANSPORT_WIFI); 1541 // Test WiFi disconnect. 1542 cv = registerConnectivityBroadcast(1); 1543 mWiFiNetworkAgent.disconnect(); 1544 waitFor(cv); 1545 verifyNoNetwork(); 1546 } 1547 1548 @Test testUnvalidatedWifiOutscoresUnvalidatedCellular()1549 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception { 1550 // Test bringing up unvalidated cellular. 1551 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 1552 ConditionVariable cv = registerConnectivityBroadcast(1); 1553 mCellNetworkAgent.connect(false); 1554 waitFor(cv); 1555 verifyActiveNetwork(TRANSPORT_CELLULAR); 1556 // Test bringing up unvalidated WiFi. 1557 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 1558 cv = registerConnectivityBroadcast(2); 1559 mWiFiNetworkAgent.connect(false); 1560 waitFor(cv); 1561 verifyActiveNetwork(TRANSPORT_WIFI); 1562 // Test WiFi disconnect. 1563 cv = registerConnectivityBroadcast(2); 1564 mWiFiNetworkAgent.disconnect(); 1565 waitFor(cv); 1566 verifyActiveNetwork(TRANSPORT_CELLULAR); 1567 // Test cellular disconnect. 1568 cv = registerConnectivityBroadcast(1); 1569 mCellNetworkAgent.disconnect(); 1570 waitFor(cv); 1571 verifyNoNetwork(); 1572 } 1573 1574 @Test testUnlingeringDoesNotValidate()1575 public void testUnlingeringDoesNotValidate() throws Exception { 1576 // Test bringing up unvalidated WiFi. 1577 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 1578 ConditionVariable cv = registerConnectivityBroadcast(1); 1579 mWiFiNetworkAgent.connect(false); 1580 waitFor(cv); 1581 verifyActiveNetwork(TRANSPORT_WIFI); 1582 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 1583 NET_CAPABILITY_VALIDATED)); 1584 // Test bringing up validated cellular. 1585 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 1586 cv = registerConnectivityBroadcast(2); 1587 mCellNetworkAgent.connect(true); 1588 waitFor(cv); 1589 verifyActiveNetwork(TRANSPORT_CELLULAR); 1590 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 1591 NET_CAPABILITY_VALIDATED)); 1592 // Test cellular disconnect. 1593 cv = registerConnectivityBroadcast(2); 1594 mCellNetworkAgent.disconnect(); 1595 waitFor(cv); 1596 verifyActiveNetwork(TRANSPORT_WIFI); 1597 // Unlingering a network should not cause it to be marked as validated. 1598 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 1599 NET_CAPABILITY_VALIDATED)); 1600 } 1601 1602 @Test testCellularOutscoresWeakWifi()1603 public void testCellularOutscoresWeakWifi() throws Exception { 1604 // Test bringing up validated cellular. 1605 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 1606 ConditionVariable cv = registerConnectivityBroadcast(1); 1607 mCellNetworkAgent.connect(true); 1608 waitFor(cv); 1609 verifyActiveNetwork(TRANSPORT_CELLULAR); 1610 // Test bringing up validated WiFi. 1611 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 1612 cv = registerConnectivityBroadcast(2); 1613 mWiFiNetworkAgent.connect(true); 1614 waitFor(cv); 1615 verifyActiveNetwork(TRANSPORT_WIFI); 1616 // Test WiFi getting really weak. 1617 cv = registerConnectivityBroadcast(2); 1618 mWiFiNetworkAgent.adjustScore(-11); 1619 waitFor(cv); 1620 verifyActiveNetwork(TRANSPORT_CELLULAR); 1621 // Test WiFi restoring signal strength. 1622 cv = registerConnectivityBroadcast(2); 1623 mWiFiNetworkAgent.adjustScore(11); 1624 waitFor(cv); 1625 verifyActiveNetwork(TRANSPORT_WIFI); 1626 } 1627 1628 @Test testReapingNetwork()1629 public void testReapingNetwork() throws Exception { 1630 // Test bringing up WiFi without NET_CAPABILITY_INTERNET. 1631 // Expect it to be torn down immediately because it satisfies no requests. 1632 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 1633 mWiFiNetworkAgent.connectWithoutInternet(); 1634 mWiFiNetworkAgent.expectDisconnected(); 1635 // Test bringing up cellular without NET_CAPABILITY_INTERNET. 1636 // Expect it to be torn down immediately because it satisfies no requests. 1637 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 1638 mCellNetworkAgent.connectWithoutInternet(); 1639 mCellNetworkAgent.expectDisconnected(); 1640 // Test bringing up validated WiFi. 1641 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 1642 final ConditionVariable cv = registerConnectivityBroadcast(1); 1643 mWiFiNetworkAgent.connect(true); 1644 waitFor(cv); 1645 verifyActiveNetwork(TRANSPORT_WIFI); 1646 // Test bringing up unvalidated cellular. 1647 // Expect it to be torn down because it could never be the highest scoring network 1648 // satisfying the default request even if it validated. 1649 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 1650 mCellNetworkAgent.connect(false); 1651 mCellNetworkAgent.expectDisconnected(); 1652 verifyActiveNetwork(TRANSPORT_WIFI); 1653 mWiFiNetworkAgent.disconnect(); 1654 mWiFiNetworkAgent.expectDisconnected(); 1655 } 1656 1657 @Test testCellularFallback()1658 public void testCellularFallback() throws Exception { 1659 // Test bringing up validated cellular. 1660 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 1661 ConditionVariable cv = registerConnectivityBroadcast(1); 1662 mCellNetworkAgent.connect(true); 1663 waitFor(cv); 1664 verifyActiveNetwork(TRANSPORT_CELLULAR); 1665 // Test bringing up validated WiFi. 1666 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 1667 cv = registerConnectivityBroadcast(2); 1668 mWiFiNetworkAgent.connect(true); 1669 waitFor(cv); 1670 verifyActiveNetwork(TRANSPORT_WIFI); 1671 // Reevaluate WiFi (it'll instantly fail DNS). 1672 cv = registerConnectivityBroadcast(2); 1673 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 1674 NET_CAPABILITY_VALIDATED)); 1675 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork()); 1676 // Should quickly fall back to Cellular. 1677 waitFor(cv); 1678 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 1679 NET_CAPABILITY_VALIDATED)); 1680 verifyActiveNetwork(TRANSPORT_CELLULAR); 1681 // Reevaluate cellular (it'll instantly fail DNS). 1682 cv = registerConnectivityBroadcast(2); 1683 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( 1684 NET_CAPABILITY_VALIDATED)); 1685 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork()); 1686 // Should quickly fall back to WiFi. 1687 waitFor(cv); 1688 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( 1689 NET_CAPABILITY_VALIDATED)); 1690 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 1691 NET_CAPABILITY_VALIDATED)); 1692 verifyActiveNetwork(TRANSPORT_WIFI); 1693 } 1694 1695 @Test testWiFiFallback()1696 public void testWiFiFallback() throws Exception { 1697 // Test bringing up unvalidated WiFi. 1698 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 1699 ConditionVariable cv = registerConnectivityBroadcast(1); 1700 mWiFiNetworkAgent.connect(false); 1701 waitFor(cv); 1702 verifyActiveNetwork(TRANSPORT_WIFI); 1703 // Test bringing up validated cellular. 1704 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 1705 cv = registerConnectivityBroadcast(2); 1706 mCellNetworkAgent.connect(true); 1707 waitFor(cv); 1708 verifyActiveNetwork(TRANSPORT_CELLULAR); 1709 // Reevaluate cellular (it'll instantly fail DNS). 1710 cv = registerConnectivityBroadcast(2); 1711 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( 1712 NET_CAPABILITY_VALIDATED)); 1713 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork()); 1714 // Should quickly fall back to WiFi. 1715 waitFor(cv); 1716 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( 1717 NET_CAPABILITY_VALIDATED)); 1718 verifyActiveNetwork(TRANSPORT_WIFI); 1719 } 1720 1721 @Test testRequiresValidation()1722 public void testRequiresValidation() { 1723 assertTrue(NetworkMonitorUtils.isValidationRequired( 1724 mCm.getDefaultRequest().networkCapabilities)); 1725 } 1726 1727 /** 1728 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks 1729 * this class receives, by calling expectCallback() exactly once each time a callback is 1730 * received. assertNoCallback may be called at any time. 1731 */ 1732 private class TestNetworkCallback extends TestableNetworkCallback { TestNetworkCallback()1733 TestNetworkCallback() { 1734 super(TEST_CALLBACK_TIMEOUT_MS); 1735 } 1736 1737 @Override assertNoCallback()1738 public void assertNoCallback() { 1739 // TODO: better support this use case in TestableNetworkCallback 1740 waitForIdle(); 1741 assertNoCallback(0 /* timeout */); 1742 } 1743 1744 @Override expectCallback(final KClass<T> type, final HasNetwork n, final long timeoutMs)1745 public <T extends CallbackEntry> T expectCallback(final KClass<T> type, final HasNetwork n, 1746 final long timeoutMs) { 1747 final T callback = super.expectCallback(type, n, timeoutMs); 1748 if (callback instanceof CallbackEntry.Losing) { 1749 // TODO : move this to the specific test(s) needing this rather than here. 1750 final CallbackEntry.Losing losing = (CallbackEntry.Losing) callback; 1751 final int maxMsToLive = losing.getMaxMsToLive(); 1752 String msg = String.format( 1753 "Invalid linger time value %d, must be between %d and %d", 1754 maxMsToLive, 0, mService.mLingerDelayMs); 1755 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs); 1756 } 1757 return callback; 1758 } 1759 } 1760 1761 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can 1762 // only be declared in a static or top level type". assertNoCallbacks(TestNetworkCallback .... callbacks)1763 static void assertNoCallbacks(TestNetworkCallback ... callbacks) { 1764 for (TestNetworkCallback c : callbacks) { 1765 c.assertNoCallback(); 1766 } 1767 } 1768 1769 @Test testStateChangeNetworkCallbacks()1770 public void testStateChangeNetworkCallbacks() throws Exception { 1771 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback(); 1772 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback(); 1773 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 1774 final NetworkRequest genericRequest = new NetworkRequest.Builder() 1775 .clearCapabilities().build(); 1776 final NetworkRequest wifiRequest = new NetworkRequest.Builder() 1777 .addTransportType(TRANSPORT_WIFI).build(); 1778 final NetworkRequest cellRequest = new NetworkRequest.Builder() 1779 .addTransportType(TRANSPORT_CELLULAR).build(); 1780 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback); 1781 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback); 1782 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback); 1783 1784 // Test unvalidated networks 1785 ConditionVariable cv = registerConnectivityBroadcast(1); 1786 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 1787 mCellNetworkAgent.connect(false); 1788 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); 1789 cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); 1790 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1791 waitFor(cv); 1792 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1793 1794 // This should not trigger spurious onAvailable() callbacks, b/21762680. 1795 mCellNetworkAgent.adjustScore(-1); 1796 waitForIdle(); 1797 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1798 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1799 1800 cv = registerConnectivityBroadcast(2); 1801 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 1802 mWiFiNetworkAgent.connect(false); 1803 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 1804 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 1805 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1806 waitFor(cv); 1807 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1808 1809 cv = registerConnectivityBroadcast(2); 1810 mWiFiNetworkAgent.disconnect(); 1811 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 1812 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 1813 cellNetworkCallback.assertNoCallback(); 1814 waitFor(cv); 1815 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1816 1817 cv = registerConnectivityBroadcast(1); 1818 mCellNetworkAgent.disconnect(); 1819 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); 1820 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); 1821 waitFor(cv); 1822 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1823 1824 // Test validated networks 1825 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 1826 mCellNetworkAgent.connect(true); 1827 genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 1828 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 1829 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1830 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1831 1832 // This should not trigger spurious onAvailable() callbacks, b/21762680. 1833 mCellNetworkAgent.adjustScore(-1); 1834 waitForIdle(); 1835 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1836 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1837 1838 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 1839 mWiFiNetworkAgent.connect(true); 1840 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 1841 genericNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); 1842 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 1843 wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); 1844 cellNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); 1845 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1846 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1847 1848 mWiFiNetworkAgent.disconnect(); 1849 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 1850 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 1851 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1852 1853 mCellNetworkAgent.disconnect(); 1854 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); 1855 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); 1856 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1857 } 1858 doNetworkCallbacksSanitizationTest(boolean sanitized)1859 private void doNetworkCallbacksSanitizationTest(boolean sanitized) throws Exception { 1860 final TestNetworkCallback callback = new TestNetworkCallback(); 1861 final TestNetworkCallback defaultCallback = new TestNetworkCallback(); 1862 final NetworkRequest wifiRequest = new NetworkRequest.Builder() 1863 .addTransportType(TRANSPORT_WIFI).build(); 1864 mCm.registerNetworkCallback(wifiRequest, callback); 1865 mCm.registerDefaultNetworkCallback(defaultCallback); 1866 1867 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 1868 mWiFiNetworkAgent.connect(false); 1869 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 1870 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 1871 1872 final LinkProperties newLp = new LinkProperties(); 1873 final Uri capportUrl = Uri.parse("https://capport.example.com/api"); 1874 final CaptivePortalData capportData = new CaptivePortalData.Builder() 1875 .setCaptive(true).build(); 1876 1877 final Uri expectedCapportUrl = sanitized ? null : capportUrl; 1878 newLp.setCaptivePortalApiUrl(capportUrl); 1879 mWiFiNetworkAgent.sendLinkProperties(newLp); 1880 callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp -> 1881 Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl())); 1882 defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp -> 1883 Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl())); 1884 1885 final CaptivePortalData expectedCapportData = sanitized ? null : capportData; 1886 mWiFiNetworkAgent.notifyCaptivePortalDataChanged(capportData); 1887 callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp -> 1888 Objects.equals(expectedCapportData, lp.getCaptivePortalData())); 1889 defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp -> 1890 Objects.equals(expectedCapportData, lp.getCaptivePortalData())); 1891 1892 final LinkProperties lp = mCm.getLinkProperties(mWiFiNetworkAgent.getNetwork()); 1893 assertEquals(expectedCapportUrl, lp.getCaptivePortalApiUrl()); 1894 assertEquals(expectedCapportData, lp.getCaptivePortalData()); 1895 } 1896 1897 @Test networkCallbacksSanitizationTest_Sanitize()1898 public void networkCallbacksSanitizationTest_Sanitize() throws Exception { 1899 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, 1900 PERMISSION_DENIED); 1901 mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, 1902 PERMISSION_DENIED); 1903 doNetworkCallbacksSanitizationTest(true /* sanitized */); 1904 } 1905 1906 @Test networkCallbacksSanitizationTest_NoSanitize_NetworkStack()1907 public void networkCallbacksSanitizationTest_NoSanitize_NetworkStack() throws Exception { 1908 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, 1909 PERMISSION_GRANTED); 1910 mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, PERMISSION_DENIED); 1911 doNetworkCallbacksSanitizationTest(false /* sanitized */); 1912 } 1913 1914 @Test networkCallbacksSanitizationTest_NoSanitize_Settings()1915 public void networkCallbacksSanitizationTest_NoSanitize_Settings() throws Exception { 1916 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, 1917 PERMISSION_DENIED); 1918 mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED); 1919 doNetworkCallbacksSanitizationTest(false /* sanitized */); 1920 } 1921 1922 @Test testMultipleLingering()1923 public void testMultipleLingering() throws Exception { 1924 // This test would be flaky with the default 120ms timer: that is short enough that 1925 // lingered networks are torn down before assertions can be run. We don't want to mock the 1926 // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful 1927 // in detecting races. 1928 mService.mLingerDelayMs = 300; 1929 1930 NetworkRequest request = new NetworkRequest.Builder() 1931 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED) 1932 .build(); 1933 TestNetworkCallback callback = new TestNetworkCallback(); 1934 mCm.registerNetworkCallback(request, callback); 1935 1936 TestNetworkCallback defaultCallback = new TestNetworkCallback(); 1937 mCm.registerDefaultNetworkCallback(defaultCallback); 1938 1939 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 1940 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 1941 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET); 1942 1943 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); 1944 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); 1945 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); 1946 1947 mCellNetworkAgent.connect(true); 1948 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 1949 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 1950 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1951 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 1952 1953 mWiFiNetworkAgent.connect(true); 1954 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request. 1955 // We then get LOSING when wifi validates and cell is outscored. 1956 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 1957 // TODO: Investigate sending validated before losing. 1958 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); 1959 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 1960 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 1961 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1962 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 1963 1964 mEthernetNetworkAgent.connect(true); 1965 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent); 1966 // TODO: Investigate sending validated before losing. 1967 callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent); 1968 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent); 1969 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent); 1970 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1971 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 1972 1973 mEthernetNetworkAgent.disconnect(); 1974 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent); 1975 defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent); 1976 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); 1977 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 1978 1979 for (int i = 0; i < 4; i++) { 1980 TestNetworkAgentWrapper oldNetwork, newNetwork; 1981 if (i % 2 == 0) { 1982 mWiFiNetworkAgent.adjustScore(-15); 1983 oldNetwork = mWiFiNetworkAgent; 1984 newNetwork = mCellNetworkAgent; 1985 } else { 1986 mWiFiNetworkAgent.adjustScore(15); 1987 oldNetwork = mCellNetworkAgent; 1988 newNetwork = mWiFiNetworkAgent; 1989 1990 } 1991 callback.expectCallback(CallbackEntry.LOSING, oldNetwork); 1992 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no 1993 // longer lingering? 1994 defaultCallback.expectAvailableCallbacksValidated(newNetwork); 1995 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork()); 1996 } 1997 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1998 1999 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even 2000 // if the network is still up. 2001 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED); 2002 // We expect a notification about the capabilities change, and nothing else. 2003 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent); 2004 defaultCallback.assertNoCallback(); 2005 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2006 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 2007 2008 // Wifi no longer satisfies our listen, which is for an unmetered network. 2009 // But because its score is 55, it's still up (and the default network). 2010 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 2011 2012 // Disconnect our test networks. 2013 mWiFiNetworkAgent.disconnect(); 2014 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2015 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 2016 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 2017 mCellNetworkAgent.disconnect(); 2018 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); 2019 waitForIdle(); 2020 assertEquals(null, mCm.getActiveNetwork()); 2021 2022 mCm.unregisterNetworkCallback(callback); 2023 waitForIdle(); 2024 2025 // Check that a network is only lingered or torn down if it would not satisfy a request even 2026 // if it validated. 2027 request = new NetworkRequest.Builder().clearCapabilities().build(); 2028 callback = new TestNetworkCallback(); 2029 2030 mCm.registerNetworkCallback(request, callback); 2031 2032 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 2033 mCellNetworkAgent.connect(false); // Score: 10 2034 callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); 2035 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); 2036 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 2037 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 2038 2039 // Bring up wifi with a score of 20. 2040 // Cell stays up because it would satisfy the default request if it validated. 2041 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2042 mWiFiNetworkAgent.connect(false); // Score: 20 2043 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2044 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2045 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 2046 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 2047 2048 mWiFiNetworkAgent.disconnect(); 2049 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2050 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2051 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); 2052 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 2053 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 2054 2055 // Bring up wifi with a score of 70. 2056 // Cell is lingered because it would not satisfy any request, even if it validated. 2057 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2058 mWiFiNetworkAgent.adjustScore(50); 2059 mWiFiNetworkAgent.connect(false); // Score: 70 2060 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2061 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); 2062 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2063 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 2064 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 2065 2066 // Tear down wifi. 2067 mWiFiNetworkAgent.disconnect(); 2068 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2069 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2070 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); 2071 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 2072 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 2073 2074 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but 2075 // it's arguably correct to linger it, since it was the default network before it validated. 2076 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2077 mWiFiNetworkAgent.connect(true); 2078 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2079 // TODO: Investigate sending validated before losing. 2080 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); 2081 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 2082 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); 2083 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 2084 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 2085 2086 mWiFiNetworkAgent.disconnect(); 2087 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2088 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2089 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); 2090 mCellNetworkAgent.disconnect(); 2091 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); 2092 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); 2093 waitForIdle(); 2094 assertEquals(null, mCm.getActiveNetwork()); 2095 2096 // If a network is lingering, and we add and remove a request from it, resume lingering. 2097 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 2098 mCellNetworkAgent.connect(true); 2099 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 2100 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 2101 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 2102 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2103 mWiFiNetworkAgent.connect(true); 2104 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 2105 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2106 // TODO: Investigate sending validated before losing. 2107 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); 2108 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 2109 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 2110 2111 NetworkRequest cellRequest = new NetworkRequest.Builder() 2112 .addTransportType(TRANSPORT_CELLULAR).build(); 2113 NetworkCallback noopCallback = new NetworkCallback(); 2114 mCm.requestNetwork(cellRequest, noopCallback); 2115 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer 2116 // lingering? 2117 mCm.unregisterNetworkCallback(noopCallback); 2118 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); 2119 2120 // Similar to the above: lingering can start even after the lingered request is removed. 2121 // Disconnect wifi and switch to cell. 2122 mWiFiNetworkAgent.disconnect(); 2123 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2124 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2125 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 2126 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 2127 2128 // Cell is now the default network. Pin it with a cell-specific request. 2129 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525 2130 mCm.requestNetwork(cellRequest, noopCallback); 2131 2132 // Now connect wifi, and expect it to become the default network. 2133 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2134 mWiFiNetworkAgent.connect(true); 2135 callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); 2136 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 2137 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 2138 // The default request is lingering on cell, but nothing happens to cell, and we send no 2139 // callbacks for it, because it's kept up by cellRequest. 2140 callback.assertNoCallback(); 2141 // Now unregister cellRequest and expect cell to start lingering. 2142 mCm.unregisterNetworkCallback(noopCallback); 2143 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); 2144 2145 // Let linger run its course. 2146 callback.assertNoCallback(); 2147 final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4; 2148 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, lingerTimeoutMs); 2149 2150 // Register a TRACK_DEFAULT request and check that it does not affect lingering. 2151 TestNetworkCallback trackDefaultCallback = new TestNetworkCallback(); 2152 mCm.registerDefaultNetworkCallback(trackDefaultCallback); 2153 trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); 2154 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET); 2155 mEthernetNetworkAgent.connect(true); 2156 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent); 2157 callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent); 2158 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent); 2159 trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent); 2160 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent); 2161 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 2162 2163 // Let linger run its course. 2164 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent, lingerTimeoutMs); 2165 2166 // Clean up. 2167 mEthernetNetworkAgent.disconnect(); 2168 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent); 2169 defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent); 2170 trackDefaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent); 2171 2172 mCm.unregisterNetworkCallback(callback); 2173 mCm.unregisterNetworkCallback(defaultCallback); 2174 mCm.unregisterNetworkCallback(trackDefaultCallback); 2175 } 2176 grantUsingBackgroundNetworksPermissionForUid(final int uid)2177 private void grantUsingBackgroundNetworksPermissionForUid(final int uid) throws Exception { 2178 final String testPackageName = mContext.getPackageName(); 2179 when(mPackageManager.getPackageInfo(eq(testPackageName), eq(GET_PERMISSIONS))) 2180 .thenReturn(buildPackageInfo(true, uid)); 2181 mService.mPermissionMonitor.onPackageAdded(testPackageName, uid); 2182 } 2183 2184 @Test testNetworkGoesIntoBackgroundAfterLinger()2185 public void testNetworkGoesIntoBackgroundAfterLinger() throws Exception { 2186 setAlwaysOnNetworks(true); 2187 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid()); 2188 NetworkRequest request = new NetworkRequest.Builder() 2189 .clearCapabilities() 2190 .build(); 2191 TestNetworkCallback callback = new TestNetworkCallback(); 2192 mCm.registerNetworkCallback(request, callback); 2193 2194 TestNetworkCallback defaultCallback = new TestNetworkCallback(); 2195 mCm.registerDefaultNetworkCallback(defaultCallback); 2196 2197 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 2198 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2199 2200 mCellNetworkAgent.connect(true); 2201 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 2202 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 2203 2204 // Wifi comes up and cell lingers. 2205 mWiFiNetworkAgent.connect(true); 2206 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 2207 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2208 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); 2209 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 2210 2211 // File a request for cellular, then release it. 2212 NetworkRequest cellRequest = new NetworkRequest.Builder() 2213 .addTransportType(TRANSPORT_CELLULAR).build(); 2214 NetworkCallback noopCallback = new NetworkCallback(); 2215 mCm.requestNetwork(cellRequest, noopCallback); 2216 mCm.unregisterNetworkCallback(noopCallback); 2217 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); 2218 2219 // Let linger run its course. 2220 callback.assertNoCallback(); 2221 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4; 2222 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent, 2223 lingerTimeoutMs); 2224 2225 // Clean up. 2226 mCm.unregisterNetworkCallback(defaultCallback); 2227 mCm.unregisterNetworkCallback(callback); 2228 } 2229 2230 @Test testExplicitlySelected()2231 public void testExplicitlySelected() throws Exception { 2232 NetworkRequest request = new NetworkRequest.Builder() 2233 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET) 2234 .build(); 2235 TestNetworkCallback callback = new TestNetworkCallback(); 2236 mCm.registerNetworkCallback(request, callback); 2237 2238 // Bring up validated cell. 2239 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 2240 mCellNetworkAgent.connect(true); 2241 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 2242 2243 // Bring up unvalidated wifi with explicitlySelected=true. 2244 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2245 mWiFiNetworkAgent.explicitlySelected(true, false); 2246 mWiFiNetworkAgent.connect(false); 2247 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2248 2249 // Cell Remains the default. 2250 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 2251 2252 // Lower wifi's score to below than cell, and check that it doesn't disconnect because 2253 // it's explicitly selected. 2254 mWiFiNetworkAgent.adjustScore(-40); 2255 mWiFiNetworkAgent.adjustScore(40); 2256 callback.assertNoCallback(); 2257 2258 // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to 2259 // wifi even though it's unvalidated. 2260 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false); 2261 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); 2262 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 2263 2264 // Disconnect wifi, and then reconnect, again with explicitlySelected=true. 2265 mWiFiNetworkAgent.disconnect(); 2266 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2267 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2268 mWiFiNetworkAgent.explicitlySelected(true, false); 2269 mWiFiNetworkAgent.connect(false); 2270 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2271 2272 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the 2273 // network to disconnect. 2274 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false); 2275 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2276 2277 // Reconnect, again with explicitlySelected=true, but this time validate. 2278 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2279 mWiFiNetworkAgent.explicitlySelected(true, false); 2280 mWiFiNetworkAgent.connect(true); 2281 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2282 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); 2283 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 2284 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 2285 2286 // BUG: the network will no longer linger, even though it's validated and outscored. 2287 // TODO: fix this. 2288 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET); 2289 mEthernetNetworkAgent.connect(true); 2290 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent); 2291 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 2292 callback.assertNoCallback(); 2293 2294 // Disconnect wifi, and then reconnect as if the user had selected "yes, don't ask again" 2295 // (i.e., with explicitlySelected=true and acceptUnvalidated=true). Expect to switch to 2296 // wifi immediately. 2297 mWiFiNetworkAgent.disconnect(); 2298 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2299 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2300 mWiFiNetworkAgent.explicitlySelected(true, true); 2301 mWiFiNetworkAgent.connect(false); 2302 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2303 callback.expectCallback(CallbackEntry.LOSING, mEthernetNetworkAgent); 2304 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 2305 mEthernetNetworkAgent.disconnect(); 2306 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent); 2307 2308 // Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true. 2309 // Check that the network is not scored specially and that the device prefers cell data. 2310 mWiFiNetworkAgent.disconnect(); 2311 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2312 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2313 mWiFiNetworkAgent.explicitlySelected(false, true); 2314 mWiFiNetworkAgent.connect(false); 2315 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2316 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 2317 2318 // Clean up. 2319 mWiFiNetworkAgent.disconnect(); 2320 mCellNetworkAgent.disconnect(); 2321 2322 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2323 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); 2324 } 2325 makeIntArray(final int size, final int value)2326 private int[] makeIntArray(final int size, final int value) { 2327 final int[] array = new int[size]; 2328 Arrays.fill(array, value); 2329 return array; 2330 } 2331 tryNetworkFactoryRequests(int capability)2332 private void tryNetworkFactoryRequests(int capability) throws Exception { 2333 // Verify NOT_RESTRICTED is set appropriately 2334 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability) 2335 .build().networkCapabilities; 2336 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN || 2337 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA || 2338 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS || 2339 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) { 2340 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); 2341 } else { 2342 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); 2343 } 2344 2345 NetworkCapabilities filter = new NetworkCapabilities(); 2346 filter.addCapability(capability); 2347 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests"); 2348 handlerThread.start(); 2349 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), 2350 mServiceContext, "testFactory", filter); 2351 testFactory.setScoreFilter(40); 2352 ConditionVariable cv = testFactory.getNetworkStartedCV(); 2353 testFactory.expectAddRequestsWithScores(0); 2354 testFactory.register(); 2355 testFactory.waitForNetworkRequests(1); 2356 int expectedRequestCount = 1; 2357 NetworkCallback networkCallback = null; 2358 // For non-INTERNET capabilities we cannot rely on the default request being present, so 2359 // add one. 2360 if (capability != NET_CAPABILITY_INTERNET) { 2361 assertFalse(testFactory.getMyStartRequested()); 2362 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build(); 2363 networkCallback = new NetworkCallback(); 2364 testFactory.expectAddRequestsWithScores(0); // New request 2365 mCm.requestNetwork(request, networkCallback); 2366 expectedRequestCount++; 2367 testFactory.waitForNetworkRequests(expectedRequestCount); 2368 } 2369 waitFor(cv); 2370 assertEquals(expectedRequestCount, testFactory.getMyRequestCount()); 2371 assertTrue(testFactory.getMyStartRequested()); 2372 2373 // Now bring in a higher scored network. 2374 TestNetworkAgentWrapper testAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 2375 // Rather than create a validated network which complicates things by registering it's 2376 // own NetworkRequest during startup, just bump up the score to cancel out the 2377 // unvalidated penalty. 2378 testAgent.adjustScore(40); 2379 cv = testFactory.getNetworkStoppedCV(); 2380 2381 // When testAgent connects, ConnectivityService will re-send us all current requests with 2382 // the new score. There are expectedRequestCount such requests, and we must wait for all of 2383 // them. 2384 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 50)); 2385 testAgent.connect(false); 2386 testAgent.addCapability(capability); 2387 waitFor(cv); 2388 testFactory.waitForNetworkRequests(expectedRequestCount); 2389 assertFalse(testFactory.getMyStartRequested()); 2390 2391 // Bring in a bunch of requests. 2392 testFactory.expectAddRequestsWithScores(makeIntArray(10, 50)); 2393 assertEquals(expectedRequestCount, testFactory.getMyRequestCount()); 2394 ConnectivityManager.NetworkCallback[] networkCallbacks = 2395 new ConnectivityManager.NetworkCallback[10]; 2396 for (int i = 0; i< networkCallbacks.length; i++) { 2397 networkCallbacks[i] = new ConnectivityManager.NetworkCallback(); 2398 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 2399 builder.addCapability(capability); 2400 mCm.requestNetwork(builder.build(), networkCallbacks[i]); 2401 } 2402 testFactory.waitForNetworkRequests(10 + expectedRequestCount); 2403 assertFalse(testFactory.getMyStartRequested()); 2404 2405 // Remove the requests. 2406 testFactory.expectRemoveRequests(10); 2407 for (int i = 0; i < networkCallbacks.length; i++) { 2408 mCm.unregisterNetworkCallback(networkCallbacks[i]); 2409 } 2410 testFactory.waitForNetworkRequests(expectedRequestCount); 2411 assertFalse(testFactory.getMyStartRequested()); 2412 2413 // Drop the higher scored network. 2414 cv = testFactory.getNetworkStartedCV(); 2415 // With the default network disconnecting, the requests are sent with score 0 to factories. 2416 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 0)); 2417 testAgent.disconnect(); 2418 waitFor(cv); 2419 testFactory.waitForNetworkRequests(expectedRequestCount); 2420 assertEquals(expectedRequestCount, testFactory.getMyRequestCount()); 2421 assertTrue(testFactory.getMyStartRequested()); 2422 2423 testFactory.terminate(); 2424 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback); 2425 handlerThread.quit(); 2426 } 2427 2428 @Test testNetworkFactoryRequests()2429 public void testNetworkFactoryRequests() throws Exception { 2430 tryNetworkFactoryRequests(NET_CAPABILITY_MMS); 2431 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL); 2432 tryNetworkFactoryRequests(NET_CAPABILITY_DUN); 2433 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA); 2434 tryNetworkFactoryRequests(NET_CAPABILITY_IMS); 2435 tryNetworkFactoryRequests(NET_CAPABILITY_CBS); 2436 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P); 2437 tryNetworkFactoryRequests(NET_CAPABILITY_IA); 2438 tryNetworkFactoryRequests(NET_CAPABILITY_RCS); 2439 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP); 2440 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS); 2441 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED); 2442 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET); 2443 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED); 2444 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN); 2445 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed. 2446 } 2447 2448 @Test testNetworkFactoryUnregister()2449 public void testNetworkFactoryUnregister() throws Exception { 2450 final NetworkCapabilities filter = new NetworkCapabilities(); 2451 filter.clearAll(); 2452 2453 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests"); 2454 handlerThread.start(); 2455 2456 // Checks that calling setScoreFilter on a NetworkFactory immediately before closing it 2457 // does not crash. 2458 for (int i = 0; i < 100; i++) { 2459 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), 2460 mServiceContext, "testFactory", filter); 2461 // Register the factory and don't be surprised when the default request arrives. 2462 testFactory.expectAddRequestsWithScores(0); 2463 testFactory.register(); 2464 testFactory.waitForNetworkRequests(1); 2465 2466 testFactory.setScoreFilter(42); 2467 testFactory.terminate(); 2468 2469 if (i % 2 == 0) { 2470 try { 2471 testFactory.register(); 2472 fail("Re-registering terminated NetworkFactory should throw"); 2473 } catch (IllegalStateException expected) { 2474 } 2475 } 2476 } 2477 handlerThread.quit(); 2478 } 2479 2480 @Test testNoMutableNetworkRequests()2481 public void testNoMutableNetworkRequests() throws Exception { 2482 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0); 2483 NetworkRequest request1 = new NetworkRequest.Builder() 2484 .addCapability(NET_CAPABILITY_VALIDATED) 2485 .build(); 2486 NetworkRequest request2 = new NetworkRequest.Builder() 2487 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL) 2488 .build(); 2489 2490 Class<IllegalArgumentException> expected = IllegalArgumentException.class; 2491 assertThrows(expected, () -> mCm.requestNetwork(request1, new NetworkCallback())); 2492 assertThrows(expected, () -> mCm.requestNetwork(request1, pendingIntent)); 2493 assertThrows(expected, () -> mCm.requestNetwork(request2, new NetworkCallback())); 2494 assertThrows(expected, () -> mCm.requestNetwork(request2, pendingIntent)); 2495 } 2496 2497 @Test testMMSonWiFi()2498 public void testMMSonWiFi() throws Exception { 2499 // Test bringing up cellular without MMS NetworkRequest gets reaped 2500 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 2501 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS); 2502 mCellNetworkAgent.connectWithoutInternet(); 2503 mCellNetworkAgent.expectDisconnected(); 2504 waitForIdle(); 2505 assertEmpty(mCm.getAllNetworks()); 2506 verifyNoNetwork(); 2507 2508 // Test bringing up validated WiFi. 2509 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2510 final ConditionVariable cv = registerConnectivityBroadcast(1); 2511 mWiFiNetworkAgent.connect(true); 2512 waitFor(cv); 2513 verifyActiveNetwork(TRANSPORT_WIFI); 2514 2515 // Register MMS NetworkRequest 2516 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 2517 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS); 2518 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 2519 mCm.requestNetwork(builder.build(), networkCallback); 2520 2521 // Test bringing up unvalidated cellular with MMS 2522 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 2523 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS); 2524 mCellNetworkAgent.connectWithoutInternet(); 2525 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); 2526 verifyActiveNetwork(TRANSPORT_WIFI); 2527 2528 // Test releasing NetworkRequest disconnects cellular with MMS 2529 mCm.unregisterNetworkCallback(networkCallback); 2530 mCellNetworkAgent.expectDisconnected(); 2531 verifyActiveNetwork(TRANSPORT_WIFI); 2532 } 2533 2534 @Test testMMSonCell()2535 public void testMMSonCell() throws Exception { 2536 // Test bringing up cellular without MMS 2537 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 2538 ConditionVariable cv = registerConnectivityBroadcast(1); 2539 mCellNetworkAgent.connect(false); 2540 waitFor(cv); 2541 verifyActiveNetwork(TRANSPORT_CELLULAR); 2542 2543 // Register MMS NetworkRequest 2544 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 2545 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS); 2546 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 2547 mCm.requestNetwork(builder.build(), networkCallback); 2548 2549 // Test bringing up MMS cellular network 2550 TestNetworkAgentWrapper 2551 mmsNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 2552 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS); 2553 mmsNetworkAgent.connectWithoutInternet(); 2554 networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent); 2555 verifyActiveNetwork(TRANSPORT_CELLULAR); 2556 2557 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent 2558 mCm.unregisterNetworkCallback(networkCallback); 2559 mmsNetworkAgent.expectDisconnected(); 2560 verifyActiveNetwork(TRANSPORT_CELLULAR); 2561 } 2562 2563 @Test testPartialConnectivity()2564 public void testPartialConnectivity() throws Exception { 2565 // Register network callback. 2566 NetworkRequest request = new NetworkRequest.Builder() 2567 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET) 2568 .build(); 2569 TestNetworkCallback callback = new TestNetworkCallback(); 2570 mCm.registerNetworkCallback(request, callback); 2571 2572 // Bring up validated mobile data. 2573 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 2574 mCellNetworkAgent.connect(true); 2575 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 2576 2577 // Bring up wifi with partial connectivity. 2578 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2579 mWiFiNetworkAgent.connectWithPartialConnectivity(); 2580 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2581 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent); 2582 2583 // Mobile data should be the default network. 2584 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 2585 callback.assertNoCallback(); 2586 2587 // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http 2588 // probe. 2589 mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */); 2590 // If the user chooses yes to use this partial connectivity wifi, switch the default 2591 // network to wifi and check if wifi becomes valid or not. 2592 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */, 2593 false /* always */); 2594 // If user accepts partial connectivity network, 2595 // NetworkMonitor#setAcceptPartialConnectivity() should be called too. 2596 waitForIdle(); 2597 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity(); 2598 2599 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is 2600 // validated. 2601 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true); 2602 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); 2603 NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, 2604 mWiFiNetworkAgent); 2605 assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY)); 2606 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 2607 2608 // Disconnect and reconnect wifi with partial connectivity again. 2609 mWiFiNetworkAgent.disconnect(); 2610 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2611 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2612 mWiFiNetworkAgent.connectWithPartialConnectivity(); 2613 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2614 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent); 2615 2616 // Mobile data should be the default network. 2617 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 2618 2619 // If the user chooses no, disconnect wifi immediately. 2620 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */, 2621 false /* always */); 2622 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2623 2624 // If user accepted partial connectivity before, and device reconnects to that network 2625 // again, but now the network has full connectivity. The network shouldn't contain 2626 // NET_CAPABILITY_PARTIAL_CONNECTIVITY. 2627 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2628 // acceptUnvalidated is also used as setting for accepting partial networks. 2629 mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */, 2630 true /* acceptUnvalidated */); 2631 mWiFiNetworkAgent.connect(true); 2632 2633 // If user accepted partial connectivity network before, 2634 // NetworkMonitor#setAcceptPartialConnectivity() will be called in 2635 // ConnectivityService#updateNetworkInfo(). 2636 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2637 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity(); 2638 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); 2639 nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 2640 assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY)); 2641 2642 // Wifi should be the default network. 2643 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 2644 mWiFiNetworkAgent.disconnect(); 2645 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2646 2647 // The user accepted partial connectivity and selected "don't ask again". Now the user 2648 // reconnects to the partial connectivity network. Switch to wifi as soon as partial 2649 // connectivity is detected. 2650 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2651 mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */, 2652 true /* acceptUnvalidated */); 2653 mWiFiNetworkAgent.connectWithPartialConnectivity(); 2654 // If user accepted partial connectivity network before, 2655 // NetworkMonitor#setAcceptPartialConnectivity() will be called in 2656 // ConnectivityService#updateNetworkInfo(). 2657 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2658 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity(); 2659 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); 2660 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 2661 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent); 2662 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */); 2663 2664 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is 2665 // validated. 2666 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true); 2667 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 2668 mWiFiNetworkAgent.disconnect(); 2669 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2670 2671 // If the user accepted partial connectivity, and the device auto-reconnects to the partial 2672 // connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED. 2673 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2674 mWiFiNetworkAgent.explicitlySelected(false /* explicitlySelected */, 2675 true /* acceptUnvalidated */); 2676 2677 // NetworkMonitor will immediately (once the HTTPS probe fails...) report the network as 2678 // valid, because ConnectivityService calls setAcceptPartialConnectivity before it calls 2679 // notifyNetworkConnected. 2680 mWiFiNetworkAgent.connectWithPartialValidConnectivity(false /* isStrictMode */); 2681 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2682 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity(); 2683 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); 2684 callback.expectCapabilitiesWith( 2685 NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 2686 mWiFiNetworkAgent.disconnect(); 2687 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2688 } 2689 2690 @Test testCaptivePortalOnPartialConnectivity()2691 public void testCaptivePortalOnPartialConnectivity() throws Exception { 2692 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); 2693 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() 2694 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build(); 2695 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback); 2696 2697 final TestNetworkCallback validatedCallback = new TestNetworkCallback(); 2698 final NetworkRequest validatedRequest = new NetworkRequest.Builder() 2699 .addCapability(NET_CAPABILITY_VALIDATED).build(); 2700 mCm.registerNetworkCallback(validatedRequest, validatedCallback); 2701 2702 // Bring up a network with a captive portal. 2703 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL. 2704 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2705 String redirectUrl = "http://android.com/path"; 2706 mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */); 2707 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2708 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), redirectUrl); 2709 2710 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor. 2711 mCm.startCaptivePortalApp(mWiFiNetworkAgent.getNetwork()); 2712 verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1)) 2713 .launchCaptivePortalApp(); 2714 2715 // Report that the captive portal is dismissed with partial connectivity, and check that 2716 // callbacks are fired. 2717 mWiFiNetworkAgent.setNetworkPartial(); 2718 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true); 2719 waitForIdle(); 2720 captivePortalCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, 2721 mWiFiNetworkAgent); 2722 2723 // Report partial connectivity is accepted. 2724 mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */); 2725 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */, 2726 false /* always */); 2727 waitForIdle(); 2728 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true); 2729 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2730 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); 2731 NetworkCapabilities nc = 2732 validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, 2733 mWiFiNetworkAgent); 2734 2735 mCm.unregisterNetworkCallback(captivePortalCallback); 2736 mCm.unregisterNetworkCallback(validatedCallback); 2737 } 2738 2739 @Test testCaptivePortal()2740 public void testCaptivePortal() throws Exception { 2741 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); 2742 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() 2743 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build(); 2744 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback); 2745 2746 final TestNetworkCallback validatedCallback = new TestNetworkCallback(); 2747 final NetworkRequest validatedRequest = new NetworkRequest.Builder() 2748 .addCapability(NET_CAPABILITY_VALIDATED).build(); 2749 mCm.registerNetworkCallback(validatedRequest, validatedCallback); 2750 2751 // Bring up a network with a captive portal. 2752 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL. 2753 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2754 String firstRedirectUrl = "http://example.com/firstPath"; 2755 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */); 2756 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2757 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl); 2758 2759 // Take down network. 2760 // Expect onLost callback. 2761 mWiFiNetworkAgent.disconnect(); 2762 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2763 2764 // Bring up a network with a captive portal. 2765 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL. 2766 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2767 String secondRedirectUrl = "http://example.com/secondPath"; 2768 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl, false /* isStrictMode */); 2769 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2770 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl); 2771 2772 // Make captive portal disappear then revalidate. 2773 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL. 2774 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */); 2775 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true); 2776 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2777 2778 // Expect NET_CAPABILITY_VALIDATED onAvailable callback. 2779 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 2780 2781 // Break network connectivity. 2782 // Expect NET_CAPABILITY_VALIDATED onLost callback. 2783 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */); 2784 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false); 2785 validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2786 } 2787 2788 @Test testCaptivePortalApp()2789 public void testCaptivePortalApp() throws Exception { 2790 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); 2791 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() 2792 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build(); 2793 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback); 2794 2795 final TestNetworkCallback validatedCallback = new TestNetworkCallback(); 2796 final NetworkRequest validatedRequest = new NetworkRequest.Builder() 2797 .addCapability(NET_CAPABILITY_VALIDATED).build(); 2798 mCm.registerNetworkCallback(validatedRequest, validatedCallback); 2799 2800 // Bring up wifi. 2801 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2802 mWiFiNetworkAgent.connect(true); 2803 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 2804 Network wifiNetwork = mWiFiNetworkAgent.getNetwork(); 2805 2806 // Check that calling startCaptivePortalApp does nothing. 2807 final int fastTimeoutMs = 100; 2808 mCm.startCaptivePortalApp(wifiNetwork); 2809 waitForIdle(); 2810 verify(mWiFiNetworkAgent.mNetworkMonitor, never()).launchCaptivePortalApp(); 2811 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs); 2812 2813 // Turn into a captive portal. 2814 mWiFiNetworkAgent.setNetworkPortal("http://example.com", false /* isStrictMode */); 2815 mCm.reportNetworkConnectivity(wifiNetwork, false); 2816 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2817 validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2818 2819 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor. 2820 mCm.startCaptivePortalApp(wifiNetwork); 2821 waitForIdle(); 2822 verify(mWiFiNetworkAgent.mNetworkMonitor).launchCaptivePortalApp(); 2823 2824 // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal) 2825 final Bundle testBundle = new Bundle(); 2826 final String testKey = "testkey"; 2827 final String testValue = "testvalue"; 2828 testBundle.putString(testKey, testValue); 2829 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, 2830 PERMISSION_GRANTED); 2831 mCm.startCaptivePortalApp(wifiNetwork, testBundle); 2832 final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS); 2833 assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction()); 2834 assertEquals(testValue, signInIntent.getStringExtra(testKey)); 2835 2836 // Report that the captive portal is dismissed, and check that callbacks are fired 2837 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */); 2838 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid()); 2839 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); 2840 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 2841 2842 mCm.unregisterNetworkCallback(validatedCallback); 2843 mCm.unregisterNetworkCallback(captivePortalCallback); 2844 } 2845 2846 @Test testAvoidOrIgnoreCaptivePortals()2847 public void testAvoidOrIgnoreCaptivePortals() throws Exception { 2848 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); 2849 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() 2850 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build(); 2851 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback); 2852 2853 final TestNetworkCallback validatedCallback = new TestNetworkCallback(); 2854 final NetworkRequest validatedRequest = new NetworkRequest.Builder() 2855 .addCapability(NET_CAPABILITY_VALIDATED).build(); 2856 mCm.registerNetworkCallback(validatedRequest, validatedCallback); 2857 2858 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID); 2859 // Bring up a network with a captive portal. 2860 // Expect it to fail to connect and not result in any callbacks. 2861 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2862 String firstRedirectUrl = "http://example.com/firstPath"; 2863 2864 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */); 2865 mWiFiNetworkAgent.expectDisconnected(); 2866 mWiFiNetworkAgent.expectPreventReconnectReceived(); 2867 2868 assertNoCallbacks(captivePortalCallback, validatedCallback); 2869 } 2870 2871 @Test testCaptivePortalApi()2872 public void testCaptivePortalApi() throws Exception { 2873 mServiceContext.setPermission( 2874 android.Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED); 2875 2876 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); 2877 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() 2878 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build(); 2879 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback); 2880 2881 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 2882 final String redirectUrl = "http://example.com/firstPath"; 2883 2884 mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */); 2885 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2886 2887 final CaptivePortalData testData = new CaptivePortalData.Builder() 2888 .setUserPortalUrl(Uri.parse(redirectUrl)) 2889 .setBytesRemaining(12345L) 2890 .build(); 2891 2892 mWiFiNetworkAgent.notifyCaptivePortalDataChanged(testData); 2893 2894 captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, 2895 lp -> testData.equals(lp.getCaptivePortalData())); 2896 2897 final LinkProperties newLps = new LinkProperties(); 2898 newLps.setMtu(1234); 2899 mWiFiNetworkAgent.sendLinkProperties(newLps); 2900 // CaptivePortalData is not lost and unchanged when LPs are received from the NetworkAgent 2901 captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, 2902 lp -> testData.equals(lp.getCaptivePortalData()) && lp.getMtu() == 1234); 2903 } 2904 newWifiRequestBuilder()2905 private NetworkRequest.Builder newWifiRequestBuilder() { 2906 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI); 2907 } 2908 2909 /** 2910 * Verify request matching behavior with network specifiers. 2911 * 2912 * Note: this test is somewhat problematic since it involves removing capabilities from 2913 * agents - i.e. agents rejecting requests which they previously accepted. This is flagged 2914 * as a WTF bug in 2915 * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but 2916 * does work. 2917 */ 2918 @Test testNetworkSpecifier()2919 public void testNetworkSpecifier() throws Exception { 2920 // A NetworkSpecifier subclass that matches all networks but must not be visible to apps. 2921 class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements 2922 Parcelable { 2923 @Override 2924 public boolean canBeSatisfiedBy(NetworkSpecifier other) { 2925 return true; 2926 } 2927 2928 @Override 2929 public int describeContents() { 2930 return 0; 2931 } 2932 2933 @Override 2934 public void writeToParcel(Parcel dest, int flags) {} 2935 2936 @Override 2937 public NetworkSpecifier redact() { 2938 return null; 2939 } 2940 } 2941 2942 // A network specifier that matches either another LocalNetworkSpecifier with the same 2943 // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is. 2944 class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable { 2945 private String mString; 2946 2947 LocalStringNetworkSpecifier(String string) { 2948 mString = string; 2949 } 2950 2951 @Override 2952 public boolean canBeSatisfiedBy(NetworkSpecifier other) { 2953 if (other instanceof LocalStringNetworkSpecifier) { 2954 return TextUtils.equals(mString, 2955 ((LocalStringNetworkSpecifier) other).mString); 2956 } 2957 if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true; 2958 return false; 2959 } 2960 2961 @Override 2962 public int describeContents() { 2963 return 0; 2964 } 2965 @Override 2966 public void writeToParcel(Parcel dest, int flags) {} 2967 } 2968 2969 2970 NetworkRequest rEmpty1 = newWifiRequestBuilder().build(); 2971 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build(); 2972 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build(); 2973 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier( 2974 (NetworkSpecifier) null).build(); 2975 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier( 2976 new LocalStringNetworkSpecifier("foo")).build(); 2977 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier( 2978 new LocalStringNetworkSpecifier("bar")).build(); 2979 2980 TestNetworkCallback cEmpty1 = new TestNetworkCallback(); 2981 TestNetworkCallback cEmpty2 = new TestNetworkCallback(); 2982 TestNetworkCallback cEmpty3 = new TestNetworkCallback(); 2983 TestNetworkCallback cEmpty4 = new TestNetworkCallback(); 2984 TestNetworkCallback cFoo = new TestNetworkCallback(); 2985 TestNetworkCallback cBar = new TestNetworkCallback(); 2986 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] { 2987 cEmpty1, cEmpty2, cEmpty3, cEmpty4 }; 2988 2989 mCm.registerNetworkCallback(rEmpty1, cEmpty1); 2990 mCm.registerNetworkCallback(rEmpty2, cEmpty2); 2991 mCm.registerNetworkCallback(rEmpty3, cEmpty3); 2992 mCm.registerNetworkCallback(rEmpty4, cEmpty4); 2993 mCm.registerNetworkCallback(rFoo, cFoo); 2994 mCm.registerNetworkCallback(rBar, cBar); 2995 2996 LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo"); 2997 LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar"); 2998 2999 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 3000 mWiFiNetworkAgent.connect(false); 3001 cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 3002 cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 3003 cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 3004 cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 3005 assertNoCallbacks(cFoo, cBar); 3006 3007 mWiFiNetworkAgent.setNetworkSpecifier(nsFoo); 3008 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 3009 for (TestNetworkCallback c: emptyCallbacks) { 3010 c.expectCapabilitiesThat(mWiFiNetworkAgent, 3011 (caps) -> caps.getNetworkSpecifier().equals(nsFoo)); 3012 } 3013 cFoo.expectCapabilitiesThat(mWiFiNetworkAgent, 3014 (caps) -> caps.getNetworkSpecifier().equals(nsFoo)); 3015 assertEquals(nsFoo, 3016 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); 3017 cFoo.assertNoCallback(); 3018 3019 mWiFiNetworkAgent.setNetworkSpecifier(nsBar); 3020 cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 3021 cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 3022 for (TestNetworkCallback c: emptyCallbacks) { 3023 c.expectCapabilitiesThat(mWiFiNetworkAgent, 3024 (caps) -> caps.getNetworkSpecifier().equals(nsBar)); 3025 } 3026 cBar.expectCapabilitiesThat(mWiFiNetworkAgent, 3027 (caps) -> caps.getNetworkSpecifier().equals(nsBar)); 3028 assertEquals(nsBar, 3029 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); 3030 cBar.assertNoCallback(); 3031 3032 mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier()); 3033 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 3034 for (TestNetworkCallback c : emptyCallbacks) { 3035 c.expectCapabilitiesThat(mWiFiNetworkAgent, 3036 (caps) -> caps.getNetworkSpecifier() == null); 3037 } 3038 cFoo.expectCapabilitiesThat(mWiFiNetworkAgent, 3039 (caps) -> caps.getNetworkSpecifier() == null); 3040 cBar.expectCapabilitiesThat(mWiFiNetworkAgent, 3041 (caps) -> caps.getNetworkSpecifier() == null); 3042 assertNull( 3043 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); 3044 cFoo.assertNoCallback(); 3045 cBar.assertNoCallback(); 3046 3047 mWiFiNetworkAgent.setNetworkSpecifier(null); 3048 cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 3049 cBar.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 3050 for (TestNetworkCallback c: emptyCallbacks) { 3051 c.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mWiFiNetworkAgent); 3052 } 3053 3054 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar); 3055 } 3056 3057 /** 3058 * @return the context's attribution tag 3059 */ getAttributionTag()3060 private String getAttributionTag() { 3061 return null; 3062 } 3063 3064 @Test testInvalidNetworkSpecifier()3065 public void testInvalidNetworkSpecifier() { 3066 assertThrows(IllegalArgumentException.class, () -> { 3067 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 3068 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier()); 3069 }); 3070 3071 assertThrows(IllegalArgumentException.class, () -> { 3072 NetworkCapabilities networkCapabilities = new NetworkCapabilities(); 3073 networkCapabilities.addTransportType(TRANSPORT_WIFI) 3074 .setNetworkSpecifier(new MatchAllNetworkSpecifier()); 3075 mService.requestNetwork(networkCapabilities, null, 0, null, 3076 ConnectivityManager.TYPE_WIFI, mContext.getPackageName(), 3077 getAttributionTag()); 3078 }); 3079 3080 class NonParcelableSpecifier extends NetworkSpecifier { 3081 @Override 3082 public boolean canBeSatisfiedBy(NetworkSpecifier other) { 3083 return false; 3084 } 3085 }; 3086 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable { 3087 @Override public int describeContents() { return 0; } 3088 @Override public void writeToParcel(Parcel p, int flags) {} 3089 } 3090 3091 final NetworkRequest.Builder builder = 3092 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET); 3093 assertThrows(ClassCastException.class, () -> { 3094 builder.setNetworkSpecifier(new NonParcelableSpecifier()); 3095 Parcel parcelW = Parcel.obtain(); 3096 builder.build().writeToParcel(parcelW, 0); 3097 }); 3098 3099 final NetworkRequest nr = 3100 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET) 3101 .setNetworkSpecifier(new ParcelableSpecifier()) 3102 .build(); 3103 assertNotNull(nr); 3104 3105 assertThrows(BadParcelableException.class, () -> { 3106 Parcel parcelW = Parcel.obtain(); 3107 nr.writeToParcel(parcelW, 0); 3108 byte[] bytes = parcelW.marshall(); 3109 parcelW.recycle(); 3110 3111 Parcel parcelR = Parcel.obtain(); 3112 parcelR.unmarshall(bytes, 0, bytes.length); 3113 parcelR.setDataPosition(0); 3114 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR); 3115 }); 3116 } 3117 3118 @Test testNetworkRequestUidSpoofSecurityException()3119 public void testNetworkRequestUidSpoofSecurityException() throws Exception { 3120 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 3121 mWiFiNetworkAgent.connect(false); 3122 NetworkRequest networkRequest = newWifiRequestBuilder().build(); 3123 TestNetworkCallback networkCallback = new TestNetworkCallback(); 3124 doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(anyInt(), anyString()); 3125 assertThrows(SecurityException.class, () -> { 3126 mCm.requestNetwork(networkRequest, networkCallback); 3127 }); 3128 } 3129 3130 @Test testInvalidSignalStrength()3131 public void testInvalidSignalStrength() { 3132 NetworkRequest r = new NetworkRequest.Builder() 3133 .addCapability(NET_CAPABILITY_INTERNET) 3134 .addTransportType(TRANSPORT_WIFI) 3135 .setSignalStrength(-75) 3136 .build(); 3137 // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP 3138 // permission should get SecurityException. 3139 assertThrows(SecurityException.class, () -> 3140 mCm.registerNetworkCallback(r, new NetworkCallback())); 3141 3142 assertThrows(SecurityException.class, () -> 3143 mCm.registerNetworkCallback(r, PendingIntent.getService( 3144 mServiceContext, 0, new Intent(), 0))); 3145 3146 // Requesting a Network with signal strength should get IllegalArgumentException. 3147 assertThrows(IllegalArgumentException.class, () -> 3148 mCm.requestNetwork(r, new NetworkCallback())); 3149 3150 assertThrows(IllegalArgumentException.class, () -> 3151 mCm.requestNetwork(r, PendingIntent.getService( 3152 mServiceContext, 0, new Intent(), 0))); 3153 } 3154 3155 @Test testRegisterDefaultNetworkCallback()3156 public void testRegisterDefaultNetworkCallback() throws Exception { 3157 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback(); 3158 mCm.registerDefaultNetworkCallback(defaultNetworkCallback); 3159 defaultNetworkCallback.assertNoCallback(); 3160 3161 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up 3162 // whenever Wi-Fi is up. Without this, the mobile network agent is 3163 // reaped before any other activity can take place. 3164 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 3165 final NetworkRequest cellRequest = new NetworkRequest.Builder() 3166 .addTransportType(TRANSPORT_CELLULAR).build(); 3167 mCm.requestNetwork(cellRequest, cellNetworkCallback); 3168 cellNetworkCallback.assertNoCallback(); 3169 3170 // Bring up cell and expect CALLBACK_AVAILABLE. 3171 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 3172 mCellNetworkAgent.connect(true); 3173 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 3174 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 3175 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 3176 3177 // Bring up wifi and expect CALLBACK_AVAILABLE. 3178 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 3179 mWiFiNetworkAgent.connect(true); 3180 cellNetworkCallback.assertNoCallback(); 3181 defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 3182 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 3183 3184 // Bring down cell. Expect no default network callback, since it wasn't the default. 3185 mCellNetworkAgent.disconnect(); 3186 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); 3187 defaultNetworkCallback.assertNoCallback(); 3188 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 3189 3190 // Bring up cell. Expect no default network callback, since it won't be the default. 3191 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 3192 mCellNetworkAgent.connect(true); 3193 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 3194 defaultNetworkCallback.assertNoCallback(); 3195 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 3196 3197 // Bring down wifi. Expect the default network callback to notified of LOST wifi 3198 // followed by AVAILABLE cell. 3199 mWiFiNetworkAgent.disconnect(); 3200 cellNetworkCallback.assertNoCallback(); 3201 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 3202 defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 3203 mCellNetworkAgent.disconnect(); 3204 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); 3205 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); 3206 waitForIdle(); 3207 assertEquals(null, mCm.getActiveNetwork()); 3208 3209 final int uid = Process.myUid(); 3210 final TestNetworkAgentWrapper 3211 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN); 3212 final ArraySet<UidRange> ranges = new ArraySet<>(); 3213 ranges.add(new UidRange(uid, uid)); 3214 mMockVpn.setNetworkAgent(vpnNetworkAgent); 3215 mMockVpn.setUids(ranges); 3216 vpnNetworkAgent.connect(true); 3217 mMockVpn.connect(); 3218 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent); 3219 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 3220 3221 vpnNetworkAgent.disconnect(); 3222 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent); 3223 waitForIdle(); 3224 assertEquals(null, mCm.getActiveNetwork()); 3225 } 3226 3227 @Test testAdditionalStateCallbacks()3228 public void testAdditionalStateCallbacks() throws Exception { 3229 // File a network request for mobile. 3230 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 3231 final NetworkRequest cellRequest = new NetworkRequest.Builder() 3232 .addTransportType(TRANSPORT_CELLULAR).build(); 3233 mCm.requestNetwork(cellRequest, cellNetworkCallback); 3234 3235 // Bring up the mobile network. 3236 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 3237 mCellNetworkAgent.connect(true); 3238 3239 // We should get onAvailable(), onCapabilitiesChanged(), and 3240 // onLinkPropertiesChanged() in rapid succession. Additionally, we 3241 // should get onCapabilitiesChanged() when the mobile network validates. 3242 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 3243 cellNetworkCallback.assertNoCallback(); 3244 3245 // Update LinkProperties. 3246 final LinkProperties lp = new LinkProperties(); 3247 lp.setInterfaceName("foonet_data0"); 3248 mCellNetworkAgent.sendLinkProperties(lp); 3249 // We should get onLinkPropertiesChanged(). 3250 cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, 3251 mCellNetworkAgent); 3252 cellNetworkCallback.assertNoCallback(); 3253 3254 // Suspend the network. 3255 mCellNetworkAgent.suspend(); 3256 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED, 3257 mCellNetworkAgent); 3258 cellNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, mCellNetworkAgent); 3259 cellNetworkCallback.assertNoCallback(); 3260 assertEquals(NetworkInfo.State.SUSPENDED, mCm.getActiveNetworkInfo().getState()); 3261 3262 // Register a garden variety default network request. 3263 TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback(); 3264 mCm.registerDefaultNetworkCallback(dfltNetworkCallback); 3265 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(), 3266 // as well as onNetworkSuspended() in rapid succession. 3267 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true); 3268 dfltNetworkCallback.assertNoCallback(); 3269 mCm.unregisterNetworkCallback(dfltNetworkCallback); 3270 3271 mCellNetworkAgent.resume(); 3272 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED, 3273 mCellNetworkAgent); 3274 cellNetworkCallback.expectCallback(CallbackEntry.RESUMED, mCellNetworkAgent); 3275 cellNetworkCallback.assertNoCallback(); 3276 assertEquals(NetworkInfo.State.CONNECTED, mCm.getActiveNetworkInfo().getState()); 3277 3278 dfltNetworkCallback = new TestNetworkCallback(); 3279 mCm.registerDefaultNetworkCallback(dfltNetworkCallback); 3280 // This time onNetworkSuspended should not be called. 3281 dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 3282 dfltNetworkCallback.assertNoCallback(); 3283 3284 mCm.unregisterNetworkCallback(dfltNetworkCallback); 3285 mCm.unregisterNetworkCallback(cellNetworkCallback); 3286 } 3287 setCaptivePortalMode(int mode)3288 private void setCaptivePortalMode(int mode) { 3289 ContentResolver cr = mServiceContext.getContentResolver(); 3290 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode); 3291 } 3292 setAlwaysOnNetworks(boolean enable)3293 private void setAlwaysOnNetworks(boolean enable) { 3294 ContentResolver cr = mServiceContext.getContentResolver(); 3295 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0); 3296 mService.updateAlwaysOnNetworks(); 3297 waitForIdle(); 3298 } 3299 setPrivateDnsSettings(String mode, String specifier)3300 private void setPrivateDnsSettings(String mode, String specifier) { 3301 final ContentResolver cr = mServiceContext.getContentResolver(); 3302 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode); 3303 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier); 3304 mService.updatePrivateDnsSettings(); 3305 waitForIdle(); 3306 } 3307 isForegroundNetwork(TestNetworkAgentWrapper network)3308 private boolean isForegroundNetwork(TestNetworkAgentWrapper network) { 3309 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork()); 3310 assertNotNull(nc); 3311 return nc.hasCapability(NET_CAPABILITY_FOREGROUND); 3312 } 3313 3314 @Test testBackgroundNetworks()3315 public void testBackgroundNetworks() throws Exception { 3316 // Create a background request. We can't do this ourselves because ConnectivityService 3317 // doesn't have an API for it. So just turn on mobile data always on. 3318 setAlwaysOnNetworks(true); 3319 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid()); 3320 final NetworkRequest request = new NetworkRequest.Builder().build(); 3321 final NetworkRequest fgRequest = new NetworkRequest.Builder() 3322 .addCapability(NET_CAPABILITY_FOREGROUND).build(); 3323 final TestNetworkCallback callback = new TestNetworkCallback(); 3324 final TestNetworkCallback fgCallback = new TestNetworkCallback(); 3325 mCm.registerNetworkCallback(request, callback); 3326 mCm.registerNetworkCallback(fgRequest, fgCallback); 3327 3328 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 3329 mCellNetworkAgent.connect(true); 3330 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 3331 fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 3332 assertTrue(isForegroundNetwork(mCellNetworkAgent)); 3333 3334 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 3335 mWiFiNetworkAgent.connect(true); 3336 3337 // When wifi connects, cell lingers. 3338 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 3339 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); 3340 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 3341 fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 3342 fgCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); 3343 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 3344 assertTrue(isForegroundNetwork(mCellNetworkAgent)); 3345 assertTrue(isForegroundNetwork(mWiFiNetworkAgent)); 3346 3347 // When lingering is complete, cell is still there but is now in the background. 3348 waitForIdle(); 3349 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4; 3350 fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, timeoutMs); 3351 // Expect a network capabilities update sans FOREGROUND. 3352 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent); 3353 assertFalse(isForegroundNetwork(mCellNetworkAgent)); 3354 assertTrue(isForegroundNetwork(mWiFiNetworkAgent)); 3355 3356 // File a cell request and check that cell comes into the foreground. 3357 final NetworkRequest cellRequest = new NetworkRequest.Builder() 3358 .addTransportType(TRANSPORT_CELLULAR).build(); 3359 final TestNetworkCallback cellCallback = new TestNetworkCallback(); 3360 mCm.requestNetwork(cellRequest, cellCallback); 3361 cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 3362 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 3363 // Expect a network capabilities update with FOREGROUND, because the most recent 3364 // request causes its state to change. 3365 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent); 3366 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent); 3367 assertTrue(isForegroundNetwork(mCellNetworkAgent)); 3368 assertTrue(isForegroundNetwork(mWiFiNetworkAgent)); 3369 3370 // Release the request. The network immediately goes into the background, since it was not 3371 // lingering. 3372 mCm.unregisterNetworkCallback(cellCallback); 3373 fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); 3374 // Expect a network capabilities update sans FOREGROUND. 3375 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent); 3376 assertFalse(isForegroundNetwork(mCellNetworkAgent)); 3377 assertTrue(isForegroundNetwork(mWiFiNetworkAgent)); 3378 3379 // Disconnect wifi and check that cell is foreground again. 3380 mWiFiNetworkAgent.disconnect(); 3381 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 3382 fgCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 3383 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 3384 assertTrue(isForegroundNetwork(mCellNetworkAgent)); 3385 3386 mCm.unregisterNetworkCallback(callback); 3387 mCm.unregisterNetworkCallback(fgCallback); 3388 } 3389 3390 @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing. benchmarkRequestRegistrationAndCallbackDispatch()3391 public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception { 3392 // TODO: turn this unit test into a real benchmarking test. 3393 // Benchmarks connecting and switching performance in the presence of a large number of 3394 // NetworkRequests. 3395 // 1. File NUM_REQUESTS requests. 3396 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire. 3397 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing 3398 // and NUM_REQUESTS onAvailable callbacks to fire. 3399 // See how long it took. 3400 final int NUM_REQUESTS = 90; 3401 final int REGISTER_TIME_LIMIT_MS = 200; 3402 final int CONNECT_TIME_LIMIT_MS = 60; 3403 final int SWITCH_TIME_LIMIT_MS = 60; 3404 final int UNREGISTER_TIME_LIMIT_MS = 20; 3405 3406 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build(); 3407 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS]; 3408 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS); 3409 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS); 3410 3411 for (int i = 0; i < NUM_REQUESTS; i++) { 3412 callbacks[i] = new NetworkCallback() { 3413 @Override public void onAvailable(Network n) { availableLatch.countDown(); } 3414 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); } 3415 }; 3416 } 3417 3418 assertRunsInAtMost("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> { 3419 for (NetworkCallback cb : callbacks) { 3420 mCm.registerNetworkCallback(request, cb); 3421 } 3422 }); 3423 3424 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 3425 // Don't request that the network validate, because otherwise connect() will block until 3426 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired, 3427 // and we won't actually measure anything. 3428 mCellNetworkAgent.connect(false); 3429 3430 long onAvailableDispatchingDuration = durationOf(() -> { 3431 await(availableLatch, 10 * CONNECT_TIME_LIMIT_MS); 3432 }); 3433 Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms", 3434 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS, 3435 onAvailableDispatchingDuration)); 3436 assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms", 3437 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS), 3438 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS); 3439 3440 // Give wifi a high enough score that we'll linger cell when wifi comes up. 3441 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 3442 mWiFiNetworkAgent.adjustScore(40); 3443 mWiFiNetworkAgent.connect(false); 3444 3445 long onLostDispatchingDuration = durationOf(() -> { 3446 await(losingLatch, 10 * SWITCH_TIME_LIMIT_MS); 3447 }); 3448 Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms", 3449 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration)); 3450 assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms", 3451 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS), 3452 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS); 3453 3454 assertRunsInAtMost("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> { 3455 for (NetworkCallback cb : callbacks) { 3456 mCm.unregisterNetworkCallback(cb); 3457 } 3458 }); 3459 } 3460 3461 @Test testMobileDataAlwaysOn()3462 public void testMobileDataAlwaysOn() throws Exception { 3463 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid()); 3464 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 3465 final NetworkRequest cellRequest = new NetworkRequest.Builder() 3466 .addTransportType(TRANSPORT_CELLULAR).build(); 3467 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback); 3468 3469 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory"); 3470 handlerThread.start(); 3471 NetworkCapabilities filter = new NetworkCapabilities() 3472 .addTransportType(TRANSPORT_CELLULAR) 3473 .addCapability(NET_CAPABILITY_INTERNET); 3474 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), 3475 mServiceContext, "testFactory", filter); 3476 testFactory.setScoreFilter(40); 3477 3478 // Register the factory and expect it to start looking for a network. 3479 testFactory.expectAddRequestsWithScores(0); // Score 0 as the request is not served yet. 3480 testFactory.register(); 3481 testFactory.waitForNetworkRequests(1); 3482 assertTrue(testFactory.getMyStartRequested()); 3483 3484 // Bring up wifi. The factory stops looking for a network. 3485 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 3486 // Score 60 - 40 penalty for not validated yet, then 60 when it validates 3487 testFactory.expectAddRequestsWithScores(20, 60); 3488 mWiFiNetworkAgent.connect(true); 3489 testFactory.waitForRequests(); 3490 assertFalse(testFactory.getMyStartRequested()); 3491 3492 ContentResolver cr = mServiceContext.getContentResolver(); 3493 3494 // Turn on mobile data always on. The factory starts looking again. 3495 testFactory.expectAddRequestsWithScores(0); // Always on requests comes up with score 0 3496 setAlwaysOnNetworks(true); 3497 testFactory.waitForNetworkRequests(2); 3498 assertTrue(testFactory.getMyStartRequested()); 3499 3500 // Bring up cell data and check that the factory stops looking. 3501 assertLength(1, mCm.getAllNetworks()); 3502 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 3503 testFactory.expectAddRequestsWithScores(10, 50); // Unvalidated, then validated 3504 mCellNetworkAgent.connect(true); 3505 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 3506 testFactory.waitForNetworkRequests(2); 3507 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us. 3508 3509 // Check that cell data stays up. 3510 waitForIdle(); 3511 verifyActiveNetwork(TRANSPORT_WIFI); 3512 assertLength(2, mCm.getAllNetworks()); 3513 3514 // Turn off mobile data always on and expect the request to disappear... 3515 testFactory.expectRemoveRequests(1); 3516 setAlwaysOnNetworks(false); 3517 testFactory.waitForNetworkRequests(1); 3518 3519 // ... and cell data to be torn down. 3520 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); 3521 assertLength(1, mCm.getAllNetworks()); 3522 3523 testFactory.terminate(); 3524 mCm.unregisterNetworkCallback(cellNetworkCallback); 3525 handlerThread.quit(); 3526 } 3527 3528 @Test testAvoidBadWifiSetting()3529 public void testAvoidBadWifiSetting() throws Exception { 3530 final ContentResolver cr = mServiceContext.getContentResolver(); 3531 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI; 3532 3533 mPolicyTracker.mConfigRestrictsAvoidBadWifi = false; 3534 String[] values = new String[] {null, "0", "1"}; 3535 for (int i = 0; i < values.length; i++) { 3536 Settings.Global.putInt(cr, settingName, 1); 3537 mPolicyTracker.reevaluate(); 3538 waitForIdle(); 3539 String msg = String.format("config=false, setting=%s", values[i]); 3540 assertTrue(mService.avoidBadWifi()); 3541 assertFalse(msg, mPolicyTracker.shouldNotifyWifiUnvalidated()); 3542 } 3543 3544 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true; 3545 3546 Settings.Global.putInt(cr, settingName, 0); 3547 mPolicyTracker.reevaluate(); 3548 waitForIdle(); 3549 assertFalse(mService.avoidBadWifi()); 3550 assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated()); 3551 3552 Settings.Global.putInt(cr, settingName, 1); 3553 mPolicyTracker.reevaluate(); 3554 waitForIdle(); 3555 assertTrue(mService.avoidBadWifi()); 3556 assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated()); 3557 3558 Settings.Global.putString(cr, settingName, null); 3559 mPolicyTracker.reevaluate(); 3560 waitForIdle(); 3561 assertFalse(mService.avoidBadWifi()); 3562 assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated()); 3563 } 3564 3565 @Test testAvoidBadWifi()3566 public void testAvoidBadWifi() throws Exception { 3567 final ContentResolver cr = mServiceContext.getContentResolver(); 3568 3569 // Pretend we're on a carrier that restricts switching away from bad wifi. 3570 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true; 3571 3572 // File a request for cell to ensure it doesn't go down. 3573 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 3574 final NetworkRequest cellRequest = new NetworkRequest.Builder() 3575 .addTransportType(TRANSPORT_CELLULAR).build(); 3576 mCm.requestNetwork(cellRequest, cellNetworkCallback); 3577 3578 TestNetworkCallback defaultCallback = new TestNetworkCallback(); 3579 mCm.registerDefaultNetworkCallback(defaultCallback); 3580 3581 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder() 3582 .addTransportType(TRANSPORT_WIFI) 3583 .addCapability(NET_CAPABILITY_VALIDATED) 3584 .build(); 3585 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback(); 3586 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback); 3587 3588 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0); 3589 mPolicyTracker.reevaluate(); 3590 3591 // Bring up validated cell. 3592 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 3593 mCellNetworkAgent.connect(true); 3594 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 3595 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 3596 Network cellNetwork = mCellNetworkAgent.getNetwork(); 3597 3598 // Bring up validated wifi. 3599 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 3600 mWiFiNetworkAgent.connect(true); 3601 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 3602 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 3603 Network wifiNetwork = mWiFiNetworkAgent.getNetwork(); 3604 3605 // Fail validation on wifi. 3606 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */); 3607 mCm.reportNetworkConnectivity(wifiNetwork, false); 3608 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 3609 validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 3610 3611 // Because avoid bad wifi is off, we don't switch to cellular. 3612 defaultCallback.assertNoCallback(); 3613 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability( 3614 NET_CAPABILITY_VALIDATED)); 3615 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability( 3616 NET_CAPABILITY_VALIDATED)); 3617 assertEquals(mCm.getActiveNetwork(), wifiNetwork); 3618 3619 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect 3620 // that we switch back to cell. 3621 mPolicyTracker.mConfigRestrictsAvoidBadWifi = false; 3622 mPolicyTracker.reevaluate(); 3623 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 3624 assertEquals(mCm.getActiveNetwork(), cellNetwork); 3625 3626 // Switch back to a restrictive carrier. 3627 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true; 3628 mPolicyTracker.reevaluate(); 3629 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 3630 assertEquals(mCm.getActiveNetwork(), wifiNetwork); 3631 3632 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell. 3633 mCm.setAvoidUnvalidated(wifiNetwork); 3634 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 3635 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability( 3636 NET_CAPABILITY_VALIDATED)); 3637 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability( 3638 NET_CAPABILITY_VALIDATED)); 3639 assertEquals(mCm.getActiveNetwork(), cellNetwork); 3640 3641 // Disconnect and reconnect wifi to clear the one-time switch above. 3642 mWiFiNetworkAgent.disconnect(); 3643 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 3644 mWiFiNetworkAgent.connect(true); 3645 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 3646 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 3647 wifiNetwork = mWiFiNetworkAgent.getNetwork(); 3648 3649 // Fail validation on wifi and expect the dialog to appear. 3650 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */); 3651 mCm.reportNetworkConnectivity(wifiNetwork, false); 3652 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 3653 validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 3654 3655 // Simulate the user selecting "switch" and checking the don't ask again checkbox. 3656 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1); 3657 mPolicyTracker.reevaluate(); 3658 3659 // We now switch to cell. 3660 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 3661 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability( 3662 NET_CAPABILITY_VALIDATED)); 3663 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability( 3664 NET_CAPABILITY_VALIDATED)); 3665 assertEquals(mCm.getActiveNetwork(), cellNetwork); 3666 3667 // Simulate the user turning the cellular fallback setting off and then on. 3668 // We switch to wifi and then to cell. 3669 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null); 3670 mPolicyTracker.reevaluate(); 3671 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 3672 assertEquals(mCm.getActiveNetwork(), wifiNetwork); 3673 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1); 3674 mPolicyTracker.reevaluate(); 3675 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 3676 assertEquals(mCm.getActiveNetwork(), cellNetwork); 3677 3678 // If cell goes down, we switch to wifi. 3679 mCellNetworkAgent.disconnect(); 3680 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); 3681 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 3682 validatedWifiCallback.assertNoCallback(); 3683 3684 mCm.unregisterNetworkCallback(cellNetworkCallback); 3685 mCm.unregisterNetworkCallback(validatedWifiCallback); 3686 mCm.unregisterNetworkCallback(defaultCallback); 3687 } 3688 3689 @Test testMeteredMultipathPreferenceSetting()3690 public void testMeteredMultipathPreferenceSetting() throws Exception { 3691 final ContentResolver cr = mServiceContext.getContentResolver(); 3692 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE; 3693 3694 for (int config : Arrays.asList(0, 3, 2)) { 3695 for (String setting: Arrays.asList(null, "0", "2", "1")) { 3696 mPolicyTracker.mConfigMeteredMultipathPreference = config; 3697 Settings.Global.putString(cr, settingName, setting); 3698 mPolicyTracker.reevaluate(); 3699 waitForIdle(); 3700 3701 final int expected = (setting != null) ? Integer.parseInt(setting) : config; 3702 String msg = String.format("config=%d, setting=%s", config, setting); 3703 assertEquals(msg, expected, mCm.getMultipathPreference(null)); 3704 } 3705 } 3706 } 3707 3708 /** 3709 * Validate that a satisfied network request does not trigger onUnavailable() once the 3710 * time-out period expires. 3711 */ 3712 @Test testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable()3713 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() throws Exception { 3714 NetworkRequest nr = new NetworkRequest.Builder().addTransportType( 3715 NetworkCapabilities.TRANSPORT_WIFI).build(); 3716 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 3717 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS); 3718 3719 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 3720 mWiFiNetworkAgent.connect(false); 3721 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false, 3722 TEST_CALLBACK_TIMEOUT_MS); 3723 3724 // pass timeout and validate that UNAVAILABLE is not called 3725 networkCallback.assertNoCallback(); 3726 } 3727 3728 /** 3729 * Validate that a satisfied network request followed by a disconnected (lost) network does 3730 * not trigger onUnavailable() once the time-out period expires. 3731 */ 3732 @Test testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable()3733 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() throws Exception { 3734 NetworkRequest nr = new NetworkRequest.Builder().addTransportType( 3735 NetworkCapabilities.TRANSPORT_WIFI).build(); 3736 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 3737 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS); 3738 3739 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 3740 mWiFiNetworkAgent.connect(false); 3741 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false, 3742 TEST_CALLBACK_TIMEOUT_MS); 3743 mWiFiNetworkAgent.disconnect(); 3744 networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 3745 3746 // Validate that UNAVAILABLE is not called 3747 networkCallback.assertNoCallback(); 3748 } 3749 3750 /** 3751 * Validate that when a time-out is specified for a network request the onUnavailable() 3752 * callback is called when time-out expires. Then validate that if network request is 3753 * (somehow) satisfied - the callback isn't called later. 3754 */ 3755 @Test testTimedoutNetworkRequest()3756 public void testTimedoutNetworkRequest() throws Exception { 3757 NetworkRequest nr = new NetworkRequest.Builder().addTransportType( 3758 NetworkCapabilities.TRANSPORT_WIFI).build(); 3759 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 3760 final int timeoutMs = 10; 3761 mCm.requestNetwork(nr, networkCallback, timeoutMs); 3762 3763 // pass timeout and validate that UNAVAILABLE is called 3764 networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, (Network) null); 3765 3766 // create a network satisfying request - validate that request not triggered 3767 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 3768 mWiFiNetworkAgent.connect(false); 3769 networkCallback.assertNoCallback(); 3770 } 3771 3772 /** 3773 * Validate that when a network request is unregistered (cancelled), no posterior event can 3774 * trigger the callback. 3775 */ 3776 @Test testNoCallbackAfterUnregisteredNetworkRequest()3777 public void testNoCallbackAfterUnregisteredNetworkRequest() throws Exception { 3778 NetworkRequest nr = new NetworkRequest.Builder().addTransportType( 3779 NetworkCapabilities.TRANSPORT_WIFI).build(); 3780 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 3781 final int timeoutMs = 10; 3782 3783 mCm.requestNetwork(nr, networkCallback, timeoutMs); 3784 mCm.unregisterNetworkCallback(networkCallback); 3785 // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures 3786 // that this callback will not be called. 3787 networkCallback.assertNoCallback(); 3788 3789 // create a network satisfying request - validate that request not triggered 3790 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 3791 mWiFiNetworkAgent.connect(false); 3792 networkCallback.assertNoCallback(); 3793 } 3794 3795 @Test testUnfulfillableNetworkRequest()3796 public void testUnfulfillableNetworkRequest() throws Exception { 3797 runUnfulfillableNetworkRequest(false); 3798 } 3799 3800 @Test testUnfulfillableNetworkRequestAfterUnregister()3801 public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception { 3802 runUnfulfillableNetworkRequest(true); 3803 } 3804 3805 /** 3806 * Validate the callback flow for a factory releasing a request as unfulfillable. 3807 */ runUnfulfillableNetworkRequest(boolean preUnregister)3808 private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception { 3809 NetworkRequest nr = new NetworkRequest.Builder().addTransportType( 3810 NetworkCapabilities.TRANSPORT_WIFI).build(); 3811 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 3812 3813 final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest"); 3814 handlerThread.start(); 3815 NetworkCapabilities filter = new NetworkCapabilities() 3816 .addTransportType(TRANSPORT_WIFI) 3817 .addCapability(NET_CAPABILITY_INTERNET); 3818 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), 3819 mServiceContext, "testFactory", filter); 3820 testFactory.setScoreFilter(40); 3821 3822 // Register the factory and expect it to receive the default request. 3823 testFactory.expectAddRequestsWithScores(0); 3824 testFactory.register(); 3825 SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1); 3826 3827 assertEquals(1, requests.size()); // have 1 request at this point 3828 int origRequestId = requests.valueAt(0).requestId; 3829 3830 // Now file the test request and expect it. 3831 testFactory.expectAddRequestsWithScores(0); 3832 mCm.requestNetwork(nr, networkCallback); 3833 requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point 3834 3835 int newRequestId = 0; 3836 for (int i = 0; i < requests.size(); ++i) { 3837 if (requests.valueAt(i).requestId != origRequestId) { 3838 newRequestId = requests.valueAt(i).requestId; 3839 break; 3840 } 3841 } 3842 3843 testFactory.expectRemoveRequests(1); 3844 if (preUnregister) { 3845 mCm.unregisterNetworkCallback(networkCallback); 3846 3847 // Simulate the factory releasing the request as unfulfillable: no-op since 3848 // the callback has already been unregistered (but a test that no exceptions are 3849 // thrown). 3850 testFactory.triggerUnfulfillable(requests.get(newRequestId)); 3851 } else { 3852 // Simulate the factory releasing the request as unfulfillable and expect onUnavailable! 3853 testFactory.triggerUnfulfillable(requests.get(newRequestId)); 3854 3855 networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, (Network) null); 3856 testFactory.waitForRequests(); 3857 3858 // unregister network callback - a no-op (since already freed by the 3859 // on-unavailable), but should not fail or throw exceptions. 3860 mCm.unregisterNetworkCallback(networkCallback); 3861 } 3862 3863 testFactory.terminate(); 3864 handlerThread.quit(); 3865 } 3866 3867 private static class TestKeepaliveCallback extends PacketKeepaliveCallback { 3868 3869 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR } 3870 3871 private class CallbackValue { 3872 public CallbackType callbackType; 3873 public int error; 3874 CallbackValue(CallbackType type)3875 public CallbackValue(CallbackType type) { 3876 this.callbackType = type; 3877 this.error = PacketKeepalive.SUCCESS; 3878 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR); 3879 } 3880 CallbackValue(CallbackType type, int error)3881 public CallbackValue(CallbackType type, int error) { 3882 this.callbackType = type; 3883 this.error = error; 3884 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR); 3885 } 3886 3887 @Override equals(Object o)3888 public boolean equals(Object o) { 3889 return o instanceof CallbackValue && 3890 this.callbackType == ((CallbackValue) o).callbackType && 3891 this.error == ((CallbackValue) o).error; 3892 } 3893 3894 @Override toString()3895 public String toString() { 3896 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error); 3897 } 3898 } 3899 3900 private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>(); 3901 3902 @Override onStarted()3903 public void onStarted() { 3904 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED)); 3905 } 3906 3907 @Override onStopped()3908 public void onStopped() { 3909 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED)); 3910 } 3911 3912 @Override onError(int error)3913 public void onError(int error) { 3914 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error)); 3915 } 3916 expectCallback(CallbackValue callbackValue)3917 private void expectCallback(CallbackValue callbackValue) throws InterruptedException { 3918 assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)); 3919 } 3920 expectStarted()3921 public void expectStarted() throws Exception { 3922 expectCallback(new CallbackValue(CallbackType.ON_STARTED)); 3923 } 3924 expectStopped()3925 public void expectStopped() throws Exception { 3926 expectCallback(new CallbackValue(CallbackType.ON_STOPPED)); 3927 } 3928 expectError(int error)3929 public void expectError(int error) throws Exception { 3930 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error)); 3931 } 3932 } 3933 3934 private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback { 3935 3936 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }; 3937 3938 private class CallbackValue { 3939 public CallbackType callbackType; 3940 public int error; 3941 CallbackValue(CallbackType type)3942 CallbackValue(CallbackType type) { 3943 this.callbackType = type; 3944 this.error = SocketKeepalive.SUCCESS; 3945 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR); 3946 } 3947 CallbackValue(CallbackType type, int error)3948 CallbackValue(CallbackType type, int error) { 3949 this.callbackType = type; 3950 this.error = error; 3951 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR); 3952 } 3953 3954 @Override equals(Object o)3955 public boolean equals(Object o) { 3956 return o instanceof CallbackValue 3957 && this.callbackType == ((CallbackValue) o).callbackType 3958 && this.error == ((CallbackValue) o).error; 3959 } 3960 3961 @Override toString()3962 public String toString() { 3963 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, 3964 error); 3965 } 3966 } 3967 3968 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>(); 3969 private final Executor mExecutor; 3970 TestSocketKeepaliveCallback(@onNull Executor executor)3971 TestSocketKeepaliveCallback(@NonNull Executor executor) { 3972 mExecutor = executor; 3973 } 3974 3975 @Override onStarted()3976 public void onStarted() { 3977 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED)); 3978 } 3979 3980 @Override onStopped()3981 public void onStopped() { 3982 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED)); 3983 } 3984 3985 @Override onError(int error)3986 public void onError(int error) { 3987 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error)); 3988 } 3989 expectCallback(CallbackValue callbackValue)3990 private void expectCallback(CallbackValue callbackValue) throws InterruptedException { 3991 assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)); 3992 3993 } 3994 expectStarted()3995 public void expectStarted() throws InterruptedException { 3996 expectCallback(new CallbackValue(CallbackType.ON_STARTED)); 3997 } 3998 expectStopped()3999 public void expectStopped() throws InterruptedException { 4000 expectCallback(new CallbackValue(CallbackType.ON_STOPPED)); 4001 } 4002 expectError(int error)4003 public void expectError(int error) throws InterruptedException { 4004 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error)); 4005 } 4006 assertNoCallback()4007 public void assertNoCallback() { 4008 waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS); 4009 CallbackValue cv = mCallbacks.peek(); 4010 assertNull("Unexpected callback: " + cv, cv); 4011 } 4012 } 4013 connectKeepaliveNetwork(LinkProperties lp)4014 private Network connectKeepaliveNetwork(LinkProperties lp) throws Exception { 4015 // Ensure the network is disconnected before we do anything. 4016 if (mWiFiNetworkAgent != null) { 4017 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork())); 4018 } 4019 4020 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 4021 ConditionVariable cv = registerConnectivityBroadcast(1); 4022 mWiFiNetworkAgent.connect(true); 4023 waitFor(cv); 4024 verifyActiveNetwork(TRANSPORT_WIFI); 4025 mWiFiNetworkAgent.sendLinkProperties(lp); 4026 waitForIdle(); 4027 return mWiFiNetworkAgent.getNetwork(); 4028 } 4029 4030 @Test 4031 @FlakyTest(bugId = 140305589) testPacketKeepalives()4032 public void testPacketKeepalives() throws Exception { 4033 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129"); 4034 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35"); 4035 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1"); 4036 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8"); 4037 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888"); 4038 4039 final int validKaInterval = 15; 4040 final int invalidKaInterval = 9; 4041 4042 LinkProperties lp = new LinkProperties(); 4043 lp.setInterfaceName("wlan12"); 4044 lp.addLinkAddress(new LinkAddress(myIPv6, 64)); 4045 lp.addLinkAddress(new LinkAddress(myIPv4, 25)); 4046 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234"))); 4047 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254"))); 4048 4049 Network notMyNet = new Network(61234); 4050 Network myNet = connectKeepaliveNetwork(lp); 4051 4052 TestKeepaliveCallback callback = new TestKeepaliveCallback(); 4053 PacketKeepalive ka; 4054 4055 // Attempt to start keepalives with invalid parameters and check for errors. 4056 ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4); 4057 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK); 4058 4059 ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4); 4060 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL); 4061 4062 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6); 4063 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 4064 4065 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4); 4066 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 4067 4068 // NAT-T is only supported for IPv4. 4069 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6); 4070 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 4071 4072 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4); 4073 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT); 4074 4075 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4); 4076 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT); 4077 4078 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4); 4079 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED); 4080 4081 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4); 4082 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED); 4083 4084 // Check that a started keepalive can be stopped. 4085 mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS); 4086 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4); 4087 callback.expectStarted(); 4088 mWiFiNetworkAgent.setStopKeepaliveEvent(PacketKeepalive.SUCCESS); 4089 ka.stop(); 4090 callback.expectStopped(); 4091 4092 // Check that deleting the IP address stops the keepalive. 4093 LinkProperties bogusLp = new LinkProperties(lp); 4094 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4); 4095 callback.expectStarted(); 4096 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25)); 4097 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25)); 4098 mWiFiNetworkAgent.sendLinkProperties(bogusLp); 4099 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 4100 mWiFiNetworkAgent.sendLinkProperties(lp); 4101 4102 // Check that a started keepalive is stopped correctly when the network disconnects. 4103 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4); 4104 callback.expectStarted(); 4105 mWiFiNetworkAgent.disconnect(); 4106 mWiFiNetworkAgent.expectDisconnected(); 4107 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK); 4108 4109 // ... and that stopping it after that has no adverse effects. 4110 waitForIdle(); 4111 final Network myNetAlias = myNet; 4112 assertNull(mCm.getNetworkCapabilities(myNetAlias)); 4113 ka.stop(); 4114 4115 // Reconnect. 4116 myNet = connectKeepaliveNetwork(lp); 4117 mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS); 4118 4119 // Check that keepalive slots start from 1 and increment. The first one gets slot 1. 4120 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1); 4121 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4); 4122 callback.expectStarted(); 4123 4124 // The second one gets slot 2. 4125 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2); 4126 TestKeepaliveCallback callback2 = new TestKeepaliveCallback(); 4127 PacketKeepalive ka2 = mCm.startNattKeepalive( 4128 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4); 4129 callback2.expectStarted(); 4130 4131 // Now stop the first one and create a third. This also gets slot 1. 4132 ka.stop(); 4133 callback.expectStopped(); 4134 4135 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1); 4136 TestKeepaliveCallback callback3 = new TestKeepaliveCallback(); 4137 PacketKeepalive ka3 = mCm.startNattKeepalive( 4138 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4); 4139 callback3.expectStarted(); 4140 4141 ka2.stop(); 4142 callback2.expectStopped(); 4143 4144 ka3.stop(); 4145 callback3.expectStopped(); 4146 } 4147 4148 // Helper method to prepare the executor and run test runTestWithSerialExecutors(ExceptionUtils.ThrowingConsumer<Executor> functor)4149 private void runTestWithSerialExecutors(ExceptionUtils.ThrowingConsumer<Executor> functor) 4150 throws Exception { 4151 final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor(); 4152 final Executor executorInline = (Runnable r) -> r.run(); 4153 functor.accept(executorSingleThread); 4154 executorSingleThread.shutdown(); 4155 functor.accept(executorInline); 4156 } 4157 4158 @Test testNattSocketKeepalives()4159 public void testNattSocketKeepalives() throws Exception { 4160 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor)); 4161 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor)); 4162 } 4163 doTestNattSocketKeepalivesWithExecutor(Executor executor)4164 private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception { 4165 // TODO: 1. Move this outside of ConnectivityServiceTest. 4166 // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService. 4167 // 3. Mock ipsec service. 4168 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129"); 4169 final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35"); 4170 final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1"); 4171 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8"); 4172 final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888"); 4173 4174 final int validKaInterval = 15; 4175 final int invalidKaInterval = 9; 4176 4177 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE); 4178 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket(); 4179 final int srcPort = testSocket.getPort(); 4180 4181 LinkProperties lp = new LinkProperties(); 4182 lp.setInterfaceName("wlan12"); 4183 lp.addLinkAddress(new LinkAddress(myIPv6, 64)); 4184 lp.addLinkAddress(new LinkAddress(myIPv4, 25)); 4185 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234"))); 4186 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254"))); 4187 4188 Network notMyNet = new Network(61234); 4189 Network myNet = connectKeepaliveNetwork(lp); 4190 4191 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor); 4192 4193 // Attempt to start keepalives with invalid parameters and check for errors. 4194 // Invalid network. 4195 try (SocketKeepalive ka = mCm.createSocketKeepalive( 4196 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) { 4197 ka.start(validKaInterval); 4198 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK); 4199 } 4200 4201 // Invalid interval. 4202 try (SocketKeepalive ka = mCm.createSocketKeepalive( 4203 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) { 4204 ka.start(invalidKaInterval); 4205 callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL); 4206 } 4207 4208 // Invalid destination. 4209 try (SocketKeepalive ka = mCm.createSocketKeepalive( 4210 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) { 4211 ka.start(validKaInterval); 4212 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS); 4213 } 4214 4215 // Invalid source; 4216 try (SocketKeepalive ka = mCm.createSocketKeepalive( 4217 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) { 4218 ka.start(validKaInterval); 4219 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS); 4220 } 4221 4222 // NAT-T is only supported for IPv4. 4223 try (SocketKeepalive ka = mCm.createSocketKeepalive( 4224 myNet, testSocket, myIPv6, dstIPv6, executor, callback)) { 4225 ka.start(validKaInterval); 4226 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS); 4227 } 4228 4229 // Basic check before testing started keepalive. 4230 try (SocketKeepalive ka = mCm.createSocketKeepalive( 4231 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) { 4232 ka.start(validKaInterval); 4233 callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED); 4234 } 4235 4236 // Check that a started keepalive can be stopped. 4237 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS); 4238 try (SocketKeepalive ka = mCm.createSocketKeepalive( 4239 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) { 4240 ka.start(validKaInterval); 4241 callback.expectStarted(); 4242 mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS); 4243 ka.stop(); 4244 callback.expectStopped(); 4245 4246 // Check that keepalive could be restarted. 4247 ka.start(validKaInterval); 4248 callback.expectStarted(); 4249 ka.stop(); 4250 callback.expectStopped(); 4251 4252 // Check that keepalive can be restarted without waiting for callback. 4253 ka.start(validKaInterval); 4254 callback.expectStarted(); 4255 ka.stop(); 4256 ka.start(validKaInterval); 4257 callback.expectStopped(); 4258 callback.expectStarted(); 4259 ka.stop(); 4260 callback.expectStopped(); 4261 } 4262 4263 // Check that deleting the IP address stops the keepalive. 4264 LinkProperties bogusLp = new LinkProperties(lp); 4265 try (SocketKeepalive ka = mCm.createSocketKeepalive( 4266 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) { 4267 ka.start(validKaInterval); 4268 callback.expectStarted(); 4269 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25)); 4270 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25)); 4271 mWiFiNetworkAgent.sendLinkProperties(bogusLp); 4272 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS); 4273 mWiFiNetworkAgent.sendLinkProperties(lp); 4274 } 4275 4276 // Check that a started keepalive is stopped correctly when the network disconnects. 4277 try (SocketKeepalive ka = mCm.createSocketKeepalive( 4278 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) { 4279 ka.start(validKaInterval); 4280 callback.expectStarted(); 4281 mWiFiNetworkAgent.disconnect(); 4282 mWiFiNetworkAgent.expectDisconnected(); 4283 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK); 4284 4285 // ... and that stopping it after that has no adverse effects. 4286 waitForIdle(); 4287 final Network myNetAlias = myNet; 4288 assertNull(mCm.getNetworkCapabilities(myNetAlias)); 4289 ka.stop(); 4290 callback.assertNoCallback(); 4291 } 4292 4293 // Reconnect. 4294 myNet = connectKeepaliveNetwork(lp); 4295 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS); 4296 4297 // Check that keepalive slots start from 1 and increment. The first one gets slot 1. 4298 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1); 4299 int srcPort2 = 0; 4300 try (SocketKeepalive ka = mCm.createSocketKeepalive( 4301 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) { 4302 ka.start(validKaInterval); 4303 callback.expectStarted(); 4304 4305 // The second one gets slot 2. 4306 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2); 4307 final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket(); 4308 srcPort2 = testSocket2.getPort(); 4309 TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor); 4310 try (SocketKeepalive ka2 = mCm.createSocketKeepalive( 4311 myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) { 4312 ka2.start(validKaInterval); 4313 callback2.expectStarted(); 4314 4315 ka.stop(); 4316 callback.expectStopped(); 4317 4318 ka2.stop(); 4319 callback2.expectStopped(); 4320 4321 testSocket.close(); 4322 testSocket2.close(); 4323 } 4324 } 4325 4326 // Check that there is no port leaked after all keepalives and sockets are closed. 4327 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7. 4328 // assertFalse(isUdpPortInUse(srcPort)); 4329 // assertFalse(isUdpPortInUse(srcPort2)); 4330 4331 mWiFiNetworkAgent.disconnect(); 4332 mWiFiNetworkAgent.expectDisconnected(); 4333 mWiFiNetworkAgent = null; 4334 } 4335 4336 @Test testTcpSocketKeepalives()4337 public void testTcpSocketKeepalives() throws Exception { 4338 runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor)); 4339 } 4340 doTestTcpSocketKeepalivesWithExecutor(Executor executor)4341 private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception { 4342 final int srcPortV4 = 12345; 4343 final int srcPortV6 = 23456; 4344 final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1"); 4345 final InetAddress myIPv6 = InetAddress.getByName("::1"); 4346 4347 final int validKaInterval = 15; 4348 4349 final LinkProperties lp = new LinkProperties(); 4350 lp.setInterfaceName("wlan12"); 4351 lp.addLinkAddress(new LinkAddress(myIPv6, 64)); 4352 lp.addLinkAddress(new LinkAddress(myIPv4, 25)); 4353 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234"))); 4354 lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254"))); 4355 4356 final Network notMyNet = new Network(61234); 4357 final Network myNet = connectKeepaliveNetwork(lp); 4358 4359 final Socket testSocketV4 = new Socket(); 4360 final Socket testSocketV6 = new Socket(); 4361 4362 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor); 4363 4364 // Attempt to start Tcp keepalives with invalid parameters and check for errors. 4365 // Invalid network. 4366 try (SocketKeepalive ka = mCm.createSocketKeepalive( 4367 notMyNet, testSocketV4, executor, callback)) { 4368 ka.start(validKaInterval); 4369 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK); 4370 } 4371 4372 // Invalid Socket (socket is not bound with IPv4 address). 4373 try (SocketKeepalive ka = mCm.createSocketKeepalive( 4374 myNet, testSocketV4, executor, callback)) { 4375 ka.start(validKaInterval); 4376 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET); 4377 } 4378 4379 // Invalid Socket (socket is not bound with IPv6 address). 4380 try (SocketKeepalive ka = mCm.createSocketKeepalive( 4381 myNet, testSocketV6, executor, callback)) { 4382 ka.start(validKaInterval); 4383 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET); 4384 } 4385 4386 // Bind the socket address 4387 testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4)); 4388 testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6)); 4389 4390 // Invalid Socket (socket is bound with IPv4 address). 4391 try (SocketKeepalive ka = mCm.createSocketKeepalive( 4392 myNet, testSocketV4, executor, callback)) { 4393 ka.start(validKaInterval); 4394 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET); 4395 } 4396 4397 // Invalid Socket (socket is bound with IPv6 address). 4398 try (SocketKeepalive ka = mCm.createSocketKeepalive( 4399 myNet, testSocketV6, executor, callback)) { 4400 ka.start(validKaInterval); 4401 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET); 4402 } 4403 4404 testSocketV4.close(); 4405 testSocketV6.close(); 4406 4407 mWiFiNetworkAgent.disconnect(); 4408 mWiFiNetworkAgent.expectDisconnected(); 4409 mWiFiNetworkAgent = null; 4410 } 4411 doTestNattSocketKeepalivesFdWithExecutor(Executor executor)4412 private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception { 4413 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129"); 4414 final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0"); 4415 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8"); 4416 final int validKaInterval = 15; 4417 4418 // Prepare the target network. 4419 LinkProperties lp = new LinkProperties(); 4420 lp.setInterfaceName("wlan12"); 4421 lp.addLinkAddress(new LinkAddress(myIPv4, 25)); 4422 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254"))); 4423 Network myNet = connectKeepaliveNetwork(lp); 4424 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS); 4425 mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS); 4426 4427 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor); 4428 4429 // Prepare the target file descriptor, keep only one instance. 4430 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE); 4431 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket(); 4432 final int srcPort = testSocket.getPort(); 4433 final ParcelFileDescriptor testPfd = 4434 ParcelFileDescriptor.dup(testSocket.getFileDescriptor()); 4435 testSocket.close(); 4436 assertTrue(isUdpPortInUse(srcPort)); 4437 4438 // Start keepalive and explicit make the variable goes out of scope with try-with-resources 4439 // block. 4440 try (SocketKeepalive ka = mCm.createNattKeepalive( 4441 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) { 4442 ka.start(validKaInterval); 4443 callback.expectStarted(); 4444 ka.stop(); 4445 callback.expectStopped(); 4446 } 4447 4448 // Check that the ParcelFileDescriptor is still valid after keepalive stopped, 4449 // ErrnoException with EBADF will be thrown if the socket is closed when checking local 4450 // address. 4451 assertTrue(isUdpPortInUse(srcPort)); 4452 final InetSocketAddress sa = 4453 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor()); 4454 assertEquals(anyIPv4, sa.getAddress()); 4455 4456 testPfd.close(); 4457 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7. 4458 // assertFalse(isUdpPortInUse(srcPort)); 4459 4460 mWiFiNetworkAgent.disconnect(); 4461 mWiFiNetworkAgent.expectDisconnected(); 4462 mWiFiNetworkAgent = null; 4463 } 4464 isUdpPortInUse(int port)4465 private static boolean isUdpPortInUse(int port) { 4466 try (DatagramSocket ignored = new DatagramSocket(port)) { 4467 return false; 4468 } catch (IOException alreadyInUse) { 4469 return true; 4470 } 4471 } 4472 4473 @Test testGetCaptivePortalServerUrl()4474 public void testGetCaptivePortalServerUrl() throws Exception { 4475 String url = mCm.getCaptivePortalServerUrl(); 4476 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url); 4477 } 4478 4479 private static class TestNetworkPinner extends NetworkPinner { awaitPin(int timeoutMs)4480 public static boolean awaitPin(int timeoutMs) throws InterruptedException { 4481 synchronized(sLock) { 4482 if (sNetwork == null) { 4483 sLock.wait(timeoutMs); 4484 } 4485 return sNetwork != null; 4486 } 4487 } 4488 awaitUnpin(int timeoutMs)4489 public static boolean awaitUnpin(int timeoutMs) throws InterruptedException { 4490 synchronized(sLock) { 4491 if (sNetwork != null) { 4492 sLock.wait(timeoutMs); 4493 } 4494 return sNetwork == null; 4495 } 4496 } 4497 } 4498 assertPinnedToWifiWithCellDefault()4499 private void assertPinnedToWifiWithCellDefault() { 4500 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess()); 4501 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 4502 } 4503 assertPinnedToWifiWithWifiDefault()4504 private void assertPinnedToWifiWithWifiDefault() { 4505 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess()); 4506 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 4507 } 4508 assertNotPinnedToWifi()4509 private void assertNotPinnedToWifi() { 4510 assertNull(mCm.getBoundNetworkForProcess()); 4511 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 4512 } 4513 4514 @Test testNetworkPinner()4515 public void testNetworkPinner() throws Exception { 4516 NetworkRequest wifiRequest = new NetworkRequest.Builder() 4517 .addTransportType(TRANSPORT_WIFI) 4518 .build(); 4519 assertNull(mCm.getBoundNetworkForProcess()); 4520 4521 TestNetworkPinner.pin(mServiceContext, wifiRequest); 4522 assertNull(mCm.getBoundNetworkForProcess()); 4523 4524 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 4525 mCellNetworkAgent.connect(true); 4526 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 4527 mWiFiNetworkAgent.connect(false); 4528 4529 // When wi-fi connects, expect to be pinned. 4530 assertTrue(TestNetworkPinner.awaitPin(100)); 4531 assertPinnedToWifiWithCellDefault(); 4532 4533 // Disconnect and expect the pin to drop. 4534 mWiFiNetworkAgent.disconnect(); 4535 assertTrue(TestNetworkPinner.awaitUnpin(100)); 4536 assertNotPinnedToWifi(); 4537 4538 // Reconnecting does not cause the pin to come back. 4539 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 4540 mWiFiNetworkAgent.connect(false); 4541 assertFalse(TestNetworkPinner.awaitPin(100)); 4542 assertNotPinnedToWifi(); 4543 4544 // Pinning while connected causes the pin to take effect immediately. 4545 TestNetworkPinner.pin(mServiceContext, wifiRequest); 4546 assertTrue(TestNetworkPinner.awaitPin(100)); 4547 assertPinnedToWifiWithCellDefault(); 4548 4549 // Explicitly unpin and expect to use the default network again. 4550 TestNetworkPinner.unpin(); 4551 assertNotPinnedToWifi(); 4552 4553 // Disconnect cell and wifi. 4554 ConditionVariable cv = registerConnectivityBroadcast(3); // cell down, wifi up, wifi down. 4555 mCellNetworkAgent.disconnect(); 4556 mWiFiNetworkAgent.disconnect(); 4557 waitFor(cv); 4558 4559 // Pinning takes effect even if the pinned network is the default when the pin is set... 4560 TestNetworkPinner.pin(mServiceContext, wifiRequest); 4561 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 4562 mWiFiNetworkAgent.connect(false); 4563 assertTrue(TestNetworkPinner.awaitPin(100)); 4564 assertPinnedToWifiWithWifiDefault(); 4565 4566 // ... and is maintained even when that network is no longer the default. 4567 cv = registerConnectivityBroadcast(1); 4568 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 4569 mCellNetworkAgent.connect(true); 4570 waitFor(cv); 4571 assertPinnedToWifiWithCellDefault(); 4572 } 4573 4574 @Test testNetworkCallbackMaximum()4575 public void testNetworkCallbackMaximum() { 4576 // We can only have 99 callbacks, because MultipathPolicyTracker is 4577 // already one of them. 4578 final int MAX_REQUESTS = 99; 4579 final int CALLBACKS = 89; 4580 final int INTENTS = 10; 4581 assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS); 4582 4583 NetworkRequest networkRequest = new NetworkRequest.Builder().build(); 4584 ArrayList<Object> registered = new ArrayList<>(); 4585 4586 int j = 0; 4587 while (j++ < CALLBACKS / 2) { 4588 NetworkCallback cb = new NetworkCallback(); 4589 mCm.requestNetwork(networkRequest, cb); 4590 registered.add(cb); 4591 } 4592 while (j++ < CALLBACKS) { 4593 NetworkCallback cb = new NetworkCallback(); 4594 mCm.registerNetworkCallback(networkRequest, cb); 4595 registered.add(cb); 4596 } 4597 j = 0; 4598 while (j++ < INTENTS / 2) { 4599 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0); 4600 mCm.requestNetwork(networkRequest, pi); 4601 registered.add(pi); 4602 } 4603 while (j++ < INTENTS) { 4604 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0); 4605 mCm.registerNetworkCallback(networkRequest, pi); 4606 registered.add(pi); 4607 } 4608 4609 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added. 4610 assertThrows(TooManyRequestsException.class, () -> 4611 mCm.requestNetwork(networkRequest, new NetworkCallback()) 4612 ); 4613 assertThrows(TooManyRequestsException.class, () -> 4614 mCm.registerNetworkCallback(networkRequest, new NetworkCallback()) 4615 ); 4616 assertThrows(TooManyRequestsException.class, () -> 4617 mCm.requestNetwork(networkRequest, 4618 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0)) 4619 ); 4620 assertThrows(TooManyRequestsException.class, () -> 4621 mCm.registerNetworkCallback(networkRequest, 4622 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0)) 4623 ); 4624 4625 for (Object o : registered) { 4626 if (o instanceof NetworkCallback) { 4627 mCm.unregisterNetworkCallback((NetworkCallback)o); 4628 } 4629 if (o instanceof PendingIntent) { 4630 mCm.unregisterNetworkCallback((PendingIntent)o); 4631 } 4632 } 4633 waitForIdle(); 4634 4635 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed. 4636 for (int i = 0; i < MAX_REQUESTS; i++) { 4637 NetworkCallback networkCallback = new NetworkCallback(); 4638 mCm.requestNetwork(networkRequest, networkCallback); 4639 mCm.unregisterNetworkCallback(networkCallback); 4640 } 4641 waitForIdle(); 4642 4643 for (int i = 0; i < MAX_REQUESTS; i++) { 4644 NetworkCallback networkCallback = new NetworkCallback(); 4645 mCm.registerNetworkCallback(networkRequest, networkCallback); 4646 mCm.unregisterNetworkCallback(networkCallback); 4647 } 4648 waitForIdle(); 4649 4650 for (int i = 0; i < MAX_REQUESTS; i++) { 4651 PendingIntent pendingIntent = 4652 PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0); 4653 mCm.requestNetwork(networkRequest, pendingIntent); 4654 mCm.unregisterNetworkCallback(pendingIntent); 4655 } 4656 waitForIdle(); 4657 4658 for (int i = 0; i < MAX_REQUESTS; i++) { 4659 PendingIntent pendingIntent = 4660 PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0); 4661 mCm.registerNetworkCallback(networkRequest, pendingIntent); 4662 mCm.unregisterNetworkCallback(pendingIntent); 4663 } 4664 } 4665 4666 @Test testNetworkInfoOfTypeNone()4667 public void testNetworkInfoOfTypeNone() throws Exception { 4668 ConditionVariable broadcastCV = registerConnectivityBroadcast(1); 4669 4670 verifyNoNetwork(); 4671 TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE); 4672 assertNull(mCm.getActiveNetworkInfo()); 4673 4674 Network[] allNetworks = mCm.getAllNetworks(); 4675 assertLength(1, allNetworks); 4676 Network network = allNetworks[0]; 4677 NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network); 4678 assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE)); 4679 4680 final NetworkRequest request = 4681 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build(); 4682 final TestNetworkCallback callback = new TestNetworkCallback(); 4683 mCm.registerNetworkCallback(request, callback); 4684 4685 // Bring up wifi aware network. 4686 wifiAware.connect(false, false, false /* isStrictMode */); 4687 callback.expectAvailableCallbacksUnvalidated(wifiAware); 4688 4689 assertNull(mCm.getActiveNetworkInfo()); 4690 assertNull(mCm.getActiveNetwork()); 4691 // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start 4692 // of this test. Fix it and uncomment the assert below. 4693 //assertEmpty(mCm.getAllNetworkInfo()); 4694 4695 // Disconnect wifi aware network. 4696 wifiAware.disconnect(); 4697 callback.expectCallbackThat(TIMEOUT_MS, (info) -> info instanceof CallbackEntry.Lost); 4698 mCm.unregisterNetworkCallback(callback); 4699 4700 verifyNoNetwork(); 4701 if (broadcastCV.block(10)) { 4702 fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast"); 4703 } 4704 } 4705 4706 @Test testDeprecatedAndUnsupportedOperations()4707 public void testDeprecatedAndUnsupportedOperations() throws Exception { 4708 final int TYPE_NONE = ConnectivityManager.TYPE_NONE; 4709 assertNull(mCm.getNetworkInfo(TYPE_NONE)); 4710 assertNull(mCm.getNetworkForType(TYPE_NONE)); 4711 assertNull(mCm.getLinkProperties(TYPE_NONE)); 4712 assertFalse(mCm.isNetworkSupported(TYPE_NONE)); 4713 4714 assertThrows(IllegalArgumentException.class, 4715 () -> mCm.networkCapabilitiesForType(TYPE_NONE)); 4716 4717 Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class; 4718 assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_WIFI, "")); 4719 assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_WIFI, "")); 4720 // TODO: let test context have configuration application target sdk version 4721 // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED 4722 assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_NONE, "")); 4723 assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_NONE, "")); 4724 assertThrows(unsupported, () -> mCm.requestRouteToHostAddress(TYPE_NONE, null)); 4725 } 4726 4727 @Test testLinkPropertiesEnsuresDirectlyConnectedRoutes()4728 public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() throws Exception { 4729 final NetworkRequest networkRequest = new NetworkRequest.Builder() 4730 .addTransportType(TRANSPORT_WIFI).build(); 4731 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 4732 mCm.registerNetworkCallback(networkRequest, networkCallback); 4733 4734 LinkProperties lp = new LinkProperties(); 4735 lp.setInterfaceName(WIFI_IFNAME); 4736 LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24"); 4737 RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null, 4738 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName()); 4739 lp.addLinkAddress(myIpv4Address); 4740 lp.addRoute(myIpv4DefaultRoute); 4741 4742 // Verify direct routes are added when network agent is first registered in 4743 // ConnectivityService. 4744 TestNetworkAgentWrapper networkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp); 4745 networkAgent.connect(true); 4746 networkCallback.expectCallback(CallbackEntry.AVAILABLE, networkAgent); 4747 networkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, networkAgent); 4748 CallbackEntry.LinkPropertiesChanged cbi = 4749 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, 4750 networkAgent); 4751 networkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, networkAgent); 4752 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent); 4753 networkCallback.assertNoCallback(); 4754 checkDirectlyConnectedRoutes(cbi.getLp(), Arrays.asList(myIpv4Address), 4755 Arrays.asList(myIpv4DefaultRoute)); 4756 checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()), 4757 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute)); 4758 4759 // Verify direct routes are added during subsequent link properties updates. 4760 LinkProperties newLp = new LinkProperties(lp); 4761 LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64"); 4762 LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64"); 4763 newLp.addLinkAddress(myIpv6Address1); 4764 newLp.addLinkAddress(myIpv6Address2); 4765 networkAgent.sendLinkProperties(newLp); 4766 cbi = networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, networkAgent); 4767 networkCallback.assertNoCallback(); 4768 checkDirectlyConnectedRoutes(cbi.getLp(), 4769 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2), 4770 Arrays.asList(myIpv4DefaultRoute)); 4771 mCm.unregisterNetworkCallback(networkCallback); 4772 } 4773 4774 @Test testStatsIfacesChanged()4775 public void testStatsIfacesChanged() throws Exception { 4776 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 4777 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 4778 4779 Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()}; 4780 Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()}; 4781 4782 LinkProperties cellLp = new LinkProperties(); 4783 cellLp.setInterfaceName(MOBILE_IFNAME); 4784 LinkProperties wifiLp = new LinkProperties(); 4785 wifiLp.setInterfaceName(WIFI_IFNAME); 4786 4787 // Simple connection should have updated ifaces 4788 mCellNetworkAgent.connect(false); 4789 mCellNetworkAgent.sendLinkProperties(cellLp); 4790 waitForIdle(); 4791 verify(mStatsService, atLeastOnce()) 4792 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME), 4793 eq(new VpnInfo[0])); 4794 reset(mStatsService); 4795 4796 // Default network switch should update ifaces. 4797 mWiFiNetworkAgent.connect(false); 4798 mWiFiNetworkAgent.sendLinkProperties(wifiLp); 4799 waitForIdle(); 4800 assertEquals(wifiLp, mService.getActiveLinkProperties()); 4801 verify(mStatsService, atLeastOnce()) 4802 .forceUpdateIfaces(eq(onlyWifi), any(NetworkState[].class), eq(WIFI_IFNAME), 4803 eq(new VpnInfo[0])); 4804 reset(mStatsService); 4805 4806 // Disconnect should update ifaces. 4807 mWiFiNetworkAgent.disconnect(); 4808 waitForIdle(); 4809 verify(mStatsService, atLeastOnce()) 4810 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), 4811 eq(MOBILE_IFNAME), eq(new VpnInfo[0])); 4812 reset(mStatsService); 4813 4814 // Metered change should update ifaces 4815 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); 4816 waitForIdle(); 4817 verify(mStatsService, atLeastOnce()) 4818 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME), 4819 eq(new VpnInfo[0])); 4820 reset(mStatsService); 4821 4822 mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); 4823 waitForIdle(); 4824 verify(mStatsService, atLeastOnce()) 4825 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME), 4826 eq(new VpnInfo[0])); 4827 reset(mStatsService); 4828 4829 // Captive portal change shouldn't update ifaces 4830 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL); 4831 waitForIdle(); 4832 verify(mStatsService, never()) 4833 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME), 4834 eq(new VpnInfo[0])); 4835 reset(mStatsService); 4836 4837 // Roaming change should update ifaces 4838 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); 4839 waitForIdle(); 4840 verify(mStatsService, atLeastOnce()) 4841 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME), 4842 eq(new VpnInfo[0])); 4843 reset(mStatsService); 4844 } 4845 4846 @Test testBasicDnsConfigurationPushed()4847 public void testBasicDnsConfigurationPushed() throws Exception { 4848 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com"); 4849 4850 // Clear any interactions that occur as a result of CS starting up. 4851 reset(mMockDnsResolver); 4852 4853 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 4854 waitForIdle(); 4855 verify(mMockDnsResolver, never()).setResolverConfiguration(any()); 4856 verifyNoMoreInteractions(mMockDnsResolver); 4857 4858 final LinkProperties cellLp = new LinkProperties(); 4859 cellLp.setInterfaceName(MOBILE_IFNAME); 4860 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does 4861 // "is-reachable" testing in order to not program netd with unreachable 4862 // nameservers that it might try repeated to validate. 4863 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24")); 4864 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"), 4865 MOBILE_IFNAME)); 4866 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64")); 4867 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"), 4868 MOBILE_IFNAME)); 4869 mCellNetworkAgent.sendLinkProperties(cellLp); 4870 mCellNetworkAgent.connect(false); 4871 waitForIdle(); 4872 4873 verify(mMockDnsResolver, times(1)).createNetworkCache( 4874 eq(mCellNetworkAgent.getNetwork().netId)); 4875 // CS tells dnsresolver about the empty DNS config for this network. 4876 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any()); 4877 reset(mMockDnsResolver); 4878 4879 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1")); 4880 mCellNetworkAgent.sendLinkProperties(cellLp); 4881 waitForIdle(); 4882 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration( 4883 mResolverParamsParcelCaptor.capture()); 4884 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue(); 4885 assertEquals(1, resolvrParams.servers.length); 4886 assertTrue(ArrayUtils.contains(resolvrParams.servers, "2001:db8::1")); 4887 // Opportunistic mode. 4888 assertTrue(ArrayUtils.contains(resolvrParams.tlsServers, "2001:db8::1")); 4889 reset(mMockDnsResolver); 4890 4891 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1")); 4892 mCellNetworkAgent.sendLinkProperties(cellLp); 4893 waitForIdle(); 4894 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration( 4895 mResolverParamsParcelCaptor.capture()); 4896 resolvrParams = mResolverParamsParcelCaptor.getValue(); 4897 assertEquals(2, resolvrParams.servers.length); 4898 assertTrue(ArrayUtils.containsAll(resolvrParams.servers, 4899 new String[]{"2001:db8::1", "192.0.2.1"})); 4900 // Opportunistic mode. 4901 assertEquals(2, resolvrParams.tlsServers.length); 4902 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers, 4903 new String[]{"2001:db8::1", "192.0.2.1"})); 4904 reset(mMockDnsResolver); 4905 4906 final String TLS_SPECIFIER = "tls.example.com"; 4907 final String TLS_SERVER6 = "2001:db8:53::53"; 4908 final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) }; 4909 final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 }; 4910 mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved( 4911 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel()); 4912 4913 waitForIdle(); 4914 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration( 4915 mResolverParamsParcelCaptor.capture()); 4916 resolvrParams = mResolverParamsParcelCaptor.getValue(); 4917 assertEquals(2, resolvrParams.servers.length); 4918 assertTrue(ArrayUtils.containsAll(resolvrParams.servers, 4919 new String[]{"2001:db8::1", "192.0.2.1"})); 4920 reset(mMockDnsResolver); 4921 } 4922 4923 @Test testDnsConfigurationTransTypesPushed()4924 public void testDnsConfigurationTransTypesPushed() throws Exception { 4925 // Clear any interactions that occur as a result of CS starting up. 4926 reset(mMockDnsResolver); 4927 4928 final NetworkRequest request = new NetworkRequest.Builder() 4929 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET) 4930 .build(); 4931 final TestNetworkCallback callback = new TestNetworkCallback(); 4932 mCm.registerNetworkCallback(request, callback); 4933 4934 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 4935 mWiFiNetworkAgent.connect(false); 4936 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 4937 verify(mMockDnsResolver, times(1)).createNetworkCache( 4938 eq(mWiFiNetworkAgent.getNetwork().netId)); 4939 verify(mMockDnsResolver, times(2)).setResolverConfiguration( 4940 mResolverParamsParcelCaptor.capture()); 4941 final ResolverParamsParcel resolverParams = mResolverParamsParcelCaptor.getValue(); 4942 assertContainsExactly(resolverParams.transportTypes, TRANSPORT_WIFI); 4943 reset(mMockDnsResolver); 4944 } 4945 4946 @Test testPrivateDnsNotification()4947 public void testPrivateDnsNotification() throws Exception { 4948 NetworkRequest request = new NetworkRequest.Builder() 4949 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET) 4950 .build(); 4951 TestNetworkCallback callback = new TestNetworkCallback(); 4952 mCm.registerNetworkCallback(request, callback); 4953 // Bring up wifi. 4954 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 4955 mWiFiNetworkAgent.connect(false); 4956 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 4957 // Private DNS resolution failed, checking if the notification will be shown or not. 4958 mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */); 4959 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid()); 4960 waitForIdle(); 4961 // If network validation failed, NetworkMonitor will re-evaluate the network. 4962 // ConnectivityService should filter the redundant notification. This part is trying to 4963 // simulate that situation and check if ConnectivityService could filter that case. 4964 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid()); 4965 waitForIdle(); 4966 verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notifyAsUser(anyString(), 4967 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL)); 4968 // If private DNS resolution successful, the PRIVATE_DNS_BROKEN notification shouldn't be 4969 // shown. 4970 mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */); 4971 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid()); 4972 waitForIdle(); 4973 verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancelAsUser(anyString(), 4974 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), eq(UserHandle.ALL)); 4975 // If private DNS resolution failed again, the PRIVATE_DNS_BROKEN notification should be 4976 // shown again. 4977 mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */); 4978 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid()); 4979 waitForIdle(); 4980 verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notifyAsUser(anyString(), 4981 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL)); 4982 } 4983 4984 @Test testPrivateDnsSettingsChange()4985 public void testPrivateDnsSettingsChange() throws Exception { 4986 // Clear any interactions that occur as a result of CS starting up. 4987 reset(mMockDnsResolver); 4988 4989 // The default on Android is opportunistic mode ("Automatic"). 4990 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com"); 4991 4992 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 4993 final NetworkRequest cellRequest = new NetworkRequest.Builder() 4994 .addTransportType(TRANSPORT_CELLULAR).build(); 4995 mCm.requestNetwork(cellRequest, cellNetworkCallback); 4996 4997 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 4998 waitForIdle(); 4999 // CS tells netd about the empty DNS config for this network. 5000 verify(mMockDnsResolver, never()).setResolverConfiguration(any()); 5001 verifyNoMoreInteractions(mMockDnsResolver); 5002 5003 final LinkProperties cellLp = new LinkProperties(); 5004 cellLp.setInterfaceName(MOBILE_IFNAME); 5005 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does 5006 // "is-reachable" testing in order to not program netd with unreachable 5007 // nameservers that it might try repeated to validate. 5008 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24")); 5009 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"), 5010 MOBILE_IFNAME)); 5011 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64")); 5012 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"), 5013 MOBILE_IFNAME)); 5014 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1")); 5015 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1")); 5016 5017 mCellNetworkAgent.sendLinkProperties(cellLp); 5018 mCellNetworkAgent.connect(false); 5019 waitForIdle(); 5020 verify(mMockDnsResolver, times(1)).createNetworkCache( 5021 eq(mCellNetworkAgent.getNetwork().netId)); 5022 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration( 5023 mResolverParamsParcelCaptor.capture()); 5024 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue(); 5025 assertEquals(2, resolvrParams.tlsServers.length); 5026 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers, 5027 new String[] { "2001:db8::1", "192.0.2.1" })); 5028 // Opportunistic mode. 5029 assertEquals(2, resolvrParams.tlsServers.length); 5030 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers, 5031 new String[] { "2001:db8::1", "192.0.2.1" })); 5032 reset(mMockDnsResolver); 5033 cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent); 5034 cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, 5035 mCellNetworkAgent); 5036 CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback( 5037 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); 5038 cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent); 5039 cellNetworkCallback.assertNoCallback(); 5040 assertFalse(cbi.getLp().isPrivateDnsActive()); 5041 assertNull(cbi.getLp().getPrivateDnsServerName()); 5042 5043 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com"); 5044 verify(mMockDnsResolver, times(1)).setResolverConfiguration( 5045 mResolverParamsParcelCaptor.capture()); 5046 resolvrParams = mResolverParamsParcelCaptor.getValue(); 5047 assertEquals(2, resolvrParams.servers.length); 5048 assertTrue(ArrayUtils.containsAll(resolvrParams.servers, 5049 new String[] { "2001:db8::1", "192.0.2.1" })); 5050 reset(mMockDnsResolver); 5051 cellNetworkCallback.assertNoCallback(); 5052 5053 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com"); 5054 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration( 5055 mResolverParamsParcelCaptor.capture()); 5056 resolvrParams = mResolverParamsParcelCaptor.getValue(); 5057 assertEquals(2, resolvrParams.servers.length); 5058 assertTrue(ArrayUtils.containsAll(resolvrParams.servers, 5059 new String[] { "2001:db8::1", "192.0.2.1" })); 5060 assertEquals(2, resolvrParams.tlsServers.length); 5061 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers, 5062 new String[] { "2001:db8::1", "192.0.2.1" })); 5063 reset(mMockDnsResolver); 5064 cellNetworkCallback.assertNoCallback(); 5065 5066 setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com"); 5067 // Can't test dns configuration for strict mode without properly mocking 5068 // out the DNS lookups, but can test that LinkProperties is updated. 5069 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, 5070 mCellNetworkAgent); 5071 cellNetworkCallback.assertNoCallback(); 5072 assertTrue(cbi.getLp().isPrivateDnsActive()); 5073 assertEquals("strict.example.com", cbi.getLp().getPrivateDnsServerName()); 5074 } 5075 5076 @Test testLinkPropertiesWithPrivateDnsValidationEvents()5077 public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception { 5078 // The default on Android is opportunistic mode ("Automatic"). 5079 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com"); 5080 5081 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 5082 final NetworkRequest cellRequest = new NetworkRequest.Builder() 5083 .addTransportType(TRANSPORT_CELLULAR).build(); 5084 mCm.requestNetwork(cellRequest, cellNetworkCallback); 5085 5086 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 5087 waitForIdle(); 5088 LinkProperties lp = new LinkProperties(); 5089 mCellNetworkAgent.sendLinkProperties(lp); 5090 mCellNetworkAgent.connect(false); 5091 waitForIdle(); 5092 cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent); 5093 cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, 5094 mCellNetworkAgent); 5095 CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback( 5096 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); 5097 cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent); 5098 cellNetworkCallback.assertNoCallback(); 5099 assertFalse(cbi.getLp().isPrivateDnsActive()); 5100 assertNull(cbi.getLp().getPrivateDnsServerName()); 5101 Set<InetAddress> dnsServers = new HashSet<>(); 5102 checkDnsServers(cbi.getLp(), dnsServers); 5103 5104 // Send a validation event for a server that is not part of the current 5105 // resolver config. The validation event should be ignored. 5106 mService.mNetdEventCallback.onPrivateDnsValidationEvent( 5107 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true); 5108 cellNetworkCallback.assertNoCallback(); 5109 5110 // Add a dns server to the LinkProperties. 5111 LinkProperties lp2 = new LinkProperties(lp); 5112 lp2.addDnsServer(InetAddress.getByName("145.100.185.16")); 5113 mCellNetworkAgent.sendLinkProperties(lp2); 5114 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, 5115 mCellNetworkAgent); 5116 cellNetworkCallback.assertNoCallback(); 5117 assertFalse(cbi.getLp().isPrivateDnsActive()); 5118 assertNull(cbi.getLp().getPrivateDnsServerName()); 5119 dnsServers.add(InetAddress.getByName("145.100.185.16")); 5120 checkDnsServers(cbi.getLp(), dnsServers); 5121 5122 // Send a validation event containing a hostname that is not part of 5123 // the current resolver config. The validation event should be ignored. 5124 mService.mNetdEventCallback.onPrivateDnsValidationEvent( 5125 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true); 5126 cellNetworkCallback.assertNoCallback(); 5127 5128 // Send a validation event where validation failed. 5129 mService.mNetdEventCallback.onPrivateDnsValidationEvent( 5130 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false); 5131 cellNetworkCallback.assertNoCallback(); 5132 5133 // Send a validation event where validation succeeded for a server in 5134 // the current resolver config. A LinkProperties callback with updated 5135 // private dns fields should be sent. 5136 mService.mNetdEventCallback.onPrivateDnsValidationEvent( 5137 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true); 5138 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, 5139 mCellNetworkAgent); 5140 cellNetworkCallback.assertNoCallback(); 5141 assertTrue(cbi.getLp().isPrivateDnsActive()); 5142 assertNull(cbi.getLp().getPrivateDnsServerName()); 5143 checkDnsServers(cbi.getLp(), dnsServers); 5144 5145 // The private dns fields in LinkProperties should be preserved when 5146 // the network agent sends unrelated changes. 5147 LinkProperties lp3 = new LinkProperties(lp2); 5148 lp3.setMtu(1300); 5149 mCellNetworkAgent.sendLinkProperties(lp3); 5150 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, 5151 mCellNetworkAgent); 5152 cellNetworkCallback.assertNoCallback(); 5153 assertTrue(cbi.getLp().isPrivateDnsActive()); 5154 assertNull(cbi.getLp().getPrivateDnsServerName()); 5155 checkDnsServers(cbi.getLp(), dnsServers); 5156 assertEquals(1300, cbi.getLp().getMtu()); 5157 5158 // Removing the only validated server should affect the private dns 5159 // fields in LinkProperties. 5160 LinkProperties lp4 = new LinkProperties(lp3); 5161 lp4.removeDnsServer(InetAddress.getByName("145.100.185.16")); 5162 mCellNetworkAgent.sendLinkProperties(lp4); 5163 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, 5164 mCellNetworkAgent); 5165 cellNetworkCallback.assertNoCallback(); 5166 assertFalse(cbi.getLp().isPrivateDnsActive()); 5167 assertNull(cbi.getLp().getPrivateDnsServerName()); 5168 dnsServers.remove(InetAddress.getByName("145.100.185.16")); 5169 checkDnsServers(cbi.getLp(), dnsServers); 5170 assertEquals(1300, cbi.getLp().getMtu()); 5171 } 5172 checkDirectlyConnectedRoutes(Object callbackObj, Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes)5173 private void checkDirectlyConnectedRoutes(Object callbackObj, 5174 Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) { 5175 assertTrue(callbackObj instanceof LinkProperties); 5176 LinkProperties lp = (LinkProperties) callbackObj; 5177 5178 Set<RouteInfo> expectedRoutes = new ArraySet<>(); 5179 expectedRoutes.addAll(otherRoutes); 5180 for (LinkAddress address : linkAddresses) { 5181 RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName()); 5182 // Duplicates in linkAddresses are considered failures 5183 assertTrue(expectedRoutes.add(localRoute)); 5184 } 5185 List<RouteInfo> observedRoutes = lp.getRoutes(); 5186 assertEquals(expectedRoutes.size(), observedRoutes.size()); 5187 assertTrue(observedRoutes.containsAll(expectedRoutes)); 5188 } 5189 checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers)5190 private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) { 5191 assertTrue(callbackObj instanceof LinkProperties); 5192 LinkProperties lp = (LinkProperties) callbackObj; 5193 assertEquals(dnsServers.size(), lp.getDnsServers().size()); 5194 assertTrue(lp.getDnsServers().containsAll(dnsServers)); 5195 } 5196 5197 @Test testVpnNetworkActive()5198 public void testVpnNetworkActive() throws Exception { 5199 final int uid = Process.myUid(); 5200 5201 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback(); 5202 final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback(); 5203 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback(); 5204 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback(); 5205 final TestNetworkCallback defaultCallback = new TestNetworkCallback(); 5206 final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build(); 5207 final NetworkRequest genericRequest = new NetworkRequest.Builder() 5208 .removeCapability(NET_CAPABILITY_NOT_VPN).build(); 5209 final NetworkRequest wifiRequest = new NetworkRequest.Builder() 5210 .addTransportType(TRANSPORT_WIFI).build(); 5211 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder() 5212 .removeCapability(NET_CAPABILITY_NOT_VPN) 5213 .addTransportType(TRANSPORT_VPN).build(); 5214 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback); 5215 mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback); 5216 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback); 5217 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback); 5218 mCm.registerDefaultNetworkCallback(defaultCallback); 5219 defaultCallback.assertNoCallback(); 5220 5221 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 5222 mWiFiNetworkAgent.connect(false); 5223 5224 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 5225 genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 5226 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 5227 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 5228 vpnNetworkCallback.assertNoCallback(); 5229 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 5230 5231 final TestNetworkAgentWrapper 5232 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN); 5233 final ArraySet<UidRange> ranges = new ArraySet<>(); 5234 ranges.add(new UidRange(uid, uid)); 5235 mMockVpn.setNetworkAgent(vpnNetworkAgent); 5236 mMockVpn.setUids(ranges); 5237 // VPN networks do not satisfy the default request and are automatically validated 5238 // by NetworkMonitor 5239 assertFalse(NetworkMonitorUtils.isValidationRequired( 5240 vpnNetworkAgent.getNetworkCapabilities())); 5241 vpnNetworkAgent.setNetworkValid(false /* isStrictMode */); 5242 5243 vpnNetworkAgent.connect(false); 5244 mMockVpn.connect(); 5245 mMockVpn.setUnderlyingNetworks(new Network[0]); 5246 5247 genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent); 5248 genericNotVpnNetworkCallback.assertNoCallback(); 5249 wifiNetworkCallback.assertNoCallback(); 5250 vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent); 5251 defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent); 5252 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 5253 5254 genericNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent); 5255 genericNotVpnNetworkCallback.assertNoCallback(); 5256 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, nc -> null == nc.getUids()); 5257 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent); 5258 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 5259 5260 ranges.clear(); 5261 vpnNetworkAgent.setUids(ranges); 5262 5263 genericNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent); 5264 genericNotVpnNetworkCallback.assertNoCallback(); 5265 wifiNetworkCallback.assertNoCallback(); 5266 vpnNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent); 5267 5268 // TODO : The default network callback should actually get a LOST call here (also see the 5269 // comment below for AVAILABLE). This is because ConnectivityService does not look at UID 5270 // ranges at all when determining whether a network should be rematched. In practice, VPNs 5271 // can't currently update their UIDs without disconnecting, so this does not matter too 5272 // much, but that is the reason the test here has to check for an update to the 5273 // capabilities instead of the expected LOST then AVAILABLE. 5274 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent); 5275 5276 ranges.add(new UidRange(uid, uid)); 5277 mMockVpn.setUids(ranges); 5278 vpnNetworkAgent.setUids(ranges); 5279 5280 genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent); 5281 genericNotVpnNetworkCallback.assertNoCallback(); 5282 wifiNetworkCallback.assertNoCallback(); 5283 vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent); 5284 // TODO : Here like above, AVAILABLE would be correct, but because this can't actually 5285 // happen outside of the test, ConnectivityService does not rematch callbacks. 5286 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent); 5287 5288 mWiFiNetworkAgent.disconnect(); 5289 5290 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 5291 genericNotVpnNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 5292 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 5293 vpnNetworkCallback.assertNoCallback(); 5294 defaultCallback.assertNoCallback(); 5295 5296 vpnNetworkAgent.disconnect(); 5297 5298 genericNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent); 5299 genericNotVpnNetworkCallback.assertNoCallback(); 5300 wifiNetworkCallback.assertNoCallback(); 5301 vpnNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent); 5302 defaultCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent); 5303 assertEquals(null, mCm.getActiveNetwork()); 5304 5305 mCm.unregisterNetworkCallback(genericNetworkCallback); 5306 mCm.unregisterNetworkCallback(wifiNetworkCallback); 5307 mCm.unregisterNetworkCallback(vpnNetworkCallback); 5308 mCm.unregisterNetworkCallback(defaultCallback); 5309 } 5310 5311 @Test testVpnWithoutInternet()5312 public void testVpnWithoutInternet() throws Exception { 5313 final int uid = Process.myUid(); 5314 5315 final TestNetworkCallback defaultCallback = new TestNetworkCallback(); 5316 mCm.registerDefaultNetworkCallback(defaultCallback); 5317 5318 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 5319 mWiFiNetworkAgent.connect(true); 5320 5321 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); 5322 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 5323 5324 TestNetworkAgentWrapper 5325 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN); 5326 final ArraySet<UidRange> ranges = new ArraySet<>(); 5327 ranges.add(new UidRange(uid, uid)); 5328 mMockVpn.setNetworkAgent(vpnNetworkAgent); 5329 mMockVpn.setUids(ranges); 5330 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */, 5331 false /* isStrictMode */); 5332 mMockVpn.connect(); 5333 5334 defaultCallback.assertNoCallback(); 5335 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 5336 5337 vpnNetworkAgent.disconnect(); 5338 defaultCallback.assertNoCallback(); 5339 5340 mCm.unregisterNetworkCallback(defaultCallback); 5341 } 5342 5343 @Test testVpnWithInternet()5344 public void testVpnWithInternet() throws Exception { 5345 final int uid = Process.myUid(); 5346 5347 final TestNetworkCallback defaultCallback = new TestNetworkCallback(); 5348 mCm.registerDefaultNetworkCallback(defaultCallback); 5349 5350 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 5351 mWiFiNetworkAgent.connect(true); 5352 5353 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); 5354 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 5355 5356 TestNetworkAgentWrapper 5357 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN); 5358 final ArraySet<UidRange> ranges = new ArraySet<>(); 5359 ranges.add(new UidRange(uid, uid)); 5360 mMockVpn.setNetworkAgent(vpnNetworkAgent); 5361 mMockVpn.setUids(ranges); 5362 vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */, 5363 false /* isStrictMode */); 5364 mMockVpn.connect(); 5365 5366 defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent); 5367 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 5368 5369 vpnNetworkAgent.disconnect(); 5370 defaultCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent); 5371 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); 5372 5373 mCm.unregisterNetworkCallback(defaultCallback); 5374 } 5375 5376 @Test testVpnUnvalidated()5377 public void testVpnUnvalidated() throws Exception { 5378 final TestNetworkCallback callback = new TestNetworkCallback(); 5379 mCm.registerDefaultNetworkCallback(callback); 5380 5381 // Bring up Ethernet. 5382 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET); 5383 mEthernetNetworkAgent.connect(true); 5384 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent); 5385 callback.assertNoCallback(); 5386 5387 // Bring up a VPN that has the INTERNET capability, initially unvalidated. 5388 final int uid = Process.myUid(); 5389 final TestNetworkAgentWrapper 5390 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN); 5391 final ArraySet<UidRange> ranges = new ArraySet<>(); 5392 ranges.add(new UidRange(uid, uid)); 5393 mMockVpn.setNetworkAgent(vpnNetworkAgent); 5394 mMockVpn.setUids(ranges); 5395 vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */, 5396 false /* isStrictMode */); 5397 mMockVpn.connect(); 5398 5399 // Even though the VPN is unvalidated, it becomes the default network for our app. 5400 callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent); 5401 callback.assertNoCallback(); 5402 5403 assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore()); 5404 assertEquals(ConnectivityConstants.VPN_DEFAULT_SCORE, vpnNetworkAgent.getScore()); 5405 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 5406 5407 NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork()); 5408 assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED)); 5409 assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET)); 5410 5411 assertFalse(NetworkMonitorUtils.isValidationRequired( 5412 vpnNetworkAgent.getNetworkCapabilities())); 5413 assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired( 5414 vpnNetworkAgent.getNetworkCapabilities())); 5415 5416 // Pretend that the VPN network validates. 5417 vpnNetworkAgent.setNetworkValid(false /* isStrictMode */); 5418 vpnNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid()); 5419 // Expect to see the validated capability, but no other changes, because the VPN is already 5420 // the default network for the app. 5421 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, vpnNetworkAgent); 5422 callback.assertNoCallback(); 5423 5424 vpnNetworkAgent.disconnect(); 5425 callback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent); 5426 callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent); 5427 } 5428 5429 @Test testVpnStartsWithUnderlyingCaps()5430 public void testVpnStartsWithUnderlyingCaps() throws Exception { 5431 final int uid = Process.myUid(); 5432 5433 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback(); 5434 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder() 5435 .removeCapability(NET_CAPABILITY_NOT_VPN) 5436 .addTransportType(TRANSPORT_VPN) 5437 .build(); 5438 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback); 5439 vpnNetworkCallback.assertNoCallback(); 5440 5441 // Connect cell. It will become the default network, and in the absence of setting 5442 // underlying networks explicitly it will become the sole underlying network for the vpn. 5443 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 5444 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED); 5445 mCellNetworkAgent.connect(true); 5446 5447 final TestNetworkAgentWrapper vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN); 5448 final ArraySet<UidRange> ranges = new ArraySet<>(); 5449 ranges.add(new UidRange(uid, uid)); 5450 mMockVpn.setNetworkAgent(vpnNetworkAgent); 5451 mMockVpn.connect(); 5452 mMockVpn.setUids(ranges); 5453 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */, 5454 false /* isStrictMode */); 5455 5456 vpnNetworkCallback.expectAvailableCallbacks(vpnNetworkAgent.getNetwork(), 5457 false /* suspended */, false /* validated */, false /* blocked */, TIMEOUT_MS); 5458 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent.getNetwork(), TIMEOUT_MS, 5459 nc -> nc.hasCapability(NET_CAPABILITY_VALIDATED)); 5460 5461 final NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork()); 5462 assertTrue(nc.hasTransport(TRANSPORT_VPN)); 5463 assertTrue(nc.hasTransport(TRANSPORT_CELLULAR)); 5464 assertFalse(nc.hasTransport(TRANSPORT_WIFI)); 5465 assertTrue(nc.hasCapability(NET_CAPABILITY_VALIDATED)); 5466 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED)); 5467 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); 5468 } 5469 5470 @Test testVpnSetUnderlyingNetworks()5471 public void testVpnSetUnderlyingNetworks() throws Exception { 5472 final int uid = Process.myUid(); 5473 5474 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback(); 5475 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder() 5476 .removeCapability(NET_CAPABILITY_NOT_VPN) 5477 .addTransportType(TRANSPORT_VPN) 5478 .build(); 5479 NetworkCapabilities nc; 5480 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback); 5481 vpnNetworkCallback.assertNoCallback(); 5482 5483 final TestNetworkAgentWrapper 5484 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN); 5485 final ArraySet<UidRange> ranges = new ArraySet<>(); 5486 ranges.add(new UidRange(uid, uid)); 5487 mMockVpn.setNetworkAgent(vpnNetworkAgent); 5488 mMockVpn.connect(); 5489 mMockVpn.setUids(ranges); 5490 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */, 5491 false /* isStrictMode */); 5492 5493 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent); 5494 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork()); 5495 assertTrue(nc.hasTransport(TRANSPORT_VPN)); 5496 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR)); 5497 assertFalse(nc.hasTransport(TRANSPORT_WIFI)); 5498 // For safety reasons a VPN without underlying networks is considered metered. 5499 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED)); 5500 // A VPN without underlying networks is not suspended. 5501 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); 5502 5503 // Connect cell and use it as an underlying network. 5504 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 5505 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED); 5506 mCellNetworkAgent.connect(true); 5507 5508 mService.setUnderlyingNetworksForVpn( 5509 new Network[] { mCellNetworkAgent.getNetwork() }); 5510 5511 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, 5512 (caps) -> caps.hasTransport(TRANSPORT_VPN) 5513 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) 5514 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) 5515 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); 5516 5517 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 5518 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); 5519 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED); 5520 mWiFiNetworkAgent.connect(true); 5521 5522 mService.setUnderlyingNetworksForVpn( 5523 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() }); 5524 5525 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, 5526 (caps) -> caps.hasTransport(TRANSPORT_VPN) 5527 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) 5528 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) 5529 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); 5530 5531 // Don't disconnect, but note the VPN is not using wifi any more. 5532 mService.setUnderlyingNetworksForVpn( 5533 new Network[] { mCellNetworkAgent.getNetwork() }); 5534 5535 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, 5536 (caps) -> caps.hasTransport(TRANSPORT_VPN) 5537 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) 5538 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) 5539 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); 5540 5541 // Remove NOT_SUSPENDED from the only network and observe VPN is now suspended. 5542 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED); 5543 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, 5544 (caps) -> caps.hasTransport(TRANSPORT_VPN) 5545 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) 5546 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) 5547 && !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); 5548 vpnNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, vpnNetworkAgent); 5549 5550 // Add NOT_SUSPENDED again and observe VPN is no longer suspended. 5551 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED); 5552 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, 5553 (caps) -> caps.hasTransport(TRANSPORT_VPN) 5554 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) 5555 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) 5556 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); 5557 vpnNetworkCallback.expectCallback(CallbackEntry.RESUMED, vpnNetworkAgent); 5558 5559 // Use Wifi but not cell. Note the VPN is now unmetered and not suspended. 5560 mService.setUnderlyingNetworksForVpn( 5561 new Network[] { mWiFiNetworkAgent.getNetwork() }); 5562 5563 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, 5564 (caps) -> caps.hasTransport(TRANSPORT_VPN) 5565 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) 5566 && caps.hasCapability(NET_CAPABILITY_NOT_METERED) 5567 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); 5568 5569 // Use both again. 5570 mService.setUnderlyingNetworksForVpn( 5571 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() }); 5572 5573 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, 5574 (caps) -> caps.hasTransport(TRANSPORT_VPN) 5575 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) 5576 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) 5577 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); 5578 5579 // Cell is suspended again. As WiFi is not, this should not cause a callback. 5580 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED); 5581 vpnNetworkCallback.assertNoCallback(); 5582 5583 // Stop using WiFi. The VPN is suspended again. 5584 mService.setUnderlyingNetworksForVpn( 5585 new Network[] { mCellNetworkAgent.getNetwork() }); 5586 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, 5587 (caps) -> caps.hasTransport(TRANSPORT_VPN) 5588 && caps.hasTransport(TRANSPORT_CELLULAR) 5589 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) 5590 && !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); 5591 // While the SUSPENDED callback should in theory be sent here, it is not. This is 5592 // a bug in ConnectivityService, but as the SUSPENDED and RESUMED callbacks have never 5593 // been public and are deprecated and slated for removal, there is no sense in spending 5594 // resources fixing this bug now. 5595 5596 // Use both again. 5597 mService.setUnderlyingNetworksForVpn( 5598 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() }); 5599 5600 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, 5601 (caps) -> caps.hasTransport(TRANSPORT_VPN) 5602 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) 5603 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) 5604 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); 5605 // As above, the RESUMED callback not being sent here is a bug, but not a bug that's 5606 // worth anybody's time to fix. 5607 5608 // Disconnect cell. Receive update without even removing the dead network from the 5609 // underlying networks – it's dead anyway. Not metered any more. 5610 mCellNetworkAgent.disconnect(); 5611 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, 5612 (caps) -> caps.hasTransport(TRANSPORT_VPN) 5613 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) 5614 && caps.hasCapability(NET_CAPABILITY_NOT_METERED)); 5615 5616 // Disconnect wifi too. No underlying networks means this is now metered. 5617 mWiFiNetworkAgent.disconnect(); 5618 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, 5619 (caps) -> caps.hasTransport(TRANSPORT_VPN) 5620 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) 5621 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)); 5622 5623 mMockVpn.disconnect(); 5624 } 5625 5626 @Test testNullUnderlyingNetworks()5627 public void testNullUnderlyingNetworks() throws Exception { 5628 final int uid = Process.myUid(); 5629 5630 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback(); 5631 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder() 5632 .removeCapability(NET_CAPABILITY_NOT_VPN) 5633 .addTransportType(TRANSPORT_VPN) 5634 .build(); 5635 NetworkCapabilities nc; 5636 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback); 5637 vpnNetworkCallback.assertNoCallback(); 5638 5639 final TestNetworkAgentWrapper 5640 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN); 5641 final ArraySet<UidRange> ranges = new ArraySet<>(); 5642 ranges.add(new UidRange(uid, uid)); 5643 mMockVpn.setNetworkAgent(vpnNetworkAgent); 5644 mMockVpn.connect(); 5645 mMockVpn.setUids(ranges); 5646 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */, 5647 false /* isStrictMode */); 5648 5649 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent); 5650 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork()); 5651 assertTrue(nc.hasTransport(TRANSPORT_VPN)); 5652 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR)); 5653 assertFalse(nc.hasTransport(TRANSPORT_WIFI)); 5654 // By default, VPN is set to track default network (i.e. its underlying networks is null). 5655 // In case of no default network, VPN is considered metered. 5656 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED)); 5657 5658 // Connect to Cell; Cell is the default network. 5659 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 5660 mCellNetworkAgent.connect(true); 5661 5662 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, 5663 (caps) -> caps.hasTransport(TRANSPORT_VPN) 5664 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) 5665 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)); 5666 5667 // Connect to WiFi; WiFi is the new default. 5668 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 5669 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); 5670 mWiFiNetworkAgent.connect(true); 5671 5672 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, 5673 (caps) -> caps.hasTransport(TRANSPORT_VPN) 5674 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) 5675 && caps.hasCapability(NET_CAPABILITY_NOT_METERED)); 5676 5677 // Disconnect Cell. The default network did not change, so there shouldn't be any changes in 5678 // the capabilities. 5679 mCellNetworkAgent.disconnect(); 5680 5681 // Disconnect wifi too. Now we have no default network. 5682 mWiFiNetworkAgent.disconnect(); 5683 5684 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, 5685 (caps) -> caps.hasTransport(TRANSPORT_VPN) 5686 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) 5687 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)); 5688 5689 mMockVpn.disconnect(); 5690 } 5691 5692 @Test testIsActiveNetworkMeteredOverWifi()5693 public void testIsActiveNetworkMeteredOverWifi() throws Exception { 5694 // Returns true by default when no network is available. 5695 assertTrue(mCm.isActiveNetworkMetered()); 5696 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 5697 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); 5698 mWiFiNetworkAgent.connect(true); 5699 waitForIdle(); 5700 5701 assertFalse(mCm.isActiveNetworkMetered()); 5702 } 5703 5704 @Test testIsActiveNetworkMeteredOverCell()5705 public void testIsActiveNetworkMeteredOverCell() throws Exception { 5706 // Returns true by default when no network is available. 5707 assertTrue(mCm.isActiveNetworkMetered()); 5708 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 5709 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED); 5710 mCellNetworkAgent.connect(true); 5711 waitForIdle(); 5712 5713 assertTrue(mCm.isActiveNetworkMetered()); 5714 } 5715 5716 @Test testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault()5717 public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() throws Exception { 5718 // Returns true by default when no network is available. 5719 assertTrue(mCm.isActiveNetworkMetered()); 5720 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 5721 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED); 5722 mCellNetworkAgent.connect(true); 5723 waitForIdle(); 5724 assertTrue(mCm.isActiveNetworkMetered()); 5725 5726 // Connect VPN network. By default it is using current default network (Cell). 5727 TestNetworkAgentWrapper 5728 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN); 5729 final ArraySet<UidRange> ranges = new ArraySet<>(); 5730 final int uid = Process.myUid(); 5731 ranges.add(new UidRange(uid, uid)); 5732 mMockVpn.setNetworkAgent(vpnNetworkAgent); 5733 mMockVpn.setUids(ranges); 5734 vpnNetworkAgent.connect(true); 5735 mMockVpn.connect(); 5736 waitForIdle(); 5737 // Ensure VPN is now the active network. 5738 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 5739 5740 // Expect VPN to be metered. 5741 assertTrue(mCm.isActiveNetworkMetered()); 5742 5743 // Connect WiFi. 5744 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 5745 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); 5746 mWiFiNetworkAgent.connect(true); 5747 waitForIdle(); 5748 // VPN should still be the active network. 5749 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 5750 5751 // Expect VPN to be unmetered as it should now be using WiFi (new default). 5752 assertFalse(mCm.isActiveNetworkMetered()); 5753 5754 // Disconnecting Cell should not affect VPN's meteredness. 5755 mCellNetworkAgent.disconnect(); 5756 waitForIdle(); 5757 5758 assertFalse(mCm.isActiveNetworkMetered()); 5759 5760 // Disconnect WiFi; Now there is no platform default network. 5761 mWiFiNetworkAgent.disconnect(); 5762 waitForIdle(); 5763 5764 // VPN without any underlying networks is treated as metered. 5765 assertTrue(mCm.isActiveNetworkMetered()); 5766 5767 vpnNetworkAgent.disconnect(); 5768 mMockVpn.disconnect(); 5769 } 5770 5771 @Test testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks()5772 public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() throws Exception { 5773 // Returns true by default when no network is available. 5774 assertTrue(mCm.isActiveNetworkMetered()); 5775 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 5776 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED); 5777 mCellNetworkAgent.connect(true); 5778 waitForIdle(); 5779 assertTrue(mCm.isActiveNetworkMetered()); 5780 5781 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 5782 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); 5783 mWiFiNetworkAgent.connect(true); 5784 waitForIdle(); 5785 assertFalse(mCm.isActiveNetworkMetered()); 5786 5787 // Connect VPN network. 5788 TestNetworkAgentWrapper 5789 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN); 5790 final ArraySet<UidRange> ranges = new ArraySet<>(); 5791 final int uid = Process.myUid(); 5792 ranges.add(new UidRange(uid, uid)); 5793 mMockVpn.setNetworkAgent(vpnNetworkAgent); 5794 mMockVpn.setUids(ranges); 5795 vpnNetworkAgent.connect(true); 5796 mMockVpn.connect(); 5797 waitForIdle(); 5798 // Ensure VPN is now the active network. 5799 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 5800 // VPN is using Cell 5801 mService.setUnderlyingNetworksForVpn( 5802 new Network[] { mCellNetworkAgent.getNetwork() }); 5803 waitForIdle(); 5804 5805 // Expect VPN to be metered. 5806 assertTrue(mCm.isActiveNetworkMetered()); 5807 5808 // VPN is now using WiFi 5809 mService.setUnderlyingNetworksForVpn( 5810 new Network[] { mWiFiNetworkAgent.getNetwork() }); 5811 waitForIdle(); 5812 5813 // Expect VPN to be unmetered 5814 assertFalse(mCm.isActiveNetworkMetered()); 5815 5816 // VPN is using Cell | WiFi. 5817 mService.setUnderlyingNetworksForVpn( 5818 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() }); 5819 waitForIdle(); 5820 5821 // Expect VPN to be metered. 5822 assertTrue(mCm.isActiveNetworkMetered()); 5823 5824 // VPN is using WiFi | Cell. 5825 mService.setUnderlyingNetworksForVpn( 5826 new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() }); 5827 waitForIdle(); 5828 5829 // Order should not matter and VPN should still be metered. 5830 assertTrue(mCm.isActiveNetworkMetered()); 5831 5832 // VPN is not using any underlying networks. 5833 mService.setUnderlyingNetworksForVpn(new Network[0]); 5834 waitForIdle(); 5835 5836 // VPN without underlying networks is treated as metered. 5837 assertTrue(mCm.isActiveNetworkMetered()); 5838 5839 vpnNetworkAgent.disconnect(); 5840 mMockVpn.disconnect(); 5841 } 5842 5843 @Test testIsActiveNetworkMeteredOverAlwaysMeteredVpn()5844 public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() throws Exception { 5845 // Returns true by default when no network is available. 5846 assertTrue(mCm.isActiveNetworkMetered()); 5847 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 5848 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); 5849 mWiFiNetworkAgent.connect(true); 5850 waitForIdle(); 5851 assertFalse(mCm.isActiveNetworkMetered()); 5852 5853 // Connect VPN network. 5854 TestNetworkAgentWrapper 5855 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN); 5856 final ArraySet<UidRange> ranges = new ArraySet<>(); 5857 final int uid = Process.myUid(); 5858 ranges.add(new UidRange(uid, uid)); 5859 mMockVpn.setNetworkAgent(vpnNetworkAgent); 5860 mMockVpn.setUids(ranges); 5861 vpnNetworkAgent.connect(true); 5862 mMockVpn.connectAsAlwaysMetered(); 5863 waitForIdle(); 5864 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 5865 5866 // VPN is tracking current platform default (WiFi). 5867 mService.setUnderlyingNetworksForVpn(null); 5868 waitForIdle(); 5869 5870 // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered. 5871 assertTrue(mCm.isActiveNetworkMetered()); 5872 5873 // VPN explicitly declares WiFi as its underlying network. 5874 mService.setUnderlyingNetworksForVpn( 5875 new Network[] { mWiFiNetworkAgent.getNetwork() }); 5876 waitForIdle(); 5877 5878 // Doesn't really matter whether VPN declares its underlying networks explicitly. 5879 assertTrue(mCm.isActiveNetworkMetered()); 5880 5881 // With WiFi lost, VPN is basically without any underlying networks. And in that case it is 5882 // anyways suppose to be metered. 5883 mWiFiNetworkAgent.disconnect(); 5884 waitForIdle(); 5885 5886 assertTrue(mCm.isActiveNetworkMetered()); 5887 5888 vpnNetworkAgent.disconnect(); 5889 } 5890 5891 @Test testNetworkBlockedStatus()5892 public void testNetworkBlockedStatus() throws Exception { 5893 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 5894 final NetworkRequest cellRequest = new NetworkRequest.Builder() 5895 .addTransportType(TRANSPORT_CELLULAR) 5896 .build(); 5897 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback); 5898 5899 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 5900 mCellNetworkAgent.connect(true); 5901 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 5902 5903 setUidRulesChanged(RULE_REJECT_ALL); 5904 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent); 5905 5906 // ConnectivityService should cache it not to invoke the callback again. 5907 setUidRulesChanged(RULE_REJECT_METERED); 5908 cellNetworkCallback.assertNoCallback(); 5909 5910 setUidRulesChanged(RULE_NONE); 5911 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent); 5912 5913 setUidRulesChanged(RULE_REJECT_METERED); 5914 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent); 5915 5916 // Restrict the network based on UID rule and NOT_METERED capability change. 5917 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); 5918 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent); 5919 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent); 5920 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED); 5921 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, 5922 mCellNetworkAgent); 5923 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent); 5924 setUidRulesChanged(RULE_ALLOW_METERED); 5925 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent); 5926 5927 setUidRulesChanged(RULE_NONE); 5928 cellNetworkCallback.assertNoCallback(); 5929 5930 // Restrict the network based on BackgroundRestricted. 5931 setRestrictBackgroundChanged(true); 5932 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent); 5933 setRestrictBackgroundChanged(true); 5934 cellNetworkCallback.assertNoCallback(); 5935 setRestrictBackgroundChanged(false); 5936 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent); 5937 cellNetworkCallback.assertNoCallback(); 5938 5939 mCm.unregisterNetworkCallback(cellNetworkCallback); 5940 } 5941 5942 @Test testNetworkBlockedStatusBeforeAndAfterConnect()5943 public void testNetworkBlockedStatusBeforeAndAfterConnect() throws Exception { 5944 final TestNetworkCallback defaultCallback = new TestNetworkCallback(); 5945 mCm.registerDefaultNetworkCallback(defaultCallback); 5946 5947 // No Networkcallbacks invoked before any network is active. 5948 setUidRulesChanged(RULE_REJECT_ALL); 5949 setUidRulesChanged(RULE_NONE); 5950 setUidRulesChanged(RULE_REJECT_METERED); 5951 defaultCallback.assertNoCallback(); 5952 5953 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 5954 mCellNetworkAgent.connect(true); 5955 defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent); 5956 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent); 5957 5958 // Allow to use the network after switching to NOT_METERED network. 5959 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 5960 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); 5961 mWiFiNetworkAgent.connect(true); 5962 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 5963 5964 // Switch to METERED network. Restrict the use of the network. 5965 mWiFiNetworkAgent.disconnect(); 5966 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 5967 defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent); 5968 5969 // Network becomes NOT_METERED. 5970 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); 5971 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent); 5972 defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent); 5973 5974 // Verify there's no Networkcallbacks invoked after data saver on/off. 5975 setRestrictBackgroundChanged(true); 5976 setRestrictBackgroundChanged(false); 5977 defaultCallback.assertNoCallback(); 5978 5979 mCellNetworkAgent.disconnect(); 5980 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); 5981 defaultCallback.assertNoCallback(); 5982 5983 mCm.unregisterNetworkCallback(defaultCallback); 5984 } 5985 5986 @Test testLoseTrusted()5987 public final void testLoseTrusted() throws Exception { 5988 final NetworkRequest trustedRequest = new NetworkRequest.Builder() 5989 .addCapability(NET_CAPABILITY_TRUSTED) 5990 .build(); 5991 final TestNetworkCallback trustedCallback = new TestNetworkCallback(); 5992 mCm.requestNetwork(trustedRequest, trustedCallback); 5993 5994 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 5995 mCellNetworkAgent.connect(true); 5996 trustedCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 5997 verify(mNetworkManagementService).setDefaultNetId(eq(mCellNetworkAgent.getNetwork().netId)); 5998 reset(mNetworkManagementService); 5999 6000 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 6001 mWiFiNetworkAgent.connect(true); 6002 trustedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 6003 verify(mNetworkManagementService).setDefaultNetId(eq(mWiFiNetworkAgent.getNetwork().netId)); 6004 reset(mNetworkManagementService); 6005 6006 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED); 6007 trustedCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 6008 verify(mNetworkManagementService).setDefaultNetId(eq(mCellNetworkAgent.getNetwork().netId)); 6009 reset(mNetworkManagementService); 6010 6011 mCellNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED); 6012 trustedCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); 6013 verify(mNetworkManagementService).clearDefaultNetId(); 6014 6015 mCm.unregisterNetworkCallback(trustedCallback); 6016 } 6017 6018 @Ignore // 40%+ flakiness : figure out why and re-enable. 6019 @Test testBatteryStatsNetworkType()6020 public final void testBatteryStatsNetworkType() throws Exception { 6021 final LinkProperties cellLp = new LinkProperties(); 6022 cellLp.setInterfaceName("cell0"); 6023 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp); 6024 mCellNetworkAgent.connect(true); 6025 waitForIdle(); 6026 verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(), 6027 TYPE_MOBILE); 6028 reset(mBatteryStatsService); 6029 6030 final LinkProperties wifiLp = new LinkProperties(); 6031 wifiLp.setInterfaceName("wifi0"); 6032 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp); 6033 mWiFiNetworkAgent.connect(true); 6034 waitForIdle(); 6035 verify(mBatteryStatsService).noteNetworkInterfaceType(wifiLp.getInterfaceName(), 6036 TYPE_WIFI); 6037 reset(mBatteryStatsService); 6038 6039 mCellNetworkAgent.disconnect(); 6040 6041 cellLp.setInterfaceName("wifi0"); 6042 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp); 6043 mCellNetworkAgent.connect(true); 6044 waitForIdle(); 6045 verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(), 6046 TYPE_MOBILE); 6047 } 6048 6049 /** 6050 * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info. 6051 */ getClatInterfaceConfig(LinkAddress la)6052 private InterfaceConfiguration getClatInterfaceConfig(LinkAddress la) { 6053 InterfaceConfiguration cfg = new InterfaceConfiguration(); 6054 cfg.setHardwareAddress("11:22:33:44:55:66"); 6055 cfg.setLinkAddress(la); 6056 return cfg; 6057 } 6058 6059 /** 6060 * Make expected stack link properties, copied from Nat464Xlat. 6061 */ makeClatLinkProperties(LinkAddress la)6062 private LinkProperties makeClatLinkProperties(LinkAddress la) { 6063 LinkAddress clatAddress = la; 6064 LinkProperties stacked = new LinkProperties(); 6065 stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME); 6066 RouteInfo ipv4Default = new RouteInfo( 6067 new LinkAddress(Inet4Address.ANY, 0), 6068 clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME); 6069 stacked.addRoute(ipv4Default); 6070 stacked.addLinkAddress(clatAddress); 6071 return stacked; 6072 } 6073 6074 @Test testStackedLinkProperties()6075 public void testStackedLinkProperties() throws Exception { 6076 final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24"); 6077 final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64"); 6078 final String kNat64PrefixString = "2001:db8:64:64:64:64::"; 6079 final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96); 6080 final String kOtherNat64PrefixString = "64:ff9b::"; 6081 final IpPrefix kOtherNat64Prefix = new IpPrefix( 6082 InetAddress.getByName(kOtherNat64PrefixString), 96); 6083 final RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, myIpv6.getAddress(), 6084 MOBILE_IFNAME); 6085 final RouteInfo ipv6Subnet = new RouteInfo(myIpv6, null, MOBILE_IFNAME); 6086 final RouteInfo ipv4Subnet = new RouteInfo(myIpv4, null, MOBILE_IFNAME); 6087 final RouteInfo stackedDefault = new RouteInfo((IpPrefix) null, myIpv4.getAddress(), 6088 CLAT_PREFIX + MOBILE_IFNAME); 6089 6090 final NetworkRequest networkRequest = new NetworkRequest.Builder() 6091 .addTransportType(TRANSPORT_CELLULAR) 6092 .addCapability(NET_CAPABILITY_INTERNET) 6093 .build(); 6094 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 6095 mCm.registerNetworkCallback(networkRequest, networkCallback); 6096 6097 // Prepare ipv6 only link properties. 6098 final LinkProperties cellLp = new LinkProperties(); 6099 cellLp.setInterfaceName(MOBILE_IFNAME); 6100 cellLp.addLinkAddress(myIpv6); 6101 cellLp.addRoute(defaultRoute); 6102 cellLp.addRoute(ipv6Subnet); 6103 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp); 6104 reset(mNetworkManagementService); 6105 reset(mMockDnsResolver); 6106 reset(mMockNetd); 6107 reset(mBatteryStatsService); 6108 6109 // Connect with ipv6 link properties. Expect prefix discovery to be started. 6110 mCellNetworkAgent.connect(true); 6111 final int cellNetId = mCellNetworkAgent.getNetwork().netId; 6112 waitForIdle(); 6113 6114 verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt()); 6115 assertRoutesAdded(cellNetId, ipv6Subnet, defaultRoute); 6116 verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId)); 6117 verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(), 6118 TYPE_MOBILE); 6119 6120 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 6121 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId); 6122 6123 // Switching default network updates TCP buffer sizes. 6124 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES); 6125 6126 // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that 6127 // the NAT64 prefix was removed because one was never discovered. 6128 cellLp.addLinkAddress(myIpv4); 6129 mCellNetworkAgent.sendLinkProperties(cellLp); 6130 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); 6131 assertRoutesAdded(cellNetId, ipv4Subnet); 6132 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId); 6133 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any()); 6134 6135 // Make sure BatteryStats was not told about any v4- interfaces, as none should have 6136 // come online yet. 6137 waitForIdle(); 6138 verify(mBatteryStatsService, never()).noteNetworkInterfaceType(startsWith("v4-"), anyInt()); 6139 6140 verifyNoMoreInteractions(mMockNetd); 6141 verifyNoMoreInteractions(mMockDnsResolver); 6142 reset(mNetworkManagementService); 6143 reset(mMockNetd); 6144 reset(mMockDnsResolver); 6145 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME)) 6146 .thenReturn(getClatInterfaceConfig(myIpv4)); 6147 6148 // Remove IPv4 address. Expect prefix discovery to be started again. 6149 cellLp.removeLinkAddress(myIpv4); 6150 mCellNetworkAgent.sendLinkProperties(cellLp); 6151 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); 6152 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId); 6153 assertRoutesRemoved(cellNetId, ipv4Subnet); 6154 6155 // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started. 6156 Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent); 6157 assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix()); 6158 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */, 6159 kNat64PrefixString, 96); 6160 LinkProperties lpBeforeClat = networkCallback.expectCallback( 6161 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent).getLp(); 6162 assertEquals(0, lpBeforeClat.getStackedLinks().size()); 6163 assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix()); 6164 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString()); 6165 6166 // Clat iface comes up. Expect stacked link to be added. 6167 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true); 6168 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); 6169 List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork()) 6170 .getStackedLinks(); 6171 assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0)); 6172 assertRoutesAdded(cellNetId, stackedDefault); 6173 6174 // Change trivial linkproperties and see if stacked link is preserved. 6175 cellLp.addDnsServer(InetAddress.getByName("8.8.8.8")); 6176 mCellNetworkAgent.sendLinkProperties(cellLp); 6177 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); 6178 6179 List<LinkProperties> stackedLpsAfterChange = 6180 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks(); 6181 assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST); 6182 assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0)); 6183 6184 verify(mMockDnsResolver, times(1)).setResolverConfiguration( 6185 mResolverParamsParcelCaptor.capture()); 6186 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue(); 6187 assertEquals(1, resolvrParams.servers.length); 6188 assertTrue(ArrayUtils.contains(resolvrParams.servers, "8.8.8.8")); 6189 6190 for (final LinkProperties stackedLp : stackedLpsAfterChange) { 6191 verify(mBatteryStatsService).noteNetworkInterfaceType(stackedLp.getInterfaceName(), 6192 TYPE_MOBILE); 6193 } 6194 reset(mMockNetd); 6195 6196 // Change the NAT64 prefix without first removing it. 6197 // Expect clatd to be stopped and started with the new prefix. 6198 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */, 6199 kOtherNat64PrefixString, 96); 6200 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, 6201 (lp) -> lp.getStackedLinks().size() == 0); 6202 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME); 6203 assertRoutesRemoved(cellNetId, stackedDefault); 6204 6205 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kOtherNat64Prefix.toString()); 6206 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, 6207 (lp) -> lp.getNat64Prefix().equals(kOtherNat64Prefix)); 6208 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true); 6209 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, 6210 (lp) -> lp.getStackedLinks().size() == 1); 6211 assertRoutesAdded(cellNetId, stackedDefault); 6212 reset(mMockNetd); 6213 6214 // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked 6215 // linkproperties are cleaned up. 6216 cellLp.addLinkAddress(myIpv4); 6217 cellLp.addRoute(ipv4Subnet); 6218 mCellNetworkAgent.sendLinkProperties(cellLp); 6219 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); 6220 assertRoutesAdded(cellNetId, ipv4Subnet); 6221 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME); 6222 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId); 6223 6224 // As soon as stop is called, the linkproperties lose the stacked interface. 6225 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); 6226 LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork()); 6227 LinkProperties expected = new LinkProperties(cellLp); 6228 expected.setNat64Prefix(kOtherNat64Prefix); 6229 assertEquals(expected, actualLpAfterIpv4); 6230 assertEquals(0, actualLpAfterIpv4.getStackedLinks().size()); 6231 assertRoutesRemoved(cellNetId, stackedDefault); 6232 6233 // The interface removed callback happens but has no effect after stop is called. 6234 clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME); 6235 networkCallback.assertNoCallback(); 6236 6237 verifyNoMoreInteractions(mMockNetd); 6238 verifyNoMoreInteractions(mMockDnsResolver); 6239 reset(mNetworkManagementService); 6240 reset(mMockNetd); 6241 reset(mMockDnsResolver); 6242 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME)) 6243 .thenReturn(getClatInterfaceConfig(myIpv4)); 6244 6245 // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone. 6246 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */, 6247 kOtherNat64PrefixString, 96); 6248 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, 6249 (lp) -> lp.getNat64Prefix() == null); 6250 6251 // Remove IPv4 address and expect prefix discovery and clatd to be started again. 6252 cellLp.removeLinkAddress(myIpv4); 6253 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME)); 6254 cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8")); 6255 mCellNetworkAgent.sendLinkProperties(cellLp); 6256 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); 6257 assertRoutesRemoved(cellNetId, ipv4Subnet); // Directly-connected routes auto-added. 6258 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId); 6259 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */, 6260 kNat64PrefixString, 96); 6261 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); 6262 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString()); 6263 6264 // Clat iface comes up. Expect stacked link to be added. 6265 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true); 6266 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, 6267 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null); 6268 assertRoutesAdded(cellNetId, stackedDefault); 6269 6270 // NAT64 prefix is removed. Expect that clat is stopped. 6271 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */, 6272 kNat64PrefixString, 96); 6273 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, 6274 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null); 6275 assertRoutesRemoved(cellNetId, ipv4Subnet, stackedDefault); 6276 6277 // Stop has no effect because clat is already stopped. 6278 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME); 6279 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, 6280 (lp) -> lp.getStackedLinks().size() == 0); 6281 verifyNoMoreInteractions(mMockNetd); 6282 6283 // Clean up. 6284 mCellNetworkAgent.disconnect(); 6285 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); 6286 networkCallback.assertNoCallback(); 6287 mCm.unregisterNetworkCallback(networkCallback); 6288 } 6289 expectNat64PrefixChange(TestableNetworkCallback callback, TestNetworkAgentWrapper agent, IpPrefix prefix)6290 private void expectNat64PrefixChange(TestableNetworkCallback callback, 6291 TestNetworkAgentWrapper agent, IpPrefix prefix) { 6292 callback.expectLinkPropertiesThat(agent, x -> Objects.equals(x.getNat64Prefix(), prefix)); 6293 } 6294 6295 @Test testNat64PrefixMultipleSources()6296 public void testNat64PrefixMultipleSources() throws Exception { 6297 final String iface = "wlan0"; 6298 final String pref64FromRaStr = "64:ff9b::"; 6299 final String pref64FromDnsStr = "2001:db8:64::"; 6300 final IpPrefix pref64FromRa = new IpPrefix(InetAddress.getByName(pref64FromRaStr), 96); 6301 final IpPrefix pref64FromDns = new IpPrefix(InetAddress.getByName(pref64FromDnsStr), 96); 6302 final IpPrefix newPref64FromRa = new IpPrefix("2001:db8:64:64:64:64::/96"); 6303 6304 final NetworkRequest request = new NetworkRequest.Builder() 6305 .addCapability(NET_CAPABILITY_INTERNET) 6306 .build(); 6307 final TestNetworkCallback callback = new TestNetworkCallback(); 6308 mCm.registerNetworkCallback(request, callback); 6309 6310 final LinkProperties baseLp = new LinkProperties(); 6311 baseLp.setInterfaceName(iface); 6312 baseLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64")); 6313 baseLp.addDnsServer(InetAddress.getByName("2001:4860:4860::6464")); 6314 6315 reset(mMockNetd, mMockDnsResolver); 6316 InOrder inOrder = inOrder(mMockNetd, mMockDnsResolver); 6317 6318 // If a network already has a NAT64 prefix on connect, clatd is started immediately and 6319 // prefix discovery is never started. 6320 LinkProperties lp = new LinkProperties(baseLp); 6321 lp.setNat64Prefix(pref64FromRa); 6322 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp); 6323 mCellNetworkAgent.connect(false); 6324 final Network network = mCellNetworkAgent.getNetwork(); 6325 int netId = network.getNetId(); 6326 callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); 6327 inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString()); 6328 inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString()); 6329 inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); 6330 callback.assertNoCallback(); 6331 assertEquals(pref64FromRa, mCm.getLinkProperties(network).getNat64Prefix()); 6332 6333 // If the RA prefix is withdrawn, clatd is stopped and prefix discovery is started. 6334 lp.setNat64Prefix(null); 6335 mCellNetworkAgent.sendLinkProperties(lp); 6336 expectNat64PrefixChange(callback, mCellNetworkAgent, null); 6337 inOrder.verify(mMockNetd).clatdStop(iface); 6338 inOrder.verify(mMockDnsResolver).setPrefix64(netId, ""); 6339 inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId); 6340 6341 // If the RA prefix appears while DNS discovery is in progress, discovery is stopped and 6342 // clatd is started with the prefix from the RA. 6343 lp.setNat64Prefix(pref64FromRa); 6344 mCellNetworkAgent.sendLinkProperties(lp); 6345 expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromRa); 6346 inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString()); 6347 inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId); 6348 inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString()); 6349 6350 // Withdraw the RA prefix so we can test the case where an RA prefix appears after DNS 6351 // discovery has succeeded. 6352 lp.setNat64Prefix(null); 6353 mCellNetworkAgent.sendLinkProperties(lp); 6354 expectNat64PrefixChange(callback, mCellNetworkAgent, null); 6355 inOrder.verify(mMockNetd).clatdStop(iface); 6356 inOrder.verify(mMockDnsResolver).setPrefix64(netId, ""); 6357 inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId); 6358 6359 mService.mNetdEventCallback.onNat64PrefixEvent(netId, true /* added */, 6360 pref64FromDnsStr, 96); 6361 expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromDns); 6362 inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString()); 6363 6364 // If an RA advertises the same prefix that was discovered by DNS, nothing happens: prefix 6365 // discovery is not stopped, and there are no callbacks. 6366 lp.setNat64Prefix(pref64FromDns); 6367 mCellNetworkAgent.sendLinkProperties(lp); 6368 callback.assertNoCallback(); 6369 inOrder.verify(mMockNetd, never()).clatdStop(iface); 6370 inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString()); 6371 inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); 6372 inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); 6373 inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString()); 6374 6375 // If the RA is later withdrawn, nothing happens again. 6376 lp.setNat64Prefix(null); 6377 mCellNetworkAgent.sendLinkProperties(lp); 6378 callback.assertNoCallback(); 6379 inOrder.verify(mMockNetd, never()).clatdStop(iface); 6380 inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString()); 6381 inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); 6382 inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); 6383 inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString()); 6384 6385 // If the RA prefix changes, clatd is restarted and prefix discovery is stopped. 6386 lp.setNat64Prefix(pref64FromRa); 6387 mCellNetworkAgent.sendLinkProperties(lp); 6388 expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromRa); 6389 inOrder.verify(mMockNetd).clatdStop(iface); 6390 inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId); 6391 6392 // Stopping prefix discovery results in a prefix removed notification. 6393 mService.mNetdEventCallback.onNat64PrefixEvent(netId, false /* added */, 6394 pref64FromDnsStr, 96); 6395 6396 inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString()); 6397 inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString()); 6398 inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); 6399 6400 // If the RA prefix changes, clatd is restarted and prefix discovery is not started. 6401 lp.setNat64Prefix(newPref64FromRa); 6402 mCellNetworkAgent.sendLinkProperties(lp); 6403 expectNat64PrefixChange(callback, mCellNetworkAgent, newPref64FromRa); 6404 inOrder.verify(mMockNetd).clatdStop(iface); 6405 inOrder.verify(mMockDnsResolver).setPrefix64(netId, ""); 6406 inOrder.verify(mMockNetd).clatdStart(iface, newPref64FromRa.toString()); 6407 inOrder.verify(mMockDnsResolver).setPrefix64(netId, newPref64FromRa.toString()); 6408 inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); 6409 inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); 6410 6411 // If the RA prefix changes to the same value, nothing happens. 6412 lp.setNat64Prefix(newPref64FromRa); 6413 mCellNetworkAgent.sendLinkProperties(lp); 6414 callback.assertNoCallback(); 6415 assertEquals(newPref64FromRa, mCm.getLinkProperties(network).getNat64Prefix()); 6416 inOrder.verify(mMockNetd, never()).clatdStop(iface); 6417 inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString()); 6418 inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); 6419 inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); 6420 inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString()); 6421 6422 // The transition between no prefix and DNS prefix is tested in testStackedLinkProperties. 6423 6424 // If the same prefix is learned first by DNS and then by RA, and clat is later stopped, 6425 // (e.g., because the network disconnects) setPrefix64(netid, "") is never called. 6426 lp.setNat64Prefix(null); 6427 mCellNetworkAgent.sendLinkProperties(lp); 6428 expectNat64PrefixChange(callback, mCellNetworkAgent, null); 6429 inOrder.verify(mMockNetd).clatdStop(iface); 6430 inOrder.verify(mMockDnsResolver).setPrefix64(netId, ""); 6431 inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId); 6432 mService.mNetdEventCallback.onNat64PrefixEvent(netId, true /* added */, 6433 pref64FromDnsStr, 96); 6434 expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromDns); 6435 inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString()); 6436 inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), any()); 6437 6438 lp.setNat64Prefix(pref64FromDns); 6439 mCellNetworkAgent.sendLinkProperties(lp); 6440 callback.assertNoCallback(); 6441 inOrder.verify(mMockNetd, never()).clatdStop(iface); 6442 inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString()); 6443 inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); 6444 inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); 6445 inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString()); 6446 6447 // When tearing down a network, clat state is only updated after CALLBACK_LOST is fired, but 6448 // before CONNECTIVITY_ACTION is sent. Wait for CONNECTIVITY_ACTION before verifying that 6449 // clat has been stopped, or the test will be flaky. 6450 ConditionVariable cv = registerConnectivityBroadcast(1); 6451 mCellNetworkAgent.disconnect(); 6452 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); 6453 waitFor(cv); 6454 6455 inOrder.verify(mMockNetd).clatdStop(iface); 6456 inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId); 6457 inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString()); 6458 6459 mCm.unregisterNetworkCallback(callback); 6460 } 6461 6462 @Test testDataActivityTracking()6463 public void testDataActivityTracking() throws Exception { 6464 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 6465 final NetworkRequest networkRequest = new NetworkRequest.Builder() 6466 .addCapability(NET_CAPABILITY_INTERNET) 6467 .build(); 6468 mCm.registerNetworkCallback(networkRequest, networkCallback); 6469 6470 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 6471 final LinkProperties cellLp = new LinkProperties(); 6472 cellLp.setInterfaceName(MOBILE_IFNAME); 6473 mCellNetworkAgent.sendLinkProperties(cellLp); 6474 reset(mNetworkManagementService); 6475 mCellNetworkAgent.connect(true); 6476 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 6477 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(), 6478 eq(ConnectivityManager.TYPE_MOBILE)); 6479 6480 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 6481 final LinkProperties wifiLp = new LinkProperties(); 6482 wifiLp.setInterfaceName(WIFI_IFNAME); 6483 mWiFiNetworkAgent.sendLinkProperties(wifiLp); 6484 6485 // Network switch 6486 reset(mNetworkManagementService); 6487 mWiFiNetworkAgent.connect(true); 6488 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 6489 networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); 6490 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 6491 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(), 6492 eq(ConnectivityManager.TYPE_WIFI)); 6493 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME)); 6494 6495 // Disconnect wifi and switch back to cell 6496 reset(mNetworkManagementService); 6497 mWiFiNetworkAgent.disconnect(); 6498 networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 6499 assertNoCallbacks(networkCallback); 6500 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME)); 6501 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(), 6502 eq(ConnectivityManager.TYPE_MOBILE)); 6503 6504 // reconnect wifi 6505 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 6506 wifiLp.setInterfaceName(WIFI_IFNAME); 6507 mWiFiNetworkAgent.sendLinkProperties(wifiLp); 6508 mWiFiNetworkAgent.connect(true); 6509 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 6510 networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); 6511 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 6512 6513 // Disconnect cell 6514 reset(mNetworkManagementService); 6515 reset(mMockNetd); 6516 mCellNetworkAgent.disconnect(); 6517 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); 6518 // LOST callback is triggered earlier than removing idle timer. Broadcast should also be 6519 // sent as network being switched. Ensure rule removal for cell will not be triggered 6520 // unexpectedly before network being removed. 6521 waitForIdle(); 6522 verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME)); 6523 verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId)); 6524 verify(mMockDnsResolver, times(1)) 6525 .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId)); 6526 6527 // Disconnect wifi 6528 ConditionVariable cv = registerConnectivityBroadcast(1); 6529 reset(mNetworkManagementService); 6530 mWiFiNetworkAgent.disconnect(); 6531 waitFor(cv); 6532 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME)); 6533 6534 // Clean up 6535 mCm.unregisterNetworkCallback(networkCallback); 6536 } 6537 verifyTcpBufferSizeChange(String tcpBufferSizes)6538 private void verifyTcpBufferSizeChange(String tcpBufferSizes) throws Exception { 6539 String[] values = tcpBufferSizes.split(","); 6540 String rmemValues = String.join(" ", values[0], values[1], values[2]); 6541 String wmemValues = String.join(" ", values[3], values[4], values[5]); 6542 verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues); 6543 reset(mMockNetd); 6544 } 6545 6546 @Test testTcpBufferReset()6547 public void testTcpBufferReset() throws Exception { 6548 final String testTcpBufferSizes = "1,2,3,4,5,6"; 6549 final NetworkRequest networkRequest = new NetworkRequest.Builder() 6550 .addTransportType(TRANSPORT_CELLULAR) 6551 .addCapability(NET_CAPABILITY_INTERNET) 6552 .build(); 6553 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 6554 mCm.registerNetworkCallback(networkRequest, networkCallback); 6555 6556 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 6557 reset(mMockNetd); 6558 // Switching default network updates TCP buffer sizes. 6559 mCellNetworkAgent.connect(false); 6560 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); 6561 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES); 6562 6563 // Change link Properties should have updated tcp buffer size. 6564 LinkProperties lp = new LinkProperties(); 6565 lp.setTcpBufferSizes(testTcpBufferSizes); 6566 mCellNetworkAgent.sendLinkProperties(lp); 6567 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); 6568 verifyTcpBufferSizeChange(testTcpBufferSizes); 6569 6570 // Clean up. 6571 mCellNetworkAgent.disconnect(); 6572 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); 6573 networkCallback.assertNoCallback(); 6574 mCm.unregisterNetworkCallback(networkCallback); 6575 } 6576 6577 @Test testGetGlobalProxyForNetwork()6578 public void testGetGlobalProxyForNetwork() throws Exception { 6579 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888); 6580 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 6581 final Network wifiNetwork = mWiFiNetworkAgent.getNetwork(); 6582 when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo); 6583 assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork)); 6584 } 6585 6586 @Test testGetProxyForActiveNetwork()6587 public void testGetProxyForActiveNetwork() throws Exception { 6588 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888); 6589 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 6590 mWiFiNetworkAgent.connect(true); 6591 waitForIdle(); 6592 assertNull(mService.getProxyForNetwork(null)); 6593 6594 final LinkProperties testLinkProperties = new LinkProperties(); 6595 testLinkProperties.setHttpProxy(testProxyInfo); 6596 6597 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties); 6598 waitForIdle(); 6599 6600 assertEquals(testProxyInfo, mService.getProxyForNetwork(null)); 6601 } 6602 6603 @Test testGetProxyForVPN()6604 public void testGetProxyForVPN() throws Exception { 6605 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888); 6606 6607 // Set up a WiFi network with no proxy 6608 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 6609 mWiFiNetworkAgent.connect(true); 6610 waitForIdle(); 6611 assertNull(mService.getProxyForNetwork(null)); 6612 6613 // Set up a VPN network with a proxy 6614 final int uid = Process.myUid(); 6615 final TestNetworkAgentWrapper 6616 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN); 6617 final ArraySet<UidRange> ranges = new ArraySet<>(); 6618 ranges.add(new UidRange(uid, uid)); 6619 mMockVpn.setUids(ranges); 6620 LinkProperties testLinkProperties = new LinkProperties(); 6621 testLinkProperties.setHttpProxy(testProxyInfo); 6622 vpnNetworkAgent.sendLinkProperties(testLinkProperties); 6623 waitForIdle(); 6624 6625 // Connect to VPN with proxy 6626 mMockVpn.setNetworkAgent(vpnNetworkAgent); 6627 vpnNetworkAgent.connect(true); 6628 mMockVpn.connect(); 6629 waitForIdle(); 6630 6631 // Test that the VPN network returns a proxy, and the WiFi does not. 6632 assertEquals(testProxyInfo, mService.getProxyForNetwork(vpnNetworkAgent.getNetwork())); 6633 assertEquals(testProxyInfo, mService.getProxyForNetwork(null)); 6634 assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork())); 6635 6636 // Test that the VPN network returns no proxy when it is set to null. 6637 testLinkProperties.setHttpProxy(null); 6638 vpnNetworkAgent.sendLinkProperties(testLinkProperties); 6639 waitForIdle(); 6640 assertNull(mService.getProxyForNetwork(vpnNetworkAgent.getNetwork())); 6641 assertNull(mService.getProxyForNetwork(null)); 6642 6643 // Set WiFi proxy and check that the vpn proxy is still null. 6644 testLinkProperties.setHttpProxy(testProxyInfo); 6645 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties); 6646 waitForIdle(); 6647 assertNull(mService.getProxyForNetwork(null)); 6648 6649 // Disconnect from VPN and check that the active network, which is now the WiFi, has the 6650 // correct proxy setting. 6651 vpnNetworkAgent.disconnect(); 6652 waitForIdle(); 6653 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 6654 assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork())); 6655 assertEquals(testProxyInfo, mService.getProxyForNetwork(null)); 6656 } 6657 6658 @Test testFullyRoutedVpnResultsInInterfaceFilteringRules()6659 public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception { 6660 LinkProperties lp = new LinkProperties(); 6661 lp.setInterfaceName("tun0"); 6662 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null)); 6663 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE)); 6664 // The uid range needs to cover the test app so the network is visible to it. 6665 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER)); 6666 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange); 6667 6668 // Connected VPN should have interface rules set up. There are two expected invocations, 6669 // one during VPN uid update, one during VPN LinkProperties update 6670 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class); 6671 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture()); 6672 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID); 6673 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID); 6674 assertTrue(mService.mPermissionMonitor.getVpnUidRanges("tun0").equals(vpnRange)); 6675 6676 vpnNetworkAgent.disconnect(); 6677 waitForIdle(); 6678 6679 // Disconnected VPN should have interface rules removed 6680 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture()); 6681 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID); 6682 assertNull(mService.mPermissionMonitor.getVpnUidRanges("tun0")); 6683 } 6684 6685 @Test testLegacyVpnDoesNotResultInInterfaceFilteringRule()6686 public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception { 6687 LinkProperties lp = new LinkProperties(); 6688 lp.setInterfaceName("tun0"); 6689 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); 6690 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null)); 6691 // The uid range needs to cover the test app so the network is visible to it. 6692 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER)); 6693 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn( 6694 lp, Process.SYSTEM_UID, vpnRange); 6695 6696 // Legacy VPN should not have interface rules set up 6697 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any()); 6698 } 6699 6700 @Test testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()6701 public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule() 6702 throws Exception { 6703 LinkProperties lp = new LinkProperties(); 6704 lp.setInterfaceName("tun0"); 6705 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0")); 6706 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE)); 6707 // The uid range needs to cover the test app so the network is visible to it. 6708 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER)); 6709 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn( 6710 lp, Process.SYSTEM_UID, vpnRange); 6711 6712 // IPv6 unreachable route should not be misinterpreted as a default route 6713 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any()); 6714 } 6715 6716 @Test testVpnHandoverChangesInterfaceFilteringRule()6717 public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception { 6718 LinkProperties lp = new LinkProperties(); 6719 lp.setInterfaceName("tun0"); 6720 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null)); 6721 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); 6722 // The uid range needs to cover the test app so the network is visible to it. 6723 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER)); 6724 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange); 6725 6726 // Connected VPN should have interface rules set up. There are two expected invocations, 6727 // one during VPN uid update, one during VPN LinkProperties update 6728 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class); 6729 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture()); 6730 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID); 6731 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID); 6732 6733 reset(mMockNetd); 6734 InOrder inOrder = inOrder(mMockNetd); 6735 lp.setInterfaceName("tun1"); 6736 vpnNetworkAgent.sendLinkProperties(lp); 6737 waitForIdle(); 6738 // VPN handover (switch to a new interface) should result in rules being updated (old rules 6739 // removed first, then new rules added) 6740 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture()); 6741 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID); 6742 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture()); 6743 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID); 6744 6745 reset(mMockNetd); 6746 lp = new LinkProperties(); 6747 lp.setInterfaceName("tun1"); 6748 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1")); 6749 vpnNetworkAgent.sendLinkProperties(lp); 6750 waitForIdle(); 6751 // VPN not routing everything should no longer have interface filtering rules 6752 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture()); 6753 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID); 6754 6755 reset(mMockNetd); 6756 lp = new LinkProperties(); 6757 lp.setInterfaceName("tun1"); 6758 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE)); 6759 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); 6760 vpnNetworkAgent.sendLinkProperties(lp); 6761 waitForIdle(); 6762 // Back to routing all IPv6 traffic should have filtering rules 6763 verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture()); 6764 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID); 6765 } 6766 6767 @Test testUidUpdateChangesInterfaceFilteringRule()6768 public void testUidUpdateChangesInterfaceFilteringRule() throws Exception { 6769 LinkProperties lp = new LinkProperties(); 6770 lp.setInterfaceName("tun0"); 6771 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE)); 6772 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); 6773 // The uid range needs to cover the test app so the network is visible to it. 6774 final UidRange vpnRange = UidRange.createForUser(VPN_USER); 6775 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, 6776 Collections.singleton(vpnRange)); 6777 6778 reset(mMockNetd); 6779 InOrder inOrder = inOrder(mMockNetd); 6780 6781 // Update to new range which is old range minus APP1, i.e. only APP2 6782 final Set<UidRange> newRanges = new HashSet<>(Arrays.asList( 6783 new UidRange(vpnRange.start, APP1_UID - 1), 6784 new UidRange(APP1_UID + 1, vpnRange.stop))); 6785 vpnNetworkAgent.setUids(newRanges); 6786 waitForIdle(); 6787 6788 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class); 6789 // Verify old rules are removed before new rules are added 6790 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture()); 6791 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID); 6792 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture()); 6793 assertContainsExactly(uidCaptor.getValue(), APP2_UID); 6794 } 6795 6796 @Test testLinkPropertiesWithWakeOnLanForActiveNetwork()6797 public void testLinkPropertiesWithWakeOnLanForActiveNetwork() throws Exception { 6798 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); 6799 6800 LinkProperties wifiLp = new LinkProperties(); 6801 wifiLp.setInterfaceName(WIFI_WOL_IFNAME); 6802 wifiLp.setWakeOnLanSupported(false); 6803 6804 // Default network switch should update ifaces. 6805 mWiFiNetworkAgent.connect(false); 6806 mWiFiNetworkAgent.sendLinkProperties(wifiLp); 6807 waitForIdle(); 6808 6809 // ConnectivityService should have changed the WakeOnLanSupported to true 6810 wifiLp.setWakeOnLanSupported(true); 6811 assertEquals(wifiLp, mService.getActiveLinkProperties()); 6812 } 6813 6814 @Test testLegacyExtraInfoSentToNetworkMonitor()6815 public void testLegacyExtraInfoSentToNetworkMonitor() throws Exception { 6816 class TestNetworkAgent extends NetworkAgent { 6817 TestNetworkAgent(Context context, Looper looper, NetworkAgentConfig config) { 6818 super(context, looper, "MockAgent", new NetworkCapabilities(), 6819 new LinkProperties(), 40 , config, null /* provider */); 6820 } 6821 } 6822 final NetworkAgent naNoExtraInfo = new TestNetworkAgent( 6823 mServiceContext, mCsHandlerThread.getLooper(), new NetworkAgentConfig()); 6824 naNoExtraInfo.register(); 6825 verify(mNetworkStack).makeNetworkMonitor(any(), isNull(String.class), any()); 6826 naNoExtraInfo.unregister(); 6827 6828 reset(mNetworkStack); 6829 final NetworkAgentConfig config = 6830 new NetworkAgentConfig.Builder().setLegacyExtraInfo("legacyinfo").build(); 6831 final NetworkAgent naExtraInfo = new TestNetworkAgent( 6832 mServiceContext, mCsHandlerThread.getLooper(), config); 6833 naExtraInfo.register(); 6834 verify(mNetworkStack).makeNetworkMonitor(any(), eq("legacyinfo"), any()); 6835 naExtraInfo.unregister(); 6836 } 6837 setupLocationPermissions( int targetSdk, boolean locationToggle, String op, String perm)6838 private void setupLocationPermissions( 6839 int targetSdk, boolean locationToggle, String op, String perm) throws Exception { 6840 final ApplicationInfo applicationInfo = new ApplicationInfo(); 6841 applicationInfo.targetSdkVersion = targetSdk; 6842 when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any())) 6843 .thenReturn(applicationInfo); 6844 6845 when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(locationToggle); 6846 6847 if (op != null) { 6848 when(mAppOpsManager.noteOp(eq(op), eq(Process.myUid()), eq(mContext.getPackageName()))) 6849 .thenReturn(AppOpsManager.MODE_ALLOWED); 6850 } 6851 6852 if (perm != null) { 6853 mServiceContext.setPermission(perm, PERMISSION_GRANTED); 6854 } 6855 } 6856 getOwnerUidNetCapsForCallerPermission(int ownerUid, int callerUid)6857 private int getOwnerUidNetCapsForCallerPermission(int ownerUid, int callerUid) { 6858 final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid); 6859 6860 return mService 6861 .maybeSanitizeLocationInfoForCaller(netCap, callerUid, mContext.getPackageName()) 6862 .getOwnerUid(); 6863 } 6864 6865 @Test testMaybeSanitizeLocationInfoForCallerWithFineLocationAfterQ()6866 public void testMaybeSanitizeLocationInfoForCallerWithFineLocationAfterQ() throws Exception { 6867 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, 6868 Manifest.permission.ACCESS_FINE_LOCATION); 6869 6870 final int myUid = Process.myUid(); 6871 assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); 6872 } 6873 6874 @Test testMaybeSanitizeLocationInfoForCallerWithCoarseLocationPreQ()6875 public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationPreQ() throws Exception { 6876 setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION, 6877 Manifest.permission.ACCESS_COARSE_LOCATION); 6878 6879 final int myUid = Process.myUid(); 6880 assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); 6881 } 6882 6883 @Test testMaybeSanitizeLocationInfoForCallerLocationOff()6884 public void testMaybeSanitizeLocationInfoForCallerLocationOff() throws Exception { 6885 // Test that even with fine location permission, and UIDs matching, the UID is sanitized. 6886 setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION, 6887 Manifest.permission.ACCESS_FINE_LOCATION); 6888 6889 final int myUid = Process.myUid(); 6890 assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); 6891 } 6892 6893 @Test testMaybeSanitizeLocationInfoForCallerWrongUid()6894 public void testMaybeSanitizeLocationInfoForCallerWrongUid() throws Exception { 6895 // Test that even with fine location permission, not being the owner leads to sanitization. 6896 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, 6897 Manifest.permission.ACCESS_FINE_LOCATION); 6898 6899 final int myUid = Process.myUid(); 6900 assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid + 1, myUid)); 6901 } 6902 6903 @Test testMaybeSanitizeLocationInfoForCallerWithCoarseLocationAfterQ()6904 public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationAfterQ() throws Exception { 6905 // Test that not having fine location permission leads to sanitization. 6906 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION, 6907 Manifest.permission.ACCESS_COARSE_LOCATION); 6908 6909 // Test that without the location permission, the owner field is sanitized. 6910 final int myUid = Process.myUid(); 6911 assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); 6912 } 6913 6914 @Test testMaybeSanitizeLocationInfoForCallerWithoutLocationPermission()6915 public void testMaybeSanitizeLocationInfoForCallerWithoutLocationPermission() throws Exception { 6916 setupLocationPermissions(Build.VERSION_CODES.Q, true, null /* op */, null /* perm */); 6917 6918 // Test that without the location permission, the owner field is sanitized. 6919 final int myUid = Process.myUid(); 6920 assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); 6921 } 6922 setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)6923 private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType) 6924 throws Exception { 6925 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER)); 6926 establishVpn(new LinkProperties(), vpnOwnerUid, vpnRange); 6927 mMockVpn.setVpnType(vpnType); 6928 6929 final VpnInfo vpnInfo = new VpnInfo(); 6930 vpnInfo.ownerUid = vpnOwnerUid; 6931 mMockVpn.setVpnInfo(vpnInfo); 6932 } 6933 setupConnectionOwnerUidAsVpnApp(int vpnOwnerUid, @VpnManager.VpnType int vpnType)6934 private void setupConnectionOwnerUidAsVpnApp(int vpnOwnerUid, @VpnManager.VpnType int vpnType) 6935 throws Exception { 6936 setupConnectionOwnerUid(vpnOwnerUid, vpnType); 6937 6938 // Test as VPN app 6939 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); 6940 mServiceContext.setPermission( 6941 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_DENIED); 6942 } 6943 getTestConnectionInfo()6944 private ConnectionInfo getTestConnectionInfo() throws Exception { 6945 return new ConnectionInfo( 6946 IPPROTO_TCP, 6947 new InetSocketAddress(InetAddresses.parseNumericAddress("1.2.3.4"), 1234), 6948 new InetSocketAddress(InetAddresses.parseNumericAddress("2.3.4.5"), 2345)); 6949 } 6950 6951 @Test testGetConnectionOwnerUidPlatformVpn()6952 public void testGetConnectionOwnerUidPlatformVpn() throws Exception { 6953 final int myUid = Process.myUid(); 6954 setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_PLATFORM); 6955 6956 try { 6957 mService.getConnectionOwnerUid(getTestConnectionInfo()); 6958 fail("Expected SecurityException for non-VpnService app"); 6959 } catch (SecurityException expected) { 6960 } 6961 } 6962 6963 @Test testGetConnectionOwnerUidVpnServiceWrongUser()6964 public void testGetConnectionOwnerUidVpnServiceWrongUser() throws Exception { 6965 final int myUid = Process.myUid(); 6966 setupConnectionOwnerUidAsVpnApp(myUid + 1, VpnManager.TYPE_VPN_SERVICE); 6967 6968 try { 6969 mService.getConnectionOwnerUid(getTestConnectionInfo()); 6970 fail("Expected SecurityException for non-VpnService app"); 6971 } catch (SecurityException expected) { 6972 } 6973 } 6974 6975 @Test testGetConnectionOwnerUidVpnServiceDoesNotThrow()6976 public void testGetConnectionOwnerUidVpnServiceDoesNotThrow() throws Exception { 6977 final int myUid = Process.myUid(); 6978 setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_SERVICE); 6979 6980 // TODO: Test the returned UID 6981 mService.getConnectionOwnerUid(getTestConnectionInfo()); 6982 } 6983 6984 @Test testGetConnectionOwnerUidVpnServiceNetworkStackDoesNotThrow()6985 public void testGetConnectionOwnerUidVpnServiceNetworkStackDoesNotThrow() throws Exception { 6986 final int myUid = Process.myUid(); 6987 setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE); 6988 mServiceContext.setPermission( 6989 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED); 6990 6991 // TODO: Test the returned UID 6992 mService.getConnectionOwnerUid(getTestConnectionInfo()); 6993 } 6994 6995 @Test testGetConnectionOwnerUidVpnServiceMainlineNetworkStackDoesNotThrow()6996 public void testGetConnectionOwnerUidVpnServiceMainlineNetworkStackDoesNotThrow() 6997 throws Exception { 6998 final int myUid = Process.myUid(); 6999 setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE); 7000 mServiceContext.setPermission( 7001 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_GRANTED); 7002 7003 // TODO: Test the returned UID 7004 mService.getConnectionOwnerUid(getTestConnectionInfo()); 7005 } 7006 establishVpn( LinkProperties lp, int ownerUid, Set<UidRange> vpnRange)7007 private TestNetworkAgentWrapper establishVpn( 7008 LinkProperties lp, int ownerUid, Set<UidRange> vpnRange) throws Exception { 7009 final TestNetworkAgentWrapper 7010 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp); 7011 vpnNetworkAgent.getNetworkCapabilities().setOwnerUid(ownerUid); 7012 mMockVpn.setNetworkAgent(vpnNetworkAgent); 7013 mMockVpn.connect(); 7014 mMockVpn.setUids(vpnRange); 7015 vpnNetworkAgent.connect(true); 7016 waitForIdle(); 7017 return vpnNetworkAgent; 7018 } 7019 buildPackageInfo(boolean hasSystemPermission, int uid)7020 private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) { 7021 final PackageInfo packageInfo = new PackageInfo(); 7022 if (hasSystemPermission) { 7023 packageInfo.requestedPermissions = new String[] { 7024 CHANGE_NETWORK_STATE, CONNECTIVITY_USE_RESTRICTED_NETWORKS }; 7025 packageInfo.requestedPermissionsFlags = new int[] { 7026 REQUESTED_PERMISSION_GRANTED, REQUESTED_PERMISSION_GRANTED }; 7027 } else { 7028 packageInfo.requestedPermissions = new String[0]; 7029 } 7030 packageInfo.applicationInfo = new ApplicationInfo(); 7031 packageInfo.applicationInfo.privateFlags = 0; 7032 packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM, 7033 UserHandle.getAppId(uid)); 7034 return packageInfo; 7035 } 7036 7037 @Test testRegisterConnectivityDiagnosticsCallbackInvalidRequest()7038 public void testRegisterConnectivityDiagnosticsCallbackInvalidRequest() throws Exception { 7039 final NetworkRequest request = 7040 new NetworkRequest( 7041 new NetworkCapabilities(), TYPE_ETHERNET, 0, NetworkRequest.Type.NONE); 7042 try { 7043 mService.registerConnectivityDiagnosticsCallback( 7044 mConnectivityDiagnosticsCallback, request, mContext.getPackageName()); 7045 fail("registerConnectivityDiagnosticsCallback should throw on invalid NetworkRequest"); 7046 } catch (IllegalArgumentException expected) { 7047 } 7048 } 7049 assertRouteInfoParcelMatches(RouteInfo route, RouteInfoParcel parcel)7050 private void assertRouteInfoParcelMatches(RouteInfo route, RouteInfoParcel parcel) { 7051 assertEquals(route.getDestination().toString(), parcel.destination); 7052 assertEquals(route.getInterface(), parcel.ifName); 7053 assertEquals(route.getMtu(), parcel.mtu); 7054 7055 switch (route.getType()) { 7056 case RouteInfo.RTN_UNICAST: 7057 if (route.hasGateway()) { 7058 assertEquals(route.getGateway().getHostAddress(), parcel.nextHop); 7059 } else { 7060 assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop); 7061 } 7062 break; 7063 case RouteInfo.RTN_UNREACHABLE: 7064 assertEquals(INetd.NEXTHOP_UNREACHABLE, parcel.nextHop); 7065 break; 7066 case RouteInfo.RTN_THROW: 7067 assertEquals(INetd.NEXTHOP_THROW, parcel.nextHop); 7068 break; 7069 default: 7070 assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop); 7071 break; 7072 } 7073 } 7074 assertRoutesAdded(int netId, RouteInfo... routes)7075 private void assertRoutesAdded(int netId, RouteInfo... routes) throws Exception { 7076 ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class); 7077 verify(mMockNetd, times(routes.length)).networkAddRouteParcel(eq(netId), captor.capture()); 7078 for (int i = 0; i < routes.length; i++) { 7079 assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i)); 7080 } 7081 } 7082 assertRoutesRemoved(int netId, RouteInfo... routes)7083 private void assertRoutesRemoved(int netId, RouteInfo... routes) throws Exception { 7084 ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class); 7085 verify(mMockNetd, times(routes.length)).networkRemoveRouteParcel(eq(netId), 7086 captor.capture()); 7087 for (int i = 0; i < routes.length; i++) { 7088 assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i)); 7089 } 7090 } 7091 7092 @Test testRegisterUnregisterConnectivityDiagnosticsCallback()7093 public void testRegisterUnregisterConnectivityDiagnosticsCallback() throws Exception { 7094 final NetworkRequest wifiRequest = 7095 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build(); 7096 when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder); 7097 7098 mService.registerConnectivityDiagnosticsCallback( 7099 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName()); 7100 7101 // Block until all other events are done processing. 7102 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); 7103 7104 verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt()); 7105 verify(mConnectivityDiagnosticsCallback).asBinder(); 7106 assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder)); 7107 7108 mService.unregisterConnectivityDiagnosticsCallback(mConnectivityDiagnosticsCallback); 7109 verify(mIBinder, timeout(TIMEOUT_MS)) 7110 .unlinkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt()); 7111 assertFalse(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder)); 7112 verify(mConnectivityDiagnosticsCallback, atLeastOnce()).asBinder(); 7113 } 7114 7115 @Test testRegisterDuplicateConnectivityDiagnosticsCallback()7116 public void testRegisterDuplicateConnectivityDiagnosticsCallback() throws Exception { 7117 final NetworkRequest wifiRequest = 7118 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build(); 7119 when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder); 7120 7121 mService.registerConnectivityDiagnosticsCallback( 7122 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName()); 7123 7124 // Block until all other events are done processing. 7125 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); 7126 7127 verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt()); 7128 verify(mConnectivityDiagnosticsCallback).asBinder(); 7129 assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder)); 7130 7131 // Register the same callback again 7132 mService.registerConnectivityDiagnosticsCallback( 7133 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName()); 7134 7135 // Block until all other events are done processing. 7136 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); 7137 7138 assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder)); 7139 } 7140 7141 @Test testCheckConnectivityDiagnosticsPermissionsNetworkStack()7142 public void testCheckConnectivityDiagnosticsPermissionsNetworkStack() throws Exception { 7143 final NetworkAgentInfo naiWithoutUid = 7144 new NetworkAgentInfo( 7145 null, null, null, null, null, new NetworkCapabilities(), 0, 7146 mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID); 7147 7148 mServiceContext.setPermission( 7149 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED); 7150 assertTrue( 7151 "NetworkStack permission not applied", 7152 mService.checkConnectivityDiagnosticsPermissions( 7153 Process.myPid(), Process.myUid(), naiWithoutUid, 7154 mContext.getOpPackageName())); 7155 } 7156 7157 @Test testCheckConnectivityDiagnosticsPermissionsWrongUidPackageName()7158 public void testCheckConnectivityDiagnosticsPermissionsWrongUidPackageName() throws Exception { 7159 final NetworkAgentInfo naiWithoutUid = 7160 new NetworkAgentInfo( 7161 null, null, null, null, null, new NetworkCapabilities(), 0, 7162 mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID); 7163 7164 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); 7165 7166 assertFalse( 7167 "Mismatched uid/package name should not pass the location permission check", 7168 mService.checkConnectivityDiagnosticsPermissions( 7169 Process.myPid() + 1, Process.myUid() + 1, naiWithoutUid, 7170 mContext.getOpPackageName())); 7171 } 7172 7173 @Test testCheckConnectivityDiagnosticsPermissionsNoLocationPermission()7174 public void testCheckConnectivityDiagnosticsPermissionsNoLocationPermission() throws Exception { 7175 final NetworkAgentInfo naiWithoutUid = 7176 new NetworkAgentInfo( 7177 null, null, null, null, null, new NetworkCapabilities(), 0, 7178 mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID); 7179 7180 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); 7181 7182 assertFalse( 7183 "ACCESS_FINE_LOCATION permission necessary for Connectivity Diagnostics", 7184 mService.checkConnectivityDiagnosticsPermissions( 7185 Process.myPid(), Process.myUid(), naiWithoutUid, 7186 mContext.getOpPackageName())); 7187 } 7188 7189 @Test testCheckConnectivityDiagnosticsPermissionsActiveVpn()7190 public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception { 7191 final Network network = new Network(NET_ID); 7192 final NetworkAgentInfo naiWithoutUid = 7193 new NetworkAgentInfo( 7194 null, null, network, null, null, new NetworkCapabilities(), 0, 7195 mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID); 7196 7197 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, 7198 Manifest.permission.ACCESS_FINE_LOCATION); 7199 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); 7200 7201 // setUp() calls mockVpn() which adds a VPN with the Test Runner's uid. Configure it to be 7202 // active 7203 final VpnInfo info = new VpnInfo(); 7204 info.ownerUid = Process.myUid(); 7205 info.vpnIface = "interface"; 7206 mMockVpn.setVpnInfo(info); 7207 mMockVpn.overrideUnderlyingNetworks(new Network[] {network}); 7208 assertTrue( 7209 "Active VPN permission not applied", 7210 mService.checkConnectivityDiagnosticsPermissions( 7211 Process.myPid(), Process.myUid(), naiWithoutUid, 7212 mContext.getOpPackageName())); 7213 7214 mMockVpn.overrideUnderlyingNetworks(null); 7215 assertFalse( 7216 "VPN shouldn't receive callback on non-underlying network", 7217 mService.checkConnectivityDiagnosticsPermissions( 7218 Process.myPid(), Process.myUid(), naiWithoutUid, 7219 mContext.getOpPackageName())); 7220 } 7221 7222 @Test testCheckConnectivityDiagnosticsPermissionsNetworkAdministrator()7223 public void testCheckConnectivityDiagnosticsPermissionsNetworkAdministrator() throws Exception { 7224 final NetworkCapabilities nc = new NetworkCapabilities(); 7225 nc.setAdministratorUids(new int[] {Process.myUid()}); 7226 final NetworkAgentInfo naiWithUid = 7227 new NetworkAgentInfo( 7228 null, null, null, null, null, nc, 0, mServiceContext, null, null, 7229 mService, null, null, null, 0, INVALID_UID); 7230 7231 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, 7232 Manifest.permission.ACCESS_FINE_LOCATION); 7233 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); 7234 7235 // Disconnect mock vpn so the uid check on NetworkAgentInfo is tested 7236 mMockVpn.disconnect(); 7237 assertTrue( 7238 "NetworkCapabilities administrator uid permission not applied", 7239 mService.checkConnectivityDiagnosticsPermissions( 7240 Process.myPid(), Process.myUid(), naiWithUid, mContext.getOpPackageName())); 7241 } 7242 7243 @Test testCheckConnectivityDiagnosticsPermissionsFails()7244 public void testCheckConnectivityDiagnosticsPermissionsFails() throws Exception { 7245 final NetworkCapabilities nc = new NetworkCapabilities(); 7246 nc.setOwnerUid(Process.myUid()); 7247 nc.setAdministratorUids(new int[] {Process.myUid()}); 7248 final NetworkAgentInfo naiWithUid = 7249 new NetworkAgentInfo( 7250 null, null, null, null, null, nc, 0, mServiceContext, null, null, 7251 mService, null, null, null, 0, INVALID_UID); 7252 7253 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, 7254 Manifest.permission.ACCESS_FINE_LOCATION); 7255 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); 7256 7257 // Use wrong pid and uid 7258 assertFalse( 7259 "Permissions allowed when they shouldn't be granted", 7260 mService.checkConnectivityDiagnosticsPermissions( 7261 Process.myPid() + 1, Process.myUid() + 1, naiWithUid, 7262 mContext.getOpPackageName())); 7263 } 7264 7265 @Test testRegisterConnectivityDiagnosticsCallbackCallsOnConnectivityReport()7266 public void testRegisterConnectivityDiagnosticsCallbackCallsOnConnectivityReport() 7267 throws Exception { 7268 // Set up the Network, which leads to a ConnectivityReport being cached for the network. 7269 final TestNetworkCallback callback = new TestNetworkCallback(); 7270 mCm.registerDefaultNetworkCallback(callback); 7271 final LinkProperties linkProperties = new LinkProperties(); 7272 linkProperties.setInterfaceName(INTERFACE_NAME); 7273 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, linkProperties); 7274 mCellNetworkAgent.connect(true); 7275 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 7276 callback.assertNoCallback(); 7277 7278 final NetworkRequest request = new NetworkRequest.Builder().build(); 7279 when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder); 7280 7281 mServiceContext.setPermission( 7282 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED); 7283 7284 mService.registerConnectivityDiagnosticsCallback( 7285 mConnectivityDiagnosticsCallback, request, mContext.getPackageName()); 7286 7287 // Block until all other events are done processing. 7288 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); 7289 7290 verify(mConnectivityDiagnosticsCallback) 7291 .onConnectivityReportAvailable(argThat(report -> { 7292 return INTERFACE_NAME.equals(report.getLinkProperties().getInterfaceName()) 7293 && report.getNetworkCapabilities().hasTransport(TRANSPORT_CELLULAR); 7294 })); 7295 } 7296 setUpConnectivityDiagnosticsCallback()7297 private void setUpConnectivityDiagnosticsCallback() throws Exception { 7298 final NetworkRequest request = new NetworkRequest.Builder().build(); 7299 when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder); 7300 7301 mServiceContext.setPermission( 7302 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED); 7303 7304 mService.registerConnectivityDiagnosticsCallback( 7305 mConnectivityDiagnosticsCallback, request, mContext.getPackageName()); 7306 7307 // Block until all other events are done processing. 7308 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); 7309 7310 // Connect the cell agent verify that it notifies TestNetworkCallback that it is available 7311 final TestNetworkCallback callback = new TestNetworkCallback(); 7312 mCm.registerDefaultNetworkCallback(callback); 7313 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 7314 mCellNetworkAgent.connect(true); 7315 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 7316 callback.assertNoCallback(); 7317 } 7318 7319 @Test testConnectivityDiagnosticsCallbackOnConnectivityReportAvailable()7320 public void testConnectivityDiagnosticsCallbackOnConnectivityReportAvailable() 7321 throws Exception { 7322 setUpConnectivityDiagnosticsCallback(); 7323 7324 // Block until all other events are done processing. 7325 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); 7326 7327 // Verify onConnectivityReport fired 7328 verify(mConnectivityDiagnosticsCallback).onConnectivityReportAvailable( 7329 argThat(report -> { 7330 final NetworkCapabilities nc = report.getNetworkCapabilities(); 7331 return nc.getUids() == null 7332 && nc.getAdministratorUids().length == 0 7333 && nc.getOwnerUid() == Process.INVALID_UID; 7334 })); 7335 } 7336 7337 @Test testConnectivityDiagnosticsCallbackOnDataStallSuspected()7338 public void testConnectivityDiagnosticsCallbackOnDataStallSuspected() throws Exception { 7339 setUpConnectivityDiagnosticsCallback(); 7340 7341 // Trigger notifyDataStallSuspected() on the INetworkMonitorCallbacks instance in the 7342 // cellular network agent 7343 mCellNetworkAgent.notifyDataStallSuspected(); 7344 7345 // Block until all other events are done processing. 7346 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); 7347 7348 // Verify onDataStallSuspected fired 7349 verify(mConnectivityDiagnosticsCallback).onDataStallSuspected( 7350 argThat(report -> { 7351 final NetworkCapabilities nc = report.getNetworkCapabilities(); 7352 return nc.getUids() == null 7353 && nc.getAdministratorUids().length == 0 7354 && nc.getOwnerUid() == Process.INVALID_UID; 7355 })); 7356 } 7357 7358 @Test testConnectivityDiagnosticsCallbackOnConnectivityReported()7359 public void testConnectivityDiagnosticsCallbackOnConnectivityReported() throws Exception { 7360 setUpConnectivityDiagnosticsCallback(); 7361 7362 final Network n = mCellNetworkAgent.getNetwork(); 7363 final boolean hasConnectivity = true; 7364 mService.reportNetworkConnectivity(n, hasConnectivity); 7365 7366 // Block until all other events are done processing. 7367 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); 7368 7369 // Verify onNetworkConnectivityReported fired 7370 verify(mConnectivityDiagnosticsCallback) 7371 .onNetworkConnectivityReported(eq(n), eq(hasConnectivity)); 7372 7373 final boolean noConnectivity = false; 7374 mService.reportNetworkConnectivity(n, noConnectivity); 7375 7376 // Block until all other events are done processing. 7377 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); 7378 7379 // Wait for onNetworkConnectivityReported to fire 7380 verify(mConnectivityDiagnosticsCallback) 7381 .onNetworkConnectivityReported(eq(n), eq(noConnectivity)); 7382 } 7383 7384 @Test testRouteAddDeleteUpdate()7385 public void testRouteAddDeleteUpdate() throws Exception { 7386 final NetworkRequest request = new NetworkRequest.Builder().build(); 7387 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 7388 mCm.registerNetworkCallback(request, networkCallback); 7389 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); 7390 reset(mMockNetd); 7391 mCellNetworkAgent.connect(false); 7392 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); 7393 final int netId = mCellNetworkAgent.getNetwork().netId; 7394 7395 final String iface = "rmnet_data0"; 7396 final InetAddress gateway = InetAddress.getByName("fe80::5678"); 7397 RouteInfo direct = RouteInfo.makeHostRoute(gateway, iface); 7398 RouteInfo rio1 = new RouteInfo(new IpPrefix("2001:db8:1::/48"), gateway, iface); 7399 RouteInfo rio2 = new RouteInfo(new IpPrefix("2001:db8:2::/48"), gateway, iface); 7400 RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, gateway, iface); 7401 RouteInfo defaultWithMtu = new RouteInfo(null, gateway, iface, RouteInfo.RTN_UNICAST, 7402 1280 /* mtu */); 7403 7404 // Send LinkProperties and check that we ask netd to add routes. 7405 LinkProperties lp = new LinkProperties(); 7406 lp.setInterfaceName(iface); 7407 lp.addRoute(direct); 7408 lp.addRoute(rio1); 7409 lp.addRoute(defaultRoute); 7410 mCellNetworkAgent.sendLinkProperties(lp); 7411 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, x -> x.getRoutes().size() == 3); 7412 7413 assertRoutesAdded(netId, direct, rio1, defaultRoute); 7414 reset(mMockNetd); 7415 7416 // Send updated LinkProperties and check that we ask netd to add, remove, update routes. 7417 assertTrue(lp.getRoutes().contains(defaultRoute)); 7418 lp.removeRoute(rio1); 7419 lp.addRoute(rio2); 7420 lp.addRoute(defaultWithMtu); 7421 // Ensure adding the same route with a different MTU replaces the previous route. 7422 assertFalse(lp.getRoutes().contains(defaultRoute)); 7423 assertTrue(lp.getRoutes().contains(defaultWithMtu)); 7424 7425 mCellNetworkAgent.sendLinkProperties(lp); 7426 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, 7427 x -> x.getRoutes().contains(rio2)); 7428 7429 assertRoutesRemoved(netId, rio1); 7430 assertRoutesAdded(netId, rio2); 7431 7432 ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class); 7433 verify(mMockNetd).networkUpdateRouteParcel(eq(netId), captor.capture()); 7434 assertRouteInfoParcelMatches(defaultWithMtu, captor.getValue()); 7435 7436 7437 mCm.unregisterNetworkCallback(networkCallback); 7438 } 7439 } 7440