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