blob: 65f9399c5a80e6f348423b0757c8ae7f5cbd3a57 [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
Jeff Sharkey3671b1e2013-01-31 17:22:26 -080026import static org.mockito.Mockito.mock;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070027
Lorenzo Colitti73b209382016-09-15 22:18:09 +090028import android.app.NotificationManager;
Paul Jensenbb2e0e92015-06-16 15:11:58 -040029import android.app.PendingIntent;
Paul Jensend7b6ca92015-05-13 14:05:12 -040030import android.content.BroadcastReceiver;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +090031import android.content.ContentResolver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070032import android.content.Context;
Paul Jensend7b6ca92015-05-13 14:05:12 -040033import android.content.ContextWrapper;
34import android.content.Intent;
35import android.content.IntentFilter;
36import android.net.ConnectivityManager;
37import android.net.ConnectivityManager.NetworkCallback;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +090038import android.net.ConnectivityManager.PacketKeepalive;
39import android.net.ConnectivityManager.PacketKeepaliveCallback;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070040import android.net.INetworkPolicyManager;
41import android.net.INetworkStatsService;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +090042import android.net.IpPrefix;
43import android.net.LinkAddress;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070044import android.net.LinkProperties;
Paul Jensend7b6ca92015-05-13 14:05:12 -040045import android.net.Network;
46import android.net.NetworkAgent;
47import android.net.NetworkCapabilities;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070048import android.net.NetworkConfig;
Robert Greenwalt348e98d2015-06-05 17:55:36 -070049import android.net.NetworkFactory;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070050import android.net.NetworkInfo;
51import android.net.NetworkInfo.DetailedState;
Paul Jensend7b6ca92015-05-13 14:05:12 -040052import android.net.NetworkMisc;
53import android.net.NetworkRequest;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070054import android.net.RouteInfo;
Hugo Benichif9fdf872016-07-28 17:53:06 +090055import android.net.metrics.IpConnectivityLog;
Erik Kline065ab6e2016-10-02 18:02:14 +090056import android.net.util.AvoidBadWifiTracker;
Paul Jensend7b6ca92015-05-13 14:05:12 -040057import android.os.ConditionVariable;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070058import android.os.Handler;
Robert Greenwalt348e98d2015-06-05 17:55:36 -070059import android.os.HandlerThread;
Etan Cohenddb9ef02015-11-18 10:56:15 -080060import android.os.IBinder;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070061import android.os.INetworkManagementService;
Lorenzo Colittie58961a2015-08-07 20:17:27 +090062import android.os.Looper;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +090063import android.os.Message;
Lorenzo Colittie58961a2015-08-07 20:17:27 +090064import android.os.MessageQueue;
Etan Cohenddb9ef02015-11-18 10:56:15 -080065import android.os.Messenger;
Lorenzo Colittie58961a2015-08-07 20:17:27 +090066import android.os.MessageQueue.IdleHandler;
Robin Leed2baf792016-03-24 12:07:00 +000067import android.os.Process;
Lorenzo Colittibfecba22016-02-21 01:09:26 +090068import android.os.SystemClock;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +090069import android.provider.Settings;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070070import android.test.AndroidTestCase;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +090071import android.test.mock.MockContentResolver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070072import android.test.suitebuilder.annotation.LargeTest;
Udam Sainib7c24872016-01-04 12:16:14 -080073import android.test.suitebuilder.annotation.SmallTest;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070074import android.util.Log;
75import android.util.LogPrinter;
76
Lorenzo Colitti6d553f62016-06-05 02:20:29 +090077import com.android.internal.util.FakeSettingsProvider;
Lorenzo Colittibfecba22016-02-21 01:09:26 +090078import com.android.internal.util.WakeupMessage;
Paul Jensencf4c2c62015-07-01 14:16:32 -040079import com.android.server.connectivity.NetworkAgentInfo;
Paul Jensend7b6ca92015-05-13 14:05:12 -040080import com.android.server.connectivity.NetworkMonitor;
Paul Jensen232437312016-04-06 09:51:26 -040081import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
Lorenzo Colitti531a3442016-03-01 12:55:58 +090082import com.android.server.net.NetworkPinner;
Paul Jensend7b6ca92015-05-13 14:05:12 -040083
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070084import java.net.InetAddress;
Paul Jensen4e1d3fd2016-04-08 13:56:52 -040085import java.util.ArrayList;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +090086import java.util.Arrays;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +090087import java.util.Objects;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +090088import java.util.concurrent.CountDownLatch;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +090089import java.util.concurrent.LinkedBlockingQueue;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +090090import java.util.concurrent.TimeUnit;
Robert Greenwalt348e98d2015-06-05 17:55:36 -070091import java.util.concurrent.atomic.AtomicBoolean;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070092
93/**
94 * Tests for {@link ConnectivityService}.
Paul Jensend7b6ca92015-05-13 14:05:12 -040095 *
96 * Build, install and run with:
97 * runtest frameworks-services -c com.android.server.ConnectivityServiceTest
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070098 */
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070099public class ConnectivityServiceTest extends AndroidTestCase {
100 private static final String TAG = "ConnectivityServiceTest";
101
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900102 private static final int TIMEOUT_MS = 500;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900103 private static final int TEST_LINGER_DELAY_MS = 120;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900104
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700105 private BroadcastInterceptingContext mServiceContext;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400106 private WrappedConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900107 private WrappedConnectivityManager mCm;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400108 private MockNetworkAgent mWiFiNetworkAgent;
109 private MockNetworkAgent mCellNetworkAgent;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900110 private MockNetworkAgent mEthernetNetworkAgent;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700111
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900112 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
113 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
114 // reflect the state of our test ConnectivityService.
115 private class WrappedConnectivityManager extends ConnectivityManager {
116 private Network mFakeBoundNetwork;
117
118 public synchronized boolean bindProcessToNetwork(Network network) {
119 mFakeBoundNetwork = network;
120 return true;
121 }
122
123 public synchronized Network getBoundNetworkForProcess() {
124 return mFakeBoundNetwork;
125 }
126
127 public WrappedConnectivityManager(Context context, ConnectivityService service) {
128 super(context, service);
129 }
130 }
131
Paul Jensend7b6ca92015-05-13 14:05:12 -0400132 private class MockContext extends BroadcastInterceptingContext {
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900133 private final MockContentResolver mContentResolver;
134
Paul Jensend7b6ca92015-05-13 14:05:12 -0400135 MockContext(Context base) {
136 super(base);
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900137 mContentResolver = new MockContentResolver();
138 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
Paul Jensend7b6ca92015-05-13 14:05:12 -0400139 }
140
141 @Override
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900142 public Object getSystemService(String name) {
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900143 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
144 if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400145 return super.getSystemService(name);
146 }
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900147
148 @Override
149 public ContentResolver getContentResolver() {
150 return mContentResolver;
151 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400152 }
153
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900154 /**
155 * A subclass of HandlerThread that allows callers to wait for it to become idle. waitForIdle
156 * will return immediately if the handler is already idle.
157 */
158 private class IdleableHandlerThread extends HandlerThread {
159 private IdleHandler mIdleHandler;
160
161 public IdleableHandlerThread(String name) {
162 super(name);
163 }
164
165 public void waitForIdle(int timeoutMs) {
166 final ConditionVariable cv = new ConditionVariable();
167 final MessageQueue queue = getLooper().getQueue();
168
169 synchronized (queue) {
170 if (queue.isIdle()) {
171 return;
172 }
173
174 assertNull("BUG: only one idle handler allowed", mIdleHandler);
175 mIdleHandler = new IdleHandler() {
176 public boolean queueIdle() {
Lorenzo Colitti5eaaf742016-03-02 21:47:42 +0900177 synchronized (queue) {
178 cv.open();
179 mIdleHandler = null;
180 return false; // Remove the handler.
181 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900182 }
183 };
184 queue.addIdleHandler(mIdleHandler);
185 }
186
187 if (!cv.block(timeoutMs)) {
188 fail("HandlerThread " + getName() +
189 " did not become idle after " + timeoutMs + " ms");
190 queue.removeIdleHandler(mIdleHandler);
191 }
192 }
193 }
194
195 // Tests that IdleableHandlerThread works as expected.
196 public void testIdleableHandlerThread() {
197 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 }
218
219 // Ensure that not calling waitForIdle causes a race condition.
220 for (int i = 0; i < attempts; i++) {
221 mWiFiNetworkAgent.setSignalStrength(i);
222 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
223 // We hit a race condition, as expected. Pass the test.
224 return;
225 }
226 }
227
228 // No race? There is a bug in this test.
229 fail("expected race condition at least once in " + attempts + " attempts");
230 }
231
Paul Jensend7b6ca92015-05-13 14:05:12 -0400232 private class MockNetworkAgent {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400233 private final WrappedNetworkMonitor mWrappedNetworkMonitor;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400234 private final NetworkInfo mNetworkInfo;
235 private final NetworkCapabilities mNetworkCapabilities;
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900236 private final IdleableHandlerThread mHandlerThread;
Paul Jensene0988542015-06-25 15:30:08 -0400237 private final ConditionVariable mDisconnected = new ConditionVariable();
Paul Jensen232437312016-04-06 09:51:26 -0400238 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
Calvin On4bc78eb2016-10-11 15:10:46 -0700239 private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
Paul Jensen3d911462015-06-12 06:40:24 -0400240 private int mScore;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400241 private NetworkAgent mNetworkAgent;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900242 private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
243 private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE;
244 private Integer mExpectedKeepaliveSlot = null;
Paul Jensen232437312016-04-06 09:51:26 -0400245 // Contains the redirectUrl from networkStatus(). Before reading, wait for
246 // mNetworkStatusReceived.
247 private String mRedirectUrl;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400248
249 MockNetworkAgent(int transport) {
250 final int type = transportToLegacyType(transport);
251 final String typeName = ConnectivityManager.getNetworkTypeName(type);
252 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
253 mNetworkCapabilities = new NetworkCapabilities();
254 mNetworkCapabilities.addTransportType(transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400255 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900256 case TRANSPORT_ETHERNET:
257 mScore = 70;
258 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400259 case TRANSPORT_WIFI:
Paul Jensen3d911462015-06-12 06:40:24 -0400260 mScore = 60;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400261 break;
262 case TRANSPORT_CELLULAR:
Paul Jensen3d911462015-06-12 06:40:24 -0400263 mScore = 50;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400264 break;
265 default:
266 throw new UnsupportedOperationException("unimplemented network type");
267 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900268 mHandlerThread = new IdleableHandlerThread("Mock-" + typeName);
269 mHandlerThread.start();
270 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
271 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
272 new LinkProperties(), mScore, new NetworkMisc()) {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900273 @Override
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900274 public void unwanted() { mDisconnected.open(); }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900275
276 @Override
277 public void startPacketKeepalive(Message msg) {
278 int slot = msg.arg1;
279 if (mExpectedKeepaliveSlot != null) {
280 assertEquals((int) mExpectedKeepaliveSlot, slot);
281 }
282 onPacketKeepaliveEvent(slot, mStartKeepaliveError);
283 }
284
285 @Override
286 public void stopPacketKeepalive(Message msg) {
287 onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
288 }
Paul Jensen232437312016-04-06 09:51:26 -0400289
290 @Override
291 public void networkStatus(int status, String redirectUrl) {
292 mRedirectUrl = redirectUrl;
293 mNetworkStatusReceived.open();
294 }
Calvin On4bc78eb2016-10-11 15:10:46 -0700295
296 @Override
297 protected void preventAutomaticReconnect() {
298 mPreventReconnectReceived.open();
299 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400300 };
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900301 // Waits for the NetworkAgent to be registered, which includes the creation of the
302 // NetworkMonitor.
303 mService.waitForIdle();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400304 mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor();
Paul Jensen3d911462015-06-12 06:40:24 -0400305 }
306
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900307 public void waitForIdle(int timeoutMs) {
308 mHandlerThread.waitForIdle(timeoutMs);
309 }
310
311 public void waitForIdle() {
312 waitForIdle(TIMEOUT_MS);
313 }
314
Paul Jensen3d911462015-06-12 06:40:24 -0400315 public void adjustScore(int change) {
316 mScore += change;
317 mNetworkAgent.sendNetworkScore(mScore);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400318 }
319
Paul Jensen85cf78e2015-06-25 13:25:07 -0400320 public void addCapability(int capability) {
321 mNetworkCapabilities.addCapability(capability);
322 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
323 }
324
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900325 public void removeCapability(int capability) {
326 mNetworkCapabilities.removeCapability(capability);
327 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
328 }
329
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900330 public void setSignalStrength(int signalStrength) {
331 mNetworkCapabilities.setSignalStrength(signalStrength);
332 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
333 }
334
Paul Jensene0988542015-06-25 15:30:08 -0400335 public void connectWithoutInternet() {
336 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
337 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
338 }
339
Paul Jensend7b6ca92015-05-13 14:05:12 -0400340 /**
Paul Jensene0988542015-06-25 15:30:08 -0400341 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400342 * @param validated Indicate if network should pretend to be validated.
343 */
344 public void connect(boolean validated) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900345 assertEquals("MockNetworkAgents can only be connected once",
346 mNetworkInfo.getDetailedState(), DetailedState.IDLE);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400347 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
348
Paul Jensend7b6ca92015-05-13 14:05:12 -0400349 NetworkCallback callback = null;
350 final ConditionVariable validatedCv = new ConditionVariable();
351 if (validated) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400352 mWrappedNetworkMonitor.gen204ProbeResult = 204;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400353 NetworkRequest request = new NetworkRequest.Builder()
354 .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
355 .build();
356 callback = new NetworkCallback() {
357 public void onCapabilitiesChanged(Network network,
358 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400359 if (network.equals(getNetwork()) &&
360 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400361 validatedCv.open();
362 }
363 }
364 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400365 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400366 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400367 addCapability(NET_CAPABILITY_INTERNET);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400368
Paul Jensene0988542015-06-25 15:30:08 -0400369 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400370
371 if (validated) {
372 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400373 waitFor(validatedCv);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400374 mWrappedNetworkMonitor.gen204ProbeResult = 500;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400375 }
376
377 if (callback != null) mCm.unregisterNetworkCallback(callback);
378 }
379
Paul Jensen232437312016-04-06 09:51:26 -0400380 public void connectWithCaptivePortal(String redirectUrl) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400381 mWrappedNetworkMonitor.gen204ProbeResult = 200;
Paul Jensen232437312016-04-06 09:51:26 -0400382 mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400383 connect(false);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400384 }
385
Paul Jensend7b6ca92015-05-13 14:05:12 -0400386 public void disconnect() {
387 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
388 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
389 }
390
391 public Network getNetwork() {
392 return new Network(mNetworkAgent.netId);
393 }
Paul Jensene0988542015-06-25 15:30:08 -0400394
Calvin On4bc78eb2016-10-11 15:10:46 -0700395 public ConditionVariable getPreventReconnectReceived() {
396 return mPreventReconnectReceived;
397 }
398
Paul Jensene0988542015-06-25 15:30:08 -0400399 public ConditionVariable getDisconnectedCV() {
400 return mDisconnected;
401 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400402
403 public WrappedNetworkMonitor getWrappedNetworkMonitor() {
404 return mWrappedNetworkMonitor;
405 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900406
407 public void sendLinkProperties(LinkProperties lp) {
408 mNetworkAgent.sendLinkProperties(lp);
409 }
410
411 public void setStartKeepaliveError(int error) {
412 mStartKeepaliveError = error;
413 }
414
415 public void setStopKeepaliveError(int error) {
416 mStopKeepaliveError = error;
417 }
418
419 public void setExpectedKeepaliveSlot(Integer slot) {
420 mExpectedKeepaliveSlot = slot;
421 }
Paul Jensen232437312016-04-06 09:51:26 -0400422
423 public String waitForRedirectUrl() {
424 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
425 return mRedirectUrl;
426 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400427 }
428
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900429 /**
430 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
431 * operations have been processed. Before ConnectivityService can add or remove any requests,
432 * the factory must be told to expect those operations by calling expectAddRequests or
433 * expectRemoveRequests.
434 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700435 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400436 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
437 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400438 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700439
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900440 // Used to expect that requests be removed or added on a separate thread, without sleeping.
441 // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then
442 // cause some other thread to add or remove requests, then call waitForRequests(). We can
443 // either expect requests to be added or removed, but not both, because CountDownLatch can
444 // only count in one direction.
445 private CountDownLatch mExpectations;
446
447 // Whether we are currently expecting requests to be added or removed. Valid only if
448 // mExpectations is non-null.
449 private boolean mExpectingAdditions;
450
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700451 public MockNetworkFactory(Looper looper, Context context, String logTag,
452 NetworkCapabilities filter) {
453 super(looper, context, logTag, filter);
454 }
455
456 public int getMyRequestCount() {
457 return getRequestCount();
458 }
459
460 protected void startNetwork() {
461 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400462 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700463 }
464
465 protected void stopNetwork() {
466 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400467 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700468 }
469
470 public boolean getMyStartRequested() {
471 return mNetworkStarted.get();
472 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400473
474 public ConditionVariable getNetworkStartedCV() {
475 mNetworkStartedCV.close();
476 return mNetworkStartedCV;
477 }
478
479 public ConditionVariable getNetworkStoppedCV() {
480 mNetworkStoppedCV.close();
481 return mNetworkStoppedCV;
482 }
483
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900484 @Override
485 protected void handleAddRequest(NetworkRequest request, int score) {
486 // If we're expecting anything, we must be expecting additions.
487 if (mExpectations != null && !mExpectingAdditions) {
488 fail("Can't add requests while expecting requests to be removed");
489 }
490
491 // Add the request.
492 super.handleAddRequest(request, score);
493
494 // Reduce the number of request additions we're waiting for.
495 if (mExpectingAdditions) {
496 assertTrue("Added more requests than expected", mExpectations.getCount() > 0);
497 mExpectations.countDown();
498 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400499 }
500
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900501 @Override
502 protected void handleRemoveRequest(NetworkRequest request) {
503 // If we're expecting anything, we must be expecting removals.
504 if (mExpectations != null && mExpectingAdditions) {
505 fail("Can't remove requests while expecting requests to be added");
506 }
507
508 // Remove the request.
509 super.handleRemoveRequest(request);
510
511 // Reduce the number of request removals we're waiting for.
512 if (!mExpectingAdditions) {
513 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0);
514 mExpectations.countDown();
515 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400516 }
517
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900518 private void assertNoExpectations() {
519 if (mExpectations != null) {
520 fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
521 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400522 }
523
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900524 // Expects that count requests will be added.
525 public void expectAddRequests(final int count) {
526 assertNoExpectations();
527 mExpectingAdditions = true;
528 mExpectations = new CountDownLatch(count);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400529 }
530
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900531 // Expects that count requests will be removed.
532 public void expectRemoveRequests(final int count) {
533 assertNoExpectations();
534 mExpectingAdditions = false;
535 mExpectations = new CountDownLatch(count);
536 }
537
538 // Waits for the expected request additions or removals to happen within a timeout.
539 public void waitForRequests() throws InterruptedException {
540 assertNotNull("Nothing to wait for", mExpectations);
541 mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
542 final long count = mExpectations.getCount();
543 final String msg = count + " requests still not " +
544 (mExpectingAdditions ? "added" : "removed") +
545 " after " + TIMEOUT_MS + " ms";
546 assertEquals(msg, 0, count);
547 mExpectations = null;
548 }
549
550 public void waitForNetworkRequests(final int count) throws InterruptedException {
551 waitForRequests();
552 assertEquals(count, getMyRequestCount());
Paul Jensen0a2823e2015-06-12 10:31:09 -0400553 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700554 }
555
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900556 private class FakeWakeupMessage extends WakeupMessage {
557 private static final int UNREASONABLY_LONG_WAIT = 1000;
558
559 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
560 super(context, handler, cmdName, cmd);
561 }
562
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900563 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
564 int arg1, int arg2, Object obj) {
565 super(context, handler, cmdName, cmd, arg1, arg2, obj);
566 }
567
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900568 @Override
569 public void schedule(long when) {
570 long delayMs = when - SystemClock.elapsedRealtime();
571 if (delayMs < 0) delayMs = 0;
572 if (delayMs > UNREASONABLY_LONG_WAIT) {
573 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
574 "ms into the future: " + delayMs);
575 }
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900576 Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
577 mHandler.sendMessageDelayed(msg, delayMs);
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900578 }
579
580 @Override
581 public void cancel() {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900582 mHandler.removeMessages(mCmd, mObj);
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900583 }
584
585 @Override
586 public void onAlarm() {
587 throw new AssertionError("Should never happen. Update this fake.");
588 }
589 }
590
Paul Jensencf4c2c62015-07-01 14:16:32 -0400591 // NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
592 private class WrappedNetworkMonitor extends NetworkMonitor {
593 // HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
594 public int gen204ProbeResult = 500;
Paul Jensen232437312016-04-06 09:51:26 -0400595 public String gen204ProbeRedirectUrl = null;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400596
597 public WrappedNetworkMonitor(Context context, Handler handler,
Hugo Benichif9fdf872016-07-28 17:53:06 +0900598 NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest,
599 IpConnectivityLog log) {
600 super(context, handler, networkAgentInfo, defaultRequest, log);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400601 }
602
603 @Override
Paul Jensen232437312016-04-06 09:51:26 -0400604 protected CaptivePortalProbeResult isCaptivePortal() {
Calvin On4bc78eb2016-10-11 15:10:46 -0700605 if (!mIsCaptivePortalCheckEnabled) { return new CaptivePortalProbeResult(204); }
Hugo Benichid953bf82016-09-27 09:22:35 +0900606 return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl, null);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400607 }
608 }
609
Erik Kline065ab6e2016-10-02 18:02:14 +0900610 private class WrappedAvoidBadWifiTracker extends AvoidBadWifiTracker {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900611 public boolean configRestrictsAvoidBadWifi;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400612
Erik Kline065ab6e2016-10-02 18:02:14 +0900613 public WrappedAvoidBadWifiTracker(Context c, Handler h, Runnable r) {
614 super(c, h, r);
615 }
616
617 @Override
618 public boolean configRestrictsAvoidBadWifi() {
619 return configRestrictsAvoidBadWifi;
620 }
621 }
622
623 private class WrappedConnectivityService extends ConnectivityService {
624 public WrappedAvoidBadWifiTracker wrappedAvoidBadWifiTracker;
625 private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
626
Paul Jensend7b6ca92015-05-13 14:05:12 -0400627 public WrappedConnectivityService(Context context, INetworkManagementService netManager,
Hugo Benichif9fdf872016-07-28 17:53:06 +0900628 INetworkStatsService statsService, INetworkPolicyManager policyManager,
629 IpConnectivityLog log) {
630 super(context, netManager, statsService, policyManager, log);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900631 mLingerDelayMs = TEST_LINGER_DELAY_MS;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400632 }
633
634 @Override
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900635 protected HandlerThread createHandlerThread() {
636 return new IdleableHandlerThread("WrappedConnectivityService");
637 }
638
639 @Override
Paul Jensend7b6ca92015-05-13 14:05:12 -0400640 protected int getDefaultTcpRwnd() {
641 // Prevent wrapped ConnectivityService from trying to write to SystemProperties.
642 return 0;
643 }
Paul Jensen67b0b072015-06-10 11:22:17 -0400644
645 @Override
646 protected int reserveNetId() {
647 while (true) {
648 final int netId = super.reserveNetId();
649
650 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
651 // can have odd side-effects, like network validations succeeding.
652 final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks();
653 boolean overlaps = false;
654 for (Network network : networks) {
655 if (netId == network.netId) {
656 overlaps = true;
657 break;
658 }
659 }
660 if (overlaps) continue;
661
662 return netId;
663 }
664 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400665
666 @Override
667 public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
668 NetworkAgentInfo nai, NetworkRequest defaultRequest) {
Hugo Benichif9fdf872016-07-28 17:53:06 +0900669 final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(
670 context, handler, nai, defaultRequest, mock(IpConnectivityLog.class));
Paul Jensencf4c2c62015-07-01 14:16:32 -0400671 mLastCreatedNetworkMonitor = monitor;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400672 return monitor;
673 }
674
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900675 @Override
Erik Kline065ab6e2016-10-02 18:02:14 +0900676 public AvoidBadWifiTracker createAvoidBadWifiTracker(
677 Context c, Handler h, Runnable r) {
678 final WrappedAvoidBadWifiTracker tracker = new WrappedAvoidBadWifiTracker(c, h, r);
679 return tracker;
680 }
681
682 public WrappedAvoidBadWifiTracker getAvoidBadWifiTracker() {
683 return (WrappedAvoidBadWifiTracker) mAvoidBadWifiTracker;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900684 }
685
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900686 @Override
Erik Kline065ab6e2016-10-02 18:02:14 +0900687 public WakeupMessage makeWakeupMessage(
688 Context context, Handler handler, String cmdName, int cmd, Object obj) {
689 return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900690 }
691
Paul Jensencf4c2c62015-07-01 14:16:32 -0400692 public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
693 return mLastCreatedNetworkMonitor;
694 }
695
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900696 public void waitForIdle(int timeoutMs) {
697 ((IdleableHandlerThread) mHandlerThread).waitForIdle(timeoutMs);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400698 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900699
700 public void waitForIdle() {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900701 waitForIdle(TIMEOUT_MS);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900702 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400703 }
704
Paul Jensen0a2823e2015-06-12 10:31:09 -0400705 private interface Criteria {
706 public boolean get();
707 }
708
Paul Jensen3d911462015-06-12 06:40:24 -0400709 /**
710 * Wait up to 500ms for {@code criteria.get()} to become true, polling.
711 * Fails if 500ms goes by before {@code criteria.get()} to become true.
712 */
Paul Jensen0a2823e2015-06-12 10:31:09 -0400713 static private void waitFor(Criteria criteria) {
714 int delays = 0;
715 while (!criteria.get()) {
716 try {
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900717 Thread.sleep(50);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400718 } catch (InterruptedException e) {
719 }
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900720 if (++delays == 10) fail();
Paul Jensen0a2823e2015-06-12 10:31:09 -0400721 }
722 }
723
Paul Jensen3d911462015-06-12 06:40:24 -0400724 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900725 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
726 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -0400727 */
728 static private void waitFor(ConditionVariable conditionVariable) {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900729 assertTrue(conditionVariable.block(TIMEOUT_MS));
Paul Jensen3d911462015-06-12 06:40:24 -0400730 }
731
Paul Jensend7b6ca92015-05-13 14:05:12 -0400732 @Override
733 public void setUp() throws Exception {
734 super.setUp();
735
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +0900736 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
737 // http://b/25897652 .
738 if (Looper.myLooper() == null) {
739 Looper.prepare();
740 }
741
Paul Jensend7b6ca92015-05-13 14:05:12 -0400742 mServiceContext = new MockContext(getContext());
Lorenzo Colitti83fa2582015-08-07 12:49:01 +0900743 mService = new WrappedConnectivityService(mServiceContext,
744 mock(INetworkManagementService.class),
745 mock(INetworkStatsService.class),
Hugo Benichif9fdf872016-07-28 17:53:06 +0900746 mock(INetworkPolicyManager.class),
747 mock(IpConnectivityLog.class));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400748
Paul Jensend7b6ca92015-05-13 14:05:12 -0400749 mService.systemReady();
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900750 mCm = new WrappedConnectivityManager(getContext(), mService);
751 mCm.bindProcessToNetwork(null);
Calvin On4bc78eb2016-10-11 15:10:46 -0700752
753 // Ensure that the default setting for Captive Portals is used for most tests
754 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400755 }
756
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +0900757 public void tearDown() throws Exception {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +0900758 setMobileDataAlwaysOn(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +0900759 if (mCellNetworkAgent != null) { mCellNetworkAgent.disconnect(); }
760 if (mWiFiNetworkAgent != null) { mWiFiNetworkAgent.disconnect(); }
761 mCellNetworkAgent = mWiFiNetworkAgent = null;
762 super.tearDown();
763 }
764
Paul Jensend7b6ca92015-05-13 14:05:12 -0400765 private int transportToLegacyType(int transport) {
766 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900767 case TRANSPORT_ETHERNET:
768 return TYPE_ETHERNET;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400769 case TRANSPORT_WIFI:
770 return TYPE_WIFI;
771 case TRANSPORT_CELLULAR:
772 return TYPE_MOBILE;
773 default:
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900774 throw new IllegalStateException("Unknown transport " + transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400775 }
776 }
777
778 private void verifyActiveNetwork(int transport) {
779 // Test getActiveNetworkInfo()
780 assertNotNull(mCm.getActiveNetworkInfo());
781 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
782 // Test getActiveNetwork()
783 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +0000784 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400785 switch (transport) {
786 case TRANSPORT_WIFI:
787 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
788 break;
789 case TRANSPORT_CELLULAR:
790 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
791 break;
792 default:
793 throw new IllegalStateException("Unknown transport" + transport);
794 }
795 // Test getNetworkInfo(Network)
796 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
797 assertEquals(transportToLegacyType(transport), mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
798 // Test getNetworkCapabilities(Network)
799 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
800 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
801 }
802
803 private void verifyNoNetwork() {
804 // Test getActiveNetworkInfo()
805 assertNull(mCm.getActiveNetworkInfo());
806 // Test getActiveNetwork()
807 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +0000808 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400809 // Test getAllNetworks()
810 assertEquals(0, mCm.getAllNetworks().length);
811 }
812
813 /**
814 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
815 * broadcasts are received.
816 */
817 private ConditionVariable waitForConnectivityBroadcasts(final int count) {
818 final ConditionVariable cv = new ConditionVariable();
819 mServiceContext.registerReceiver(new BroadcastReceiver() {
820 private int remaining = count;
821 public void onReceive(Context context, Intent intent) {
822 if (--remaining == 0) {
823 cv.open();
824 mServiceContext.unregisterReceiver(this);
825 }
826 }
827 }, new IntentFilter(CONNECTIVITY_ACTION));
828 return cv;
829 }
830
831 @LargeTest
832 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400833 verifyNoNetwork();
834 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
835 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
836 assertNull(mCm.getActiveNetworkInfo());
837 assertNull(mCm.getActiveNetwork());
838 // Test bringing up validated cellular.
839 ConditionVariable cv = waitForConnectivityBroadcasts(1);
840 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -0400841 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400842 verifyActiveNetwork(TRANSPORT_CELLULAR);
843 assertEquals(2, mCm.getAllNetworks().length);
844 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
845 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
846 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
847 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
848 // Test bringing up validated WiFi.
849 cv = waitForConnectivityBroadcasts(2);
850 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -0400851 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400852 verifyActiveNetwork(TRANSPORT_WIFI);
853 assertEquals(2, mCm.getAllNetworks().length);
854 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
855 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
856 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
857 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
858 // Test cellular linger timeout.
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900859 waitFor(new Criteria() {
860 public boolean get() { return mCm.getAllNetworks().length == 1; } });
Paul Jensend7b6ca92015-05-13 14:05:12 -0400861 verifyActiveNetwork(TRANSPORT_WIFI);
862 assertEquals(1, mCm.getAllNetworks().length);
863 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
864 // Test WiFi disconnect.
865 cv = waitForConnectivityBroadcasts(1);
866 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400867 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400868 verifyNoNetwork();
869 }
870
871 @LargeTest
872 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
873 // Test bringing up unvalidated WiFi
874 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
875 ConditionVariable cv = waitForConnectivityBroadcasts(1);
876 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -0400877 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400878 verifyActiveNetwork(TRANSPORT_WIFI);
879 // Test bringing up unvalidated cellular
880 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
881 mCellNetworkAgent.connect(false);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900882 mService.waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400883 verifyActiveNetwork(TRANSPORT_WIFI);
884 // Test cellular disconnect.
885 mCellNetworkAgent.disconnect();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900886 mService.waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400887 verifyActiveNetwork(TRANSPORT_WIFI);
888 // Test bringing up validated cellular
889 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
890 cv = waitForConnectivityBroadcasts(2);
891 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -0400892 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400893 verifyActiveNetwork(TRANSPORT_CELLULAR);
894 // Test cellular disconnect.
895 cv = waitForConnectivityBroadcasts(2);
896 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400897 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400898 verifyActiveNetwork(TRANSPORT_WIFI);
899 // Test WiFi disconnect.
900 cv = waitForConnectivityBroadcasts(1);
901 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400902 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400903 verifyNoNetwork();
904 }
905
906 @LargeTest
907 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
908 // Test bringing up unvalidated cellular.
909 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
910 ConditionVariable cv = waitForConnectivityBroadcasts(1);
911 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -0400912 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400913 verifyActiveNetwork(TRANSPORT_CELLULAR);
914 // Test bringing up unvalidated WiFi.
915 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
916 cv = waitForConnectivityBroadcasts(2);
917 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -0400918 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400919 verifyActiveNetwork(TRANSPORT_WIFI);
920 // Test WiFi disconnect.
921 cv = waitForConnectivityBroadcasts(2);
922 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400923 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400924 verifyActiveNetwork(TRANSPORT_CELLULAR);
925 // Test cellular disconnect.
926 cv = waitForConnectivityBroadcasts(1);
927 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400928 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400929 verifyNoNetwork();
930 }
931
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700932 @LargeTest
Paul Jensene0988542015-06-25 15:30:08 -0400933 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400934 // Test bringing up unvalidated WiFi.
Paul Jensene0988542015-06-25 15:30:08 -0400935 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400936 ConditionVariable cv = waitForConnectivityBroadcasts(1);
937 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -0400938 waitFor(cv);
939 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400940 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -0400941 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -0400942 // Test bringing up validated cellular.
943 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -0400944 cv = waitForConnectivityBroadcasts(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400945 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -0400946 waitFor(cv);
947 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400948 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
949 NET_CAPABILITY_VALIDATED));
950 // Test cellular disconnect.
951 cv = waitForConnectivityBroadcasts(2);
952 mCellNetworkAgent.disconnect();
953 waitFor(cv);
954 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -0400955 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -0400956 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -0400957 NET_CAPABILITY_VALIDATED));
958 }
959
960 @LargeTest
Paul Jensen3d911462015-06-12 06:40:24 -0400961 public void testCellularOutscoresWeakWifi() throws Exception {
962 // Test bringing up validated cellular.
963 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
964 ConditionVariable cv = waitForConnectivityBroadcasts(1);
965 mCellNetworkAgent.connect(true);
966 waitFor(cv);
967 verifyActiveNetwork(TRANSPORT_CELLULAR);
968 // Test bringing up validated WiFi.
969 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
970 cv = waitForConnectivityBroadcasts(2);
971 mWiFiNetworkAgent.connect(true);
972 waitFor(cv);
973 verifyActiveNetwork(TRANSPORT_WIFI);
974 // Test WiFi getting really weak.
975 cv = waitForConnectivityBroadcasts(2);
976 mWiFiNetworkAgent.adjustScore(-11);
977 waitFor(cv);
978 verifyActiveNetwork(TRANSPORT_CELLULAR);
979 // Test WiFi restoring signal strength.
980 cv = waitForConnectivityBroadcasts(2);
981 mWiFiNetworkAgent.adjustScore(11);
982 waitFor(cv);
983 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -0400984 }
985
Paul Jensene0988542015-06-25 15:30:08 -0400986 @LargeTest
987 public void testReapingNetwork() throws Exception {
988 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
989 // Expect it to be torn down immediately because it satisfies no requests.
990 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
991 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
992 mWiFiNetworkAgent.connectWithoutInternet();
993 waitFor(cv);
994 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
995 // Expect it to be torn down immediately because it satisfies no requests.
996 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
997 cv = mCellNetworkAgent.getDisconnectedCV();
998 mCellNetworkAgent.connectWithoutInternet();
999 waitFor(cv);
1000 // Test bringing up validated WiFi.
1001 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1002 cv = waitForConnectivityBroadcasts(1);
1003 mWiFiNetworkAgent.connect(true);
1004 waitFor(cv);
1005 verifyActiveNetwork(TRANSPORT_WIFI);
1006 // Test bringing up unvalidated cellular.
1007 // Expect it to be torn down because it could never be the highest scoring network
1008 // satisfying the default request even if it validated.
1009 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1010 cv = mCellNetworkAgent.getDisconnectedCV();
1011 mCellNetworkAgent.connect(false);
1012 waitFor(cv);
1013 verifyActiveNetwork(TRANSPORT_WIFI);
1014 cv = mWiFiNetworkAgent.getDisconnectedCV();
1015 mWiFiNetworkAgent.disconnect();
1016 waitFor(cv);
1017 }
1018
1019 @LargeTest
1020 public void testCellularFallback() throws Exception {
1021 // Test bringing up validated cellular.
1022 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1023 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1024 mCellNetworkAgent.connect(true);
1025 waitFor(cv);
1026 verifyActiveNetwork(TRANSPORT_CELLULAR);
1027 // Test bringing up validated WiFi.
1028 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1029 cv = waitForConnectivityBroadcasts(2);
1030 mWiFiNetworkAgent.connect(true);
1031 waitFor(cv);
1032 verifyActiveNetwork(TRANSPORT_WIFI);
1033 // Reevaluate WiFi (it'll instantly fail DNS).
1034 cv = waitForConnectivityBroadcasts(2);
1035 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1036 NET_CAPABILITY_VALIDATED));
1037 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1038 // Should quickly fall back to Cellular.
1039 waitFor(cv);
1040 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1041 NET_CAPABILITY_VALIDATED));
1042 verifyActiveNetwork(TRANSPORT_CELLULAR);
1043 // Reevaluate cellular (it'll instantly fail DNS).
1044 cv = waitForConnectivityBroadcasts(2);
1045 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1046 NET_CAPABILITY_VALIDATED));
1047 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1048 // Should quickly fall back to WiFi.
1049 waitFor(cv);
1050 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1051 NET_CAPABILITY_VALIDATED));
1052 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1053 NET_CAPABILITY_VALIDATED));
1054 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001055 }
1056
1057 @LargeTest
1058 public void testWiFiFallback() throws Exception {
1059 // Test bringing up unvalidated WiFi.
1060 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1061 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1062 mWiFiNetworkAgent.connect(false);
1063 waitFor(cv);
1064 verifyActiveNetwork(TRANSPORT_WIFI);
1065 // Test bringing up validated cellular.
1066 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1067 cv = waitForConnectivityBroadcasts(2);
1068 mCellNetworkAgent.connect(true);
1069 waitFor(cv);
1070 verifyActiveNetwork(TRANSPORT_CELLULAR);
1071 // Reevaluate cellular (it'll instantly fail DNS).
1072 cv = waitForConnectivityBroadcasts(2);
1073 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1074 NET_CAPABILITY_VALIDATED));
1075 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1076 // Should quickly fall back to WiFi.
1077 waitFor(cv);
1078 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1079 NET_CAPABILITY_VALIDATED));
1080 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001081 }
1082
Paul Jensen3d911462015-06-12 06:40:24 -04001083 enum CallbackState {
1084 NONE,
1085 AVAILABLE,
Erik Klineacdd6392016-07-07 16:50:58 +09001086 NETWORK_CAPABILITIES,
1087 LINK_PROPERTIES,
Paul Jensen3d911462015-06-12 06:40:24 -04001088 LOSING,
1089 LOST
1090 }
1091
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001092 /**
1093 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1094 * this class receives, by calling expectCallback() exactly once each time a callback is
1095 * received. assertNoCallback may be called at any time.
1096 */
Paul Jensen3d911462015-06-12 06:40:24 -04001097 private class TestNetworkCallback extends NetworkCallback {
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001098 // Chosen to be much less than the linger timeout. This ensures that we can distinguish
1099 // between a LOST callback that arrives immediately and a LOST callback that arrives after
1100 // the linger timeout.
1101 private final static int TIMEOUT_MS = 50;
1102
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001103 private class CallbackInfo {
1104 public final CallbackState state;
1105 public final Network network;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001106 public Object arg;
1107 public CallbackInfo(CallbackState s, Network n, Object o) {
1108 state = s; network = n; arg = o;
1109 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001110 public String toString() { return String.format("%s (%s)", state, network); }
1111 public boolean equals(Object o) {
1112 if (!(o instanceof CallbackInfo)) return false;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001113 // Ignore timeMs, since it's unpredictable.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001114 CallbackInfo other = (CallbackInfo) o;
1115 return state == other.state && Objects.equals(network, other.network);
1116 }
1117 }
1118 private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
1119
Erik Klineacdd6392016-07-07 16:50:58 +09001120 protected void setLastCallback(CallbackState state, Network network, Object o) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001121 mCallbacks.offer(new CallbackInfo(state, network, o));
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001122 }
Paul Jensen3d911462015-06-12 06:40:24 -04001123
Erik Klineacdd6392016-07-07 16:50:58 +09001124 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001125 public void onAvailable(Network network) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001126 setLastCallback(CallbackState.AVAILABLE, network, null);
Paul Jensen3d911462015-06-12 06:40:24 -04001127 }
1128
Erik Klineacdd6392016-07-07 16:50:58 +09001129 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001130 public void onLosing(Network network, int maxMsToLive) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001131 setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
Paul Jensen3d911462015-06-12 06:40:24 -04001132 }
1133
Erik Klineacdd6392016-07-07 16:50:58 +09001134 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001135 public void onLost(Network network) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001136 setLastCallback(CallbackState.LOST, network, null);
1137 }
1138
1139 void expectCallback(CallbackState state, MockNetworkAgent mockAgent, int timeoutMs) {
1140 CallbackInfo expected = new CallbackInfo(
1141 state, (mockAgent != null) ? mockAgent.getNetwork() : null, 0);
1142 CallbackInfo actual;
1143 try {
1144 actual = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
1145 assertEquals("Unexpected callback:", expected, actual);
1146 } catch (InterruptedException e) {
1147 fail("Did not receive expected " + expected + " after " + TIMEOUT_MS + "ms");
1148 actual = null; // Or the compiler can't tell it's never used uninitialized.
1149 }
1150 if (state == CallbackState.LOSING) {
1151 String msg = String.format(
1152 "Invalid linger time value %d, must be between %d and %d",
1153 actual.arg, 0, TEST_LINGER_DELAY_MS);
1154 int maxMsToLive = (Integer) actual.arg;
1155 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= TEST_LINGER_DELAY_MS);
1156 }
Erik Klinea2d29402016-03-16 15:31:39 +09001157 }
1158
1159 void expectCallback(CallbackState state, MockNetworkAgent mockAgent) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001160 expectCallback(state, mockAgent, TIMEOUT_MS);
Paul Jensen3d911462015-06-12 06:40:24 -04001161 }
1162
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001163 void assertNoCallback() {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001164 mService.waitForIdle();
1165 CallbackInfo c = mCallbacks.peek();
1166 assertNull("Unexpected callback: " + c, c);
1167 }
1168 }
1169
1170 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1171 // only be declared in a static or top level type".
1172 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1173 for (TestNetworkCallback c : callbacks) {
1174 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001175 }
1176 }
1177
1178 @LargeTest
1179 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001180 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001181 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1182 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001183 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1184 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001185 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1186 .addTransportType(TRANSPORT_WIFI).build();
1187 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1188 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001189 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001190 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1191 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1192
1193 // Test unvalidated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001194 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1195 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1196 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001197 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1198 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001199 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1200 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001201 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001202
Paul Jensen3d911462015-06-12 06:40:24 -04001203 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1204 mCellNetworkAgent.adjustScore(-1);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001205 mService.waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001206 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001207 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1208
Paul Jensen3d911462015-06-12 06:40:24 -04001209 cv = waitForConnectivityBroadcasts(2);
1210 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1211 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001212 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1213 wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001214 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1215 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001216 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001217
Paul Jensen3d911462015-06-12 06:40:24 -04001218 cv = waitForConnectivityBroadcasts(2);
1219 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001220 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1221 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001222 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001223 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001224 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001225
Paul Jensen3d911462015-06-12 06:40:24 -04001226 cv = waitForConnectivityBroadcasts(1);
1227 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001228 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1229 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001230 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001231 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001232
1233 // Test validated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001234 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1235 mCellNetworkAgent.connect(true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001236 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1237 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001238 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001239 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001240
Paul Jensen3d911462015-06-12 06:40:24 -04001241 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1242 mCellNetworkAgent.adjustScore(-1);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001243 mService.waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001244 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001245 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1246
Paul Jensen3d911462015-06-12 06:40:24 -04001247 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1248 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001249 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1250 genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1251 wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1252 cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001253 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001254 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001255
Paul Jensen3d911462015-06-12 06:40:24 -04001256 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001257 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1258 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1259 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001260
Paul Jensen3d911462015-06-12 06:40:24 -04001261 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001262 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1263 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1264 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001265 }
1266
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001267 @SmallTest
1268 public void testMultipleLingering() {
1269 NetworkRequest request = new NetworkRequest.Builder()
1270 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1271 .build();
1272 TestNetworkCallback callback = new TestNetworkCallback();
1273 mCm.registerNetworkCallback(request, callback);
1274
1275 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1276 mCm.registerDefaultNetworkCallback(defaultCallback);
1277
1278 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1279 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1280 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
1281
1282 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1283 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1284 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1285
1286 mCellNetworkAgent.connect(true);
1287 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1288 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1289 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1290
1291 mWiFiNetworkAgent.connect(true);
1292 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1293 // We then get LOSING when wifi validates and cell is outscored.
1294 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1295 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1296 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1297 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1298
1299 mEthernetNetworkAgent.connect(true);
1300 callback.expectCallback(CallbackState.AVAILABLE, mEthernetNetworkAgent);
1301 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
1302 defaultCallback.expectCallback(CallbackState.AVAILABLE, mEthernetNetworkAgent);
1303 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1304
1305 mEthernetNetworkAgent.disconnect();
1306 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1307 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1308 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1309
1310 for (int i = 0; i < 4; i++) {
1311 MockNetworkAgent oldNetwork, newNetwork;
1312 if (i % 2 == 0) {
1313 mWiFiNetworkAgent.adjustScore(-15);
1314 oldNetwork = mWiFiNetworkAgent;
1315 newNetwork = mCellNetworkAgent;
1316 } else {
1317 mWiFiNetworkAgent.adjustScore(15);
1318 oldNetwork = mCellNetworkAgent;
1319 newNetwork = mWiFiNetworkAgent;
1320
1321 }
1322 callback.expectCallback(CallbackState.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001323 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1324 // longer lingering?
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001325 defaultCallback.expectCallback(CallbackState.AVAILABLE, newNetwork);
1326 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
1327 }
1328 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1329
1330 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
1331 // if the network is still up.
1332 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
1333 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1334
1335 // Wifi no longer satisfies our listen, which is for an unmetered network.
1336 // But because its score is 55, it's still up (and the default network).
1337 defaultCallback.assertNoCallback();
1338 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1339
1340 // Disconnect our test networks.
1341 mWiFiNetworkAgent.disconnect();
1342 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1343 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1344 mCellNetworkAgent.disconnect();
1345 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1346
1347 mCm.unregisterNetworkCallback(callback);
1348 mService.waitForIdle();
1349
1350 // Check that a network is only lingered or torn down if it would not satisfy a request even
1351 // if it validated.
1352 request = new NetworkRequest.Builder().clearCapabilities().build();
1353 callback = new TestNetworkCallback();
1354
1355 mCm.registerNetworkCallback(request, callback);
1356
1357 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1358 mCellNetworkAgent.connect(false); // Score: 10
1359 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1360 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1361 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1362
1363 // Bring up wifi with a score of 20.
1364 // Cell stays up because it would satisfy the default request if it validated.
1365 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1366 mWiFiNetworkAgent.connect(false); // Score: 20
1367 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1368 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1369 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1370
1371 mWiFiNetworkAgent.disconnect();
1372 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1373 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1374 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1375 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1376
1377 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001378 // Cell is lingered because it would not satisfy any request, even if it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001379 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1380 mWiFiNetworkAgent.adjustScore(50);
1381 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001382 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001383 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001384 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1385 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1386
1387 // Tear down wifi.
1388 mWiFiNetworkAgent.disconnect();
1389 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1390 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1391 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1392 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1393
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001394 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
1395 // it's arguably correct to linger it, since it was the default network before it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001396 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1397 mWiFiNetworkAgent.connect(true);
1398 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001399 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001400 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1401 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1402
1403 mWiFiNetworkAgent.disconnect();
1404 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001405 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001406 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1407 mCellNetworkAgent.disconnect();
1408 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1409 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001410
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001411 // If a network is lingering, and we add and remove a request from it, resume lingering.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001412 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1413 mCellNetworkAgent.connect(true);
1414 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1415 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1416 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1417 mWiFiNetworkAgent.connect(true);
1418 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1419 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1420 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1421
1422 NetworkRequest cellRequest = new NetworkRequest.Builder()
1423 .addTransportType(TRANSPORT_CELLULAR).build();
1424 NetworkCallback noopCallback = new NetworkCallback();
1425 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001426 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
1427 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001428 mCm.unregisterNetworkCallback(noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001429 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001430
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001431 // Similar to the above: lingering can start even after the lingered request is removed.
1432 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001433 mWiFiNetworkAgent.disconnect();
1434 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001435 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1436 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1437
1438 // Cell is now the default network. Pin it with a cell-specific request.
1439 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
1440 mCm.requestNetwork(cellRequest, noopCallback);
1441
1442 // Now connect wifi, and expect it to become the default network.
1443 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1444 mWiFiNetworkAgent.connect(true);
1445 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1446 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1447 // The default request is lingering on cell, but nothing happens to cell, and we send no
1448 // callbacks for it, because it's kept up by cellRequest.
1449 callback.assertNoCallback();
1450 // Now unregister cellRequest and expect cell to start lingering.
1451 mCm.unregisterNetworkCallback(noopCallback);
1452 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1453
1454 // Let linger run its course.
1455 callback.assertNoCallback();
1456 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent,
1457 TEST_LINGER_DELAY_MS /* timeoutMs */);
1458
1459 // Clean up.
1460 mWiFiNetworkAgent.disconnect();
1461 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1462 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001463
1464 mCm.unregisterNetworkCallback(callback);
1465 mCm.unregisterNetworkCallback(defaultCallback);
1466 }
1467
Paul Jensen85cf78e2015-06-25 13:25:07 -04001468 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04001469 // Verify NOT_RESTRICTED is set appropriately
1470 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
1471 .build().networkCapabilities;
1472 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
1473 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
1474 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04001475 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04001476 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1477 } else {
1478 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1479 }
1480
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001481 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001482 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001483 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
1484 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04001485 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001486 mServiceContext, "testFactory", filter);
1487 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04001488 ConditionVariable cv = testFactory.getNetworkStartedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001489 testFactory.expectAddRequests(1);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001490 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001491 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001492 int expectedRequestCount = 1;
1493 NetworkCallback networkCallback = null;
1494 // For non-INTERNET capabilities we cannot rely on the default request being present, so
1495 // add one.
1496 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04001497 assertFalse(testFactory.getMyStartRequested());
1498 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
1499 networkCallback = new NetworkCallback();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001500 testFactory.expectAddRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001501 mCm.requestNetwork(request, networkCallback);
1502 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001503 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001504 }
Paul Jensen3d911462015-06-12 06:40:24 -04001505 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001506 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1507 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001508
Paul Jensen85cf78e2015-06-25 13:25:07 -04001509 // Now bring in a higher scored network.
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001510 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001511 // Rather than create a validated network which complicates things by registering it's
1512 // own NetworkRequest during startup, just bump up the score to cancel out the
1513 // unvalidated penalty.
1514 testAgent.adjustScore(40);
1515 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001516
1517 // When testAgent connects, ConnectivityService will re-send us all current requests with
1518 // the new score. There are expectedRequestCount such requests, and we must wait for all of
1519 // them.
1520 testFactory.expectAddRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001521 testAgent.connect(false);
1522 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04001523 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001524 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001525 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001526
Paul Jensen85cf78e2015-06-25 13:25:07 -04001527 // Bring in a bunch of requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001528 testFactory.expectAddRequests(10);
1529 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001530 ConnectivityManager.NetworkCallback[] networkCallbacks =
1531 new ConnectivityManager.NetworkCallback[10];
1532 for (int i = 0; i< networkCallbacks.length; i++) {
1533 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
1534 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001535 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001536 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
1537 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04001538 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
1539 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001540
Paul Jensen85cf78e2015-06-25 13:25:07 -04001541 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001542 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001543 for (int i = 0; i < networkCallbacks.length; i++) {
1544 mCm.unregisterNetworkCallback(networkCallbacks[i]);
1545 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04001546 testFactory.waitForNetworkRequests(expectedRequestCount);
1547 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001548
Paul Jensen85cf78e2015-06-25 13:25:07 -04001549 // Drop the higher scored network.
1550 cv = testFactory.getNetworkStartedCV();
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001551 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001552 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001553 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1554 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001555
1556 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001557 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001558 handlerThread.quit();
1559 }
1560
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001561 @LargeTest
Paul Jensen85cf78e2015-06-25 13:25:07 -04001562 public void testNetworkFactoryRequests() throws Exception {
1563 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
1564 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
1565 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
1566 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
1567 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
1568 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
1569 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
1570 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
1571 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
1572 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
1573 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
1574 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
1575 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
1576 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
1577 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
1578 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
1579 }
1580
1581 @LargeTest
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001582 public void testNoMutableNetworkRequests() throws Exception {
1583 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
1584 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001585 builder.addCapability(NET_CAPABILITY_VALIDATED);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001586 try {
1587 mCm.requestNetwork(builder.build(), new NetworkCallback());
1588 fail();
1589 } catch (IllegalArgumentException expected) {}
1590 try {
1591 mCm.requestNetwork(builder.build(), pendingIntent);
1592 fail();
1593 } catch (IllegalArgumentException expected) {}
1594 builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001595 builder.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001596 try {
1597 mCm.requestNetwork(builder.build(), new NetworkCallback());
1598 fail();
1599 } catch (IllegalArgumentException expected) {}
1600 try {
1601 mCm.requestNetwork(builder.build(), pendingIntent);
1602 fail();
1603 } catch (IllegalArgumentException expected) {}
1604 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001605
Paul Jensene0988542015-06-25 15:30:08 -04001606 @LargeTest
1607 public void testMMSonWiFi() throws Exception {
1608 // Test bringing up cellular without MMS NetworkRequest gets reaped
1609 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1610 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1611 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
1612 mCellNetworkAgent.connectWithoutInternet();
1613 waitFor(cv);
1614 waitFor(new Criteria() {
1615 public boolean get() { return mCm.getAllNetworks().length == 0; } });
1616 verifyNoNetwork();
1617 // Test bringing up validated WiFi.
1618 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1619 cv = waitForConnectivityBroadcasts(1);
1620 mWiFiNetworkAgent.connect(true);
1621 waitFor(cv);
1622 verifyActiveNetwork(TRANSPORT_WIFI);
1623 // Register MMS NetworkRequest
1624 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1625 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1626 final TestNetworkCallback networkCallback = new TestNetworkCallback();
1627 mCm.requestNetwork(builder.build(), networkCallback);
1628 // Test bringing up unvalidated cellular with MMS
1629 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1630 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04001631 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001632 networkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04001633 verifyActiveNetwork(TRANSPORT_WIFI);
1634 // Test releasing NetworkRequest disconnects cellular with MMS
1635 cv = mCellNetworkAgent.getDisconnectedCV();
1636 mCm.unregisterNetworkCallback(networkCallback);
1637 waitFor(cv);
1638 verifyActiveNetwork(TRANSPORT_WIFI);
1639 }
1640
1641 @LargeTest
1642 public void testMMSonCell() throws Exception {
1643 // Test bringing up cellular without MMS
1644 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1645 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1646 mCellNetworkAgent.connect(false);
1647 waitFor(cv);
1648 verifyActiveNetwork(TRANSPORT_CELLULAR);
1649 // Register MMS NetworkRequest
1650 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1651 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1652 final TestNetworkCallback networkCallback = new TestNetworkCallback();
1653 mCm.requestNetwork(builder.build(), networkCallback);
1654 // Test bringing up MMS cellular network
Paul Jensene0988542015-06-25 15:30:08 -04001655 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1656 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1657 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001658 networkCallback.expectCallback(CallbackState.AVAILABLE, mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04001659 verifyActiveNetwork(TRANSPORT_CELLULAR);
1660 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
1661 cv = mmsNetworkAgent.getDisconnectedCV();
1662 mCm.unregisterNetworkCallback(networkCallback);
1663 waitFor(cv);
1664 verifyActiveNetwork(TRANSPORT_CELLULAR);
1665 }
1666
Paul Jensencf4c2c62015-07-01 14:16:32 -04001667 @LargeTest
1668 public void testCaptivePortal() {
1669 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1670 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1671 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1672 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1673
1674 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1675 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1676 .addCapability(NET_CAPABILITY_VALIDATED).build();
1677 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001678
1679 // Bring up a network with a captive portal.
1680 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001681 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04001682 String firstRedirectUrl = "http://example.com/firstPath";
1683 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001684 captivePortalCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04001685 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001686
1687 // Take down network.
1688 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001689 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001690 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001691
1692 // Bring up a network with a captive portal.
1693 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001694 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04001695 String secondRedirectUrl = "http://example.com/secondPath";
1696 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001697 captivePortalCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04001698 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001699
1700 // Make captive portal disappear then revalidate.
1701 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001702 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
1703 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001704 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001705
1706 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001707 validatedCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001708
1709 // Break network connectivity.
1710 // Expect NET_CAPABILITY_VALIDATED onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001711 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
1712 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001713 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001714 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09001715
Calvin On4bc78eb2016-10-11 15:10:46 -07001716 @LargeTest
1717 public void testAvoidOrIgnoreCaptivePortals() {
1718 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1719 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1720 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1721 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1722
1723 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1724 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1725 .addCapability(NET_CAPABILITY_VALIDATED).build();
1726 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
1727
1728 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
1729 // Bring up a network with a captive portal.
1730 // Expect it to fail to connect and not result in any callbacks.
1731 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1732 String firstRedirectUrl = "http://example.com/firstPath";
1733
1734 ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
1735 ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
1736 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
1737 waitFor(disconnectCv);
1738 waitFor(avoidCv);
1739
1740 assertNoCallbacks(captivePortalCallback, validatedCallback);
1741
1742 // Now test ignore mode.
1743 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE);
1744
1745 // Bring up a network with a captive portal.
1746 // Since we're ignoring captive portals, the network will validate.
1747 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1748 String secondRedirectUrl = "http://example.com/secondPath";
1749 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
1750
1751 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
1752 validatedCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1753 // But there should be no CaptivePortal callback.
1754 captivePortalCallback.assertNoCallback();
1755 }
1756
Etan Cohenddb9ef02015-11-18 10:56:15 -08001757 @SmallTest
1758 public void testInvalidNetworkSpecifier() {
1759 boolean execptionCalled = true;
1760
1761 try {
1762 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1763 builder.setNetworkSpecifier(MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
1764 execptionCalled = false;
1765 } catch (IllegalArgumentException e) {
1766 // do nothing - should get here
1767 }
1768
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001769 assertTrue("NetworkRequest builder with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
Etan Cohenddb9ef02015-11-18 10:56:15 -08001770 execptionCalled);
1771
1772 try {
1773 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
1774 networkCapabilities.addTransportType(TRANSPORT_WIFI)
1775 .setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
1776 mService.requestNetwork(networkCapabilities, null, 0, null,
1777 ConnectivityManager.TYPE_WIFI);
1778 execptionCalled = false;
1779 } catch (IllegalArgumentException e) {
1780 // do nothing - should get here
1781 }
1782
1783 assertTrue("ConnectivityService requestNetwork with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
1784 execptionCalled);
1785 }
1786
Erik Klinea2d29402016-03-16 15:31:39 +09001787 @LargeTest
1788 public void testRegisterDefaultNetworkCallback() throws Exception {
1789 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
1790 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
1791 defaultNetworkCallback.assertNoCallback();
1792
1793 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
1794 // whenever Wi-Fi is up. Without this, the mobile network agent is
1795 // reaped before any other activity can take place.
1796 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
1797 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1798 .addTransportType(TRANSPORT_CELLULAR).build();
1799 mCm.requestNetwork(cellRequest, cellNetworkCallback);
1800 cellNetworkCallback.assertNoCallback();
1801
1802 // Bring up cell and expect CALLBACK_AVAILABLE.
1803 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1804 mCellNetworkAgent.connect(true);
1805 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1806 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1807
1808 // Bring up wifi and expect CALLBACK_AVAILABLE.
1809 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1810 mWiFiNetworkAgent.connect(true);
1811 cellNetworkCallback.assertNoCallback();
1812 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1813
1814 // Bring down cell. Expect no default network callback, since it wasn't the default.
1815 mCellNetworkAgent.disconnect();
1816 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1817 defaultNetworkCallback.assertNoCallback();
1818
1819 // Bring up cell. Expect no default network callback, since it won't be the default.
1820 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1821 mCellNetworkAgent.connect(true);
1822 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1823 defaultNetworkCallback.assertNoCallback();
1824
1825 // Bring down wifi. Expect the default network callback to notified of LOST wifi
1826 // followed by AVAILABLE cell.
1827 mWiFiNetworkAgent.disconnect();
1828 cellNetworkCallback.assertNoCallback();
1829 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1830 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1831 mCellNetworkAgent.disconnect();
1832 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1833 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1834 }
1835
Erik Klineacdd6392016-07-07 16:50:58 +09001836 private class TestRequestUpdateCallback extends TestNetworkCallback {
1837 @Override
1838 public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
1839 setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
1840 }
1841
1842 @Override
1843 public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
1844 setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
1845 }
1846 }
1847
1848 @LargeTest
1849 public void testRequestCallbackUpdates() throws Exception {
1850 // File a network request for mobile.
1851 final TestNetworkCallback cellNetworkCallback = new TestRequestUpdateCallback();
1852 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1853 .addTransportType(TRANSPORT_CELLULAR).build();
1854 mCm.requestNetwork(cellRequest, cellNetworkCallback);
1855
1856 // Bring up the mobile network.
1857 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1858 mCellNetworkAgent.connect(true);
1859
1860 // We should get onAvailable().
1861 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1862 // We should get onCapabilitiesChanged(), when the mobile network successfully validates.
1863 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
1864 cellNetworkCallback.assertNoCallback();
1865
1866 // Update LinkProperties.
1867 final LinkProperties lp = new LinkProperties();
1868 lp.setInterfaceName("foonet_data0");
1869 mCellNetworkAgent.sendLinkProperties(lp);
1870 // We should get onLinkPropertiesChanged().
1871 cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
1872 cellNetworkCallback.assertNoCallback();
1873
1874 // Register a garden variety default network request.
1875 final TestNetworkCallback dfltNetworkCallback = new TestRequestUpdateCallback();
1876 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
1877 // Only onAvailable() is called; no other information is delivered.
1878 dfltNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1879 dfltNetworkCallback.assertNoCallback();
1880
1881 // Request a NetworkCapabilities update; only the requesting callback is notified.
1882 mCm.requestNetworkCapabilities(dfltNetworkCallback);
1883 dfltNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
1884 cellNetworkCallback.assertNoCallback();
1885 dfltNetworkCallback.assertNoCallback();
1886
1887 // Request a LinkProperties update; only the requesting callback is notified.
1888 mCm.requestLinkProperties(dfltNetworkCallback);
1889 dfltNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
1890 cellNetworkCallback.assertNoCallback();
1891 dfltNetworkCallback.assertNoCallback();
1892
1893 mCm.unregisterNetworkCallback(dfltNetworkCallback);
1894 mCm.unregisterNetworkCallback(cellNetworkCallback);
1895 }
1896
Calvin On4bc78eb2016-10-11 15:10:46 -07001897 private void setCaptivePortalMode(int mode) {
1898 ContentResolver cr = mServiceContext.getContentResolver();
1899 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
1900 }
1901
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09001902 private void setMobileDataAlwaysOn(boolean enable) {
1903 ContentResolver cr = mServiceContext.getContentResolver();
1904 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
1905 mService.updateMobileDataAlwaysOn();
1906 mService.waitForIdle();
1907 }
1908
1909 private boolean isForegroundNetwork(MockNetworkAgent network) {
1910 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
1911 assertNotNull(nc);
1912 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
1913 }
1914
1915 @SmallTest
1916 public void testBackgroundNetworks() throws Exception {
1917 // Create a background request. We can't do this ourselves because ConnectivityService
1918 // doesn't have an API for it. So just turn on mobile data always on.
1919 setMobileDataAlwaysOn(true);
1920 final NetworkRequest request = new NetworkRequest.Builder().build();
1921 final NetworkRequest fgRequest = new NetworkRequest.Builder()
1922 .addCapability(NET_CAPABILITY_FOREGROUND).build();
1923 final TestNetworkCallback callback = new TestNetworkCallback();
1924 final TestNetworkCallback fgCallback = new TestNetworkCallback();
1925 mCm.registerNetworkCallback(request, callback);
1926 mCm.registerNetworkCallback(fgRequest, fgCallback);
1927
1928 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1929 mCellNetworkAgent.connect(true);
1930 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1931 fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1932 assertTrue(isForegroundNetwork(mCellNetworkAgent));
1933
1934 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1935 mWiFiNetworkAgent.connect(true);
1936
1937 // When wifi connects, cell lingers.
1938 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1939 fgCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1940 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1941 fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1942 assertTrue(isForegroundNetwork(mCellNetworkAgent));
1943 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1944
1945 // When lingering is complete, cell is still there but is now in the background.
1946 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, TEST_LINGER_DELAY_MS);
1947 callback.assertNoCallback();
1948 assertFalse(isForegroundNetwork(mCellNetworkAgent));
1949 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1950
1951 // File a cell request and check that cell comes into the foreground.
1952 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1953 .addTransportType(TRANSPORT_CELLULAR).build();
1954 final TestNetworkCallback cellCallback = new TestNetworkCallback();
1955 mCm.requestNetwork(cellRequest, cellCallback);
1956 cellCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1957 fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1958 callback.assertNoCallback(); // Because the network is already up.
1959 assertTrue(isForegroundNetwork(mCellNetworkAgent));
1960 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1961
1962 // Release the request. The network immediately goes into the background, since it was not
1963 // lingering.
1964 mCm.unregisterNetworkCallback(cellCallback);
1965 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1966 callback.assertNoCallback();
1967 assertFalse(isForegroundNetwork(mCellNetworkAgent));
1968 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1969
1970 // Disconnect wifi and check that cell is foreground again.
1971 mWiFiNetworkAgent.disconnect();
1972 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1973 fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1974 fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1975 assertTrue(isForegroundNetwork(mCellNetworkAgent));
1976
1977 mCm.unregisterNetworkCallback(callback);
1978 mCm.unregisterNetworkCallback(fgCallback);
1979 }
1980
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09001981 @SmallTest
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001982 public void testRequestBenchmark() throws Exception {
1983 // Benchmarks connecting and switching performance in the presence of a large number of
1984 // NetworkRequests.
1985 // 1. File NUM_REQUESTS requests.
1986 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
1987 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
1988 // and NUM_REQUESTS onAvailable callbacks to fire.
1989 // See how long it took.
1990 final int NUM_REQUESTS = 90;
1991 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
1992 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
1993 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
1994 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
1995
1996 final int REGISTER_TIME_LIMIT_MS = 100;
1997 long startTime = System.currentTimeMillis();
1998 for (int i = 0; i < NUM_REQUESTS; i++) {
1999 callbacks[i] = new NetworkCallback() {
2000 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
2001 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
2002 };
2003 mCm.registerNetworkCallback(request, callbacks[i]);
2004 }
2005 long timeTaken = System.currentTimeMillis() - startTime;
2006 String msg = String.format("Register %d callbacks: %dms, acceptable %dms",
2007 NUM_REQUESTS, timeTaken, REGISTER_TIME_LIMIT_MS);
2008 Log.d(TAG, msg);
2009 assertTrue(msg, timeTaken < REGISTER_TIME_LIMIT_MS);
2010
2011 final int CONNECT_TIME_LIMIT_MS = 30;
2012 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2013 // Don't request that the network validate, because otherwise connect() will block until
2014 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
2015 // and we won't actually measure anything.
2016 mCellNetworkAgent.connect(false);
2017 startTime = System.currentTimeMillis();
2018 if (!availableLatch.await(CONNECT_TIME_LIMIT_MS, TimeUnit.MILLISECONDS)) {
2019 fail(String.format("Only dispatched %d/%d onAvailable callbacks in %dms",
2020 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
2021 CONNECT_TIME_LIMIT_MS));
2022 }
2023 timeTaken = System.currentTimeMillis() - startTime;
2024 Log.d(TAG, String.format("Connect, %d callbacks: %dms, acceptable %dms",
2025 NUM_REQUESTS, timeTaken, CONNECT_TIME_LIMIT_MS));
2026
2027 final int SWITCH_TIME_LIMIT_MS = 30;
2028 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2029 // Give wifi a high enough score that we'll linger cell when wifi comes up.
2030 mWiFiNetworkAgent.adjustScore(40);
2031 mWiFiNetworkAgent.connect(false);
2032 startTime = System.currentTimeMillis();
2033 if (!losingLatch.await(SWITCH_TIME_LIMIT_MS, TimeUnit.MILLISECONDS)) {
2034 fail(String.format("Only dispatched %d/%d onLosing callbacks in %dms",
2035 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, SWITCH_TIME_LIMIT_MS));
2036 }
2037 timeTaken = System.currentTimeMillis() - startTime;
2038 Log.d(TAG, String.format("Linger, %d callbacks: %dms, acceptable %dms",
2039 NUM_REQUESTS, timeTaken, SWITCH_TIME_LIMIT_MS));
2040
2041 final int UNREGISTER_TIME_LIMIT_MS = 10;
2042 startTime = System.currentTimeMillis();
2043 for (int i = 0; i < NUM_REQUESTS; i++) {
2044 mCm.unregisterNetworkCallback(callbacks[i]);
2045 }
2046 timeTaken = System.currentTimeMillis() - startTime;
2047 msg = String.format("Unregister %d callbacks: %dms, acceptable %dms",
2048 NUM_REQUESTS, timeTaken, UNREGISTER_TIME_LIMIT_MS);
2049 Log.d(TAG, msg);
2050 assertTrue(msg, timeTaken < UNREGISTER_TIME_LIMIT_MS);
2051 }
2052
2053 @SmallTest
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002054 public void testMobileDataAlwaysOn() throws Exception {
2055 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2056 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2057 .addTransportType(TRANSPORT_CELLULAR).build();
2058 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
2059
2060 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
2061 handlerThread.start();
2062 NetworkCapabilities filter = new NetworkCapabilities()
2063 .addTransportType(TRANSPORT_CELLULAR)
2064 .addCapability(NET_CAPABILITY_INTERNET);
2065 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
2066 mServiceContext, "testFactory", filter);
2067 testFactory.setScoreFilter(40);
2068
2069 // Register the factory and expect it to start looking for a network.
2070 testFactory.expectAddRequests(1);
2071 testFactory.register();
2072 testFactory.waitForNetworkRequests(1);
2073 assertTrue(testFactory.getMyStartRequested());
2074
2075 // Bring up wifi. The factory stops looking for a network.
2076 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2077 testFactory.expectAddRequests(2); // Because the default request changes score twice.
2078 mWiFiNetworkAgent.connect(true);
2079 testFactory.waitForNetworkRequests(1);
2080 assertFalse(testFactory.getMyStartRequested());
2081
2082 ContentResolver cr = mServiceContext.getContentResolver();
2083
2084 // Turn on mobile data always on. The factory starts looking again.
2085 testFactory.expectAddRequests(1);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002086 setMobileDataAlwaysOn(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002087 testFactory.waitForNetworkRequests(2);
2088 assertTrue(testFactory.getMyStartRequested());
2089
2090 // Bring up cell data and check that the factory stops looking.
2091 assertEquals(1, mCm.getAllNetworks().length);
2092 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2093 testFactory.expectAddRequests(2); // Because the cell request changes score twice.
2094 mCellNetworkAgent.connect(true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002095 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002096 testFactory.waitForNetworkRequests(2);
2097 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
2098
2099 // Check that cell data stays up.
2100 mService.waitForIdle();
2101 verifyActiveNetwork(TRANSPORT_WIFI);
2102 assertEquals(2, mCm.getAllNetworks().length);
2103
2104 // Turn off mobile data always on and expect the request to disappear...
2105 testFactory.expectRemoveRequests(1);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002106 setMobileDataAlwaysOn(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002107 testFactory.waitForNetworkRequests(1);
2108
2109 // ... and cell data to be torn down.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002110 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002111 assertEquals(1, mCm.getAllNetworks().length);
2112
2113 testFactory.unregister();
2114 mCm.unregisterNetworkCallback(cellNetworkCallback);
2115 handlerThread.quit();
2116 }
2117
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002118 @SmallTest
2119 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002120 final ContentResolver cr = mServiceContext.getContentResolver();
Erik Kline065ab6e2016-10-02 18:02:14 +09002121 final WrappedAvoidBadWifiTracker tracker = mService.getAvoidBadWifiTracker();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002122 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
2123
Erik Kline065ab6e2016-10-02 18:02:14 +09002124 tracker.configRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002125 String[] values = new String[] {null, "0", "1"};
2126 for (int i = 0; i < values.length; i++) {
2127 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002128 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002129 mService.waitForIdle();
2130 String msg = String.format("config=false, setting=%s", values[i]);
2131 assertTrue(msg, mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09002132 assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002133 }
2134
Erik Kline065ab6e2016-10-02 18:02:14 +09002135 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002136
2137 Settings.Global.putInt(cr, settingName, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09002138 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002139 mService.waitForIdle();
2140 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09002141 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002142
2143 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002144 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002145 mService.waitForIdle();
2146 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09002147 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002148
2149 Settings.Global.putString(cr, settingName, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09002150 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002151 mService.waitForIdle();
2152 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09002153 assertTrue(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002154 }
2155
2156 @SmallTest
2157 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09002158 final ContentResolver cr = mServiceContext.getContentResolver();
2159 final WrappedAvoidBadWifiTracker tracker = mService.getAvoidBadWifiTracker();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002160
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002161 // Pretend we're on a carrier that restricts switching away from bad wifi.
Erik Kline065ab6e2016-10-02 18:02:14 +09002162 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002163
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002164 // File a request for cell to ensure it doesn't go down.
2165 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2166 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2167 .addTransportType(TRANSPORT_CELLULAR).build();
2168 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2169
2170 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2171 mCm.registerDefaultNetworkCallback(defaultCallback);
2172
2173 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
2174 .addTransportType(TRANSPORT_WIFI)
2175 .addCapability(NET_CAPABILITY_VALIDATED)
2176 .build();
2177 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
2178 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
2179
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002180 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09002181 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002182
2183 // Bring up validated cell.
2184 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2185 mCellNetworkAgent.connect(true);
2186 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2187 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2188 Network cellNetwork = mCellNetworkAgent.getNetwork();
2189
2190 // Bring up validated wifi.
2191 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2192 mWiFiNetworkAgent.connect(true);
2193 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2194 validatedWifiCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2195 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2196
2197 // Fail validation on wifi.
2198 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
2199 mCm.reportNetworkConnectivity(wifiNetwork, false);
2200 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2201
2202 // Because avoid bad wifi is off, we don't switch to cellular.
2203 defaultCallback.assertNoCallback();
2204 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2205 NET_CAPABILITY_VALIDATED));
2206 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2207 NET_CAPABILITY_VALIDATED));
2208 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2209
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002210 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
2211 // that we switch back to cell.
Erik Kline065ab6e2016-10-02 18:02:14 +09002212 tracker.configRestrictsAvoidBadWifi = false;
2213 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002214 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2215 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2216
2217 // Switch back to a restrictive carrier.
Erik Kline065ab6e2016-10-02 18:02:14 +09002218 tracker.configRestrictsAvoidBadWifi = true;
2219 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002220 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2221 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2222
2223 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
2224 mCm.setAvoidUnvalidated(wifiNetwork);
2225 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2226 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2227 NET_CAPABILITY_VALIDATED));
2228 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2229 NET_CAPABILITY_VALIDATED));
2230 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2231
2232 // Disconnect and reconnect wifi to clear the one-time switch above.
2233 mWiFiNetworkAgent.disconnect();
2234 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2235 mWiFiNetworkAgent.connect(true);
2236 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2237 validatedWifiCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2238 wifiNetwork = mWiFiNetworkAgent.getNetwork();
2239
2240 // Fail validation on wifi and expect the dialog to appear.
2241 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
2242 mCm.reportNetworkConnectivity(wifiNetwork, false);
2243 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2244
2245 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002246 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002247 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002248
2249 // We now switch to cell.
2250 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2251 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2252 NET_CAPABILITY_VALIDATED));
2253 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2254 NET_CAPABILITY_VALIDATED));
2255 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2256
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002257 // Simulate the user turning the cellular fallback setting off and then on.
2258 // We switch to wifi and then to cell.
2259 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09002260 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002261 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2262 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2263 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002264 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002265 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2266 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2267
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002268 // If cell goes down, we switch to wifi.
2269 mCellNetworkAgent.disconnect();
2270 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2271 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2272 validatedWifiCallback.assertNoCallback();
2273
2274 mCm.unregisterNetworkCallback(cellNetworkCallback);
2275 mCm.unregisterNetworkCallback(validatedWifiCallback);
2276 mCm.unregisterNetworkCallback(defaultCallback);
2277 }
2278
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002279 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
2280
2281 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
2282
2283 private class CallbackValue {
2284 public CallbackType callbackType;
2285 public int error;
2286
2287 public CallbackValue(CallbackType type) {
2288 this.callbackType = type;
2289 this.error = PacketKeepalive.SUCCESS;
2290 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
2291 }
2292
2293 public CallbackValue(CallbackType type, int error) {
2294 this.callbackType = type;
2295 this.error = error;
2296 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
2297 }
2298
2299 @Override
2300 public boolean equals(Object o) {
2301 return o instanceof CallbackValue &&
2302 this.callbackType == ((CallbackValue) o).callbackType &&
2303 this.error == ((CallbackValue) o).error;
2304 }
2305
2306 @Override
2307 public String toString() {
2308 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
2309 }
2310 }
2311
2312 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
2313
2314 @Override
2315 public void onStarted() {
2316 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
2317 }
2318
2319 @Override
2320 public void onStopped() {
2321 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
2322 }
2323
2324 @Override
2325 public void onError(int error) {
2326 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
2327 }
2328
2329 private void expectCallback(CallbackValue callbackValue) {
2330 try {
2331 assertEquals(
2332 callbackValue,
2333 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
2334 } catch (InterruptedException e) {
2335 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
2336 }
2337 }
2338
2339 public void expectStarted() {
2340 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
2341 }
2342
2343 public void expectStopped() {
2344 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
2345 }
2346
2347 public void expectError(int error) {
2348 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
2349 }
2350 }
2351
2352 private Network connectKeepaliveNetwork(LinkProperties lp) {
2353 // Ensure the network is disconnected before we do anything.
2354 if (mWiFiNetworkAgent != null) {
2355 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
2356 }
2357
2358 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2359 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2360 mWiFiNetworkAgent.connect(true);
2361 waitFor(cv);
2362 verifyActiveNetwork(TRANSPORT_WIFI);
2363 mWiFiNetworkAgent.sendLinkProperties(lp);
2364 mService.waitForIdle();
2365 return mWiFiNetworkAgent.getNetwork();
2366 }
2367
2368 public void testPacketKeepalives() throws Exception {
2369 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
2370 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
2371 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
2372 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
2373 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
2374
2375 LinkProperties lp = new LinkProperties();
2376 lp.setInterfaceName("wlan12");
2377 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
2378 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
2379 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
2380 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
2381
2382 Network notMyNet = new Network(61234);
2383 Network myNet = connectKeepaliveNetwork(lp);
2384
2385 TestKeepaliveCallback callback = new TestKeepaliveCallback();
2386 PacketKeepalive ka;
2387
2388 // Attempt to start keepalives with invalid parameters and check for errors.
2389 ka = mCm.startNattKeepalive(notMyNet, 25, callback, myIPv4, 1234, dstIPv4);
2390 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
2391
2392 ka = mCm.startNattKeepalive(myNet, 19, callback, notMyIPv4, 1234, dstIPv4);
2393 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
2394
2395 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 1234, dstIPv6);
2396 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2397
2398 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv4);
2399 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2400
2401 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv6);
2402 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); // NAT-T is IPv4-only.
2403
2404 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
2405 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
2406
2407 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
2408 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
2409
2410 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2411 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
2412
2413 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2414 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
2415
2416 // Check that a started keepalive can be stopped.
2417 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2418 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2419 callback.expectStarted();
2420 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
2421 ka.stop();
2422 callback.expectStopped();
2423
2424 // Check that deleting the IP address stops the keepalive.
2425 LinkProperties bogusLp = new LinkProperties(lp);
2426 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2427 callback.expectStarted();
2428 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
2429 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
2430 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
2431 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2432 mWiFiNetworkAgent.sendLinkProperties(lp);
2433
2434 // Check that a started keepalive is stopped correctly when the network disconnects.
2435 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2436 callback.expectStarted();
2437 mWiFiNetworkAgent.disconnect();
2438 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
2439
2440 // ... and that stopping it after that has no adverse effects.
2441 assertNull(mCm.getNetworkCapabilities(myNet));
2442 ka.stop();
2443
2444 // Reconnect.
2445 myNet = connectKeepaliveNetwork(lp);
2446 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2447
2448 // Check things work as expected when the keepalive is stopped and the network disconnects.
2449 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2450 callback.expectStarted();
2451 ka.stop();
2452 mWiFiNetworkAgent.disconnect();
2453 mService.waitForIdle();
2454 callback.expectStopped();
2455
2456 // Reconnect.
2457 myNet = connectKeepaliveNetwork(lp);
2458 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2459
2460 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
2461 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
2462 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2463 callback.expectStarted();
2464
2465 // The second one gets slot 2.
2466 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
2467 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
2468 PacketKeepalive ka2 = mCm.startNattKeepalive(myNet, 25, callback2, myIPv4, 6789, dstIPv4);
2469 callback2.expectStarted();
2470
2471 // Now stop the first one and create a third. This also gets slot 1.
2472 ka.stop();
2473 callback.expectStopped();
2474
2475 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
2476 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
2477 PacketKeepalive ka3 = mCm.startNattKeepalive(myNet, 25, callback3, myIPv4, 9876, dstIPv4);
2478 callback3.expectStarted();
2479
2480 ka2.stop();
2481 callback2.expectStopped();
2482
2483 ka3.stop();
2484 callback3.expectStopped();
2485 }
Udam Sainib7c24872016-01-04 12:16:14 -08002486
2487 @SmallTest
2488 public void testGetCaptivePortalServerUrl() throws Exception {
2489 String url = mCm.getCaptivePortalServerUrl();
2490 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
2491 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09002492
2493 private static class TestNetworkPinner extends NetworkPinner {
2494 public static boolean awaitPin(int timeoutMs) {
2495 synchronized(sLock) {
2496 if (sNetwork == null) {
2497 try {
2498 sLock.wait(timeoutMs);
2499 } catch (InterruptedException e) {}
2500 }
2501 return sNetwork != null;
2502 }
2503 }
2504
2505 public static boolean awaitUnpin(int timeoutMs) {
2506 synchronized(sLock) {
2507 if (sNetwork != null) {
2508 try {
2509 sLock.wait(timeoutMs);
2510 } catch (InterruptedException e) {}
2511 }
2512 return sNetwork == null;
2513 }
2514 }
2515 }
2516
2517 private void assertPinnedToWifiWithCellDefault() {
2518 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
2519 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2520 }
2521
2522 private void assertPinnedToWifiWithWifiDefault() {
2523 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
2524 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2525 }
2526
2527 private void assertNotPinnedToWifi() {
2528 assertNull(mCm.getBoundNetworkForProcess());
2529 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2530 }
2531
2532 @SmallTest
2533 public void testNetworkPinner() {
2534 NetworkRequest wifiRequest = new NetworkRequest.Builder()
2535 .addTransportType(TRANSPORT_WIFI)
2536 .build();
2537 assertNull(mCm.getBoundNetworkForProcess());
2538
2539 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2540 assertNull(mCm.getBoundNetworkForProcess());
2541
2542 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2543 mCellNetworkAgent.connect(true);
2544 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2545 mWiFiNetworkAgent.connect(false);
2546
2547 // When wi-fi connects, expect to be pinned.
2548 assertTrue(TestNetworkPinner.awaitPin(100));
2549 assertPinnedToWifiWithCellDefault();
2550
2551 // Disconnect and expect the pin to drop.
2552 mWiFiNetworkAgent.disconnect();
2553 assertTrue(TestNetworkPinner.awaitUnpin(100));
2554 assertNotPinnedToWifi();
2555
2556 // Reconnecting does not cause the pin to come back.
2557 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2558 mWiFiNetworkAgent.connect(false);
2559 assertFalse(TestNetworkPinner.awaitPin(100));
2560 assertNotPinnedToWifi();
2561
2562 // Pinning while connected causes the pin to take effect immediately.
2563 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2564 assertTrue(TestNetworkPinner.awaitPin(100));
2565 assertPinnedToWifiWithCellDefault();
2566
2567 // Explicitly unpin and expect to use the default network again.
2568 TestNetworkPinner.unpin();
2569 assertNotPinnedToWifi();
2570
2571 // Disconnect cell and wifi.
2572 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
2573 mCellNetworkAgent.disconnect();
2574 mWiFiNetworkAgent.disconnect();
2575 waitFor(cv);
2576
2577 // Pinning takes effect even if the pinned network is the default when the pin is set...
2578 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2579 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2580 mWiFiNetworkAgent.connect(false);
2581 assertTrue(TestNetworkPinner.awaitPin(100));
2582 assertPinnedToWifiWithWifiDefault();
2583
2584 // ... and is maintained even when that network is no longer the default.
2585 cv = waitForConnectivityBroadcasts(1);
2586 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2587 mCellNetworkAgent.connect(true);
2588 waitFor(cv);
2589 assertPinnedToWifiWithCellDefault();
2590 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04002591
2592 @SmallTest
2593 public void testNetworkRequestMaximum() {
2594 final int MAX_REQUESTS = 100;
2595 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
2596 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
2597 ArrayList<NetworkCallback> networkCallbacks = new ArrayList<NetworkCallback>();
2598 try {
2599 for (int i = 0; i < MAX_REQUESTS; i++) {
2600 NetworkCallback networkCallback = new NetworkCallback();
2601 mCm.requestNetwork(networkRequest, networkCallback);
2602 networkCallbacks.add(networkCallback);
2603 }
2604 fail("Registering " + MAX_REQUESTS + " NetworkRequests did not throw exception");
2605 } catch (IllegalArgumentException expected) {}
2606 for (NetworkCallback networkCallback : networkCallbacks) {
2607 mCm.unregisterNetworkCallback(networkCallback);
2608 }
2609 networkCallbacks.clear();
2610
2611 try {
2612 for (int i = 0; i < MAX_REQUESTS; i++) {
2613 NetworkCallback networkCallback = new NetworkCallback();
2614 mCm.registerNetworkCallback(networkRequest, networkCallback);
2615 networkCallbacks.add(networkCallback);
2616 }
2617 fail("Registering " + MAX_REQUESTS + " NetworkCallbacks did not throw exception");
2618 } catch (IllegalArgumentException expected) {}
2619 for (NetworkCallback networkCallback : networkCallbacks) {
2620 mCm.unregisterNetworkCallback(networkCallback);
2621 }
2622 networkCallbacks.clear();
2623
2624 ArrayList<PendingIntent> pendingIntents = new ArrayList<PendingIntent>();
2625 try {
2626 for (int i = 0; i < MAX_REQUESTS + 1; i++) {
2627 PendingIntent pendingIntent =
2628 PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
2629 mCm.requestNetwork(networkRequest, pendingIntent);
2630 pendingIntents.add(pendingIntent);
2631 }
2632 fail("Registering " + MAX_REQUESTS +
2633 " PendingIntent NetworkRequests did not throw exception");
2634 } catch (IllegalArgumentException expected) {}
2635 for (PendingIntent pendingIntent : pendingIntents) {
2636 mCm.unregisterNetworkCallback(pendingIntent);
2637 }
2638 pendingIntents.clear();
2639
2640 try {
2641 for (int i = 0; i < MAX_REQUESTS + 1; i++) {
2642 PendingIntent pendingIntent =
2643 PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
2644 mCm.registerNetworkCallback(networkRequest, pendingIntent);
2645 pendingIntents.add(pendingIntent);
2646 }
2647 fail("Registering " + MAX_REQUESTS +
2648 " PendingIntent NetworkCallbacks did not throw exception");
2649 } catch (IllegalArgumentException expected) {}
2650 for (PendingIntent pendingIntent : pendingIntents) {
2651 mCm.unregisterNetworkCallback(pendingIntent);
2652 }
2653 pendingIntents.clear();
2654 mService.waitForIdle(5000);
2655
2656 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
2657 for (int i = 0; i < MAX_REQUESTS; i++) {
2658 NetworkCallback networkCallback = new NetworkCallback();
2659 mCm.requestNetwork(networkRequest, networkCallback);
2660 mCm.unregisterNetworkCallback(networkCallback);
2661 }
2662 mService.waitForIdle();
2663 for (int i = 0; i < MAX_REQUESTS; i++) {
2664 NetworkCallback networkCallback = new NetworkCallback();
2665 mCm.registerNetworkCallback(networkRequest, networkCallback);
2666 mCm.unregisterNetworkCallback(networkCallback);
2667 }
2668 mService.waitForIdle();
2669 for (int i = 0; i < MAX_REQUESTS; i++) {
2670 PendingIntent pendingIntent =
2671 PendingIntent.getBroadcast(mContext, 0, new Intent("b" + i), 0);
2672 mCm.requestNetwork(networkRequest, pendingIntent);
2673 mCm.unregisterNetworkCallback(pendingIntent);
2674 }
2675 mService.waitForIdle();
2676 for (int i = 0; i < MAX_REQUESTS; i++) {
2677 PendingIntent pendingIntent =
2678 PendingIntent.getBroadcast(mContext, 0, new Intent("c" + i), 0);
2679 mCm.registerNetworkCallback(networkRequest, pendingIntent);
2680 mCm.unregisterNetworkCallback(pendingIntent);
2681 }
2682 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07002683}