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 bindProcessToNetwork(Network network)300 public synchronized boolean bindProcessToNetwork(Network network) { 301 mFakeBoundNetwork = network; 302 return true; 303 } 304 getBoundNetworkForProcess()305 public synchronized Network getBoundNetworkForProcess() { 306 return mFakeBoundNetwork; 307 } 308 WrappedConnectivityManager(Context context, ConnectivityService service)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 MockContext(Context base, ContentProvider settingsProvider)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 startActivityAsUser(Intent intent, UserHandle handle)336 public void startActivityAsUser(Intent intent, UserHandle handle) { 337 mStartedActivities.offer(intent); 338 } 339 expectStartActivityIntent(int timeoutMs)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 expectNoStartActivityIntent(int timeoutMs)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 getSystemService(String name)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 getContentResolver()366 public ContentResolver getContentResolver() { 367 return mContentResolver; 368 } 369 370 @Override getResources()371 public Resources getResources() { 372 return mResources; 373 } 374 375 @Override getPackageManager()376 public PackageManager getPackageManager() { 377 return mPackageManager; 378 } 379 380 @Override enforceCallingOrSelfPermission(String permission, String message)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 waitForIdle(int timeoutMsAsInt)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 waitForIdle(MockNetworkAgent agent, long timeoutMs)401 public void waitForIdle(MockNetworkAgent agent, long timeoutMs) { 402 if (agent == null) { 403 return; 404 } 405 waitForIdleHandler(agent.mHandlerThread, timeoutMs); 406 } 407 waitForIdle()408 private void waitForIdle() { 409 waitForIdle(TIMEOUT_MS); 410 } 411 412 @Test testWaitForIdle()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 verifyThatNotWaitingForIdleCausesRaceConditions()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 setNetworkValid()495 void setNetworkValid() { 496 mNmValidationResult = VALIDATION_RESULT_VALID; 497 mNmValidationRedirectUrl = null; 498 } 499 setNetworkInvalid()500 void setNetworkInvalid() { 501 mNmValidationResult = VALIDATION_RESULT_INVALID; 502 mNmValidationRedirectUrl = null; 503 } 504 setNetworkPortal(String redirectUrl)505 void setNetworkPortal(String redirectUrl) { 506 setNetworkInvalid(); 507 mNmValidationRedirectUrl = redirectUrl; 508 } 509 setNetworkPartial()510 void setNetworkPartial() { 511 mNmValidationResult = VALIDATION_RESULT_PARTIAL; 512 mNmValidationRedirectUrl = null; 513 } 514 setNetworkPartialValid()515 void setNetworkPartialValid() { 516 mNmValidationResult = VALIDATION_RESULT_PARTIAL | VALIDATION_RESULT_VALID; 517 mNmValidationRedirectUrl = null; 518 } 519 MockNetworkAgent(int transport)520 MockNetworkAgent(int transport) { 521 this(transport, new LinkProperties()); 522 } 523 MockNetworkAgent(int transport, LinkProperties linkProperties)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 onValidationRequested()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 adjustScore(int change)651 public void adjustScore(int change) { 652 mScore += change; 653 mNetworkAgent.sendNetworkScore(mScore); 654 } 655 getScore()656 public int getScore() { 657 return mScore; 658 } 659 explicitlySelected(boolean acceptUnvalidated)660 public void explicitlySelected(boolean acceptUnvalidated) { 661 mNetworkAgent.explicitlySelected(acceptUnvalidated); 662 } 663 addCapability(int capability)664 public void addCapability(int capability) { 665 mNetworkCapabilities.addCapability(capability); 666 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 667 } 668 removeCapability(int capability)669 public void removeCapability(int capability) { 670 mNetworkCapabilities.removeCapability(capability); 671 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 672 } 673 setUids(Set<UidRange> uids)674 public void setUids(Set<UidRange> uids) { 675 mNetworkCapabilities.setUids(uids); 676 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 677 } 678 setSignalStrength(int signalStrength)679 public void setSignalStrength(int signalStrength) { 680 mNetworkCapabilities.setSignalStrength(signalStrength); 681 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 682 } 683 setNetworkSpecifier(NetworkSpecifier networkSpecifier)684 public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) { 685 mNetworkCapabilities.setNetworkSpecifier(networkSpecifier); 686 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 687 } 688 setNetworkCapabilities(NetworkCapabilities nc, boolean sendToConnectivityService)689 public void setNetworkCapabilities(NetworkCapabilities nc, 690 boolean sendToConnectivityService) { 691 mNetworkCapabilities.set(nc); 692 if (sendToConnectivityService) { 693 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 694 } 695 } 696 connectWithoutInternet()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 */ connect(boolean validated)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 */ connect(boolean validated, boolean hasInternet)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 connectWithCaptivePortal(String redirectUrl)754 public void connectWithCaptivePortal(String redirectUrl) { 755 setNetworkPortal(redirectUrl); 756 connect(false); 757 } 758 connectWithPartialConnectivity()759 public void connectWithPartialConnectivity() { 760 setNetworkPartial(); 761 connect(false); 762 } 763 suspend()764 public void suspend() { 765 mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null); 766 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 767 } 768 resume()769 public void resume() { 770 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null); 771 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 772 } 773 disconnect()774 public void disconnect() { 775 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); 776 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 777 } 778 getNetwork()779 public Network getNetwork() { 780 return new Network(mNetworkAgent.netId); 781 } 782 getPreventReconnectReceived()783 public ConditionVariable getPreventReconnectReceived() { 784 return mPreventReconnectReceived; 785 } 786 getDisconnectedCV()787 public ConditionVariable getDisconnectedCV() { 788 return mDisconnected; 789 } 790 sendLinkProperties(LinkProperties lp)791 public void sendLinkProperties(LinkProperties lp) { 792 mNetworkAgent.sendLinkProperties(lp); 793 } 794 setStartKeepaliveError(int error)795 public void setStartKeepaliveError(int error) { 796 mStartKeepaliveError = error; 797 } 798 setStopKeepaliveError(int error)799 public void setStopKeepaliveError(int error) { 800 mStopKeepaliveError = error; 801 } 802 setExpectedKeepaliveSlot(Integer slot)803 public void setExpectedKeepaliveSlot(Integer slot) { 804 mExpectedKeepaliveSlot = slot; 805 } 806 waitForRedirectUrl()807 public String waitForRedirectUrl() { 808 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS)); 809 return mRedirectUrl; 810 } 811 getNetworkAgent()812 public NetworkAgent getNetworkAgent() { 813 return mNetworkAgent; 814 } 815 getNetworkCapabilities()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 MockNetworkFactory(Looper looper, Context context, String logTag, NetworkCapabilities filter)849 public MockNetworkFactory(Looper looper, Context context, String logTag, 850 NetworkCapabilities filter) { 851 super(looper, context, logTag, filter); 852 mExpectations = new LinkedBlockingQueue<>(); 853 } 854 getMyRequestCount()855 public int getMyRequestCount() { 856 return getRequestCount(); 857 } 858 startNetwork()859 protected void startNetwork() { 860 mNetworkStarted.set(true); 861 mNetworkStartedCV.open(); 862 } 863 stopNetwork()864 protected void stopNetwork() { 865 mNetworkStarted.set(false); 866 mNetworkStoppedCV.open(); 867 } 868 getMyStartRequested()869 public boolean getMyStartRequested() { 870 return mNetworkStarted.get(); 871 } 872 getNetworkStartedCV()873 public ConditionVariable getNetworkStartedCV() { 874 mNetworkStartedCV.close(); 875 return mNetworkStartedCV; 876 } 877 getNetworkStoppedCV()878 public ConditionVariable getNetworkStoppedCV() { 879 mNetworkStoppedCV.close(); 880 return mNetworkStoppedCV; 881 } 882 883 @Override handleAddRequest(NetworkRequest request, int score, int factorySerialNumber)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 handleRemoveRequest(NetworkRequest request)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 triggerUnfulfillable(NetworkRequest r)926 public void triggerUnfulfillable(NetworkRequest r) { 927 super.releaseRequestAsUnfulfillableByAnyFactory(r); 928 } 929 assertNoExpectations()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. expectAddRequestsWithScores(final int... scores)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. expectRemoveRequests(final int count)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. waitForRequests()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 waitForNetworkRequests(final int count)969 public SparseArray<NetworkRequest> waitForNetworkRequests(final int count) 970 throws InterruptedException { 971 waitForRequests(); 972 assertEquals(count, getMyRequestCount()); 973 return mNetworkRequests; 974 } 975 } 976 startHandlerThreadAndReturnLooper()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 MockVpn(int userId)998 public MockVpn(int userId) { 999 super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService, 1000 userId); 1001 } 1002 setNetworkAgent(MockNetworkAgent agent)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 setUids(Set<UidRange> uids)1010 public void setUids(Set<UidRange> uids) { 1011 mNetworkCapabilities.setUids(uids); 1012 updateCapabilities(null /* defaultNetwork */); 1013 } 1014 1015 @Override getNetId()1016 public int getNetId() { 1017 if (mMockNetworkAgent == null) { 1018 return NETID_UNSET; 1019 } 1020 return mMockNetworkAgent.getNetwork().netId; 1021 } 1022 1023 @Override appliesToUid(int uid)1024 public boolean appliesToUid(int uid) { 1025 return mConnected; // Trickery to simplify testing. 1026 } 1027 1028 @Override isCallerEstablishedOwnerLocked()1029 protected boolean isCallerEstablishedOwnerLocked() { 1030 return mConnected; // Similar trickery 1031 } 1032 connect(boolean isAlwaysMetered)1033 private void connect(boolean isAlwaysMetered) { 1034 mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities()); 1035 mConnected = true; 1036 mConfig = new VpnConfig(); 1037 mConfig.isMetered = isAlwaysMetered; 1038 } 1039 connectAsAlwaysMetered()1040 public void connectAsAlwaysMetered() { 1041 connect(true /* isAlwaysMetered */); 1042 } 1043 connect()1044 public void connect() { 1045 connect(false /* isAlwaysMetered */); 1046 } 1047 1048 @Override updateCapabilities(Network defaultNetwork)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 copyCapabilitiesToNetworkAgent()1058 private void copyCapabilitiesToNetworkAgent() { 1059 if (null != mMockNetworkAgent) { 1060 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities, 1061 false /* sendToConnectivityService */); 1062 } 1063 } 1064 disconnect()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 FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd)1074 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) { 1075 super(context, handler, cmdName, cmd); 1076 } 1077 FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd, int arg1, int arg2, Object obj)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 schedule(long when)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 cancel()1096 public void cancel() { 1097 mHandler.removeMessages(mCmd, mObj); 1098 } 1099 1100 @Override onAlarm()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 WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r)1110 public WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) { 1111 super(c, h, r); 1112 } 1113 1114 @Override configRestrictsAvoidBadWifi()1115 public boolean configRestrictsAvoidBadWifi() { 1116 return configRestrictsAvoidBadWifi; 1117 } 1118 1119 @Override configMeteredMultipathPreference()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 WrappedConnectivityService(Context context, INetworkManagementService netManager, INetworkStatsService statsService, INetworkPolicyManager policyManager, IpConnectivityLog log, INetd netd, IDnsResolver dnsResolver)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 getSystemProperties()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 makeTethering()1148 protected Tethering makeTethering() { 1149 return mock(Tethering.class); 1150 } 1151 1152 @Override makeProxyTracker()1153 protected ProxyTracker makeProxyTracker() { 1154 return mock(ProxyTracker.class); 1155 } 1156 1157 @Override reserveNetId()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 queryUserAccess(int uid, int netId)1180 protected boolean queryUserAccess(int uid, int netId) { 1181 return true; 1182 } 1183 getNat464Xlat(MockNetworkAgent mna)1184 public Nat464Xlat getNat464Xlat(MockNetworkAgent mna) { 1185 return getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd; 1186 } 1187 1188 @Override createMultinetworkPolicyTracker( Context c, Handler h, Runnable r)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 getMultinetworkPolicyTracker()1195 public WrappedMultinetworkPolicyTracker getMultinetworkPolicyTracker() { 1196 return (WrappedMultinetworkPolicyTracker) mMultinetworkPolicyTracker; 1197 } 1198 1199 @Override getNetworkStack()1200 protected NetworkStackClient getNetworkStack() { 1201 return mNetworkStack; 1202 } 1203 1204 @Override makeWakeupMessage( Context context, Handler handler, String cmdName, int cmd, Object obj)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 hasService(String name)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 metricsLogger()1218 protected IpConnectivityMetrics.Logger metricsLogger() { 1219 return mMetricsService; 1220 } 1221 1222 @Override registerNetdEventCallback()1223 protected void registerNetdEventCallback() { 1224 } 1225 mockVpn(int uid)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 waitForIdle(int timeoutMs)1237 public void waitForIdle(int timeoutMs) { 1238 waitForIdleHandler(mHandlerThread, timeoutMs); 1239 } 1240 waitForIdle()1241 public void waitForIdle() { 1242 waitForIdle(TIMEOUT_MS); 1243 } 1244 setUidRulesChanged(int uidRules)1245 public void setUidRulesChanged(int uidRules) { 1246 try { 1247 mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules); 1248 } catch (RemoteException ignored) { 1249 } 1250 } 1251 setRestrictBackgroundChanged(boolean restrictBackground)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 */ waitFor(ConditionVariable conditionVariable)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 setUp()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 tearDown()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 mockDefaultPackages()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 transportToLegacyType(int transport)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 verifyActiveNetwork(int transport)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 verifyNoNetwork()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 */ waitForConnectivityBroadcasts(final int count)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 testNetworkTypes()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 testLingering()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 testValidatedCellularOutscoresUnvalidatedWiFi()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 testUnvalidatedWifiOutscoresUnvalidatedCellular()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 testUnlingeringDoesNotValidate()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 testCellularOutscoresWeakWifi()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 testReapingNetwork()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 testCellularFallback()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 testWiFiFallback()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 testRequiresValidation()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; CallbackInfo(CallbackState s, Network n, Object o)1728 public CallbackInfo(CallbackState s, Network n, Object o) { 1729 state = s; network = n; arg = o; 1730 } toString()1731 public String toString() { 1732 return String.format("%s (%s) (%s)", state, network, arg); 1733 } 1734 @Override equals(Object o)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 hashCode()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 setLastCallback(CallbackState state, Network network, Object o)1756 protected void setLastCallback(CallbackState state, Network network, Object o) { 1757 mCallbacks.offer(new CallbackInfo(state, network, o)); 1758 } 1759 1760 @Override onAvailable(Network network)1761 public void onAvailable(Network network) { 1762 mLastAvailableNetwork = network; 1763 setLastCallback(CallbackState.AVAILABLE, network, null); 1764 } 1765 1766 @Override onCapabilitiesChanged(Network network, NetworkCapabilities netCap)1767 public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) { 1768 setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap); 1769 } 1770 1771 @Override onLinkPropertiesChanged(Network network, LinkProperties linkProp)1772 public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) { 1773 setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp); 1774 } 1775 1776 @Override onUnavailable()1777 public void onUnavailable() { 1778 setLastCallback(CallbackState.UNAVAILABLE, null, null); 1779 } 1780 1781 @Override onNetworkSuspended(Network network)1782 public void onNetworkSuspended(Network network) { 1783 setLastCallback(CallbackState.SUSPENDED, network, null); 1784 } 1785 1786 @Override onNetworkResumed(Network network)1787 public void onNetworkResumed(Network network) { 1788 setLastCallback(CallbackState.RESUMED, network, null); 1789 } 1790 1791 @Override onLosing(Network network, int maxMsToLive)1792 public void onLosing(Network network, int maxMsToLive) { 1793 setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */); 1794 } 1795 1796 @Override onLost(Network network)1797 public void onLost(Network network) { 1798 mLastAvailableNetwork = null; 1799 setLastCallback(CallbackState.LOST, network, null); 1800 } 1801 1802 @Override onBlockedStatusChanged(Network network, boolean blocked)1803 public void onBlockedStatusChanged(Network network, boolean blocked) { 1804 setLastCallback(CallbackState.BLOCKED_STATUS, network, blocked); 1805 } 1806 getLastAvailableNetwork()1807 public Network getLastAvailableNetwork() { 1808 return mLastAvailableNetwork; 1809 } 1810 nextCallback(int timeoutMs)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 expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs)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 expectCallback(CallbackState state, MockNetworkAgent agent)1841 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) { 1842 return expectCallback(state, agent, TEST_CALLBACK_TIMEOUT_MS); 1843 } 1844 expectCallbackLike(Predicate<CallbackInfo> fn)1845 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) { 1846 return expectCallbackLike(fn, TEST_CALLBACK_TIMEOUT_MS); 1847 } 1848 expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs)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. expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended, boolean expectValidated, boolean expectBlocked, int timeoutMs)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. expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated)1890 void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) { 1891 expectAvailableCallbacks(agent, true, expectValidated, false, TEST_CALLBACK_TIMEOUT_MS); 1892 } 1893 expectAvailableCallbacksValidated(MockNetworkAgent agent)1894 void expectAvailableCallbacksValidated(MockNetworkAgent agent) { 1895 expectAvailableCallbacks(agent, false, true, false, TEST_CALLBACK_TIMEOUT_MS); 1896 } 1897 expectAvailableCallbacksValidatedAndBlocked(MockNetworkAgent agent)1898 void expectAvailableCallbacksValidatedAndBlocked(MockNetworkAgent agent) { 1899 expectAvailableCallbacks(agent, false, true, true, TEST_CALLBACK_TIMEOUT_MS); 1900 } 1901 expectAvailableCallbacksUnvalidated(MockNetworkAgent agent)1902 void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) { 1903 expectAvailableCallbacks(agent, false, false, false, TEST_CALLBACK_TIMEOUT_MS); 1904 } 1905 expectAvailableCallbacksUnvalidatedAndBlocked(MockNetworkAgent agent)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. expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent)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. expectAvailableThenValidatedCallbacks(MockNetworkAgent agent)1928 void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) { 1929 expectAvailableCallbacksUnvalidated(agent); 1930 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent); 1931 } 1932 expectCapabilitiesWith(int capability, MockNetworkAgent agent)1933 NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent) { 1934 return expectCapabilitiesWith(capability, agent, TEST_CALLBACK_TIMEOUT_MS); 1935 } 1936 expectCapabilitiesWith(int capability, MockNetworkAgent agent, int timeoutMs)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 expectCapabilitiesWithout(int capability, MockNetworkAgent agent)1945 NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent) { 1946 return expectCapabilitiesWithout(capability, agent, TEST_CALLBACK_TIMEOUT_MS); 1947 } 1948 expectCapabilitiesWithout(int capability, MockNetworkAgent agent, int timeoutMs)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 expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent)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 expectLinkPropertiesLike(Predicate<LinkProperties> fn, MockNetworkAgent agent)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 expectBlockedStatusCallback(boolean expectBlocked, MockNetworkAgent agent)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 assertNoCallback()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". assertNoCallbacks(TestNetworkCallback .... callbacks)1984 static void assertNoCallbacks(TestNetworkCallback ... callbacks) { 1985 for (TestNetworkCallback c : callbacks) { 1986 c.assertNoCallback(); 1987 } 1988 } 1989 1990 @Test testStateChangeNetworkCallbacks()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 testMultipleLingering()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 testNetworkGoesIntoBackgroundAfterLinger()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 testExplicitlySelected()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 makeIntArray(final int size, final int value)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 tryNetworkFactoryRequests(int capability)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 testNetworkFactoryRequests()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 testNoMutableNetworkRequests()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 testMMSonWiFi()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 testMMSonCell()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 testPartialConnectivity()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 testCaptivePortalOnPartialConnectivity()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 testCaptivePortal()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 testCaptivePortalApp()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 testAvoidOrIgnoreCaptivePortals()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 newWifiRequestBuilder()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 testNetworkSpecifier()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 testInvalidNetworkSpecifier()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 testNetworkSpecifierUidSpoofSecurityException()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 testInvalidSignalStrength()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 testRegisterDefaultNetworkCallback()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 testAdditionalStateCallbacks()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 setCaptivePortalMode(int mode)3387 private void setCaptivePortalMode(int mode) { 3388 ContentResolver cr = mServiceContext.getContentResolver(); 3389 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode); 3390 } 3391 setAlwaysOnNetworks(boolean enable)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 setPrivateDnsSettings(String mode, String specifier)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 isForegroundNetwork(MockNetworkAgent network)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 testBackgroundNetworks()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. benchmarkRequestRegistrationAndCallbackDispatch()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 durationOf(Runnable fn)3562 private long durationOf(Runnable fn) { 3563 long startTime = SystemClock.elapsedRealtime(); 3564 fn.run(); 3565 return SystemClock.elapsedRealtime() - startTime; 3566 } 3567 assertTimeLimit(String descr, long timeLimit, Runnable fn)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 awaitLatch(CountDownLatch l, long timeoutMs)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 testMobileDataAlwaysOn()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 testAvoidBadWifiSetting()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 testAvoidBadWifi()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 testMeteredMultipathPreferenceSetting()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 testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable()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 testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable()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 testTimedoutNetworkRequest()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 testNoCallbackAfterUnregisteredNetworkRequest()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 testUnfulfillableNetworkRequest()3919 public void testUnfulfillableNetworkRequest() throws Exception { 3920 runUnfulfillableNetworkRequest(false); 3921 } 3922 3923 @Test testUnfulfillableNetworkRequestAfterUnregister()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 */ runUnfulfillableNetworkRequest(boolean preUnregister)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 CallbackValue(CallbackType type)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 CallbackValue(CallbackType type, int error)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 equals(Object o)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 toString()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 onStarted()4026 public void onStarted() { 4027 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED)); 4028 } 4029 4030 @Override onStopped()4031 public void onStopped() { 4032 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED)); 4033 } 4034 4035 @Override onError(int error)4036 public void onError(int error) { 4037 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error)); 4038 } 4039 expectCallback(CallbackValue callbackValue)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 expectStarted()4050 public void expectStarted() { 4051 expectCallback(new CallbackValue(CallbackType.ON_STARTED)); 4052 } 4053 expectStopped()4054 public void expectStopped() { 4055 expectCallback(new CallbackValue(CallbackType.ON_STOPPED)); 4056 } 4057 expectError(int error)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 CallbackValue(CallbackType type)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 CallbackValue(CallbackType type, int error)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 equals(Object o)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 toString()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 TestSocketKeepaliveCallback(@onNull Executor executor)4100 TestSocketKeepaliveCallback(@NonNull Executor executor) { 4101 mExecutor = executor; 4102 } 4103 4104 @Override onStarted()4105 public void onStarted() { 4106 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED)); 4107 } 4108 4109 @Override onStopped()4110 public void onStopped() { 4111 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED)); 4112 } 4113 4114 @Override onError(int error)4115 public void onError(int error) { 4116 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error)); 4117 } 4118 expectCallback(CallbackValue callbackValue)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 expectStarted()4129 public void expectStarted() { 4130 expectCallback(new CallbackValue(CallbackType.ON_STARTED)); 4131 } 4132 expectStopped()4133 public void expectStopped() { 4134 expectCallback(new CallbackValue(CallbackType.ON_STOPPED)); 4135 } 4136 expectError(int error)4137 public void expectError(int error) { 4138 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error)); 4139 } 4140 assertNoCallback()4141 public void assertNoCallback() { 4142 waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS); 4143 CallbackValue cv = mCallbacks.peek(); 4144 assertNull("Unexpected callback: " + cv, cv); 4145 } 4146 } 4147 connectKeepaliveNetwork(LinkProperties lp)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 testPacketKeepalives()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> { accept(T t)4283 void accept(T t) throws Exception; 4284 } 4285 4286 // Helper method to prepare the executor and run test runTestWithSerialExecutors(ThrowingConsumer<Executor> functor)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 testNattSocketKeepalives()4296 public void testNattSocketKeepalives() throws Exception { 4297 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor)); 4298 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor)); 4299 } 4300 doTestNattSocketKeepalivesWithExecutor(Executor executor)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 testTcpSocketKeepalives()4474 public void testTcpSocketKeepalives() throws Exception { 4475 runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor)); 4476 } 4477 doTestTcpSocketKeepalivesWithExecutor(Executor executor)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 doTestNattSocketKeepalivesFdWithExecutor(Executor executor)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 isUdpPortInUse(int port)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 testGetCaptivePortalServerUrl()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 { awaitPin(int timeoutMs)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 awaitUnpin(int timeoutMs)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 assertPinnedToWifiWithCellDefault()4640 private void assertPinnedToWifiWithCellDefault() { 4641 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess()); 4642 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 4643 } 4644 assertPinnedToWifiWithWifiDefault()4645 private void assertPinnedToWifiWithWifiDefault() { 4646 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess()); 4647 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 4648 } 4649 assertNotPinnedToWifi()4650 private void assertNotPinnedToWifi() { 4651 assertNull(mCm.getBoundNetworkForProcess()); 4652 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 4653 } 4654 4655 @Test testNetworkPinner()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 testNetworkCallbackMaximum()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 testNetworkInfoOfTypeNone()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 testDeprecatedAndUnsupportedOperations()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 testLinkPropertiesEnsuresDirectlyConnectedRoutes()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 testStatsIfacesChanged()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 testBasicDnsConfigurationPushed()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 testPrivateDnsSettingsChange()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 testLinkPropertiesWithPrivateDnsValidationEvents()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 checkDirectlyConnectedRoutes(Object callbackObj, Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes)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 checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers)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 assertEmpty(T[] ts)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 assertLength(int expected, T[] got)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 assertException(Runnable block, Class<T> expected)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 testVpnNetworkActive()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 testVpnWithoutInternet()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 testVpnWithInternet()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 testVpnUnvalidated()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 testVpnSetUnderlyingNetworks()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 testNullUnderlyingNetworks()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 testIsActiveNetworkMeteredOverWifi()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 testIsActiveNetworkMeteredOverCell()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 testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault()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 testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks()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 testIsActiveNetworkMeteredOverAlwaysMeteredVpn()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 testNetworkBlockedStatus()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 testNetworkBlockedStatusBeforeAndAfterConnect()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 */ getClatInterfaceConfig(LinkAddress la)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 */ makeClatLinkProperties(LinkAddress la)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 testStackedLinkProperties()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 testDataActivityTracking()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 verifyTcpBufferSizeChange(String tcpBufferSizes)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 testTcpBufferReset()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 testGetGlobalProxyForNetwork()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 testGetProxyForActiveNetwork()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 testGetProxyForVPN()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 testFullyRoutedVpnResultsInInterfaceFilteringRules()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 testLegacyVpnDoesNotResultInInterfaceFilteringRule()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 testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()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 testVpnHandoverChangesInterfaceFilteringRule()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 testUidUpdateChangesInterfaceFilteringRule()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 establishVpn(LinkProperties lp, int establishingUid, Set<UidRange> vpnRange)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 assertContainsExactly(int[] actual, int... expected)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 buildPackageInfo(boolean hasSystemPermission, int uid)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