blob: 1cf0d5350fd2a4f334ec24e7f2b8300eed1ca835 [file] [log] [blame]
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07001/*
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
17package com.android.server;
18
Erik Klinef851d6d2015-04-20 16:03:48 +090019import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +090020import static android.net.ConnectivityManager.TYPE_ETHERNET;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070021import static android.net.ConnectivityManager.TYPE_MOBILE;
22import static android.net.ConnectivityManager.TYPE_WIFI;
23import static android.net.ConnectivityManager.getNetworkTypeName;
Lorenzo Colitti83fa2582015-08-07 12:49:01 +090024import static android.net.NetworkCapabilities.*;
25
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090026import static org.mockito.Mockito.anyBoolean;
27import static org.mockito.Mockito.anyInt;
28import static org.mockito.Mockito.eq;
Jeff Sharkey3671b1e2013-01-31 17:22:26 -080029import static org.mockito.Mockito.mock;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090030import static org.mockito.Mockito.spy;
31import static org.mockito.Mockito.when;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070032
Lorenzo Colitti73b209382016-09-15 22:18:09 +090033import android.app.NotificationManager;
Paul Jensenbb2e0e92015-06-16 15:11:58 -040034import android.app.PendingIntent;
Paul Jensend7b6ca92015-05-13 14:05:12 -040035import android.content.BroadcastReceiver;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +090036import android.content.ContentResolver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070037import android.content.Context;
Paul Jensend7b6ca92015-05-13 14:05:12 -040038import android.content.ContextWrapper;
39import android.content.Intent;
40import android.content.IntentFilter;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090041import android.content.res.Resources;
Paul Jensend7b6ca92015-05-13 14:05:12 -040042import android.net.ConnectivityManager;
43import android.net.ConnectivityManager.NetworkCallback;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +090044import android.net.ConnectivityManager.PacketKeepalive;
45import android.net.ConnectivityManager.PacketKeepaliveCallback;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070046import android.net.INetworkPolicyManager;
47import android.net.INetworkStatsService;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +090048import android.net.IpPrefix;
49import android.net.LinkAddress;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070050import android.net.LinkProperties;
Paul Jensend7b6ca92015-05-13 14:05:12 -040051import android.net.Network;
52import android.net.NetworkAgent;
53import android.net.NetworkCapabilities;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070054import android.net.NetworkConfig;
Robert Greenwalt348e98d2015-06-05 17:55:36 -070055import android.net.NetworkFactory;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070056import android.net.NetworkInfo;
57import android.net.NetworkInfo.DetailedState;
Paul Jensend7b6ca92015-05-13 14:05:12 -040058import android.net.NetworkMisc;
59import android.net.NetworkRequest;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070060import android.net.RouteInfo;
Hugo Benichif9fdf872016-07-28 17:53:06 +090061import android.net.metrics.IpConnectivityLog;
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +090062import android.net.util.MultinetworkPolicyTracker;
Paul Jensend7b6ca92015-05-13 14:05:12 -040063import android.os.ConditionVariable;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070064import android.os.Handler;
Robert Greenwalt348e98d2015-06-05 17:55:36 -070065import android.os.HandlerThread;
Etan Cohenddb9ef02015-11-18 10:56:15 -080066import android.os.IBinder;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070067import android.os.INetworkManagementService;
Lorenzo Colittie58961a2015-08-07 20:17:27 +090068import android.os.Looper;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +090069import android.os.Message;
Lorenzo Colittie58961a2015-08-07 20:17:27 +090070import android.os.MessageQueue;
Etan Cohenddb9ef02015-11-18 10:56:15 -080071import android.os.Messenger;
Lorenzo Colittie58961a2015-08-07 20:17:27 +090072import android.os.MessageQueue.IdleHandler;
Robin Leed2baf792016-03-24 12:07:00 +000073import android.os.Process;
Lorenzo Colittibfecba22016-02-21 01:09:26 +090074import android.os.SystemClock;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +090075import android.provider.Settings;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070076import android.test.AndroidTestCase;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +090077import android.test.mock.MockContentResolver;
Udam Sainib7c24872016-01-04 12:16:14 -080078import android.test.suitebuilder.annotation.SmallTest;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070079import android.util.Log;
80import android.util.LogPrinter;
81
Lorenzo Colittibfecba22016-02-21 01:09:26 +090082import com.android.internal.util.WakeupMessage;
Lorenzo Colitti3c295b52016-10-28 12:56:03 +090083import com.android.internal.util.test.BroadcastInterceptingContext;
Lorenzo Colittib8df76e42016-10-28 12:37:38 +090084import com.android.internal.util.test.FakeSettingsProvider;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090085import com.android.server.connectivity.MockableSystemProperties;
Paul Jensencf4c2c62015-07-01 14:16:32 -040086import com.android.server.connectivity.NetworkAgentInfo;
Paul Jensend7b6ca92015-05-13 14:05:12 -040087import com.android.server.connectivity.NetworkMonitor;
Paul Jensen232437312016-04-06 09:51:26 -040088import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
Lorenzo Colitti531a3442016-03-01 12:55:58 +090089import com.android.server.net.NetworkPinner;
Paul Jensend7b6ca92015-05-13 14:05:12 -040090
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090091import org.mockito.Mock;
92import org.mockito.MockitoAnnotations;
93import org.mockito.Spy;
94
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070095import java.net.InetAddress;
Paul Jensen4e1d3fd2016-04-08 13:56:52 -040096import java.util.ArrayList;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +090097import java.util.Arrays;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +090098import java.util.Objects;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +090099import java.util.concurrent.CountDownLatch;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900100import java.util.concurrent.LinkedBlockingQueue;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900101import java.util.concurrent.TimeUnit;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700102import java.util.concurrent.atomic.AtomicBoolean;
Hugo Benichi53d83d52016-11-15 13:42:34 +0900103import java.util.function.BooleanSupplier;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700104
105/**
106 * Tests for {@link ConnectivityService}.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400107 *
108 * Build, install and run with:
109 * runtest frameworks-services -c com.android.server.ConnectivityServiceTest
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700110 */
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700111public class ConnectivityServiceTest extends AndroidTestCase {
112 private static final String TAG = "ConnectivityServiceTest";
113
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900114 private static final int TIMEOUT_MS = 500;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900115 private static final int TEST_LINGER_DELAY_MS = 120;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900116
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700117 private BroadcastInterceptingContext mServiceContext;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400118 private WrappedConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900119 private WrappedConnectivityManager mCm;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400120 private MockNetworkAgent mWiFiNetworkAgent;
121 private MockNetworkAgent mCellNetworkAgent;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900122 private MockNetworkAgent mEthernetNetworkAgent;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700123
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900124 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
125 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
126 // reflect the state of our test ConnectivityService.
127 private class WrappedConnectivityManager extends ConnectivityManager {
128 private Network mFakeBoundNetwork;
129
130 public synchronized boolean bindProcessToNetwork(Network network) {
131 mFakeBoundNetwork = network;
132 return true;
133 }
134
135 public synchronized Network getBoundNetworkForProcess() {
136 return mFakeBoundNetwork;
137 }
138
139 public WrappedConnectivityManager(Context context, ConnectivityService service) {
140 super(context, service);
141 }
142 }
143
Paul Jensend7b6ca92015-05-13 14:05:12 -0400144 private class MockContext extends BroadcastInterceptingContext {
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900145 private final MockContentResolver mContentResolver;
146
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900147 @Spy private Resources mResources;
148
Paul Jensend7b6ca92015-05-13 14:05:12 -0400149 MockContext(Context base) {
150 super(base);
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900151
152 mResources = spy(base.getResources());
153 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
154 thenReturn(new String[] {
155 "wifi,1,1,1,-1,true",
156 "mobile,0,0,0,-1,true",
157 "mobile_mms,2,0,2,60000,true",
158 });
159
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900160 mContentResolver = new MockContentResolver();
161 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
Paul Jensend7b6ca92015-05-13 14:05:12 -0400162 }
163
164 @Override
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900165 public Object getSystemService(String name) {
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900166 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
167 if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400168 return super.getSystemService(name);
169 }
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900170
171 @Override
172 public ContentResolver getContentResolver() {
173 return mContentResolver;
174 }
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900175
176 @Override
177 public Resources getResources() {
178 return mResources;
179 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400180 }
181
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900182 /**
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900183 * Block until the given handler becomes idle, or until timeoutMs has passed.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900184 */
Lorenzo Colittiae3ce812017-01-25 23:09:07 +0900185 private static void waitForIdleHandler(HandlerThread handlerThread, int timeoutMs) {
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900186 final ConditionVariable cv = new ConditionVariable();
Lorenzo Colittiae3ce812017-01-25 23:09:07 +0900187 final Handler handler = new Handler(handlerThread.getLooper());
188 handler.post(() -> cv.open());
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900189 if (!cv.block(timeoutMs)) {
Lorenzo Colittiae3ce812017-01-25 23:09:07 +0900190 fail("HandlerThread " + handlerThread.getName() +
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900191 " did not become idle after " + timeoutMs + " ms");
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900192 }
193 }
194
Hugo Benichicfcc1cb2016-11-04 16:06:34 +0900195 @SmallTest
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900196 public void testWaitForIdle() {
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900197 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
198
199 // Tests that waitForIdle returns immediately if the service is already idle.
200 for (int i = 0; i < attempts; i++) {
201 mService.waitForIdle();
202 }
203
204 // Bring up a network that we can use to send messages to ConnectivityService.
205 ConditionVariable cv = waitForConnectivityBroadcasts(1);
206 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
207 mWiFiNetworkAgent.connect(false);
208 waitFor(cv);
209 Network n = mWiFiNetworkAgent.getNetwork();
210 assertNotNull(n);
211
212 // Tests that calling waitForIdle waits for messages to be processed.
213 for (int i = 0; i < attempts; i++) {
214 mWiFiNetworkAgent.setSignalStrength(i);
215 mService.waitForIdle();
216 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
217 }
Hugo Benichi5d540d12016-10-17 15:54:51 +0900218 }
219
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900220 // This test has an inherent race condition in it, and cannot be enabled for continuous testing
221 // or presubmit tests. It is kept for manual runs and documentation purposes.
222 public void verifyThatNotWaitingForIdleCausesRaceConditions() {
Hugo Benichi5d540d12016-10-17 15:54:51 +0900223 // Bring up a network that we can use to send messages to ConnectivityService.
224 ConditionVariable cv = waitForConnectivityBroadcasts(1);
225 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
226 mWiFiNetworkAgent.connect(false);
227 waitFor(cv);
228 Network n = mWiFiNetworkAgent.getNetwork();
229 assertNotNull(n);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900230
231 // Ensure that not calling waitForIdle causes a race condition.
Hugo Benichi5d540d12016-10-17 15:54:51 +0900232 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900233 for (int i = 0; i < attempts; i++) {
234 mWiFiNetworkAgent.setSignalStrength(i);
235 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
236 // We hit a race condition, as expected. Pass the test.
237 return;
238 }
239 }
240
241 // No race? There is a bug in this test.
242 fail("expected race condition at least once in " + attempts + " attempts");
243 }
244
Paul Jensend7b6ca92015-05-13 14:05:12 -0400245 private class MockNetworkAgent {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400246 private final WrappedNetworkMonitor mWrappedNetworkMonitor;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400247 private final NetworkInfo mNetworkInfo;
248 private final NetworkCapabilities mNetworkCapabilities;
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900249 private final HandlerThread mHandlerThread;
Paul Jensene0988542015-06-25 15:30:08 -0400250 private final ConditionVariable mDisconnected = new ConditionVariable();
Paul Jensen232437312016-04-06 09:51:26 -0400251 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
Calvin On1f64f3f2016-10-11 15:10:46 -0700252 private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
Paul Jensen3d911462015-06-12 06:40:24 -0400253 private int mScore;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400254 private NetworkAgent mNetworkAgent;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900255 private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
256 private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE;
257 private Integer mExpectedKeepaliveSlot = null;
Paul Jensen232437312016-04-06 09:51:26 -0400258 // Contains the redirectUrl from networkStatus(). Before reading, wait for
259 // mNetworkStatusReceived.
260 private String mRedirectUrl;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400261
262 MockNetworkAgent(int transport) {
263 final int type = transportToLegacyType(transport);
264 final String typeName = ConnectivityManager.getNetworkTypeName(type);
265 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
266 mNetworkCapabilities = new NetworkCapabilities();
267 mNetworkCapabilities.addTransportType(transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400268 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900269 case TRANSPORT_ETHERNET:
270 mScore = 70;
271 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400272 case TRANSPORT_WIFI:
Paul Jensen3d911462015-06-12 06:40:24 -0400273 mScore = 60;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400274 break;
275 case TRANSPORT_CELLULAR:
Paul Jensen3d911462015-06-12 06:40:24 -0400276 mScore = 50;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400277 break;
278 default:
279 throw new UnsupportedOperationException("unimplemented network type");
280 }
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900281 mHandlerThread = new HandlerThread("Mock-" + typeName);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900282 mHandlerThread.start();
283 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
284 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
285 new LinkProperties(), mScore, new NetworkMisc()) {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900286 @Override
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900287 public void unwanted() { mDisconnected.open(); }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900288
289 @Override
290 public void startPacketKeepalive(Message msg) {
291 int slot = msg.arg1;
292 if (mExpectedKeepaliveSlot != null) {
293 assertEquals((int) mExpectedKeepaliveSlot, slot);
294 }
295 onPacketKeepaliveEvent(slot, mStartKeepaliveError);
296 }
297
298 @Override
299 public void stopPacketKeepalive(Message msg) {
300 onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
301 }
Paul Jensen232437312016-04-06 09:51:26 -0400302
303 @Override
304 public void networkStatus(int status, String redirectUrl) {
305 mRedirectUrl = redirectUrl;
306 mNetworkStatusReceived.open();
307 }
Calvin On1f64f3f2016-10-11 15:10:46 -0700308
309 @Override
310 protected void preventAutomaticReconnect() {
311 mPreventReconnectReceived.open();
312 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400313 };
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900314 // Waits for the NetworkAgent to be registered, which includes the creation of the
315 // NetworkMonitor.
316 mService.waitForIdle();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400317 mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor();
Paul Jensen3d911462015-06-12 06:40:24 -0400318 }
319
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900320 public void waitForIdle(int timeoutMs) {
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900321 waitForIdleHandler(mHandlerThread, timeoutMs);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900322 }
323
324 public void waitForIdle() {
325 waitForIdle(TIMEOUT_MS);
326 }
327
Paul Jensen3d911462015-06-12 06:40:24 -0400328 public void adjustScore(int change) {
329 mScore += change;
330 mNetworkAgent.sendNetworkScore(mScore);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400331 }
332
Paul Jensen85cf78e2015-06-25 13:25:07 -0400333 public void addCapability(int capability) {
334 mNetworkCapabilities.addCapability(capability);
335 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
336 }
337
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900338 public void removeCapability(int capability) {
339 mNetworkCapabilities.removeCapability(capability);
340 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
341 }
342
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900343 public void setSignalStrength(int signalStrength) {
344 mNetworkCapabilities.setSignalStrength(signalStrength);
345 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
346 }
347
Lorenzo Colitti6556a222017-04-03 17:46:35 +0900348 public void setNetworkSpecifier(String specifier) {
349 mNetworkCapabilities.setNetworkSpecifier(specifier);
350 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
351 }
352
Paul Jensene0988542015-06-25 15:30:08 -0400353 public void connectWithoutInternet() {
354 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
355 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
356 }
357
Paul Jensend7b6ca92015-05-13 14:05:12 -0400358 /**
Paul Jensene0988542015-06-25 15:30:08 -0400359 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400360 * @param validated Indicate if network should pretend to be validated.
361 */
362 public void connect(boolean validated) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900363 assertEquals("MockNetworkAgents can only be connected once",
364 mNetworkInfo.getDetailedState(), DetailedState.IDLE);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400365 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
366
Paul Jensend7b6ca92015-05-13 14:05:12 -0400367 NetworkCallback callback = null;
368 final ConditionVariable validatedCv = new ConditionVariable();
369 if (validated) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400370 mWrappedNetworkMonitor.gen204ProbeResult = 204;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400371 NetworkRequest request = new NetworkRequest.Builder()
372 .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
373 .build();
374 callback = new NetworkCallback() {
375 public void onCapabilitiesChanged(Network network,
376 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400377 if (network.equals(getNetwork()) &&
378 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400379 validatedCv.open();
380 }
381 }
382 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400383 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400384 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400385 addCapability(NET_CAPABILITY_INTERNET);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400386
Paul Jensene0988542015-06-25 15:30:08 -0400387 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400388
389 if (validated) {
390 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400391 waitFor(validatedCv);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400392 mWrappedNetworkMonitor.gen204ProbeResult = 500;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400393 }
394
395 if (callback != null) mCm.unregisterNetworkCallback(callback);
396 }
397
Paul Jensen232437312016-04-06 09:51:26 -0400398 public void connectWithCaptivePortal(String redirectUrl) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400399 mWrappedNetworkMonitor.gen204ProbeResult = 200;
Paul Jensen232437312016-04-06 09:51:26 -0400400 mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400401 connect(false);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400402 }
403
Erik Kline1d3db322017-02-28 16:20:20 +0900404 public void suspend() {
405 mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null);
406 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
407 }
408
Paul Jensend7b6ca92015-05-13 14:05:12 -0400409 public void disconnect() {
410 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
411 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
412 }
413
414 public Network getNetwork() {
415 return new Network(mNetworkAgent.netId);
416 }
Paul Jensene0988542015-06-25 15:30:08 -0400417
Calvin On1f64f3f2016-10-11 15:10:46 -0700418 public ConditionVariable getPreventReconnectReceived() {
419 return mPreventReconnectReceived;
420 }
421
Paul Jensene0988542015-06-25 15:30:08 -0400422 public ConditionVariable getDisconnectedCV() {
423 return mDisconnected;
424 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400425
426 public WrappedNetworkMonitor getWrappedNetworkMonitor() {
427 return mWrappedNetworkMonitor;
428 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900429
430 public void sendLinkProperties(LinkProperties lp) {
431 mNetworkAgent.sendLinkProperties(lp);
432 }
433
434 public void setStartKeepaliveError(int error) {
435 mStartKeepaliveError = error;
436 }
437
438 public void setStopKeepaliveError(int error) {
439 mStopKeepaliveError = error;
440 }
441
442 public void setExpectedKeepaliveSlot(Integer slot) {
443 mExpectedKeepaliveSlot = slot;
444 }
Paul Jensen232437312016-04-06 09:51:26 -0400445
446 public String waitForRedirectUrl() {
447 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
448 return mRedirectUrl;
449 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400450 }
451
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900452 /**
453 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
454 * operations have been processed. Before ConnectivityService can add or remove any requests,
455 * the factory must be told to expect those operations by calling expectAddRequests or
456 * expectRemoveRequests.
457 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700458 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400459 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
460 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400461 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700462
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900463 // Used to expect that requests be removed or added on a separate thread, without sleeping.
464 // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then
465 // cause some other thread to add or remove requests, then call waitForRequests(). We can
466 // either expect requests to be added or removed, but not both, because CountDownLatch can
467 // only count in one direction.
468 private CountDownLatch mExpectations;
469
470 // Whether we are currently expecting requests to be added or removed. Valid only if
471 // mExpectations is non-null.
472 private boolean mExpectingAdditions;
473
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700474 public MockNetworkFactory(Looper looper, Context context, String logTag,
475 NetworkCapabilities filter) {
476 super(looper, context, logTag, filter);
477 }
478
479 public int getMyRequestCount() {
480 return getRequestCount();
481 }
482
483 protected void startNetwork() {
484 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400485 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700486 }
487
488 protected void stopNetwork() {
489 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400490 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700491 }
492
493 public boolean getMyStartRequested() {
494 return mNetworkStarted.get();
495 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400496
497 public ConditionVariable getNetworkStartedCV() {
498 mNetworkStartedCV.close();
499 return mNetworkStartedCV;
500 }
501
502 public ConditionVariable getNetworkStoppedCV() {
503 mNetworkStoppedCV.close();
504 return mNetworkStoppedCV;
505 }
506
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900507 @Override
508 protected void handleAddRequest(NetworkRequest request, int score) {
509 // If we're expecting anything, we must be expecting additions.
510 if (mExpectations != null && !mExpectingAdditions) {
511 fail("Can't add requests while expecting requests to be removed");
512 }
513
514 // Add the request.
515 super.handleAddRequest(request, score);
516
517 // Reduce the number of request additions we're waiting for.
518 if (mExpectingAdditions) {
519 assertTrue("Added more requests than expected", mExpectations.getCount() > 0);
520 mExpectations.countDown();
521 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400522 }
523
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900524 @Override
525 protected void handleRemoveRequest(NetworkRequest request) {
526 // If we're expecting anything, we must be expecting removals.
527 if (mExpectations != null && mExpectingAdditions) {
528 fail("Can't remove requests while expecting requests to be added");
529 }
530
531 // Remove the request.
532 super.handleRemoveRequest(request);
533
534 // Reduce the number of request removals we're waiting for.
535 if (!mExpectingAdditions) {
536 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0);
537 mExpectations.countDown();
538 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400539 }
540
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900541 private void assertNoExpectations() {
542 if (mExpectations != null) {
543 fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
544 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400545 }
546
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900547 // Expects that count requests will be added.
548 public void expectAddRequests(final int count) {
549 assertNoExpectations();
550 mExpectingAdditions = true;
551 mExpectations = new CountDownLatch(count);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400552 }
553
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900554 // Expects that count requests will be removed.
555 public void expectRemoveRequests(final int count) {
556 assertNoExpectations();
557 mExpectingAdditions = false;
558 mExpectations = new CountDownLatch(count);
559 }
560
561 // Waits for the expected request additions or removals to happen within a timeout.
562 public void waitForRequests() throws InterruptedException {
563 assertNotNull("Nothing to wait for", mExpectations);
564 mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
565 final long count = mExpectations.getCount();
566 final String msg = count + " requests still not " +
567 (mExpectingAdditions ? "added" : "removed") +
568 " after " + TIMEOUT_MS + " ms";
569 assertEquals(msg, 0, count);
570 mExpectations = null;
571 }
572
573 public void waitForNetworkRequests(final int count) throws InterruptedException {
574 waitForRequests();
575 assertEquals(count, getMyRequestCount());
Paul Jensen0a2823e2015-06-12 10:31:09 -0400576 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700577 }
578
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900579 private class FakeWakeupMessage extends WakeupMessage {
580 private static final int UNREASONABLY_LONG_WAIT = 1000;
581
582 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
583 super(context, handler, cmdName, cmd);
584 }
585
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900586 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
587 int arg1, int arg2, Object obj) {
588 super(context, handler, cmdName, cmd, arg1, arg2, obj);
589 }
590
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900591 @Override
592 public void schedule(long when) {
593 long delayMs = when - SystemClock.elapsedRealtime();
594 if (delayMs < 0) delayMs = 0;
595 if (delayMs > UNREASONABLY_LONG_WAIT) {
596 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
597 "ms into the future: " + delayMs);
598 }
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900599 Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
600 mHandler.sendMessageDelayed(msg, delayMs);
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900601 }
602
603 @Override
604 public void cancel() {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900605 mHandler.removeMessages(mCmd, mObj);
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900606 }
607
608 @Override
609 public void onAlarm() {
610 throw new AssertionError("Should never happen. Update this fake.");
611 }
612 }
613
Paul Jensencf4c2c62015-07-01 14:16:32 -0400614 // NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
615 private class WrappedNetworkMonitor extends NetworkMonitor {
616 // HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
617 public int gen204ProbeResult = 500;
Paul Jensen232437312016-04-06 09:51:26 -0400618 public String gen204ProbeRedirectUrl = null;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400619
620 public WrappedNetworkMonitor(Context context, Handler handler,
Hugo Benichif9fdf872016-07-28 17:53:06 +0900621 NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest,
622 IpConnectivityLog log) {
623 super(context, handler, networkAgentInfo, defaultRequest, log);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400624 }
625
626 @Override
Paul Jensen232437312016-04-06 09:51:26 -0400627 protected CaptivePortalProbeResult isCaptivePortal() {
Calvin On1f64f3f2016-10-11 15:10:46 -0700628 if (!mIsCaptivePortalCheckEnabled) { return new CaptivePortalProbeResult(204); }
Hugo Benichid953bf82016-09-27 09:22:35 +0900629 return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl, null);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400630 }
631 }
632
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900633 private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
Hugo Benichi53d83d52016-11-15 13:42:34 +0900634 public volatile boolean configRestrictsAvoidBadWifi;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400635
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900636 public WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
Erik Kline065ab6e2016-10-02 18:02:14 +0900637 super(c, h, r);
638 }
639
640 @Override
641 public boolean configRestrictsAvoidBadWifi() {
642 return configRestrictsAvoidBadWifi;
643 }
644 }
645
646 private class WrappedConnectivityService extends ConnectivityService {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900647 public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
Erik Kline065ab6e2016-10-02 18:02:14 +0900648 private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900649 private MockableSystemProperties mSystemProperties;
Erik Kline065ab6e2016-10-02 18:02:14 +0900650
Paul Jensend7b6ca92015-05-13 14:05:12 -0400651 public WrappedConnectivityService(Context context, INetworkManagementService netManager,
Hugo Benichif9fdf872016-07-28 17:53:06 +0900652 INetworkStatsService statsService, INetworkPolicyManager policyManager,
653 IpConnectivityLog log) {
654 super(context, netManager, statsService, policyManager, log);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900655 mLingerDelayMs = TEST_LINGER_DELAY_MS;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400656 }
657
658 @Override
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900659 protected MockableSystemProperties getSystemProperties() {
660 // Minimal approach to overriding system properties: let most calls fall through to real
661 // device values, and only override ones values that are important to this test.
662 mSystemProperties = spy(new MockableSystemProperties());
663 when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
664 when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
665 return mSystemProperties;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400666 }
Paul Jensen67b0b072015-06-10 11:22:17 -0400667
668 @Override
669 protected int reserveNetId() {
670 while (true) {
671 final int netId = super.reserveNetId();
672
673 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
674 // can have odd side-effects, like network validations succeeding.
675 final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks();
676 boolean overlaps = false;
677 for (Network network : networks) {
678 if (netId == network.netId) {
679 overlaps = true;
680 break;
681 }
682 }
683 if (overlaps) continue;
684
685 return netId;
686 }
687 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400688
689 @Override
690 public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
691 NetworkAgentInfo nai, NetworkRequest defaultRequest) {
Hugo Benichif9fdf872016-07-28 17:53:06 +0900692 final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(
693 context, handler, nai, defaultRequest, mock(IpConnectivityLog.class));
Paul Jensencf4c2c62015-07-01 14:16:32 -0400694 mLastCreatedNetworkMonitor = monitor;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400695 return monitor;
696 }
697
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900698 @Override
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900699 public MultinetworkPolicyTracker createMultinetworkPolicyTracker(
Erik Kline065ab6e2016-10-02 18:02:14 +0900700 Context c, Handler h, Runnable r) {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900701 final WrappedMultinetworkPolicyTracker tracker = new WrappedMultinetworkPolicyTracker(c, h, r);
Erik Kline065ab6e2016-10-02 18:02:14 +0900702 return tracker;
703 }
704
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900705 public WrappedMultinetworkPolicyTracker getMultinetworkPolicyTracker() {
706 return (WrappedMultinetworkPolicyTracker) mMultinetworkPolicyTracker;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900707 }
708
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900709 @Override
Erik Kline065ab6e2016-10-02 18:02:14 +0900710 public WakeupMessage makeWakeupMessage(
711 Context context, Handler handler, String cmdName, int cmd, Object obj) {
712 return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900713 }
714
Paul Jensencf4c2c62015-07-01 14:16:32 -0400715 public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
716 return mLastCreatedNetworkMonitor;
717 }
718
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900719 public void waitForIdle(int timeoutMs) {
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900720 waitForIdleHandler(mHandlerThread, timeoutMs);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400721 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900722
723 public void waitForIdle() {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900724 waitForIdle(TIMEOUT_MS);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900725 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400726 }
727
Paul Jensen3d911462015-06-12 06:40:24 -0400728 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900729 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
730 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -0400731 */
732 static private void waitFor(ConditionVariable conditionVariable) {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900733 assertTrue(conditionVariable.block(TIMEOUT_MS));
Paul Jensen3d911462015-06-12 06:40:24 -0400734 }
735
Paul Jensend7b6ca92015-05-13 14:05:12 -0400736 @Override
737 public void setUp() throws Exception {
738 super.setUp();
739
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +0900740 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
741 // http://b/25897652 .
742 if (Looper.myLooper() == null) {
743 Looper.prepare();
744 }
745
Paul Jensend7b6ca92015-05-13 14:05:12 -0400746 mServiceContext = new MockContext(getContext());
Lorenzo Colitti83fa2582015-08-07 12:49:01 +0900747 mService = new WrappedConnectivityService(mServiceContext,
748 mock(INetworkManagementService.class),
749 mock(INetworkStatsService.class),
Hugo Benichif9fdf872016-07-28 17:53:06 +0900750 mock(INetworkPolicyManager.class),
751 mock(IpConnectivityLog.class));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400752
Paul Jensend7b6ca92015-05-13 14:05:12 -0400753 mService.systemReady();
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900754 mCm = new WrappedConnectivityManager(getContext(), mService);
755 mCm.bindProcessToNetwork(null);
Calvin On1f64f3f2016-10-11 15:10:46 -0700756
757 // Ensure that the default setting for Captive Portals is used for most tests
758 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400759 }
760
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +0900761 public void tearDown() throws Exception {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +0900762 setMobileDataAlwaysOn(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +0900763 if (mCellNetworkAgent != null) { mCellNetworkAgent.disconnect(); }
764 if (mWiFiNetworkAgent != null) { mWiFiNetworkAgent.disconnect(); }
765 mCellNetworkAgent = mWiFiNetworkAgent = null;
766 super.tearDown();
767 }
768
Paul Jensend7b6ca92015-05-13 14:05:12 -0400769 private int transportToLegacyType(int transport) {
770 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900771 case TRANSPORT_ETHERNET:
772 return TYPE_ETHERNET;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400773 case TRANSPORT_WIFI:
774 return TYPE_WIFI;
775 case TRANSPORT_CELLULAR:
776 return TYPE_MOBILE;
777 default:
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900778 throw new IllegalStateException("Unknown transport " + transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400779 }
780 }
781
782 private void verifyActiveNetwork(int transport) {
783 // Test getActiveNetworkInfo()
784 assertNotNull(mCm.getActiveNetworkInfo());
785 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
786 // Test getActiveNetwork()
787 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +0000788 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400789 switch (transport) {
790 case TRANSPORT_WIFI:
791 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
792 break;
793 case TRANSPORT_CELLULAR:
794 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
795 break;
796 default:
797 throw new IllegalStateException("Unknown transport" + transport);
798 }
799 // Test getNetworkInfo(Network)
800 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
801 assertEquals(transportToLegacyType(transport), mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
802 // Test getNetworkCapabilities(Network)
803 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
804 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
805 }
806
807 private void verifyNoNetwork() {
808 // Test getActiveNetworkInfo()
809 assertNull(mCm.getActiveNetworkInfo());
810 // Test getActiveNetwork()
811 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +0000812 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400813 // Test getAllNetworks()
814 assertEquals(0, mCm.getAllNetworks().length);
815 }
816
817 /**
818 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
819 * broadcasts are received.
820 */
821 private ConditionVariable waitForConnectivityBroadcasts(final int count) {
822 final ConditionVariable cv = new ConditionVariable();
823 mServiceContext.registerReceiver(new BroadcastReceiver() {
824 private int remaining = count;
825 public void onReceive(Context context, Intent intent) {
826 if (--remaining == 0) {
827 cv.open();
828 mServiceContext.unregisterReceiver(this);
829 }
830 }
831 }, new IntentFilter(CONNECTIVITY_ACTION));
832 return cv;
833 }
834
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900835 public void testNetworkTypes() {
836 // Ensure that our mocks for the networkAttributes config variable work as expected. If they
837 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
838 // will fail. Failing here is much easier to debug.
839 assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
840 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
841 }
842
Hugo Benichicfcc1cb2016-11-04 16:06:34 +0900843 @SmallTest
Paul Jensend7b6ca92015-05-13 14:05:12 -0400844 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400845 verifyNoNetwork();
846 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
847 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
848 assertNull(mCm.getActiveNetworkInfo());
849 assertNull(mCm.getActiveNetwork());
850 // Test bringing up validated cellular.
851 ConditionVariable cv = waitForConnectivityBroadcasts(1);
852 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -0400853 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400854 verifyActiveNetwork(TRANSPORT_CELLULAR);
855 assertEquals(2, mCm.getAllNetworks().length);
856 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
857 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
858 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
859 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
860 // Test bringing up validated WiFi.
861 cv = waitForConnectivityBroadcasts(2);
862 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -0400863 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400864 verifyActiveNetwork(TRANSPORT_WIFI);
865 assertEquals(2, mCm.getAllNetworks().length);
866 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
867 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
868 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
869 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
870 // Test cellular linger timeout.
Lorenzo Colittid2706122017-01-30 17:45:49 +0900871 waitFor(mCellNetworkAgent.getDisconnectedCV());
872 mService.waitForIdle();
873 assertEquals(1, mCm.getAllNetworks().length);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400874 verifyActiveNetwork(TRANSPORT_WIFI);
875 assertEquals(1, mCm.getAllNetworks().length);
876 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
877 // Test WiFi disconnect.
878 cv = waitForConnectivityBroadcasts(1);
879 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400880 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400881 verifyNoNetwork();
882 }
883
Hugo Benichicfcc1cb2016-11-04 16:06:34 +0900884 @SmallTest
Paul Jensend7b6ca92015-05-13 14:05:12 -0400885 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
886 // Test bringing up unvalidated WiFi
887 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
888 ConditionVariable cv = waitForConnectivityBroadcasts(1);
889 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -0400890 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400891 verifyActiveNetwork(TRANSPORT_WIFI);
892 // Test bringing up unvalidated cellular
893 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
894 mCellNetworkAgent.connect(false);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900895 mService.waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400896 verifyActiveNetwork(TRANSPORT_WIFI);
897 // Test cellular disconnect.
898 mCellNetworkAgent.disconnect();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900899 mService.waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400900 verifyActiveNetwork(TRANSPORT_WIFI);
901 // Test bringing up validated cellular
902 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
903 cv = waitForConnectivityBroadcasts(2);
904 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -0400905 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400906 verifyActiveNetwork(TRANSPORT_CELLULAR);
907 // Test cellular disconnect.
908 cv = waitForConnectivityBroadcasts(2);
909 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400910 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400911 verifyActiveNetwork(TRANSPORT_WIFI);
912 // Test WiFi disconnect.
913 cv = waitForConnectivityBroadcasts(1);
914 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400915 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400916 verifyNoNetwork();
917 }
918
Hugo Benichicfcc1cb2016-11-04 16:06:34 +0900919 @SmallTest
Paul Jensend7b6ca92015-05-13 14:05:12 -0400920 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
921 // Test bringing up unvalidated cellular.
922 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
923 ConditionVariable cv = waitForConnectivityBroadcasts(1);
924 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -0400925 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400926 verifyActiveNetwork(TRANSPORT_CELLULAR);
927 // Test bringing up unvalidated WiFi.
928 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
929 cv = waitForConnectivityBroadcasts(2);
930 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -0400931 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400932 verifyActiveNetwork(TRANSPORT_WIFI);
933 // Test WiFi disconnect.
934 cv = waitForConnectivityBroadcasts(2);
935 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400936 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400937 verifyActiveNetwork(TRANSPORT_CELLULAR);
938 // Test cellular disconnect.
939 cv = waitForConnectivityBroadcasts(1);
940 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400941 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400942 verifyNoNetwork();
943 }
944
Hugo Benichicfcc1cb2016-11-04 16:06:34 +0900945 @SmallTest
Paul Jensene0988542015-06-25 15:30:08 -0400946 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400947 // Test bringing up unvalidated WiFi.
Paul Jensene0988542015-06-25 15:30:08 -0400948 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400949 ConditionVariable cv = waitForConnectivityBroadcasts(1);
950 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -0400951 waitFor(cv);
952 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400953 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -0400954 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -0400955 // Test bringing up validated cellular.
956 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -0400957 cv = waitForConnectivityBroadcasts(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400958 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -0400959 waitFor(cv);
960 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400961 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
962 NET_CAPABILITY_VALIDATED));
963 // Test cellular disconnect.
964 cv = waitForConnectivityBroadcasts(2);
965 mCellNetworkAgent.disconnect();
966 waitFor(cv);
967 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -0400968 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -0400969 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -0400970 NET_CAPABILITY_VALIDATED));
971 }
972
Hugo Benichicfcc1cb2016-11-04 16:06:34 +0900973 @SmallTest
Paul Jensen3d911462015-06-12 06:40:24 -0400974 public void testCellularOutscoresWeakWifi() throws Exception {
975 // Test bringing up validated cellular.
976 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
977 ConditionVariable cv = waitForConnectivityBroadcasts(1);
978 mCellNetworkAgent.connect(true);
979 waitFor(cv);
980 verifyActiveNetwork(TRANSPORT_CELLULAR);
981 // Test bringing up validated WiFi.
982 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
983 cv = waitForConnectivityBroadcasts(2);
984 mWiFiNetworkAgent.connect(true);
985 waitFor(cv);
986 verifyActiveNetwork(TRANSPORT_WIFI);
987 // Test WiFi getting really weak.
988 cv = waitForConnectivityBroadcasts(2);
989 mWiFiNetworkAgent.adjustScore(-11);
990 waitFor(cv);
991 verifyActiveNetwork(TRANSPORT_CELLULAR);
992 // Test WiFi restoring signal strength.
993 cv = waitForConnectivityBroadcasts(2);
994 mWiFiNetworkAgent.adjustScore(11);
995 waitFor(cv);
996 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -0400997 }
998
Hugo Benichicfcc1cb2016-11-04 16:06:34 +0900999 @SmallTest
Paul Jensene0988542015-06-25 15:30:08 -04001000 public void testReapingNetwork() throws Exception {
1001 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1002 // Expect it to be torn down immediately because it satisfies no requests.
1003 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1004 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
1005 mWiFiNetworkAgent.connectWithoutInternet();
1006 waitFor(cv);
1007 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1008 // Expect it to be torn down immediately because it satisfies no requests.
1009 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1010 cv = mCellNetworkAgent.getDisconnectedCV();
1011 mCellNetworkAgent.connectWithoutInternet();
1012 waitFor(cv);
1013 // Test bringing up validated WiFi.
1014 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1015 cv = waitForConnectivityBroadcasts(1);
1016 mWiFiNetworkAgent.connect(true);
1017 waitFor(cv);
1018 verifyActiveNetwork(TRANSPORT_WIFI);
1019 // Test bringing up unvalidated cellular.
1020 // Expect it to be torn down because it could never be the highest scoring network
1021 // satisfying the default request even if it validated.
1022 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1023 cv = mCellNetworkAgent.getDisconnectedCV();
1024 mCellNetworkAgent.connect(false);
1025 waitFor(cv);
1026 verifyActiveNetwork(TRANSPORT_WIFI);
1027 cv = mWiFiNetworkAgent.getDisconnectedCV();
1028 mWiFiNetworkAgent.disconnect();
1029 waitFor(cv);
1030 }
1031
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001032 @SmallTest
Paul Jensene0988542015-06-25 15:30:08 -04001033 public void testCellularFallback() throws Exception {
1034 // Test bringing up validated cellular.
1035 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1036 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1037 mCellNetworkAgent.connect(true);
1038 waitFor(cv);
1039 verifyActiveNetwork(TRANSPORT_CELLULAR);
1040 // Test bringing up validated WiFi.
1041 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1042 cv = waitForConnectivityBroadcasts(2);
1043 mWiFiNetworkAgent.connect(true);
1044 waitFor(cv);
1045 verifyActiveNetwork(TRANSPORT_WIFI);
1046 // Reevaluate WiFi (it'll instantly fail DNS).
1047 cv = waitForConnectivityBroadcasts(2);
1048 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1049 NET_CAPABILITY_VALIDATED));
1050 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1051 // Should quickly fall back to Cellular.
1052 waitFor(cv);
1053 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1054 NET_CAPABILITY_VALIDATED));
1055 verifyActiveNetwork(TRANSPORT_CELLULAR);
1056 // Reevaluate cellular (it'll instantly fail DNS).
1057 cv = waitForConnectivityBroadcasts(2);
1058 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1059 NET_CAPABILITY_VALIDATED));
1060 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1061 // Should quickly fall back to WiFi.
1062 waitFor(cv);
1063 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1064 NET_CAPABILITY_VALIDATED));
1065 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1066 NET_CAPABILITY_VALIDATED));
1067 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001068 }
1069
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001070 @SmallTest
Paul Jensene0988542015-06-25 15:30:08 -04001071 public void testWiFiFallback() throws Exception {
1072 // Test bringing up unvalidated WiFi.
1073 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1074 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1075 mWiFiNetworkAgent.connect(false);
1076 waitFor(cv);
1077 verifyActiveNetwork(TRANSPORT_WIFI);
1078 // Test bringing up validated cellular.
1079 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1080 cv = waitForConnectivityBroadcasts(2);
1081 mCellNetworkAgent.connect(true);
1082 waitFor(cv);
1083 verifyActiveNetwork(TRANSPORT_CELLULAR);
1084 // Reevaluate cellular (it'll instantly fail DNS).
1085 cv = waitForConnectivityBroadcasts(2);
1086 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1087 NET_CAPABILITY_VALIDATED));
1088 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1089 // Should quickly fall back to WiFi.
1090 waitFor(cv);
1091 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1092 NET_CAPABILITY_VALIDATED));
1093 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001094 }
1095
Paul Jensen3d911462015-06-12 06:40:24 -04001096 enum CallbackState {
1097 NONE,
1098 AVAILABLE,
Erik Klineacdd6392016-07-07 16:50:58 +09001099 NETWORK_CAPABILITIES,
1100 LINK_PROPERTIES,
Erik Kline1d3db322017-02-28 16:20:20 +09001101 SUSPENDED,
Paul Jensen3d911462015-06-12 06:40:24 -04001102 LOSING,
Erik Kline3841a482015-11-25 12:49:38 +09001103 LOST,
1104 UNAVAILABLE
Paul Jensen3d911462015-06-12 06:40:24 -04001105 }
1106
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001107 private static class CallbackInfo {
1108 public final CallbackState state;
1109 public final Network network;
1110 public final Object arg;
1111 public CallbackInfo(CallbackState s, Network n, Object o) {
1112 state = s; network = n; arg = o;
1113 }
1114 public String toString() {
Erik Kline1d3db322017-02-28 16:20:20 +09001115 return String.format("%s (%s) (%s)", state, network, arg);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001116 }
1117 @Override
1118 public boolean equals(Object o) {
1119 if (!(o instanceof CallbackInfo)) return false;
1120 // Ignore timeMs, since it's unpredictable.
1121 CallbackInfo other = (CallbackInfo) o;
1122 return (state == other.state) && Objects.equals(network, other.network);
1123 }
1124 @Override
1125 public int hashCode() {
1126 return Objects.hash(state, network);
1127 }
1128 }
1129
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001130 /**
1131 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1132 * this class receives, by calling expectCallback() exactly once each time a callback is
1133 * received. assertNoCallback may be called at any time.
1134 */
Paul Jensen3d911462015-06-12 06:40:24 -04001135 private class TestNetworkCallback extends NetworkCallback {
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001136 // Chosen to be much less than the linger timeout. This ensures that we can distinguish
1137 // between a LOST callback that arrives immediately and a LOST callback that arrives after
1138 // the linger timeout.
Hugo Benichidfb559a2016-12-20 14:57:49 +09001139 private final static int TIMEOUT_MS = 100;
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001140
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001141 private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
1142
Erik Klineacdd6392016-07-07 16:50:58 +09001143 protected void setLastCallback(CallbackState state, Network network, Object o) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001144 mCallbacks.offer(new CallbackInfo(state, network, o));
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001145 }
Paul Jensen3d911462015-06-12 06:40:24 -04001146
Erik Klineacdd6392016-07-07 16:50:58 +09001147 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001148 public void onAvailable(Network network) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001149 setLastCallback(CallbackState.AVAILABLE, network, null);
Paul Jensen3d911462015-06-12 06:40:24 -04001150 }
1151
Erik Klineacdd6392016-07-07 16:50:58 +09001152 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001153 public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
1154 setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
1155 }
1156
1157 @Override
1158 public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
1159 setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
1160 }
1161
1162 @Override
Erik Kline3841a482015-11-25 12:49:38 +09001163 public void onUnavailable() {
1164 setLastCallback(CallbackState.UNAVAILABLE, null, null);
1165 }
1166
1167 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001168 public void onNetworkSuspended(Network network) {
1169 setLastCallback(CallbackState.SUSPENDED, network, null);
1170 }
1171
1172 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001173 public void onLosing(Network network, int maxMsToLive) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001174 setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
Paul Jensen3d911462015-06-12 06:40:24 -04001175 }
1176
Erik Klineacdd6392016-07-07 16:50:58 +09001177 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001178 public void onLost(Network network) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001179 setLastCallback(CallbackState.LOST, network, null);
1180 }
1181
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001182 CallbackInfo nextCallback(int timeoutMs) {
1183 CallbackInfo cb = null;
1184 try {
1185 cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
1186 } catch (InterruptedException e) {
1187 }
1188 if (cb == null) {
1189 // LinkedBlockingQueue.poll() returns null if it timeouts.
1190 fail("Did not receive callback after " + timeoutMs + "ms");
1191 }
1192 return cb;
1193 }
1194
Erik Kline1d3db322017-02-28 16:20:20 +09001195 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs) {
1196 final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null;
1197 CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001198 CallbackInfo actual = nextCallback(timeoutMs);
1199 assertEquals("Unexpected callback:", expected, actual);
Erik Kline1d3db322017-02-28 16:20:20 +09001200
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001201 if (state == CallbackState.LOSING) {
1202 String msg = String.format(
1203 "Invalid linger time value %d, must be between %d and %d",
1204 actual.arg, 0, TEST_LINGER_DELAY_MS);
1205 int maxMsToLive = (Integer) actual.arg;
1206 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= TEST_LINGER_DELAY_MS);
1207 }
Erik Kline1d3db322017-02-28 16:20:20 +09001208
1209 return actual;
Erik Klinea2d29402016-03-16 15:31:39 +09001210 }
1211
Erik Kline1d3db322017-02-28 16:20:20 +09001212 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) {
1213 return expectCallback(state, agent, TIMEOUT_MS);
1214 }
1215
1216 void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended, int timeoutMs) {
1217 expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
Erik Klinec75d4fa2017-02-15 19:59:17 +09001218 if (expectSuspended) {
1219 expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001220 }
Erik Klinec75d4fa2017-02-15 19:59:17 +09001221 expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
1222 expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001223 }
1224
1225 void expectAvailableCallbacks(MockNetworkAgent agent) {
1226 expectAvailableCallbacks(agent, false, TIMEOUT_MS);
1227 }
1228
1229 void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent) {
1230 expectAvailableCallbacks(agent, true, TIMEOUT_MS);
1231 }
1232
1233 void expectAvailableAndValidatedCallbacks(MockNetworkAgent agent) {
Erik Klinec75d4fa2017-02-15 19:59:17 +09001234 expectAvailableCallbacks(agent, false, TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001235 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1236 }
1237
1238 void expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
1239 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
1240 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1241 assertTrue(nc.hasCapability(capability));
1242 }
1243
1244 void expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
1245 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
1246 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1247 assertFalse(nc.hasCapability(capability));
Paul Jensen3d911462015-06-12 06:40:24 -04001248 }
1249
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001250 void assertNoCallback() {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001251 mService.waitForIdle();
1252 CallbackInfo c = mCallbacks.peek();
1253 assertNull("Unexpected callback: " + c, c);
1254 }
1255 }
1256
1257 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1258 // only be declared in a static or top level type".
1259 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1260 for (TestNetworkCallback c : callbacks) {
1261 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001262 }
1263 }
1264
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001265 @SmallTest
Paul Jensen3d911462015-06-12 06:40:24 -04001266 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001267 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001268 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1269 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001270 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1271 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001272 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1273 .addTransportType(TRANSPORT_WIFI).build();
1274 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1275 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001276 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001277 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1278 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1279
1280 // Test unvalidated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001281 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1282 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1283 mCellNetworkAgent.connect(false);
Erik Kline1d3db322017-02-28 16:20:20 +09001284 genericNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent);
1285 cellNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001286 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1287 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001288 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001289
Paul Jensen3d911462015-06-12 06:40:24 -04001290 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1291 mCellNetworkAgent.adjustScore(-1);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001292 mService.waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001293 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001294 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1295
Paul Jensen3d911462015-06-12 06:40:24 -04001296 cv = waitForConnectivityBroadcasts(2);
1297 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1298 mWiFiNetworkAgent.connect(false);
Erik Kline1d3db322017-02-28 16:20:20 +09001299 genericNetworkCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
1300 wifiNetworkCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001301 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1302 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001303 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001304
Paul Jensen3d911462015-06-12 06:40:24 -04001305 cv = waitForConnectivityBroadcasts(2);
1306 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001307 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1308 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001309 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001310 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001311 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001312
Paul Jensen3d911462015-06-12 06:40:24 -04001313 cv = waitForConnectivityBroadcasts(1);
1314 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001315 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1316 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001317 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001318 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001319
1320 // Test validated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001321 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1322 mCellNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09001323 genericNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
1324 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001325 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001326 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001327
Paul Jensen3d911462015-06-12 06:40:24 -04001328 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1329 mCellNetworkAgent.adjustScore(-1);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001330 mService.waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001331 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001332 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1333
Paul Jensen3d911462015-06-12 06:40:24 -04001334 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1335 mWiFiNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09001336 genericNetworkCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001337 genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001338 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
1339 wifiNetworkCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001340 cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001341 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001342 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001343
Paul Jensen3d911462015-06-12 06:40:24 -04001344 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001345 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1346 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1347 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001348
Paul Jensen3d911462015-06-12 06:40:24 -04001349 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001350 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1351 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1352 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001353 }
1354
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001355 @SmallTest
1356 public void testMultipleLingering() {
1357 NetworkRequest request = new NetworkRequest.Builder()
1358 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1359 .build();
1360 TestNetworkCallback callback = new TestNetworkCallback();
1361 mCm.registerNetworkCallback(request, callback);
1362
1363 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1364 mCm.registerDefaultNetworkCallback(defaultCallback);
1365
1366 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1367 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1368 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
1369
1370 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1371 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1372 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1373
1374 mCellNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09001375 callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
1376 defaultCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001377 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1378
1379 mWiFiNetworkAgent.connect(true);
1380 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1381 // We then get LOSING when wifi validates and cell is outscored.
Erik Kline1d3db322017-02-28 16:20:20 +09001382 callback.expectAvailableCallbacks(mWiFiNetworkAgent);
1383 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001384 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001385 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
1386 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001387 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1388
1389 mEthernetNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09001390 callback.expectAvailableCallbacks(mEthernetNetworkAgent);
1391 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001392 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001393 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
1394 defaultCallback.expectAvailableAndValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001395 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1396
1397 mEthernetNetworkAgent.disconnect();
1398 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1399 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001400 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001401
1402 for (int i = 0; i < 4; i++) {
1403 MockNetworkAgent oldNetwork, newNetwork;
1404 if (i % 2 == 0) {
1405 mWiFiNetworkAgent.adjustScore(-15);
1406 oldNetwork = mWiFiNetworkAgent;
1407 newNetwork = mCellNetworkAgent;
1408 } else {
1409 mWiFiNetworkAgent.adjustScore(15);
1410 oldNetwork = mCellNetworkAgent;
1411 newNetwork = mWiFiNetworkAgent;
1412
1413 }
1414 callback.expectCallback(CallbackState.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001415 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1416 // longer lingering?
Erik Kline1d3db322017-02-28 16:20:20 +09001417 defaultCallback.expectAvailableCallbacks(newNetwork);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001418 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
1419 }
1420 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1421
1422 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
1423 // if the network is still up.
1424 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
Erik Kline1d3db322017-02-28 16:20:20 +09001425 // We expect a notification about the capabilities change, and nothing else.
1426 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
1427 defaultCallback.assertNoCallback();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001428 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1429
1430 // Wifi no longer satisfies our listen, which is for an unmetered network.
1431 // But because its score is 55, it's still up (and the default network).
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001432 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1433
1434 // Disconnect our test networks.
1435 mWiFiNetworkAgent.disconnect();
1436 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001437 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001438 mCellNetworkAgent.disconnect();
1439 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1440
1441 mCm.unregisterNetworkCallback(callback);
1442 mService.waitForIdle();
1443
1444 // Check that a network is only lingered or torn down if it would not satisfy a request even
1445 // if it validated.
1446 request = new NetworkRequest.Builder().clearCapabilities().build();
1447 callback = new TestNetworkCallback();
1448
1449 mCm.registerNetworkCallback(request, callback);
1450
1451 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1452 mCellNetworkAgent.connect(false); // Score: 10
Erik Kline1d3db322017-02-28 16:20:20 +09001453 callback.expectAvailableCallbacks(mCellNetworkAgent);
1454 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001455 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1456
1457 // Bring up wifi with a score of 20.
1458 // Cell stays up because it would satisfy the default request if it validated.
1459 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1460 mWiFiNetworkAgent.connect(false); // Score: 20
Erik Kline1d3db322017-02-28 16:20:20 +09001461 callback.expectAvailableCallbacks(mWiFiNetworkAgent);
1462 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001463 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1464
1465 mWiFiNetworkAgent.disconnect();
1466 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1467 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001468 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001469 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1470
1471 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001472 // Cell is lingered because it would not satisfy any request, even if it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001473 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1474 mWiFiNetworkAgent.adjustScore(50);
1475 mWiFiNetworkAgent.connect(false); // Score: 70
Erik Kline1d3db322017-02-28 16:20:20 +09001476 callback.expectAvailableCallbacks(mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001477 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001478 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001479 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1480
1481 // Tear down wifi.
1482 mWiFiNetworkAgent.disconnect();
1483 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1484 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001485 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001486 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1487
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001488 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
1489 // it's arguably correct to linger it, since it was the default network before it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001490 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1491 mWiFiNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09001492 callback.expectAvailableCallbacks(mWiFiNetworkAgent);
1493 // TODO: Investigate sending validated before losing.
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001494 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001495 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
1496 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001497 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1498
1499 mWiFiNetworkAgent.disconnect();
1500 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001501 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001502 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001503 mCellNetworkAgent.disconnect();
1504 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1505 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001506
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001507 // If a network is lingering, and we add and remove a request from it, resume lingering.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001508 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1509 mCellNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09001510 callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
1511 defaultCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001512 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1513 mWiFiNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09001514 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
1515 callback.expectAvailableCallbacks(mWiFiNetworkAgent);
1516 // TODO: Investigate sending validated before losing.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001517 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001518 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001519
1520 NetworkRequest cellRequest = new NetworkRequest.Builder()
1521 .addTransportType(TRANSPORT_CELLULAR).build();
1522 NetworkCallback noopCallback = new NetworkCallback();
1523 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001524 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
1525 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001526 mCm.unregisterNetworkCallback(noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001527 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001528
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001529 // Similar to the above: lingering can start even after the lingered request is removed.
1530 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001531 mWiFiNetworkAgent.disconnect();
1532 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001533 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001534 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001535
1536 // Cell is now the default network. Pin it with a cell-specific request.
1537 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
1538 mCm.requestNetwork(cellRequest, noopCallback);
1539
1540 // Now connect wifi, and expect it to become the default network.
1541 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1542 mWiFiNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09001543 callback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
1544 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001545 // The default request is lingering on cell, but nothing happens to cell, and we send no
1546 // callbacks for it, because it's kept up by cellRequest.
1547 callback.assertNoCallback();
1548 // Now unregister cellRequest and expect cell to start lingering.
1549 mCm.unregisterNetworkCallback(noopCallback);
1550 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1551
1552 // Let linger run its course.
1553 callback.assertNoCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09001554 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
1555 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001556
1557 // Clean up.
1558 mWiFiNetworkAgent.disconnect();
1559 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1560 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001561
1562 mCm.unregisterNetworkCallback(callback);
1563 mCm.unregisterNetworkCallback(defaultCallback);
1564 }
1565
Paul Jensen85cf78e2015-06-25 13:25:07 -04001566 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04001567 // Verify NOT_RESTRICTED is set appropriately
1568 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
1569 .build().networkCapabilities;
1570 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
1571 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
1572 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04001573 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04001574 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1575 } else {
1576 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1577 }
1578
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001579 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001580 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001581 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
1582 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04001583 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001584 mServiceContext, "testFactory", filter);
1585 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04001586 ConditionVariable cv = testFactory.getNetworkStartedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001587 testFactory.expectAddRequests(1);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001588 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001589 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001590 int expectedRequestCount = 1;
1591 NetworkCallback networkCallback = null;
1592 // For non-INTERNET capabilities we cannot rely on the default request being present, so
1593 // add one.
1594 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04001595 assertFalse(testFactory.getMyStartRequested());
1596 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
1597 networkCallback = new NetworkCallback();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001598 testFactory.expectAddRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001599 mCm.requestNetwork(request, networkCallback);
1600 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001601 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001602 }
Paul Jensen3d911462015-06-12 06:40:24 -04001603 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001604 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1605 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001606
Paul Jensen85cf78e2015-06-25 13:25:07 -04001607 // Now bring in a higher scored network.
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001608 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001609 // Rather than create a validated network which complicates things by registering it's
1610 // own NetworkRequest during startup, just bump up the score to cancel out the
1611 // unvalidated penalty.
1612 testAgent.adjustScore(40);
1613 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001614
1615 // When testAgent connects, ConnectivityService will re-send us all current requests with
1616 // the new score. There are expectedRequestCount such requests, and we must wait for all of
1617 // them.
1618 testFactory.expectAddRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001619 testAgent.connect(false);
1620 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04001621 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001622 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001623 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001624
Paul Jensen85cf78e2015-06-25 13:25:07 -04001625 // Bring in a bunch of requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001626 testFactory.expectAddRequests(10);
1627 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001628 ConnectivityManager.NetworkCallback[] networkCallbacks =
1629 new ConnectivityManager.NetworkCallback[10];
1630 for (int i = 0; i< networkCallbacks.length; i++) {
1631 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
1632 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001633 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001634 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
1635 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04001636 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
1637 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001638
Paul Jensen85cf78e2015-06-25 13:25:07 -04001639 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001640 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001641 for (int i = 0; i < networkCallbacks.length; i++) {
1642 mCm.unregisterNetworkCallback(networkCallbacks[i]);
1643 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04001644 testFactory.waitForNetworkRequests(expectedRequestCount);
1645 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001646
Paul Jensen85cf78e2015-06-25 13:25:07 -04001647 // Drop the higher scored network.
1648 cv = testFactory.getNetworkStartedCV();
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001649 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001650 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001651 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1652 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001653
1654 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001655 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001656 handlerThread.quit();
1657 }
1658
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001659 @SmallTest
Paul Jensen85cf78e2015-06-25 13:25:07 -04001660 public void testNetworkFactoryRequests() throws Exception {
1661 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
1662 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
1663 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
1664 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
1665 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
1666 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
1667 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
1668 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
1669 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
1670 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
1671 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
1672 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
1673 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
1674 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
1675 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
1676 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
1677 }
1678
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001679 @SmallTest
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001680 public void testNoMutableNetworkRequests() throws Exception {
1681 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
1682 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001683 builder.addCapability(NET_CAPABILITY_VALIDATED);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001684 try {
1685 mCm.requestNetwork(builder.build(), new NetworkCallback());
1686 fail();
1687 } catch (IllegalArgumentException expected) {}
1688 try {
1689 mCm.requestNetwork(builder.build(), pendingIntent);
1690 fail();
1691 } catch (IllegalArgumentException expected) {}
1692 builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001693 builder.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001694 try {
1695 mCm.requestNetwork(builder.build(), new NetworkCallback());
1696 fail();
1697 } catch (IllegalArgumentException expected) {}
1698 try {
1699 mCm.requestNetwork(builder.build(), pendingIntent);
1700 fail();
1701 } catch (IllegalArgumentException expected) {}
1702 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001703
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001704 @SmallTest
Paul Jensene0988542015-06-25 15:30:08 -04001705 public void testMMSonWiFi() throws Exception {
1706 // Test bringing up cellular without MMS NetworkRequest gets reaped
1707 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1708 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1709 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
1710 mCellNetworkAgent.connectWithoutInternet();
1711 waitFor(cv);
Lorenzo Colittid2706122017-01-30 17:45:49 +09001712 mService.waitForIdle();
1713 assertEquals(0, mCm.getAllNetworks().length);
Paul Jensene0988542015-06-25 15:30:08 -04001714 verifyNoNetwork();
1715 // Test bringing up validated WiFi.
1716 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1717 cv = waitForConnectivityBroadcasts(1);
1718 mWiFiNetworkAgent.connect(true);
1719 waitFor(cv);
1720 verifyActiveNetwork(TRANSPORT_WIFI);
1721 // Register MMS NetworkRequest
1722 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1723 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1724 final TestNetworkCallback networkCallback = new TestNetworkCallback();
1725 mCm.requestNetwork(builder.build(), networkCallback);
1726 // Test bringing up unvalidated cellular with MMS
1727 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1728 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04001729 mCellNetworkAgent.connectWithoutInternet();
Erik Kline1d3db322017-02-28 16:20:20 +09001730 networkCallback.expectAvailableCallbacks(mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04001731 verifyActiveNetwork(TRANSPORT_WIFI);
1732 // Test releasing NetworkRequest disconnects cellular with MMS
1733 cv = mCellNetworkAgent.getDisconnectedCV();
1734 mCm.unregisterNetworkCallback(networkCallback);
1735 waitFor(cv);
1736 verifyActiveNetwork(TRANSPORT_WIFI);
1737 }
1738
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001739 @SmallTest
Paul Jensene0988542015-06-25 15:30:08 -04001740 public void testMMSonCell() throws Exception {
1741 // Test bringing up cellular without MMS
1742 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1743 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1744 mCellNetworkAgent.connect(false);
1745 waitFor(cv);
1746 verifyActiveNetwork(TRANSPORT_CELLULAR);
1747 // Register MMS NetworkRequest
1748 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1749 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1750 final TestNetworkCallback networkCallback = new TestNetworkCallback();
1751 mCm.requestNetwork(builder.build(), networkCallback);
1752 // Test bringing up MMS cellular network
Paul Jensene0988542015-06-25 15:30:08 -04001753 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1754 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1755 mmsNetworkAgent.connectWithoutInternet();
Erik Kline1d3db322017-02-28 16:20:20 +09001756 networkCallback.expectAvailableCallbacks(mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04001757 verifyActiveNetwork(TRANSPORT_CELLULAR);
1758 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
1759 cv = mmsNetworkAgent.getDisconnectedCV();
1760 mCm.unregisterNetworkCallback(networkCallback);
1761 waitFor(cv);
1762 verifyActiveNetwork(TRANSPORT_CELLULAR);
1763 }
1764
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001765 @SmallTest
Paul Jensencf4c2c62015-07-01 14:16:32 -04001766 public void testCaptivePortal() {
1767 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1768 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1769 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1770 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1771
1772 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1773 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1774 .addCapability(NET_CAPABILITY_VALIDATED).build();
1775 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001776
1777 // Bring up a network with a captive portal.
1778 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001779 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04001780 String firstRedirectUrl = "http://example.com/firstPath";
1781 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
Erik Kline1d3db322017-02-28 16:20:20 +09001782 captivePortalCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04001783 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001784
1785 // Take down network.
1786 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001787 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001788 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001789
1790 // Bring up a network with a captive portal.
1791 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001792 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04001793 String secondRedirectUrl = "http://example.com/secondPath";
1794 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
Erik Kline1d3db322017-02-28 16:20:20 +09001795 captivePortalCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04001796 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001797
1798 // Make captive portal disappear then revalidate.
1799 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001800 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
1801 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001802 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001803
1804 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Erik Kline1d3db322017-02-28 16:20:20 +09001805 validatedCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
1806 // TODO: Investigate only sending available callbacks.
1807 validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001808
1809 // Break network connectivity.
1810 // Expect NET_CAPABILITY_VALIDATED onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001811 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
1812 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001813 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001814 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09001815
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001816 @SmallTest
Calvin On1f64f3f2016-10-11 15:10:46 -07001817 public void testAvoidOrIgnoreCaptivePortals() {
1818 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1819 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1820 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1821 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1822
1823 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1824 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1825 .addCapability(NET_CAPABILITY_VALIDATED).build();
1826 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
1827
1828 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
1829 // Bring up a network with a captive portal.
1830 // Expect it to fail to connect and not result in any callbacks.
1831 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1832 String firstRedirectUrl = "http://example.com/firstPath";
1833
1834 ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
1835 ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
1836 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
1837 waitFor(disconnectCv);
1838 waitFor(avoidCv);
1839
1840 assertNoCallbacks(captivePortalCallback, validatedCallback);
1841
1842 // Now test ignore mode.
1843 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE);
1844
1845 // Bring up a network with a captive portal.
1846 // Since we're ignoring captive portals, the network will validate.
1847 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1848 String secondRedirectUrl = "http://example.com/secondPath";
1849 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
1850
1851 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Erik Kline1d3db322017-02-28 16:20:20 +09001852 validatedCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Calvin On1f64f3f2016-10-11 15:10:46 -07001853 // But there should be no CaptivePortal callback.
1854 captivePortalCallback.assertNoCallback();
1855 }
1856
Lorenzo Colitti6556a222017-04-03 17:46:35 +09001857 private NetworkRequest.Builder newWifiRequestBuilder() {
1858 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
1859 }
1860
1861 @SmallTest
1862 public void testNetworkSpecifier() {
1863 NetworkRequest.Builder b = new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
1864 NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
1865 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier(null).build();
1866 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
1867 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier("foo").build();
1868 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier("bar").build();
1869
1870 TestNetworkCallback cEmpty1 = new TestNetworkCallback();
1871 TestNetworkCallback cEmpty2 = new TestNetworkCallback();
1872 TestNetworkCallback cEmpty3 = new TestNetworkCallback();
1873 TestNetworkCallback cFoo = new TestNetworkCallback();
1874 TestNetworkCallback cBar = new TestNetworkCallback();
1875 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
1876 cEmpty1, cEmpty2, cEmpty3 };
1877
1878 mCm.registerNetworkCallback(rEmpty1, cEmpty1);
1879 mCm.registerNetworkCallback(rEmpty2, cEmpty2);
1880 mCm.registerNetworkCallback(rEmpty3, cEmpty3);
1881 mCm.registerNetworkCallback(rFoo, cFoo);
1882 mCm.registerNetworkCallback(rBar, cBar);
1883
1884 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1885 mWiFiNetworkAgent.connect(false);
1886 cEmpty1.expectAvailableCallbacks(mWiFiNetworkAgent);
1887 cEmpty2.expectAvailableCallbacks(mWiFiNetworkAgent);
1888 cEmpty3.expectAvailableCallbacks(mWiFiNetworkAgent);
1889 assertNoCallbacks(cFoo, cBar);
1890
1891 mWiFiNetworkAgent.setNetworkSpecifier("foo");
1892 cFoo.expectAvailableCallbacks(mWiFiNetworkAgent);
1893 for (TestNetworkCallback c: emptyCallbacks) {
1894 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
1895 }
1896 cFoo.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
1897 cFoo.assertNoCallback();
1898
1899 mWiFiNetworkAgent.setNetworkSpecifier("bar");
1900 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1901 cBar.expectAvailableCallbacks(mWiFiNetworkAgent);
1902 for (TestNetworkCallback c: emptyCallbacks) {
1903 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
1904 }
1905 cBar.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
1906 cBar.assertNoCallback();
1907
1908 mWiFiNetworkAgent.setNetworkSpecifier(null);
1909 cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1910 for (TestNetworkCallback c: emptyCallbacks) {
1911 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
1912 }
1913
1914 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cFoo, cBar);
1915 }
1916
Etan Cohenddb9ef02015-11-18 10:56:15 -08001917 @SmallTest
1918 public void testInvalidNetworkSpecifier() {
1919 boolean execptionCalled = true;
1920
1921 try {
1922 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1923 builder.setNetworkSpecifier(MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
1924 execptionCalled = false;
1925 } catch (IllegalArgumentException e) {
1926 // do nothing - should get here
1927 }
1928
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001929 assertTrue("NetworkRequest builder with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
Etan Cohenddb9ef02015-11-18 10:56:15 -08001930 execptionCalled);
1931
1932 try {
1933 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
1934 networkCapabilities.addTransportType(TRANSPORT_WIFI)
1935 .setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
1936 mService.requestNetwork(networkCapabilities, null, 0, null,
1937 ConnectivityManager.TYPE_WIFI);
1938 execptionCalled = false;
1939 } catch (IllegalArgumentException e) {
1940 // do nothing - should get here
1941 }
1942
1943 assertTrue("ConnectivityService requestNetwork with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
1944 execptionCalled);
1945 }
1946
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001947 @SmallTest
Erik Klinea2d29402016-03-16 15:31:39 +09001948 public void testRegisterDefaultNetworkCallback() throws Exception {
1949 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
1950 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
1951 defaultNetworkCallback.assertNoCallback();
1952
1953 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
1954 // whenever Wi-Fi is up. Without this, the mobile network agent is
1955 // reaped before any other activity can take place.
1956 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
1957 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1958 .addTransportType(TRANSPORT_CELLULAR).build();
1959 mCm.requestNetwork(cellRequest, cellNetworkCallback);
1960 cellNetworkCallback.assertNoCallback();
1961
1962 // Bring up cell and expect CALLBACK_AVAILABLE.
1963 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1964 mCellNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09001965 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
1966 defaultNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09001967
1968 // Bring up wifi and expect CALLBACK_AVAILABLE.
1969 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1970 mWiFiNetworkAgent.connect(true);
1971 cellNetworkCallback.assertNoCallback();
Erik Kline1d3db322017-02-28 16:20:20 +09001972 defaultNetworkCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09001973
1974 // Bring down cell. Expect no default network callback, since it wasn't the default.
1975 mCellNetworkAgent.disconnect();
1976 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1977 defaultNetworkCallback.assertNoCallback();
1978
1979 // Bring up cell. Expect no default network callback, since it won't be the default.
1980 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1981 mCellNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09001982 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09001983 defaultNetworkCallback.assertNoCallback();
1984
1985 // Bring down wifi. Expect the default network callback to notified of LOST wifi
1986 // followed by AVAILABLE cell.
1987 mWiFiNetworkAgent.disconnect();
1988 cellNetworkCallback.assertNoCallback();
1989 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001990 defaultNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09001991 mCellNetworkAgent.disconnect();
1992 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1993 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1994 }
1995
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001996 @SmallTest
Erik Kline1d3db322017-02-28 16:20:20 +09001997 public void testAdditionalStateCallbacks() throws Exception {
Erik Klineacdd6392016-07-07 16:50:58 +09001998 // File a network request for mobile.
Erik Kline1d3db322017-02-28 16:20:20 +09001999 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09002000 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2001 .addTransportType(TRANSPORT_CELLULAR).build();
2002 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2003
2004 // Bring up the mobile network.
2005 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2006 mCellNetworkAgent.connect(true);
2007
Erik Kline1d3db322017-02-28 16:20:20 +09002008 // We should get onAvailable(), onCapabilitiesChanged(), and
2009 // onLinkPropertiesChanged() in rapid succession. Additionally, we
2010 // should get onCapabilitiesChanged() when the mobile network validates.
2011 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09002012 cellNetworkCallback.assertNoCallback();
2013
2014 // Update LinkProperties.
2015 final LinkProperties lp = new LinkProperties();
2016 lp.setInterfaceName("foonet_data0");
2017 mCellNetworkAgent.sendLinkProperties(lp);
2018 // We should get onLinkPropertiesChanged().
2019 cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
2020 cellNetworkCallback.assertNoCallback();
2021
Erik Kline1d3db322017-02-28 16:20:20 +09002022 // Suspend the network.
2023 mCellNetworkAgent.suspend();
2024 cellNetworkCallback.expectCallback(CallbackState.SUSPENDED, mCellNetworkAgent);
2025 cellNetworkCallback.assertNoCallback();
2026
Erik Klineacdd6392016-07-07 16:50:58 +09002027 // Register a garden variety default network request.
Erik Kline1d3db322017-02-28 16:20:20 +09002028 final TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09002029 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09002030 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
2031 // as well as onNetworkSuspended() in rapid succession.
2032 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09002033 dfltNetworkCallback.assertNoCallback();
2034
Erik Klineacdd6392016-07-07 16:50:58 +09002035 mCm.unregisterNetworkCallback(dfltNetworkCallback);
2036 mCm.unregisterNetworkCallback(cellNetworkCallback);
2037 }
2038
Calvin On1f64f3f2016-10-11 15:10:46 -07002039 private void setCaptivePortalMode(int mode) {
2040 ContentResolver cr = mServiceContext.getContentResolver();
2041 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
2042 }
2043
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002044 private void setMobileDataAlwaysOn(boolean enable) {
2045 ContentResolver cr = mServiceContext.getContentResolver();
2046 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
2047 mService.updateMobileDataAlwaysOn();
2048 mService.waitForIdle();
2049 }
2050
2051 private boolean isForegroundNetwork(MockNetworkAgent network) {
2052 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
2053 assertNotNull(nc);
2054 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
2055 }
2056
2057 @SmallTest
2058 public void testBackgroundNetworks() throws Exception {
2059 // Create a background request. We can't do this ourselves because ConnectivityService
2060 // doesn't have an API for it. So just turn on mobile data always on.
2061 setMobileDataAlwaysOn(true);
2062 final NetworkRequest request = new NetworkRequest.Builder().build();
2063 final NetworkRequest fgRequest = new NetworkRequest.Builder()
2064 .addCapability(NET_CAPABILITY_FOREGROUND).build();
2065 final TestNetworkCallback callback = new TestNetworkCallback();
2066 final TestNetworkCallback fgCallback = new TestNetworkCallback();
2067 mCm.registerNetworkCallback(request, callback);
2068 mCm.registerNetworkCallback(fgRequest, fgCallback);
2069
2070 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2071 mCellNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09002072 callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
2073 fgCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002074 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2075
2076 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2077 mWiFiNetworkAgent.connect(true);
2078
2079 // When wifi connects, cell lingers.
Erik Kline1d3db322017-02-28 16:20:20 +09002080 callback.expectAvailableCallbacks(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002081 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002082 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2083 fgCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002084 fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002085 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002086 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2087 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2088
2089 // When lingering is complete, cell is still there but is now in the background.
Hugo Benichidfb559a2016-12-20 14:57:49 +09002090 mService.waitForIdle();
2091 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2092 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09002093 // Expect a network capabilities update sans FOREGROUND.
2094 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002095 assertFalse(isForegroundNetwork(mCellNetworkAgent));
2096 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2097
2098 // File a cell request and check that cell comes into the foreground.
2099 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2100 .addTransportType(TRANSPORT_CELLULAR).build();
2101 final TestNetworkCallback cellCallback = new TestNetworkCallback();
2102 mCm.requestNetwork(cellRequest, cellCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09002103 // NOTE: This request causes the network's capabilities to change. This
2104 // is currently delivered before the onAvailable() callbacks.
2105 // TODO: Fix this.
2106 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
2107 cellCallback.expectAvailableCallbacks(mCellNetworkAgent);
2108 fgCallback.expectAvailableCallbacks(mCellNetworkAgent);
2109 // Expect a network capabilities update with FOREGROUND, because the most recent
2110 // request causes its state to change.
2111 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002112 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2113 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2114
2115 // Release the request. The network immediately goes into the background, since it was not
2116 // lingering.
2117 mCm.unregisterNetworkCallback(cellCallback);
2118 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002119 // Expect a network capabilities update sans FOREGROUND.
2120 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002121 assertFalse(isForegroundNetwork(mCellNetworkAgent));
2122 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2123
2124 // Disconnect wifi and check that cell is foreground again.
2125 mWiFiNetworkAgent.disconnect();
2126 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2127 fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002128 fgCallback.expectAvailableCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002129 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2130
2131 mCm.unregisterNetworkCallback(callback);
2132 mCm.unregisterNetworkCallback(fgCallback);
2133 }
2134
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002135 @SmallTest
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002136 public void testRequestBenchmark() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002137 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002138 // Benchmarks connecting and switching performance in the presence of a large number of
2139 // NetworkRequests.
2140 // 1. File NUM_REQUESTS requests.
2141 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
2142 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
2143 // and NUM_REQUESTS onAvailable callbacks to fire.
2144 // See how long it took.
2145 final int NUM_REQUESTS = 90;
2146 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
2147 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
2148 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
2149 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
2150
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002151 for (int i = 0; i < NUM_REQUESTS; i++) {
2152 callbacks[i] = new NetworkCallback() {
2153 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
2154 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
2155 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002156 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002157
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002158 final int REGISTER_TIME_LIMIT_MS = 180;
2159 assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
2160 for (NetworkCallback cb : callbacks) {
2161 mCm.registerNetworkCallback(request, cb);
2162 }
2163 });
2164
2165 final int CONNECT_TIME_LIMIT_MS = 40;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002166 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2167 // Don't request that the network validate, because otherwise connect() will block until
2168 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
2169 // and we won't actually measure anything.
2170 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002171
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002172 long onAvailableDispatchingDuration = durationOf(() -> {
2173 if (!awaitLatch(availableLatch, CONNECT_TIME_LIMIT_MS)) {
2174 fail(String.format("Only dispatched %d/%d onAvailable callbacks in %dms",
2175 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
2176 CONNECT_TIME_LIMIT_MS));
2177 }
2178 });
2179 Log.d(TAG, String.format("Connect, %d callbacks: %dms, acceptable %dms",
2180 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS));
2181
2182 final int SWITCH_TIME_LIMIT_MS = 40;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002183 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2184 // Give wifi a high enough score that we'll linger cell when wifi comes up.
2185 mWiFiNetworkAgent.adjustScore(40);
2186 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002187
2188 long onLostDispatchingDuration = durationOf(() -> {
2189 if (!awaitLatch(losingLatch, SWITCH_TIME_LIMIT_MS)) {
2190 fail(String.format("Only dispatched %d/%d onLosing callbacks in %dms",
2191 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, SWITCH_TIME_LIMIT_MS));
2192 }
2193 });
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002194 Log.d(TAG, String.format("Linger, %d callbacks: %dms, acceptable %dms",
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002195 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS));
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002196
2197 final int UNREGISTER_TIME_LIMIT_MS = 10;
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002198 assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
2199 for (NetworkCallback cb : callbacks) {
2200 mCm.unregisterNetworkCallback(cb);
2201 }
2202 });
2203 }
2204
2205 private long durationOf(Runnable fn) {
2206 long startTime = SystemClock.elapsedRealtime();
2207 fn.run();
2208 return SystemClock.elapsedRealtime() - startTime;
2209 }
2210
2211 private void assertTimeLimit(String descr, long timeLimit, Runnable fn) {
2212 long timeTaken = durationOf(fn);
2213 String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002214 Log.d(TAG, msg);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002215 assertTrue(msg, timeTaken <= timeLimit);
2216 }
2217
2218 private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
2219 try {
2220 if (l.await(timeoutMs, TimeUnit.MILLISECONDS)) {
2221 return true;
2222 }
2223 } catch (InterruptedException e) {}
2224 return false;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002225 }
2226
2227 @SmallTest
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002228 public void testMobileDataAlwaysOn() throws Exception {
2229 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2230 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2231 .addTransportType(TRANSPORT_CELLULAR).build();
2232 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
2233
2234 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
2235 handlerThread.start();
2236 NetworkCapabilities filter = new NetworkCapabilities()
2237 .addTransportType(TRANSPORT_CELLULAR)
2238 .addCapability(NET_CAPABILITY_INTERNET);
2239 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
2240 mServiceContext, "testFactory", filter);
2241 testFactory.setScoreFilter(40);
2242
2243 // Register the factory and expect it to start looking for a network.
2244 testFactory.expectAddRequests(1);
2245 testFactory.register();
2246 testFactory.waitForNetworkRequests(1);
2247 assertTrue(testFactory.getMyStartRequested());
2248
2249 // Bring up wifi. The factory stops looking for a network.
2250 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2251 testFactory.expectAddRequests(2); // Because the default request changes score twice.
2252 mWiFiNetworkAgent.connect(true);
2253 testFactory.waitForNetworkRequests(1);
2254 assertFalse(testFactory.getMyStartRequested());
2255
2256 ContentResolver cr = mServiceContext.getContentResolver();
2257
2258 // Turn on mobile data always on. The factory starts looking again.
2259 testFactory.expectAddRequests(1);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002260 setMobileDataAlwaysOn(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002261 testFactory.waitForNetworkRequests(2);
2262 assertTrue(testFactory.getMyStartRequested());
2263
2264 // Bring up cell data and check that the factory stops looking.
2265 assertEquals(1, mCm.getAllNetworks().length);
2266 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2267 testFactory.expectAddRequests(2); // Because the cell request changes score twice.
2268 mCellNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09002269 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002270 testFactory.waitForNetworkRequests(2);
2271 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
2272
2273 // Check that cell data stays up.
2274 mService.waitForIdle();
2275 verifyActiveNetwork(TRANSPORT_WIFI);
2276 assertEquals(2, mCm.getAllNetworks().length);
2277
2278 // Turn off mobile data always on and expect the request to disappear...
2279 testFactory.expectRemoveRequests(1);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002280 setMobileDataAlwaysOn(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002281 testFactory.waitForNetworkRequests(1);
2282
2283 // ... and cell data to be torn down.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002284 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002285 assertEquals(1, mCm.getAllNetworks().length);
2286
2287 testFactory.unregister();
2288 mCm.unregisterNetworkCallback(cellNetworkCallback);
2289 handlerThread.quit();
2290 }
2291
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002292 @SmallTest
2293 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002294 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09002295 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002296 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
2297
Erik Kline065ab6e2016-10-02 18:02:14 +09002298 tracker.configRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002299 String[] values = new String[] {null, "0", "1"};
2300 for (int i = 0; i < values.length; i++) {
2301 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002302 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002303 mService.waitForIdle();
2304 String msg = String.format("config=false, setting=%s", values[i]);
Lorenzo Colitti30145d72017-01-27 18:46:03 +09002305 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09002306 assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002307 }
2308
Erik Kline065ab6e2016-10-02 18:02:14 +09002309 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002310
2311 Settings.Global.putInt(cr, settingName, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09002312 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002313 mService.waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09002314 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09002315 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002316
2317 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002318 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002319 mService.waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09002320 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09002321 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002322
2323 Settings.Global.putString(cr, settingName, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09002324 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002325 mService.waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09002326 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09002327 assertTrue(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002328 }
2329
2330 @SmallTest
2331 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09002332 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09002333 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002334
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002335 // Pretend we're on a carrier that restricts switching away from bad wifi.
Erik Kline065ab6e2016-10-02 18:02:14 +09002336 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002337
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002338 // File a request for cell to ensure it doesn't go down.
2339 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2340 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2341 .addTransportType(TRANSPORT_CELLULAR).build();
2342 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2343
2344 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2345 mCm.registerDefaultNetworkCallback(defaultCallback);
2346
2347 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
2348 .addTransportType(TRANSPORT_WIFI)
2349 .addCapability(NET_CAPABILITY_VALIDATED)
2350 .build();
2351 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
2352 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
2353
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002354 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09002355 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002356
2357 // Bring up validated cell.
2358 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2359 mCellNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09002360 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
2361 defaultCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002362 Network cellNetwork = mCellNetworkAgent.getNetwork();
2363
2364 // Bring up validated wifi.
2365 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2366 mWiFiNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09002367 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
2368 validatedWifiCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
2369 validatedWifiCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002370 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2371
2372 // Fail validation on wifi.
2373 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
2374 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09002375 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002376 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2377
2378 // Because avoid bad wifi is off, we don't switch to cellular.
2379 defaultCallback.assertNoCallback();
2380 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2381 NET_CAPABILITY_VALIDATED));
2382 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2383 NET_CAPABILITY_VALIDATED));
2384 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2385
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002386 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
2387 // that we switch back to cell.
Erik Kline065ab6e2016-10-02 18:02:14 +09002388 tracker.configRestrictsAvoidBadWifi = false;
2389 tracker.reevaluate();
Erik Kline1d3db322017-02-28 16:20:20 +09002390 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002391 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2392
2393 // Switch back to a restrictive carrier.
Erik Kline065ab6e2016-10-02 18:02:14 +09002394 tracker.configRestrictsAvoidBadWifi = true;
2395 tracker.reevaluate();
Erik Kline1d3db322017-02-28 16:20:20 +09002396 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002397 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2398
2399 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
2400 mCm.setAvoidUnvalidated(wifiNetwork);
Erik Kline1d3db322017-02-28 16:20:20 +09002401 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002402 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2403 NET_CAPABILITY_VALIDATED));
2404 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2405 NET_CAPABILITY_VALIDATED));
2406 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2407
2408 // Disconnect and reconnect wifi to clear the one-time switch above.
2409 mWiFiNetworkAgent.disconnect();
2410 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2411 mWiFiNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09002412 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
2413 validatedWifiCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
2414 validatedWifiCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002415 wifiNetwork = mWiFiNetworkAgent.getNetwork();
2416
2417 // Fail validation on wifi and expect the dialog to appear.
2418 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
2419 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09002420 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002421 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2422
2423 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002424 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002425 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002426
2427 // We now switch to cell.
Erik Kline1d3db322017-02-28 16:20:20 +09002428 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002429 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2430 NET_CAPABILITY_VALIDATED));
2431 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2432 NET_CAPABILITY_VALIDATED));
2433 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2434
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002435 // Simulate the user turning the cellular fallback setting off and then on.
2436 // We switch to wifi and then to cell.
2437 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09002438 tracker.reevaluate();
Erik Kline1d3db322017-02-28 16:20:20 +09002439 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002440 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2441 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002442 tracker.reevaluate();
Erik Kline1d3db322017-02-28 16:20:20 +09002443 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002444 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2445
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002446 // If cell goes down, we switch to wifi.
2447 mCellNetworkAgent.disconnect();
2448 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002449 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002450 validatedWifiCallback.assertNoCallback();
2451
2452 mCm.unregisterNetworkCallback(cellNetworkCallback);
2453 mCm.unregisterNetworkCallback(validatedWifiCallback);
2454 mCm.unregisterNetworkCallback(defaultCallback);
2455 }
2456
Erik Kline3841a482015-11-25 12:49:38 +09002457 /**
2458 * Validate that a satisfied network request does not trigger onUnavailable() once the
2459 * time-out period expires.
2460 */
2461 @SmallTest
2462 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
2463 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2464 NetworkCapabilities.TRANSPORT_WIFI).build();
2465 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09002466 final int timeoutMs = 150;
2467 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09002468
2469 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2470 mWiFiNetworkAgent.connect(false);
Erik Kline1d3db322017-02-28 16:20:20 +09002471 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09002472
2473 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07002474 networkCallback.assertNoCallback();
2475 }
2476
2477 /**
2478 * Validate that a satisfied network request followed by a disconnected (lost) network does
2479 * not trigger onUnavailable() once the time-out period expires.
2480 */
2481 @SmallTest
2482 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
2483 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2484 NetworkCapabilities.TRANSPORT_WIFI).build();
2485 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09002486 final int requestTimeoutMs = 100;
2487 mCm.requestNetwork(nr, networkCallback, requestTimeoutMs);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07002488
2489 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2490 mWiFiNetworkAgent.connect(false);
Hugo Benichidfb559a2016-12-20 14:57:49 +09002491 final int assertTimeoutMs = 150;
Erik Kline1d3db322017-02-28 16:20:20 +09002492 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, assertTimeoutMs);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07002493 sleepFor(20);
2494 mWiFiNetworkAgent.disconnect();
2495 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2496
2497 // pass timeout and validate that UNAVAILABLE is not called
Hugo Benichidfb559a2016-12-20 14:57:49 +09002498 sleepFor(100);
Erik Kline3841a482015-11-25 12:49:38 +09002499 networkCallback.assertNoCallback();
2500 }
2501
2502 /**
2503 * Validate that when a time-out is specified for a network request the onUnavailable()
2504 * callback is called when time-out expires. Then validate that if network request is
2505 * (somehow) satisfied - the callback isn't called later.
2506 */
2507 @SmallTest
2508 public void testTimedoutNetworkRequest() {
2509 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2510 NetworkCapabilities.TRANSPORT_WIFI).build();
2511 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09002512 final int timeoutMs = 10;
2513 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09002514
2515 // pass timeout and validate that UNAVAILABLE is called
2516 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
2517
2518 // create a network satisfying request - validate that request not triggered
2519 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2520 mWiFiNetworkAgent.connect(false);
2521 networkCallback.assertNoCallback();
2522 }
2523
2524 /**
2525 * Validate that when a network request is unregistered (cancelled) the time-out for that
2526 * request doesn't trigger the onUnavailable() callback.
2527 */
2528 @SmallTest
2529 public void testTimedoutAfterUnregisteredNetworkRequest() {
2530 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2531 NetworkCapabilities.TRANSPORT_WIFI).build();
2532 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09002533 final int timeoutMs = 10;
2534 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09002535
2536 // remove request
2537 mCm.unregisterNetworkCallback(networkCallback);
2538
2539 // pass timeout and validate that no callbacks
2540 // Note: doesn't validate that nothing called from CS since even if called the CM already
2541 // unregisters the callback and won't pass it through!
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07002542 sleepFor(15);
Erik Kline3841a482015-11-25 12:49:38 +09002543 networkCallback.assertNoCallback();
2544
2545 // create a network satisfying request - validate that request not triggered
2546 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2547 mWiFiNetworkAgent.connect(false);
2548 networkCallback.assertNoCallback();
2549 }
2550
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002551 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
2552
2553 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
2554
2555 private class CallbackValue {
2556 public CallbackType callbackType;
2557 public int error;
2558
2559 public CallbackValue(CallbackType type) {
2560 this.callbackType = type;
2561 this.error = PacketKeepalive.SUCCESS;
2562 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
2563 }
2564
2565 public CallbackValue(CallbackType type, int error) {
2566 this.callbackType = type;
2567 this.error = error;
2568 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
2569 }
2570
2571 @Override
2572 public boolean equals(Object o) {
2573 return o instanceof CallbackValue &&
2574 this.callbackType == ((CallbackValue) o).callbackType &&
2575 this.error == ((CallbackValue) o).error;
2576 }
2577
2578 @Override
2579 public String toString() {
2580 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
2581 }
2582 }
2583
2584 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
2585
2586 @Override
2587 public void onStarted() {
2588 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
2589 }
2590
2591 @Override
2592 public void onStopped() {
2593 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
2594 }
2595
2596 @Override
2597 public void onError(int error) {
2598 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
2599 }
2600
2601 private void expectCallback(CallbackValue callbackValue) {
2602 try {
2603 assertEquals(
2604 callbackValue,
2605 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
2606 } catch (InterruptedException e) {
2607 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
2608 }
2609 }
2610
2611 public void expectStarted() {
2612 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
2613 }
2614
2615 public void expectStopped() {
2616 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
2617 }
2618
2619 public void expectError(int error) {
2620 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
2621 }
2622 }
2623
2624 private Network connectKeepaliveNetwork(LinkProperties lp) {
2625 // Ensure the network is disconnected before we do anything.
2626 if (mWiFiNetworkAgent != null) {
2627 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
2628 }
2629
2630 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2631 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2632 mWiFiNetworkAgent.connect(true);
2633 waitFor(cv);
2634 verifyActiveNetwork(TRANSPORT_WIFI);
2635 mWiFiNetworkAgent.sendLinkProperties(lp);
2636 mService.waitForIdle();
2637 return mWiFiNetworkAgent.getNetwork();
2638 }
2639
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09002640 @SmallTest
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002641 public void testPacketKeepalives() throws Exception {
2642 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
2643 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
2644 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
2645 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
2646 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
2647
2648 LinkProperties lp = new LinkProperties();
2649 lp.setInterfaceName("wlan12");
2650 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
2651 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
2652 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
2653 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
2654
2655 Network notMyNet = new Network(61234);
2656 Network myNet = connectKeepaliveNetwork(lp);
2657
2658 TestKeepaliveCallback callback = new TestKeepaliveCallback();
2659 PacketKeepalive ka;
2660
2661 // Attempt to start keepalives with invalid parameters and check for errors.
2662 ka = mCm.startNattKeepalive(notMyNet, 25, callback, myIPv4, 1234, dstIPv4);
2663 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
2664
2665 ka = mCm.startNattKeepalive(myNet, 19, callback, notMyIPv4, 1234, dstIPv4);
2666 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
2667
2668 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 1234, dstIPv6);
2669 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2670
2671 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv4);
2672 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2673
2674 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv6);
2675 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); // NAT-T is IPv4-only.
2676
2677 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
2678 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
2679
2680 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
2681 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
2682
2683 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2684 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
2685
2686 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2687 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
2688
2689 // Check that a started keepalive can be stopped.
2690 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2691 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2692 callback.expectStarted();
2693 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
2694 ka.stop();
2695 callback.expectStopped();
2696
2697 // Check that deleting the IP address stops the keepalive.
2698 LinkProperties bogusLp = new LinkProperties(lp);
2699 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2700 callback.expectStarted();
2701 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
2702 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
2703 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
2704 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2705 mWiFiNetworkAgent.sendLinkProperties(lp);
2706
2707 // Check that a started keepalive is stopped correctly when the network disconnects.
2708 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2709 callback.expectStarted();
2710 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09002711 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002712 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
2713
2714 // ... and that stopping it after that has no adverse effects.
Lorenzo Colitti30145d72017-01-27 18:46:03 +09002715 mService.waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09002716 final Network myNetAlias = myNet;
Lorenzo Colitti30145d72017-01-27 18:46:03 +09002717 assertNull(mCm.getNetworkCapabilities(myNetAlias));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002718 ka.stop();
2719
2720 // Reconnect.
2721 myNet = connectKeepaliveNetwork(lp);
2722 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2723
2724 // Check things work as expected when the keepalive is stopped and the network disconnects.
2725 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2726 callback.expectStarted();
2727 ka.stop();
2728 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09002729 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002730 mService.waitForIdle();
2731 callback.expectStopped();
2732
2733 // Reconnect.
2734 myNet = connectKeepaliveNetwork(lp);
2735 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2736
2737 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
2738 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
2739 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2740 callback.expectStarted();
2741
2742 // The second one gets slot 2.
2743 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
2744 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
2745 PacketKeepalive ka2 = mCm.startNattKeepalive(myNet, 25, callback2, myIPv4, 6789, dstIPv4);
2746 callback2.expectStarted();
2747
2748 // Now stop the first one and create a third. This also gets slot 1.
2749 ka.stop();
2750 callback.expectStopped();
2751
2752 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
2753 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
2754 PacketKeepalive ka3 = mCm.startNattKeepalive(myNet, 25, callback3, myIPv4, 9876, dstIPv4);
2755 callback3.expectStarted();
2756
2757 ka2.stop();
2758 callback2.expectStopped();
2759
2760 ka3.stop();
2761 callback3.expectStopped();
2762 }
Udam Sainib7c24872016-01-04 12:16:14 -08002763
2764 @SmallTest
2765 public void testGetCaptivePortalServerUrl() throws Exception {
2766 String url = mCm.getCaptivePortalServerUrl();
2767 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
2768 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09002769
2770 private static class TestNetworkPinner extends NetworkPinner {
2771 public static boolean awaitPin(int timeoutMs) {
2772 synchronized(sLock) {
2773 if (sNetwork == null) {
2774 try {
2775 sLock.wait(timeoutMs);
2776 } catch (InterruptedException e) {}
2777 }
2778 return sNetwork != null;
2779 }
2780 }
2781
2782 public static boolean awaitUnpin(int timeoutMs) {
2783 synchronized(sLock) {
2784 if (sNetwork != null) {
2785 try {
2786 sLock.wait(timeoutMs);
2787 } catch (InterruptedException e) {}
2788 }
2789 return sNetwork == null;
2790 }
2791 }
2792 }
2793
2794 private void assertPinnedToWifiWithCellDefault() {
2795 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
2796 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2797 }
2798
2799 private void assertPinnedToWifiWithWifiDefault() {
2800 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
2801 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2802 }
2803
2804 private void assertNotPinnedToWifi() {
2805 assertNull(mCm.getBoundNetworkForProcess());
2806 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2807 }
2808
2809 @SmallTest
2810 public void testNetworkPinner() {
2811 NetworkRequest wifiRequest = new NetworkRequest.Builder()
2812 .addTransportType(TRANSPORT_WIFI)
2813 .build();
2814 assertNull(mCm.getBoundNetworkForProcess());
2815
2816 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2817 assertNull(mCm.getBoundNetworkForProcess());
2818
2819 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2820 mCellNetworkAgent.connect(true);
2821 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2822 mWiFiNetworkAgent.connect(false);
2823
2824 // When wi-fi connects, expect to be pinned.
2825 assertTrue(TestNetworkPinner.awaitPin(100));
2826 assertPinnedToWifiWithCellDefault();
2827
2828 // Disconnect and expect the pin to drop.
2829 mWiFiNetworkAgent.disconnect();
2830 assertTrue(TestNetworkPinner.awaitUnpin(100));
2831 assertNotPinnedToWifi();
2832
2833 // Reconnecting does not cause the pin to come back.
2834 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2835 mWiFiNetworkAgent.connect(false);
2836 assertFalse(TestNetworkPinner.awaitPin(100));
2837 assertNotPinnedToWifi();
2838
2839 // Pinning while connected causes the pin to take effect immediately.
2840 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2841 assertTrue(TestNetworkPinner.awaitPin(100));
2842 assertPinnedToWifiWithCellDefault();
2843
2844 // Explicitly unpin and expect to use the default network again.
2845 TestNetworkPinner.unpin();
2846 assertNotPinnedToWifi();
2847
2848 // Disconnect cell and wifi.
2849 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
2850 mCellNetworkAgent.disconnect();
2851 mWiFiNetworkAgent.disconnect();
2852 waitFor(cv);
2853
2854 // Pinning takes effect even if the pinned network is the default when the pin is set...
2855 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2856 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2857 mWiFiNetworkAgent.connect(false);
2858 assertTrue(TestNetworkPinner.awaitPin(100));
2859 assertPinnedToWifiWithWifiDefault();
2860
2861 // ... and is maintained even when that network is no longer the default.
2862 cv = waitForConnectivityBroadcasts(1);
2863 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2864 mCellNetworkAgent.connect(true);
2865 waitFor(cv);
2866 assertPinnedToWifiWithCellDefault();
2867 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04002868
2869 @SmallTest
2870 public void testNetworkRequestMaximum() {
2871 final int MAX_REQUESTS = 100;
2872 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
2873 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
2874 ArrayList<NetworkCallback> networkCallbacks = new ArrayList<NetworkCallback>();
2875 try {
2876 for (int i = 0; i < MAX_REQUESTS; i++) {
2877 NetworkCallback networkCallback = new NetworkCallback();
2878 mCm.requestNetwork(networkRequest, networkCallback);
2879 networkCallbacks.add(networkCallback);
2880 }
2881 fail("Registering " + MAX_REQUESTS + " NetworkRequests did not throw exception");
2882 } catch (IllegalArgumentException expected) {}
2883 for (NetworkCallback networkCallback : networkCallbacks) {
2884 mCm.unregisterNetworkCallback(networkCallback);
2885 }
2886 networkCallbacks.clear();
2887
2888 try {
2889 for (int i = 0; i < MAX_REQUESTS; i++) {
2890 NetworkCallback networkCallback = new NetworkCallback();
2891 mCm.registerNetworkCallback(networkRequest, networkCallback);
2892 networkCallbacks.add(networkCallback);
2893 }
2894 fail("Registering " + MAX_REQUESTS + " NetworkCallbacks did not throw exception");
2895 } catch (IllegalArgumentException expected) {}
2896 for (NetworkCallback networkCallback : networkCallbacks) {
2897 mCm.unregisterNetworkCallback(networkCallback);
2898 }
2899 networkCallbacks.clear();
2900
2901 ArrayList<PendingIntent> pendingIntents = new ArrayList<PendingIntent>();
2902 try {
2903 for (int i = 0; i < MAX_REQUESTS + 1; i++) {
2904 PendingIntent pendingIntent =
2905 PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
2906 mCm.requestNetwork(networkRequest, pendingIntent);
2907 pendingIntents.add(pendingIntent);
2908 }
2909 fail("Registering " + MAX_REQUESTS +
2910 " PendingIntent NetworkRequests did not throw exception");
2911 } catch (IllegalArgumentException expected) {}
2912 for (PendingIntent pendingIntent : pendingIntents) {
2913 mCm.unregisterNetworkCallback(pendingIntent);
2914 }
2915 pendingIntents.clear();
2916
2917 try {
2918 for (int i = 0; i < MAX_REQUESTS + 1; i++) {
2919 PendingIntent pendingIntent =
2920 PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
2921 mCm.registerNetworkCallback(networkRequest, pendingIntent);
2922 pendingIntents.add(pendingIntent);
2923 }
2924 fail("Registering " + MAX_REQUESTS +
2925 " PendingIntent NetworkCallbacks did not throw exception");
2926 } catch (IllegalArgumentException expected) {}
2927 for (PendingIntent pendingIntent : pendingIntents) {
2928 mCm.unregisterNetworkCallback(pendingIntent);
2929 }
2930 pendingIntents.clear();
2931 mService.waitForIdle(5000);
2932
2933 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
2934 for (int i = 0; i < MAX_REQUESTS; i++) {
2935 NetworkCallback networkCallback = new NetworkCallback();
2936 mCm.requestNetwork(networkRequest, networkCallback);
2937 mCm.unregisterNetworkCallback(networkCallback);
2938 }
2939 mService.waitForIdle();
2940 for (int i = 0; i < MAX_REQUESTS; i++) {
2941 NetworkCallback networkCallback = new NetworkCallback();
2942 mCm.registerNetworkCallback(networkRequest, networkCallback);
2943 mCm.unregisterNetworkCallback(networkCallback);
2944 }
2945 mService.waitForIdle();
2946 for (int i = 0; i < MAX_REQUESTS; i++) {
2947 PendingIntent pendingIntent =
2948 PendingIntent.getBroadcast(mContext, 0, new Intent("b" + i), 0);
2949 mCm.requestNetwork(networkRequest, pendingIntent);
2950 mCm.unregisterNetworkCallback(pendingIntent);
2951 }
2952 mService.waitForIdle();
2953 for (int i = 0; i < MAX_REQUESTS; i++) {
2954 PendingIntent pendingIntent =
2955 PendingIntent.getBroadcast(mContext, 0, new Intent("c" + i), 0);
2956 mCm.registerNetworkCallback(networkRequest, pendingIntent);
2957 mCm.unregisterNetworkCallback(pendingIntent);
2958 }
2959 }
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07002960
2961 /* test utilities */
Hugo Benichidfb559a2016-12-20 14:57:49 +09002962 // TODO: eliminate all usages of sleepFor and replace by proper timeouts/waitForIdle.
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07002963 static private void sleepFor(int ms) {
2964 try {
2965 Thread.sleep(ms);
2966 } catch (InterruptedException e) {
2967 }
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07002968 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07002969}