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