blob: 26eed24c4f39ed54ef52fe4d9aae52dbcc3ab8c7 [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;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070020import static android.net.ConnectivityManager.TYPE_MOBILE;
21import static android.net.ConnectivityManager.TYPE_WIFI;
22import static android.net.ConnectivityManager.getNetworkTypeName;
Lorenzo Colitti83fa2582015-08-07 12:49:01 +090023import static android.net.NetworkCapabilities.*;
24
Jeff Sharkey3671b1e2013-01-31 17:22:26 -080025import static org.mockito.Mockito.mock;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070026
Paul Jensenbb2e0e92015-06-16 15:11:58 -040027import android.app.PendingIntent;
Paul Jensend7b6ca92015-05-13 14:05:12 -040028import android.content.BroadcastReceiver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070029import android.content.Context;
Paul Jensend7b6ca92015-05-13 14:05:12 -040030import android.content.ContextWrapper;
31import android.content.Intent;
32import android.content.IntentFilter;
33import android.net.ConnectivityManager;
34import android.net.ConnectivityManager.NetworkCallback;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +090035import android.net.ConnectivityManager.PacketKeepalive;
36import android.net.ConnectivityManager.PacketKeepaliveCallback;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070037import android.net.INetworkPolicyManager;
38import android.net.INetworkStatsService;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +090039import android.net.IpPrefix;
40import android.net.LinkAddress;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070041import android.net.LinkProperties;
Paul Jensend7b6ca92015-05-13 14:05:12 -040042import android.net.Network;
43import android.net.NetworkAgent;
44import android.net.NetworkCapabilities;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070045import android.net.NetworkConfig;
Robert Greenwalt348e98d2015-06-05 17:55:36 -070046import android.net.NetworkFactory;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070047import android.net.NetworkInfo;
48import android.net.NetworkInfo.DetailedState;
Paul Jensend7b6ca92015-05-13 14:05:12 -040049import android.net.NetworkMisc;
50import android.net.NetworkRequest;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070051import android.net.RouteInfo;
Paul Jensend7b6ca92015-05-13 14:05:12 -040052import android.os.ConditionVariable;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070053import android.os.Handler;
Robert Greenwalt348e98d2015-06-05 17:55:36 -070054import android.os.HandlerThread;
Etan Cohenddb9ef02015-11-18 10:56:15 -080055import android.os.IBinder;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070056import android.os.INetworkManagementService;
Lorenzo Colittie58961a2015-08-07 20:17:27 +090057import android.os.Looper;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +090058import android.os.Message;
Lorenzo Colittie58961a2015-08-07 20:17:27 +090059import android.os.MessageQueue;
Etan Cohenddb9ef02015-11-18 10:56:15 -080060import android.os.Messenger;
Lorenzo Colittie58961a2015-08-07 20:17:27 +090061import android.os.MessageQueue.IdleHandler;
Robin Leed2baf792016-03-24 12:07:00 +000062import android.os.Process;
Lorenzo Colittibfecba22016-02-21 01:09:26 +090063import android.os.SystemClock;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070064import android.test.AndroidTestCase;
65import android.test.suitebuilder.annotation.LargeTest;
Udam Sainib7c24872016-01-04 12:16:14 -080066import android.test.suitebuilder.annotation.SmallTest;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070067import android.util.Log;
68import android.util.LogPrinter;
69
Lorenzo Colittibfecba22016-02-21 01:09:26 +090070import com.android.internal.util.WakeupMessage;
Paul Jensencf4c2c62015-07-01 14:16:32 -040071import com.android.server.connectivity.NetworkAgentInfo;
Paul Jensend7b6ca92015-05-13 14:05:12 -040072import com.android.server.connectivity.NetworkMonitor;
Paul Jensen232437312016-04-06 09:51:26 -040073import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
Lorenzo Colitti531a3442016-03-01 12:55:58 +090074import com.android.server.net.NetworkPinner;
Paul Jensend7b6ca92015-05-13 14:05:12 -040075
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070076import java.net.InetAddress;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +090077import java.util.concurrent.CountDownLatch;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +090078import java.util.concurrent.LinkedBlockingQueue;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +090079import java.util.concurrent.TimeUnit;
Robert Greenwalt348e98d2015-06-05 17:55:36 -070080import java.util.concurrent.atomic.AtomicBoolean;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070081
82/**
83 * Tests for {@link ConnectivityService}.
Paul Jensend7b6ca92015-05-13 14:05:12 -040084 *
85 * Build, install and run with:
86 * runtest frameworks-services -c com.android.server.ConnectivityServiceTest
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070087 */
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070088public class ConnectivityServiceTest extends AndroidTestCase {
89 private static final String TAG = "ConnectivityServiceTest";
90
Lorenzo Colittiffa390b2015-08-08 01:55:44 +090091 private static final int TIMEOUT_MS = 500;
92
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070093 private BroadcastInterceptingContext mServiceContext;
Paul Jensencf4c2c62015-07-01 14:16:32 -040094 private WrappedConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +090095 private WrappedConnectivityManager mCm;
Paul Jensend7b6ca92015-05-13 14:05:12 -040096 private MockNetworkAgent mWiFiNetworkAgent;
97 private MockNetworkAgent mCellNetworkAgent;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070098
Lorenzo Colitti531a3442016-03-01 12:55:58 +090099 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
100 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
101 // reflect the state of our test ConnectivityService.
102 private class WrappedConnectivityManager extends ConnectivityManager {
103 private Network mFakeBoundNetwork;
104
105 public synchronized boolean bindProcessToNetwork(Network network) {
106 mFakeBoundNetwork = network;
107 return true;
108 }
109
110 public synchronized Network getBoundNetworkForProcess() {
111 return mFakeBoundNetwork;
112 }
113
114 public WrappedConnectivityManager(Context context, ConnectivityService service) {
115 super(context, service);
116 }
117 }
118
Paul Jensend7b6ca92015-05-13 14:05:12 -0400119 private class MockContext extends BroadcastInterceptingContext {
120 MockContext(Context base) {
121 super(base);
122 }
123
124 @Override
125 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
126 // PendingIntents sent by the AlarmManager are not intercepted by
127 // BroadcastInterceptingContext so we must really register the receiver.
128 // This shouldn't effect the real NetworkMonitors as the action contains a random token.
129 if (filter.getAction(0).startsWith("android.net.netmon.lingerExpired")) {
130 return getBaseContext().registerReceiver(receiver, filter);
131 } else {
132 return super.registerReceiver(receiver, filter);
133 }
134 }
135
136 @Override
137 public Object getSystemService (String name) {
138 if (name == Context.CONNECTIVITY_SERVICE) return mCm;
139 return super.getSystemService(name);
140 }
141 }
142
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900143 /**
144 * A subclass of HandlerThread that allows callers to wait for it to become idle. waitForIdle
145 * will return immediately if the handler is already idle.
146 */
147 private class IdleableHandlerThread extends HandlerThread {
148 private IdleHandler mIdleHandler;
149
150 public IdleableHandlerThread(String name) {
151 super(name);
152 }
153
154 public void waitForIdle(int timeoutMs) {
155 final ConditionVariable cv = new ConditionVariable();
156 final MessageQueue queue = getLooper().getQueue();
157
158 synchronized (queue) {
159 if (queue.isIdle()) {
160 return;
161 }
162
163 assertNull("BUG: only one idle handler allowed", mIdleHandler);
164 mIdleHandler = new IdleHandler() {
165 public boolean queueIdle() {
Lorenzo Colitti5eaaf742016-03-02 21:47:42 +0900166 synchronized (queue) {
167 cv.open();
168 mIdleHandler = null;
169 return false; // Remove the handler.
170 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900171 }
172 };
173 queue.addIdleHandler(mIdleHandler);
174 }
175
176 if (!cv.block(timeoutMs)) {
177 fail("HandlerThread " + getName() +
178 " did not become idle after " + timeoutMs + " ms");
179 queue.removeIdleHandler(mIdleHandler);
180 }
181 }
182 }
183
184 // Tests that IdleableHandlerThread works as expected.
185 public void testIdleableHandlerThread() {
186 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
187
188 // Tests that waitForIdle returns immediately if the service is already idle.
189 for (int i = 0; i < attempts; i++) {
190 mService.waitForIdle();
191 }
192
193 // Bring up a network that we can use to send messages to ConnectivityService.
194 ConditionVariable cv = waitForConnectivityBroadcasts(1);
195 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
196 mWiFiNetworkAgent.connect(false);
197 waitFor(cv);
198 Network n = mWiFiNetworkAgent.getNetwork();
199 assertNotNull(n);
200
201 // Tests that calling waitForIdle waits for messages to be processed.
202 for (int i = 0; i < attempts; i++) {
203 mWiFiNetworkAgent.setSignalStrength(i);
204 mService.waitForIdle();
205 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
206 }
207
208 // Ensure that not calling waitForIdle causes a race condition.
209 for (int i = 0; i < attempts; i++) {
210 mWiFiNetworkAgent.setSignalStrength(i);
211 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
212 // We hit a race condition, as expected. Pass the test.
213 return;
214 }
215 }
216
217 // No race? There is a bug in this test.
218 fail("expected race condition at least once in " + attempts + " attempts");
219 }
220
Paul Jensend7b6ca92015-05-13 14:05:12 -0400221 private class MockNetworkAgent {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400222 private final WrappedNetworkMonitor mWrappedNetworkMonitor;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400223 private final NetworkInfo mNetworkInfo;
224 private final NetworkCapabilities mNetworkCapabilities;
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900225 private final IdleableHandlerThread mHandlerThread;
Paul Jensene0988542015-06-25 15:30:08 -0400226 private final ConditionVariable mDisconnected = new ConditionVariable();
Paul Jensen232437312016-04-06 09:51:26 -0400227 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
Paul Jensen3d911462015-06-12 06:40:24 -0400228 private int mScore;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400229 private NetworkAgent mNetworkAgent;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900230 private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
231 private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE;
232 private Integer mExpectedKeepaliveSlot = null;
Paul Jensen232437312016-04-06 09:51:26 -0400233 // Contains the redirectUrl from networkStatus(). Before reading, wait for
234 // mNetworkStatusReceived.
235 private String mRedirectUrl;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400236
237 MockNetworkAgent(int transport) {
238 final int type = transportToLegacyType(transport);
239 final String typeName = ConnectivityManager.getNetworkTypeName(type);
240 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
241 mNetworkCapabilities = new NetworkCapabilities();
242 mNetworkCapabilities.addTransportType(transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400243 switch (transport) {
244 case TRANSPORT_WIFI:
Paul Jensen3d911462015-06-12 06:40:24 -0400245 mScore = 60;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400246 break;
247 case TRANSPORT_CELLULAR:
Paul Jensen3d911462015-06-12 06:40:24 -0400248 mScore = 50;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400249 break;
250 default:
251 throw new UnsupportedOperationException("unimplemented network type");
252 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900253 mHandlerThread = new IdleableHandlerThread("Mock-" + typeName);
254 mHandlerThread.start();
255 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
256 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
257 new LinkProperties(), mScore, new NetworkMisc()) {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900258 @Override
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900259 public void unwanted() { mDisconnected.open(); }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900260
261 @Override
262 public void startPacketKeepalive(Message msg) {
263 int slot = msg.arg1;
264 if (mExpectedKeepaliveSlot != null) {
265 assertEquals((int) mExpectedKeepaliveSlot, slot);
266 }
267 onPacketKeepaliveEvent(slot, mStartKeepaliveError);
268 }
269
270 @Override
271 public void stopPacketKeepalive(Message msg) {
272 onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
273 }
Paul Jensen232437312016-04-06 09:51:26 -0400274
275 @Override
276 public void networkStatus(int status, String redirectUrl) {
277 mRedirectUrl = redirectUrl;
278 mNetworkStatusReceived.open();
279 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400280 };
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900281 // Waits for the NetworkAgent to be registered, which includes the creation of the
282 // NetworkMonitor.
283 mService.waitForIdle();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400284 mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor();
Paul Jensen3d911462015-06-12 06:40:24 -0400285 }
286
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900287 public void waitForIdle(int timeoutMs) {
288 mHandlerThread.waitForIdle(timeoutMs);
289 }
290
291 public void waitForIdle() {
292 waitForIdle(TIMEOUT_MS);
293 }
294
Paul Jensen3d911462015-06-12 06:40:24 -0400295 public void adjustScore(int change) {
296 mScore += change;
297 mNetworkAgent.sendNetworkScore(mScore);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400298 }
299
Paul Jensen85cf78e2015-06-25 13:25:07 -0400300 public void addCapability(int capability) {
301 mNetworkCapabilities.addCapability(capability);
302 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
303 }
304
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900305 public void setSignalStrength(int signalStrength) {
306 mNetworkCapabilities.setSignalStrength(signalStrength);
307 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
308 }
309
Paul Jensene0988542015-06-25 15:30:08 -0400310 public void connectWithoutInternet() {
311 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
312 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
313 }
314
Paul Jensend7b6ca92015-05-13 14:05:12 -0400315 /**
Paul Jensene0988542015-06-25 15:30:08 -0400316 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400317 * @param validated Indicate if network should pretend to be validated.
318 */
319 public void connect(boolean validated) {
320 assertEquals(mNetworkInfo.getDetailedState(), DetailedState.IDLE);
321 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
322
Paul Jensend7b6ca92015-05-13 14:05:12 -0400323 NetworkCallback callback = null;
324 final ConditionVariable validatedCv = new ConditionVariable();
325 if (validated) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400326 mWrappedNetworkMonitor.gen204ProbeResult = 204;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400327 NetworkRequest request = new NetworkRequest.Builder()
328 .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
329 .build();
330 callback = new NetworkCallback() {
331 public void onCapabilitiesChanged(Network network,
332 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400333 if (network.equals(getNetwork()) &&
334 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400335 validatedCv.open();
336 }
337 }
338 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400339 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400340 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400341 addCapability(NET_CAPABILITY_INTERNET);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400342
Paul Jensene0988542015-06-25 15:30:08 -0400343 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400344
345 if (validated) {
346 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400347 waitFor(validatedCv);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400348 mWrappedNetworkMonitor.gen204ProbeResult = 500;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400349 }
350
351 if (callback != null) mCm.unregisterNetworkCallback(callback);
352 }
353
Paul Jensen232437312016-04-06 09:51:26 -0400354 public void connectWithCaptivePortal(String redirectUrl) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400355 mWrappedNetworkMonitor.gen204ProbeResult = 200;
Paul Jensen232437312016-04-06 09:51:26 -0400356 mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400357 connect(false);
358 waitFor(new Criteria() { public boolean get() {
359 NetworkCapabilities caps = mCm.getNetworkCapabilities(getNetwork());
360 return caps != null && caps.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL);} });
361 mWrappedNetworkMonitor.gen204ProbeResult = 500;
Paul Jensen232437312016-04-06 09:51:26 -0400362 mWrappedNetworkMonitor.gen204ProbeRedirectUrl = null;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400363 }
364
Paul Jensend7b6ca92015-05-13 14:05:12 -0400365 public void disconnect() {
366 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
367 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
368 }
369
370 public Network getNetwork() {
371 return new Network(mNetworkAgent.netId);
372 }
Paul Jensene0988542015-06-25 15:30:08 -0400373
374 public ConditionVariable getDisconnectedCV() {
375 return mDisconnected;
376 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400377
378 public WrappedNetworkMonitor getWrappedNetworkMonitor() {
379 return mWrappedNetworkMonitor;
380 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900381
382 public void sendLinkProperties(LinkProperties lp) {
383 mNetworkAgent.sendLinkProperties(lp);
384 }
385
386 public void setStartKeepaliveError(int error) {
387 mStartKeepaliveError = error;
388 }
389
390 public void setStopKeepaliveError(int error) {
391 mStopKeepaliveError = error;
392 }
393
394 public void setExpectedKeepaliveSlot(Integer slot) {
395 mExpectedKeepaliveSlot = slot;
396 }
Paul Jensen232437312016-04-06 09:51:26 -0400397
398 public String waitForRedirectUrl() {
399 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
400 return mRedirectUrl;
401 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400402 }
403
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900404 /**
405 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
406 * operations have been processed. Before ConnectivityService can add or remove any requests,
407 * the factory must be told to expect those operations by calling expectAddRequests or
408 * expectRemoveRequests.
409 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700410 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400411 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
412 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400413 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700414
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900415 // Used to expect that requests be removed or added on a separate thread, without sleeping.
416 // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then
417 // cause some other thread to add or remove requests, then call waitForRequests(). We can
418 // either expect requests to be added or removed, but not both, because CountDownLatch can
419 // only count in one direction.
420 private CountDownLatch mExpectations;
421
422 // Whether we are currently expecting requests to be added or removed. Valid only if
423 // mExpectations is non-null.
424 private boolean mExpectingAdditions;
425
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700426 public MockNetworkFactory(Looper looper, Context context, String logTag,
427 NetworkCapabilities filter) {
428 super(looper, context, logTag, filter);
429 }
430
431 public int getMyRequestCount() {
432 return getRequestCount();
433 }
434
435 protected void startNetwork() {
436 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400437 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700438 }
439
440 protected void stopNetwork() {
441 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400442 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700443 }
444
445 public boolean getMyStartRequested() {
446 return mNetworkStarted.get();
447 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400448
449 public ConditionVariable getNetworkStartedCV() {
450 mNetworkStartedCV.close();
451 return mNetworkStartedCV;
452 }
453
454 public ConditionVariable getNetworkStoppedCV() {
455 mNetworkStoppedCV.close();
456 return mNetworkStoppedCV;
457 }
458
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900459 @Override
460 protected void handleAddRequest(NetworkRequest request, int score) {
461 // If we're expecting anything, we must be expecting additions.
462 if (mExpectations != null && !mExpectingAdditions) {
463 fail("Can't add requests while expecting requests to be removed");
464 }
465
466 // Add the request.
467 super.handleAddRequest(request, score);
468
469 // Reduce the number of request additions we're waiting for.
470 if (mExpectingAdditions) {
471 assertTrue("Added more requests than expected", mExpectations.getCount() > 0);
472 mExpectations.countDown();
473 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400474 }
475
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900476 @Override
477 protected void handleRemoveRequest(NetworkRequest request) {
478 // If we're expecting anything, we must be expecting removals.
479 if (mExpectations != null && mExpectingAdditions) {
480 fail("Can't remove requests while expecting requests to be added");
481 }
482
483 // Remove the request.
484 super.handleRemoveRequest(request);
485
486 // Reduce the number of request removals we're waiting for.
487 if (!mExpectingAdditions) {
488 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0);
489 mExpectations.countDown();
490 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400491 }
492
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900493 private void assertNoExpectations() {
494 if (mExpectations != null) {
495 fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
496 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400497 }
498
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900499 // Expects that count requests will be added.
500 public void expectAddRequests(final int count) {
501 assertNoExpectations();
502 mExpectingAdditions = true;
503 mExpectations = new CountDownLatch(count);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400504 }
505
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900506 // Expects that count requests will be removed.
507 public void expectRemoveRequests(final int count) {
508 assertNoExpectations();
509 mExpectingAdditions = false;
510 mExpectations = new CountDownLatch(count);
511 }
512
513 // Waits for the expected request additions or removals to happen within a timeout.
514 public void waitForRequests() throws InterruptedException {
515 assertNotNull("Nothing to wait for", mExpectations);
516 mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
517 final long count = mExpectations.getCount();
518 final String msg = count + " requests still not " +
519 (mExpectingAdditions ? "added" : "removed") +
520 " after " + TIMEOUT_MS + " ms";
521 assertEquals(msg, 0, count);
522 mExpectations = null;
523 }
524
525 public void waitForNetworkRequests(final int count) throws InterruptedException {
526 waitForRequests();
527 assertEquals(count, getMyRequestCount());
Paul Jensen0a2823e2015-06-12 10:31:09 -0400528 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700529 }
530
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900531 private class FakeWakeupMessage extends WakeupMessage {
532 private static final int UNREASONABLY_LONG_WAIT = 1000;
533
534 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
535 super(context, handler, cmdName, cmd);
536 }
537
538 @Override
539 public void schedule(long when) {
540 long delayMs = when - SystemClock.elapsedRealtime();
541 if (delayMs < 0) delayMs = 0;
542 if (delayMs > UNREASONABLY_LONG_WAIT) {
543 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
544 "ms into the future: " + delayMs);
545 }
546 mHandler.sendEmptyMessageDelayed(mCmd, delayMs);
547 }
548
549 @Override
550 public void cancel() {
551 mHandler.removeMessages(mCmd);
552 }
553
554 @Override
555 public void onAlarm() {
556 throw new AssertionError("Should never happen. Update this fake.");
557 }
558 }
559
Paul Jensencf4c2c62015-07-01 14:16:32 -0400560 // NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
561 private class WrappedNetworkMonitor extends NetworkMonitor {
562 // HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
563 public int gen204ProbeResult = 500;
Paul Jensen232437312016-04-06 09:51:26 -0400564 public String gen204ProbeRedirectUrl = null;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400565
566 public WrappedNetworkMonitor(Context context, Handler handler,
567 NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest) {
568 super(context, handler, networkAgentInfo, defaultRequest);
569 }
570
571 @Override
Paul Jensen232437312016-04-06 09:51:26 -0400572 protected CaptivePortalProbeResult isCaptivePortal() {
573 return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400574 }
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900575
576 @Override
577 protected WakeupMessage makeWakeupMessage(
578 Context context, Handler handler, String cmdName, int cmd) {
579 return new FakeWakeupMessage(context, handler, cmdName, cmd);
580 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400581 }
582
Paul Jensend7b6ca92015-05-13 14:05:12 -0400583 private class WrappedConnectivityService extends ConnectivityService {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400584 private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
585
Paul Jensend7b6ca92015-05-13 14:05:12 -0400586 public WrappedConnectivityService(Context context, INetworkManagementService netManager,
587 INetworkStatsService statsService, INetworkPolicyManager policyManager) {
588 super(context, netManager, statsService, policyManager);
589 }
590
591 @Override
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900592 protected HandlerThread createHandlerThread() {
593 return new IdleableHandlerThread("WrappedConnectivityService");
594 }
595
596 @Override
Paul Jensend7b6ca92015-05-13 14:05:12 -0400597 protected int getDefaultTcpRwnd() {
598 // Prevent wrapped ConnectivityService from trying to write to SystemProperties.
599 return 0;
600 }
Paul Jensen67b0b072015-06-10 11:22:17 -0400601
602 @Override
603 protected int reserveNetId() {
604 while (true) {
605 final int netId = super.reserveNetId();
606
607 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
608 // can have odd side-effects, like network validations succeeding.
609 final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks();
610 boolean overlaps = false;
611 for (Network network : networks) {
612 if (netId == network.netId) {
613 overlaps = true;
614 break;
615 }
616 }
617 if (overlaps) continue;
618
619 return netId;
620 }
621 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400622
623 @Override
624 public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
625 NetworkAgentInfo nai, NetworkRequest defaultRequest) {
626 final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(context, handler, nai,
627 defaultRequest);
628 mLastCreatedNetworkMonitor = monitor;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400629 return monitor;
630 }
631
632 public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
633 return mLastCreatedNetworkMonitor;
634 }
635
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900636 public void waitForIdle(int timeoutMs) {
637 ((IdleableHandlerThread) mHandlerThread).waitForIdle(timeoutMs);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400638 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900639
640 public void waitForIdle() {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900641 waitForIdle(TIMEOUT_MS);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900642 }
643
Paul Jensend7b6ca92015-05-13 14:05:12 -0400644 }
645
Paul Jensen0a2823e2015-06-12 10:31:09 -0400646 private interface Criteria {
647 public boolean get();
648 }
649
Paul Jensen3d911462015-06-12 06:40:24 -0400650 /**
651 * Wait up to 500ms for {@code criteria.get()} to become true, polling.
652 * Fails if 500ms goes by before {@code criteria.get()} to become true.
653 */
Paul Jensen0a2823e2015-06-12 10:31:09 -0400654 static private void waitFor(Criteria criteria) {
655 int delays = 0;
656 while (!criteria.get()) {
657 try {
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900658 Thread.sleep(50);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400659 } catch (InterruptedException e) {
660 }
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900661 if (++delays == 10) fail();
Paul Jensen0a2823e2015-06-12 10:31:09 -0400662 }
663 }
664
Paul Jensen3d911462015-06-12 06:40:24 -0400665 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900666 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
667 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -0400668 */
669 static private void waitFor(ConditionVariable conditionVariable) {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900670 assertTrue(conditionVariable.block(TIMEOUT_MS));
Paul Jensen3d911462015-06-12 06:40:24 -0400671 }
672
Paul Jensend7b6ca92015-05-13 14:05:12 -0400673 @Override
674 public void setUp() throws Exception {
675 super.setUp();
676
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900677 NetworkMonitor.SetDefaultLingerTime(120);
678
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +0900679 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
680 // http://b/25897652 .
681 if (Looper.myLooper() == null) {
682 Looper.prepare();
683 }
684
Paul Jensend7b6ca92015-05-13 14:05:12 -0400685 mServiceContext = new MockContext(getContext());
Lorenzo Colitti83fa2582015-08-07 12:49:01 +0900686 mService = new WrappedConnectivityService(mServiceContext,
687 mock(INetworkManagementService.class),
688 mock(INetworkStatsService.class),
689 mock(INetworkPolicyManager.class));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400690
Paul Jensend7b6ca92015-05-13 14:05:12 -0400691 mService.systemReady();
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900692 mCm = new WrappedConnectivityManager(getContext(), mService);
693 mCm.bindProcessToNetwork(null);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400694 }
695
696 private int transportToLegacyType(int transport) {
697 switch (transport) {
698 case TRANSPORT_WIFI:
699 return TYPE_WIFI;
700 case TRANSPORT_CELLULAR:
701 return TYPE_MOBILE;
702 default:
703 throw new IllegalStateException("Unknown transport" + transport);
704 }
705 }
706
707 private void verifyActiveNetwork(int transport) {
708 // Test getActiveNetworkInfo()
709 assertNotNull(mCm.getActiveNetworkInfo());
710 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
711 // Test getActiveNetwork()
712 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +0000713 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400714 switch (transport) {
715 case TRANSPORT_WIFI:
716 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
717 break;
718 case TRANSPORT_CELLULAR:
719 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
720 break;
721 default:
722 throw new IllegalStateException("Unknown transport" + transport);
723 }
724 // Test getNetworkInfo(Network)
725 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
726 assertEquals(transportToLegacyType(transport), mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
727 // Test getNetworkCapabilities(Network)
728 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
729 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
730 }
731
732 private void verifyNoNetwork() {
733 // Test getActiveNetworkInfo()
734 assertNull(mCm.getActiveNetworkInfo());
735 // Test getActiveNetwork()
736 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +0000737 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400738 // Test getAllNetworks()
739 assertEquals(0, mCm.getAllNetworks().length);
740 }
741
742 /**
743 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
744 * broadcasts are received.
745 */
746 private ConditionVariable waitForConnectivityBroadcasts(final int count) {
747 final ConditionVariable cv = new ConditionVariable();
748 mServiceContext.registerReceiver(new BroadcastReceiver() {
749 private int remaining = count;
750 public void onReceive(Context context, Intent intent) {
751 if (--remaining == 0) {
752 cv.open();
753 mServiceContext.unregisterReceiver(this);
754 }
755 }
756 }, new IntentFilter(CONNECTIVITY_ACTION));
757 return cv;
758 }
759
760 @LargeTest
761 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400762 verifyNoNetwork();
763 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
764 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
765 assertNull(mCm.getActiveNetworkInfo());
766 assertNull(mCm.getActiveNetwork());
767 // Test bringing up validated cellular.
768 ConditionVariable cv = waitForConnectivityBroadcasts(1);
769 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -0400770 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400771 verifyActiveNetwork(TRANSPORT_CELLULAR);
772 assertEquals(2, mCm.getAllNetworks().length);
773 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
774 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
775 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
776 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
777 // Test bringing up validated WiFi.
778 cv = waitForConnectivityBroadcasts(2);
779 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -0400780 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400781 verifyActiveNetwork(TRANSPORT_WIFI);
782 assertEquals(2, mCm.getAllNetworks().length);
783 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
784 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
785 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
786 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
787 // Test cellular linger timeout.
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900788 waitFor(new Criteria() {
789 public boolean get() { return mCm.getAllNetworks().length == 1; } });
Paul Jensend7b6ca92015-05-13 14:05:12 -0400790 verifyActiveNetwork(TRANSPORT_WIFI);
791 assertEquals(1, mCm.getAllNetworks().length);
792 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
793 // Test WiFi disconnect.
794 cv = waitForConnectivityBroadcasts(1);
795 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400796 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400797 verifyNoNetwork();
798 }
799
800 @LargeTest
801 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
802 // Test bringing up unvalidated WiFi
803 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
804 ConditionVariable cv = waitForConnectivityBroadcasts(1);
805 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -0400806 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400807 verifyActiveNetwork(TRANSPORT_WIFI);
808 // Test bringing up unvalidated cellular
809 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
810 mCellNetworkAgent.connect(false);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900811 mService.waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400812 verifyActiveNetwork(TRANSPORT_WIFI);
813 // Test cellular disconnect.
814 mCellNetworkAgent.disconnect();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900815 mService.waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400816 verifyActiveNetwork(TRANSPORT_WIFI);
817 // Test bringing up validated cellular
818 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
819 cv = waitForConnectivityBroadcasts(2);
820 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -0400821 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400822 verifyActiveNetwork(TRANSPORT_CELLULAR);
823 // Test cellular disconnect.
824 cv = waitForConnectivityBroadcasts(2);
825 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400826 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400827 verifyActiveNetwork(TRANSPORT_WIFI);
828 // Test WiFi disconnect.
829 cv = waitForConnectivityBroadcasts(1);
830 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400831 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400832 verifyNoNetwork();
833 }
834
835 @LargeTest
836 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
837 // Test bringing up unvalidated cellular.
838 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
839 ConditionVariable cv = waitForConnectivityBroadcasts(1);
840 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -0400841 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400842 verifyActiveNetwork(TRANSPORT_CELLULAR);
843 // Test bringing up unvalidated WiFi.
844 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
845 cv = waitForConnectivityBroadcasts(2);
846 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -0400847 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400848 verifyActiveNetwork(TRANSPORT_WIFI);
849 // Test WiFi disconnect.
850 cv = waitForConnectivityBroadcasts(2);
851 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400852 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400853 verifyActiveNetwork(TRANSPORT_CELLULAR);
854 // Test cellular disconnect.
855 cv = waitForConnectivityBroadcasts(1);
856 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400857 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400858 verifyNoNetwork();
859 }
860
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700861 @LargeTest
Paul Jensene0988542015-06-25 15:30:08 -0400862 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400863 // Test bringing up unvalidated WiFi.
Paul Jensene0988542015-06-25 15:30:08 -0400864 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400865 ConditionVariable cv = waitForConnectivityBroadcasts(1);
866 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -0400867 waitFor(cv);
868 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400869 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -0400870 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -0400871 // Test bringing up validated cellular.
872 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -0400873 cv = waitForConnectivityBroadcasts(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400874 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -0400875 waitFor(cv);
876 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400877 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
878 NET_CAPABILITY_VALIDATED));
879 // Test cellular disconnect.
880 cv = waitForConnectivityBroadcasts(2);
881 mCellNetworkAgent.disconnect();
882 waitFor(cv);
883 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -0400884 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -0400885 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -0400886 NET_CAPABILITY_VALIDATED));
887 }
888
889 @LargeTest
Paul Jensen3d911462015-06-12 06:40:24 -0400890 public void testCellularOutscoresWeakWifi() throws Exception {
891 // Test bringing up validated cellular.
892 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
893 ConditionVariable cv = waitForConnectivityBroadcasts(1);
894 mCellNetworkAgent.connect(true);
895 waitFor(cv);
896 verifyActiveNetwork(TRANSPORT_CELLULAR);
897 // Test bringing up validated WiFi.
898 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
899 cv = waitForConnectivityBroadcasts(2);
900 mWiFiNetworkAgent.connect(true);
901 waitFor(cv);
902 verifyActiveNetwork(TRANSPORT_WIFI);
903 // Test WiFi getting really weak.
904 cv = waitForConnectivityBroadcasts(2);
905 mWiFiNetworkAgent.adjustScore(-11);
906 waitFor(cv);
907 verifyActiveNetwork(TRANSPORT_CELLULAR);
908 // Test WiFi restoring signal strength.
909 cv = waitForConnectivityBroadcasts(2);
910 mWiFiNetworkAgent.adjustScore(11);
911 waitFor(cv);
912 verifyActiveNetwork(TRANSPORT_WIFI);
913 mCellNetworkAgent.disconnect();
914 mWiFiNetworkAgent.disconnect();
915 }
916
Paul Jensene0988542015-06-25 15:30:08 -0400917 @LargeTest
918 public void testReapingNetwork() throws Exception {
919 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
920 // Expect it to be torn down immediately because it satisfies no requests.
921 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
922 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
923 mWiFiNetworkAgent.connectWithoutInternet();
924 waitFor(cv);
925 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
926 // Expect it to be torn down immediately because it satisfies no requests.
927 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
928 cv = mCellNetworkAgent.getDisconnectedCV();
929 mCellNetworkAgent.connectWithoutInternet();
930 waitFor(cv);
931 // Test bringing up validated WiFi.
932 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
933 cv = waitForConnectivityBroadcasts(1);
934 mWiFiNetworkAgent.connect(true);
935 waitFor(cv);
936 verifyActiveNetwork(TRANSPORT_WIFI);
937 // Test bringing up unvalidated cellular.
938 // Expect it to be torn down because it could never be the highest scoring network
939 // satisfying the default request even if it validated.
940 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
941 cv = mCellNetworkAgent.getDisconnectedCV();
942 mCellNetworkAgent.connect(false);
943 waitFor(cv);
944 verifyActiveNetwork(TRANSPORT_WIFI);
945 cv = mWiFiNetworkAgent.getDisconnectedCV();
946 mWiFiNetworkAgent.disconnect();
947 waitFor(cv);
948 }
949
950 @LargeTest
951 public void testCellularFallback() throws Exception {
952 // Test bringing up validated cellular.
953 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
954 ConditionVariable cv = waitForConnectivityBroadcasts(1);
955 mCellNetworkAgent.connect(true);
956 waitFor(cv);
957 verifyActiveNetwork(TRANSPORT_CELLULAR);
958 // Test bringing up validated WiFi.
959 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
960 cv = waitForConnectivityBroadcasts(2);
961 mWiFiNetworkAgent.connect(true);
962 waitFor(cv);
963 verifyActiveNetwork(TRANSPORT_WIFI);
964 // Reevaluate WiFi (it'll instantly fail DNS).
965 cv = waitForConnectivityBroadcasts(2);
966 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
967 NET_CAPABILITY_VALIDATED));
968 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
969 // Should quickly fall back to Cellular.
970 waitFor(cv);
971 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
972 NET_CAPABILITY_VALIDATED));
973 verifyActiveNetwork(TRANSPORT_CELLULAR);
974 // Reevaluate cellular (it'll instantly fail DNS).
975 cv = waitForConnectivityBroadcasts(2);
976 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
977 NET_CAPABILITY_VALIDATED));
978 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
979 // Should quickly fall back to WiFi.
980 waitFor(cv);
981 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
982 NET_CAPABILITY_VALIDATED));
983 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
984 NET_CAPABILITY_VALIDATED));
985 verifyActiveNetwork(TRANSPORT_WIFI);
986 mCellNetworkAgent.disconnect();
987 mWiFiNetworkAgent.disconnect();
988 }
989
990 @LargeTest
991 public void testWiFiFallback() throws Exception {
992 // Test bringing up unvalidated WiFi.
993 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
994 ConditionVariable cv = waitForConnectivityBroadcasts(1);
995 mWiFiNetworkAgent.connect(false);
996 waitFor(cv);
997 verifyActiveNetwork(TRANSPORT_WIFI);
998 // Test bringing up validated cellular.
999 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1000 cv = waitForConnectivityBroadcasts(2);
1001 mCellNetworkAgent.connect(true);
1002 waitFor(cv);
1003 verifyActiveNetwork(TRANSPORT_CELLULAR);
1004 // Reevaluate cellular (it'll instantly fail DNS).
1005 cv = waitForConnectivityBroadcasts(2);
1006 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1007 NET_CAPABILITY_VALIDATED));
1008 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1009 // Should quickly fall back to WiFi.
1010 waitFor(cv);
1011 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1012 NET_CAPABILITY_VALIDATED));
1013 verifyActiveNetwork(TRANSPORT_WIFI);
1014 mCellNetworkAgent.disconnect();
1015 mWiFiNetworkAgent.disconnect();
1016 }
1017
Paul Jensen3d911462015-06-12 06:40:24 -04001018 enum CallbackState {
1019 NONE,
1020 AVAILABLE,
1021 LOSING,
1022 LOST
1023 }
1024
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001025 /**
1026 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1027 * this class receives, by calling expectCallback() exactly once each time a callback is
1028 * received. assertNoCallback may be called at any time.
1029 */
Paul Jensen3d911462015-06-12 06:40:24 -04001030 private class TestNetworkCallback extends NetworkCallback {
1031 private final ConditionVariable mConditionVariable = new ConditionVariable();
1032 private CallbackState mLastCallback = CallbackState.NONE;
Erik Klinea2d29402016-03-16 15:31:39 +09001033 private Network mLastNetwork;
Paul Jensen3d911462015-06-12 06:40:24 -04001034
1035 public void onAvailable(Network network) {
1036 assertEquals(CallbackState.NONE, mLastCallback);
1037 mLastCallback = CallbackState.AVAILABLE;
Erik Klinea2d29402016-03-16 15:31:39 +09001038 mLastNetwork = network;
Paul Jensen3d911462015-06-12 06:40:24 -04001039 mConditionVariable.open();
1040 }
1041
1042 public void onLosing(Network network, int maxMsToLive) {
1043 assertEquals(CallbackState.NONE, mLastCallback);
1044 mLastCallback = CallbackState.LOSING;
Erik Klinea2d29402016-03-16 15:31:39 +09001045 mLastNetwork = network;
Paul Jensen3d911462015-06-12 06:40:24 -04001046 mConditionVariable.open();
1047 }
1048
1049 public void onLost(Network network) {
1050 assertEquals(CallbackState.NONE, mLastCallback);
1051 mLastCallback = CallbackState.LOST;
Erik Klinea2d29402016-03-16 15:31:39 +09001052 mLastNetwork = network;
Paul Jensen3d911462015-06-12 06:40:24 -04001053 mConditionVariable.open();
1054 }
1055
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001056 void expectCallback(CallbackState state) {
Erik Klinea2d29402016-03-16 15:31:39 +09001057 expectCallback(state, null);
1058 }
1059
1060 void expectCallback(CallbackState state, MockNetworkAgent mockAgent) {
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001061 waitFor(mConditionVariable);
1062 assertEquals(state, mLastCallback);
Erik Klinea2d29402016-03-16 15:31:39 +09001063 if (mockAgent != null) {
1064 assertEquals(mockAgent.getNetwork(), mLastNetwork);
1065 }
Paul Jensen3d911462015-06-12 06:40:24 -04001066 mLastCallback = CallbackState.NONE;
Erik Klinea2d29402016-03-16 15:31:39 +09001067 mLastNetwork = null;
Paul Jensen3d911462015-06-12 06:40:24 -04001068 mConditionVariable.close();
Paul Jensen3d911462015-06-12 06:40:24 -04001069 }
1070
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001071 void assertNoCallback() {
1072 assertEquals(CallbackState.NONE, mLastCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001073 }
1074 }
1075
1076 @LargeTest
1077 public void testStateChangeNetworkCallbacks() throws Exception {
1078 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1079 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
1080 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1081 .addTransportType(TRANSPORT_WIFI).build();
1082 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1083 .addTransportType(TRANSPORT_CELLULAR).build();
1084 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1085 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1086
1087 // Test unvalidated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001088 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1089 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1090 mCellNetworkAgent.connect(false);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001091 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE);
1092 wifiNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001093 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1094 waitFor(cv);
1095
Paul Jensen3d911462015-06-12 06:40:24 -04001096 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1097 mCellNetworkAgent.adjustScore(-1);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001098 mService.waitForIdle();
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001099 wifiNetworkCallback.assertNoCallback();
1100 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001101 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1102
Paul Jensen3d911462015-06-12 06:40:24 -04001103 cv = waitForConnectivityBroadcasts(2);
1104 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1105 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001106 wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE);
1107 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001108 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1109 waitFor(cv);
1110
Paul Jensen3d911462015-06-12 06:40:24 -04001111 cv = waitForConnectivityBroadcasts(2);
1112 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001113 wifiNetworkCallback.expectCallback(CallbackState.LOST);
1114 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001115 waitFor(cv);
1116
Paul Jensen3d911462015-06-12 06:40:24 -04001117 cv = waitForConnectivityBroadcasts(1);
1118 mCellNetworkAgent.disconnect();
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001119 cellNetworkCallback.expectCallback(CallbackState.LOST);
1120 wifiNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001121 waitFor(cv);
1122
1123 // Test validated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001124 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1125 mCellNetworkAgent.connect(true);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001126 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE);
1127 wifiNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001128 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1129
Paul Jensen3d911462015-06-12 06:40:24 -04001130 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1131 mCellNetworkAgent.adjustScore(-1);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001132 mService.waitForIdle();
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001133 wifiNetworkCallback.assertNoCallback();
1134 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001135 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1136
Paul Jensen3d911462015-06-12 06:40:24 -04001137 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1138 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001139 wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE);
1140 cellNetworkCallback.expectCallback(CallbackState.LOSING);
Paul Jensen3d911462015-06-12 06:40:24 -04001141 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1142
Paul Jensen3d911462015-06-12 06:40:24 -04001143 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001144 wifiNetworkCallback.expectCallback(CallbackState.LOST);
1145 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001146
Paul Jensen3d911462015-06-12 06:40:24 -04001147 mCellNetworkAgent.disconnect();
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001148 cellNetworkCallback.expectCallback(CallbackState.LOST);
1149 wifiNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001150 }
1151
Paul Jensen85cf78e2015-06-25 13:25:07 -04001152 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04001153 // Verify NOT_RESTRICTED is set appropriately
1154 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
1155 .build().networkCapabilities;
1156 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
1157 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
1158 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04001159 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04001160 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1161 } else {
1162 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1163 }
1164
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001165 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001166 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001167 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
1168 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04001169 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001170 mServiceContext, "testFactory", filter);
1171 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04001172 ConditionVariable cv = testFactory.getNetworkStartedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001173 testFactory.expectAddRequests(1);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001174 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001175 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001176 int expectedRequestCount = 1;
1177 NetworkCallback networkCallback = null;
1178 // For non-INTERNET capabilities we cannot rely on the default request being present, so
1179 // add one.
1180 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04001181 assertFalse(testFactory.getMyStartRequested());
1182 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
1183 networkCallback = new NetworkCallback();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001184 testFactory.expectAddRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001185 mCm.requestNetwork(request, networkCallback);
1186 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001187 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001188 }
Paul Jensen3d911462015-06-12 06:40:24 -04001189 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001190 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1191 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001192
Paul Jensen85cf78e2015-06-25 13:25:07 -04001193 // Now bring in a higher scored network.
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001194 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001195 // Rather than create a validated network which complicates things by registering it's
1196 // own NetworkRequest during startup, just bump up the score to cancel out the
1197 // unvalidated penalty.
1198 testAgent.adjustScore(40);
1199 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001200
1201 // When testAgent connects, ConnectivityService will re-send us all current requests with
1202 // the new score. There are expectedRequestCount such requests, and we must wait for all of
1203 // them.
1204 testFactory.expectAddRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001205 testAgent.connect(false);
1206 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04001207 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001208 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001209 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001210
Paul Jensen85cf78e2015-06-25 13:25:07 -04001211 // Bring in a bunch of requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001212 testFactory.expectAddRequests(10);
1213 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001214 ConnectivityManager.NetworkCallback[] networkCallbacks =
1215 new ConnectivityManager.NetworkCallback[10];
1216 for (int i = 0; i< networkCallbacks.length; i++) {
1217 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
1218 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001219 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001220 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
1221 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04001222 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
1223 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001224
Paul Jensen85cf78e2015-06-25 13:25:07 -04001225 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001226 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001227 for (int i = 0; i < networkCallbacks.length; i++) {
1228 mCm.unregisterNetworkCallback(networkCallbacks[i]);
1229 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04001230 testFactory.waitForNetworkRequests(expectedRequestCount);
1231 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001232
Paul Jensen85cf78e2015-06-25 13:25:07 -04001233 // Drop the higher scored network.
1234 cv = testFactory.getNetworkStartedCV();
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001235 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001236 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001237 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1238 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001239
1240 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001241 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001242 handlerThread.quit();
1243 }
1244
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001245 @LargeTest
Paul Jensen85cf78e2015-06-25 13:25:07 -04001246 public void testNetworkFactoryRequests() throws Exception {
1247 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
1248 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
1249 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
1250 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
1251 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
1252 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
1253 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
1254 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
1255 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
1256 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
1257 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
1258 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
1259 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
1260 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
1261 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
1262 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
1263 }
1264
1265 @LargeTest
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001266 public void testNoMutableNetworkRequests() throws Exception {
1267 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
1268 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001269 builder.addCapability(NET_CAPABILITY_VALIDATED);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001270 try {
1271 mCm.requestNetwork(builder.build(), new NetworkCallback());
1272 fail();
1273 } catch (IllegalArgumentException expected) {}
1274 try {
1275 mCm.requestNetwork(builder.build(), pendingIntent);
1276 fail();
1277 } catch (IllegalArgumentException expected) {}
1278 builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001279 builder.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001280 try {
1281 mCm.requestNetwork(builder.build(), new NetworkCallback());
1282 fail();
1283 } catch (IllegalArgumentException expected) {}
1284 try {
1285 mCm.requestNetwork(builder.build(), pendingIntent);
1286 fail();
1287 } catch (IllegalArgumentException expected) {}
1288 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001289
Paul Jensene0988542015-06-25 15:30:08 -04001290 @LargeTest
1291 public void testMMSonWiFi() throws Exception {
1292 // Test bringing up cellular without MMS NetworkRequest gets reaped
1293 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1294 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1295 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
1296 mCellNetworkAgent.connectWithoutInternet();
1297 waitFor(cv);
1298 waitFor(new Criteria() {
1299 public boolean get() { return mCm.getAllNetworks().length == 0; } });
1300 verifyNoNetwork();
1301 // Test bringing up validated WiFi.
1302 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1303 cv = waitForConnectivityBroadcasts(1);
1304 mWiFiNetworkAgent.connect(true);
1305 waitFor(cv);
1306 verifyActiveNetwork(TRANSPORT_WIFI);
1307 // Register MMS NetworkRequest
1308 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1309 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1310 final TestNetworkCallback networkCallback = new TestNetworkCallback();
1311 mCm.requestNetwork(builder.build(), networkCallback);
1312 // Test bringing up unvalidated cellular with MMS
1313 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1314 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04001315 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001316 networkCallback.expectCallback(CallbackState.AVAILABLE);
Paul Jensene0988542015-06-25 15:30:08 -04001317 verifyActiveNetwork(TRANSPORT_WIFI);
1318 // Test releasing NetworkRequest disconnects cellular with MMS
1319 cv = mCellNetworkAgent.getDisconnectedCV();
1320 mCm.unregisterNetworkCallback(networkCallback);
1321 waitFor(cv);
1322 verifyActiveNetwork(TRANSPORT_WIFI);
1323 }
1324
1325 @LargeTest
1326 public void testMMSonCell() throws Exception {
1327 // Test bringing up cellular without MMS
1328 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1329 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1330 mCellNetworkAgent.connect(false);
1331 waitFor(cv);
1332 verifyActiveNetwork(TRANSPORT_CELLULAR);
1333 // Register MMS NetworkRequest
1334 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1335 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1336 final TestNetworkCallback networkCallback = new TestNetworkCallback();
1337 mCm.requestNetwork(builder.build(), networkCallback);
1338 // Test bringing up MMS cellular network
Paul Jensene0988542015-06-25 15:30:08 -04001339 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1340 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1341 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001342 networkCallback.expectCallback(CallbackState.AVAILABLE);
Paul Jensene0988542015-06-25 15:30:08 -04001343 verifyActiveNetwork(TRANSPORT_CELLULAR);
1344 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
1345 cv = mmsNetworkAgent.getDisconnectedCV();
1346 mCm.unregisterNetworkCallback(networkCallback);
1347 waitFor(cv);
1348 verifyActiveNetwork(TRANSPORT_CELLULAR);
1349 }
1350
Paul Jensencf4c2c62015-07-01 14:16:32 -04001351 @LargeTest
1352 public void testCaptivePortal() {
1353 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1354 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1355 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1356 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1357
1358 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1359 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1360 .addCapability(NET_CAPABILITY_VALIDATED).build();
1361 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001362
1363 // Bring up a network with a captive portal.
1364 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001365 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04001366 String firstRedirectUrl = "http://example.com/firstPath";
1367 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001368 captivePortalCallback.expectCallback(CallbackState.AVAILABLE);
Paul Jensen232437312016-04-06 09:51:26 -04001369 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001370
1371 // Take down network.
1372 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001373 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001374 captivePortalCallback.expectCallback(CallbackState.LOST);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001375
1376 // Bring up a network with a captive portal.
1377 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001378 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04001379 String secondRedirectUrl = "http://example.com/secondPath";
1380 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001381 captivePortalCallback.expectCallback(CallbackState.AVAILABLE);
Paul Jensen232437312016-04-06 09:51:26 -04001382 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001383
1384 // Make captive portal disappear then revalidate.
1385 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001386 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
1387 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001388 captivePortalCallback.expectCallback(CallbackState.LOST);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001389
1390 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001391 validatedCallback.expectCallback(CallbackState.AVAILABLE);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001392
1393 // Break network connectivity.
1394 // Expect NET_CAPABILITY_VALIDATED onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001395 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
1396 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001397 validatedCallback.expectCallback(CallbackState.LOST);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001398 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09001399
Etan Cohenddb9ef02015-11-18 10:56:15 -08001400 @SmallTest
1401 public void testInvalidNetworkSpecifier() {
1402 boolean execptionCalled = true;
1403
1404 try {
1405 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1406 builder.setNetworkSpecifier(MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
1407 execptionCalled = false;
1408 } catch (IllegalArgumentException e) {
1409 // do nothing - should get here
1410 }
1411
1412 assertTrue("NetworkReqeuest builder with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
1413 execptionCalled);
1414
1415 try {
1416 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
1417 networkCapabilities.addTransportType(TRANSPORT_WIFI)
1418 .setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
1419 mService.requestNetwork(networkCapabilities, null, 0, null,
1420 ConnectivityManager.TYPE_WIFI);
1421 execptionCalled = false;
1422 } catch (IllegalArgumentException e) {
1423 // do nothing - should get here
1424 }
1425
1426 assertTrue("ConnectivityService requestNetwork with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
1427 execptionCalled);
1428 }
1429
Erik Klinea2d29402016-03-16 15:31:39 +09001430 @LargeTest
1431 public void testRegisterDefaultNetworkCallback() throws Exception {
1432 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
1433 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
1434 defaultNetworkCallback.assertNoCallback();
1435
1436 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
1437 // whenever Wi-Fi is up. Without this, the mobile network agent is
1438 // reaped before any other activity can take place.
1439 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
1440 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1441 .addTransportType(TRANSPORT_CELLULAR).build();
1442 mCm.requestNetwork(cellRequest, cellNetworkCallback);
1443 cellNetworkCallback.assertNoCallback();
1444
1445 // Bring up cell and expect CALLBACK_AVAILABLE.
1446 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1447 mCellNetworkAgent.connect(true);
1448 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1449 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1450
1451 // Bring up wifi and expect CALLBACK_AVAILABLE.
1452 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1453 mWiFiNetworkAgent.connect(true);
1454 cellNetworkCallback.assertNoCallback();
1455 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1456
1457 // Bring down cell. Expect no default network callback, since it wasn't the default.
1458 mCellNetworkAgent.disconnect();
1459 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1460 defaultNetworkCallback.assertNoCallback();
1461
1462 // Bring up cell. Expect no default network callback, since it won't be the default.
1463 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1464 mCellNetworkAgent.connect(true);
1465 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1466 defaultNetworkCallback.assertNoCallback();
1467
1468 // Bring down wifi. Expect the default network callback to notified of LOST wifi
1469 // followed by AVAILABLE cell.
1470 mWiFiNetworkAgent.disconnect();
1471 cellNetworkCallback.assertNoCallback();
1472 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1473 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1474 mCellNetworkAgent.disconnect();
1475 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1476 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1477 }
1478
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09001479 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
1480
1481 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
1482
1483 private class CallbackValue {
1484 public CallbackType callbackType;
1485 public int error;
1486
1487 public CallbackValue(CallbackType type) {
1488 this.callbackType = type;
1489 this.error = PacketKeepalive.SUCCESS;
1490 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
1491 }
1492
1493 public CallbackValue(CallbackType type, int error) {
1494 this.callbackType = type;
1495 this.error = error;
1496 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
1497 }
1498
1499 @Override
1500 public boolean equals(Object o) {
1501 return o instanceof CallbackValue &&
1502 this.callbackType == ((CallbackValue) o).callbackType &&
1503 this.error == ((CallbackValue) o).error;
1504 }
1505
1506 @Override
1507 public String toString() {
1508 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
1509 }
1510 }
1511
1512 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
1513
1514 @Override
1515 public void onStarted() {
1516 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
1517 }
1518
1519 @Override
1520 public void onStopped() {
1521 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
1522 }
1523
1524 @Override
1525 public void onError(int error) {
1526 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
1527 }
1528
1529 private void expectCallback(CallbackValue callbackValue) {
1530 try {
1531 assertEquals(
1532 callbackValue,
1533 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
1534 } catch (InterruptedException e) {
1535 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
1536 }
1537 }
1538
1539 public void expectStarted() {
1540 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
1541 }
1542
1543 public void expectStopped() {
1544 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
1545 }
1546
1547 public void expectError(int error) {
1548 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
1549 }
1550 }
1551
1552 private Network connectKeepaliveNetwork(LinkProperties lp) {
1553 // Ensure the network is disconnected before we do anything.
1554 if (mWiFiNetworkAgent != null) {
1555 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
1556 }
1557
1558 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1559 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1560 mWiFiNetworkAgent.connect(true);
1561 waitFor(cv);
1562 verifyActiveNetwork(TRANSPORT_WIFI);
1563 mWiFiNetworkAgent.sendLinkProperties(lp);
1564 mService.waitForIdle();
1565 return mWiFiNetworkAgent.getNetwork();
1566 }
1567
1568 public void testPacketKeepalives() throws Exception {
1569 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
1570 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
1571 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
1572 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
1573 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
1574
1575 LinkProperties lp = new LinkProperties();
1576 lp.setInterfaceName("wlan12");
1577 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
1578 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
1579 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
1580 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
1581
1582 Network notMyNet = new Network(61234);
1583 Network myNet = connectKeepaliveNetwork(lp);
1584
1585 TestKeepaliveCallback callback = new TestKeepaliveCallback();
1586 PacketKeepalive ka;
1587
1588 // Attempt to start keepalives with invalid parameters and check for errors.
1589 ka = mCm.startNattKeepalive(notMyNet, 25, callback, myIPv4, 1234, dstIPv4);
1590 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
1591
1592 ka = mCm.startNattKeepalive(myNet, 19, callback, notMyIPv4, 1234, dstIPv4);
1593 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
1594
1595 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 1234, dstIPv6);
1596 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
1597
1598 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv4);
1599 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
1600
1601 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv6);
1602 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); // NAT-T is IPv4-only.
1603
1604 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
1605 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
1606
1607 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
1608 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
1609
1610 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1611 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
1612
1613 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1614 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
1615
1616 // Check that a started keepalive can be stopped.
1617 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
1618 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1619 callback.expectStarted();
1620 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
1621 ka.stop();
1622 callback.expectStopped();
1623
1624 // Check that deleting the IP address stops the keepalive.
1625 LinkProperties bogusLp = new LinkProperties(lp);
1626 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1627 callback.expectStarted();
1628 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
1629 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
1630 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
1631 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
1632 mWiFiNetworkAgent.sendLinkProperties(lp);
1633
1634 // Check that a started keepalive is stopped correctly when the network disconnects.
1635 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1636 callback.expectStarted();
1637 mWiFiNetworkAgent.disconnect();
1638 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
1639
1640 // ... and that stopping it after that has no adverse effects.
1641 assertNull(mCm.getNetworkCapabilities(myNet));
1642 ka.stop();
1643
1644 // Reconnect.
1645 myNet = connectKeepaliveNetwork(lp);
1646 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
1647
1648 // Check things work as expected when the keepalive is stopped and the network disconnects.
1649 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1650 callback.expectStarted();
1651 ka.stop();
1652 mWiFiNetworkAgent.disconnect();
1653 mService.waitForIdle();
1654 callback.expectStopped();
1655
1656 // Reconnect.
1657 myNet = connectKeepaliveNetwork(lp);
1658 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
1659
1660 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
1661 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
1662 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1663 callback.expectStarted();
1664
1665 // The second one gets slot 2.
1666 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
1667 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
1668 PacketKeepalive ka2 = mCm.startNattKeepalive(myNet, 25, callback2, myIPv4, 6789, dstIPv4);
1669 callback2.expectStarted();
1670
1671 // Now stop the first one and create a third. This also gets slot 1.
1672 ka.stop();
1673 callback.expectStopped();
1674
1675 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
1676 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
1677 PacketKeepalive ka3 = mCm.startNattKeepalive(myNet, 25, callback3, myIPv4, 9876, dstIPv4);
1678 callback3.expectStarted();
1679
1680 ka2.stop();
1681 callback2.expectStopped();
1682
1683 ka3.stop();
1684 callback3.expectStopped();
1685 }
Udam Sainib7c24872016-01-04 12:16:14 -08001686
1687 @SmallTest
1688 public void testGetCaptivePortalServerUrl() throws Exception {
1689 String url = mCm.getCaptivePortalServerUrl();
1690 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
1691 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09001692
1693 private static class TestNetworkPinner extends NetworkPinner {
1694 public static boolean awaitPin(int timeoutMs) {
1695 synchronized(sLock) {
1696 if (sNetwork == null) {
1697 try {
1698 sLock.wait(timeoutMs);
1699 } catch (InterruptedException e) {}
1700 }
1701 return sNetwork != null;
1702 }
1703 }
1704
1705 public static boolean awaitUnpin(int timeoutMs) {
1706 synchronized(sLock) {
1707 if (sNetwork != null) {
1708 try {
1709 sLock.wait(timeoutMs);
1710 } catch (InterruptedException e) {}
1711 }
1712 return sNetwork == null;
1713 }
1714 }
1715 }
1716
1717 private void assertPinnedToWifiWithCellDefault() {
1718 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
1719 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1720 }
1721
1722 private void assertPinnedToWifiWithWifiDefault() {
1723 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
1724 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1725 }
1726
1727 private void assertNotPinnedToWifi() {
1728 assertNull(mCm.getBoundNetworkForProcess());
1729 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1730 }
1731
1732 @SmallTest
1733 public void testNetworkPinner() {
1734 NetworkRequest wifiRequest = new NetworkRequest.Builder()
1735 .addTransportType(TRANSPORT_WIFI)
1736 .build();
1737 assertNull(mCm.getBoundNetworkForProcess());
1738
1739 TestNetworkPinner.pin(mServiceContext, wifiRequest);
1740 assertNull(mCm.getBoundNetworkForProcess());
1741
1742 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1743 mCellNetworkAgent.connect(true);
1744 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1745 mWiFiNetworkAgent.connect(false);
1746
1747 // When wi-fi connects, expect to be pinned.
1748 assertTrue(TestNetworkPinner.awaitPin(100));
1749 assertPinnedToWifiWithCellDefault();
1750
1751 // Disconnect and expect the pin to drop.
1752 mWiFiNetworkAgent.disconnect();
1753 assertTrue(TestNetworkPinner.awaitUnpin(100));
1754 assertNotPinnedToWifi();
1755
1756 // Reconnecting does not cause the pin to come back.
1757 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1758 mWiFiNetworkAgent.connect(false);
1759 assertFalse(TestNetworkPinner.awaitPin(100));
1760 assertNotPinnedToWifi();
1761
1762 // Pinning while connected causes the pin to take effect immediately.
1763 TestNetworkPinner.pin(mServiceContext, wifiRequest);
1764 assertTrue(TestNetworkPinner.awaitPin(100));
1765 assertPinnedToWifiWithCellDefault();
1766
1767 // Explicitly unpin and expect to use the default network again.
1768 TestNetworkPinner.unpin();
1769 assertNotPinnedToWifi();
1770
1771 // Disconnect cell and wifi.
1772 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
1773 mCellNetworkAgent.disconnect();
1774 mWiFiNetworkAgent.disconnect();
1775 waitFor(cv);
1776
1777 // Pinning takes effect even if the pinned network is the default when the pin is set...
1778 TestNetworkPinner.pin(mServiceContext, wifiRequest);
1779 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1780 mWiFiNetworkAgent.connect(false);
1781 assertTrue(TestNetworkPinner.awaitPin(100));
1782 assertPinnedToWifiWithWifiDefault();
1783
1784 // ... and is maintained even when that network is no longer the default.
1785 cv = waitForConnectivityBroadcasts(1);
1786 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1787 mCellNetworkAgent.connect(true);
1788 waitFor(cv);
1789 assertPinnedToWifiWithCellDefault();
1790 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07001791}