blob: d62c30da583d2c34dcec13a9253d9e4e1e6862b4 [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;
Hugo Benichi5d540d12016-10-17 15:54:51 +090071import android.test.FlakyTest;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +090072import android.test.mock.MockContentResolver;
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 Colittibfecba22016-02-21 01:09:26 +090077import com.android.internal.util.WakeupMessage;
Lorenzo Colitti3c295b52016-10-28 12:56:03 +090078import com.android.internal.util.test.BroadcastInterceptingContext;
Lorenzo Colittib8df76e42016-10-28 12:37:38 +090079import com.android.internal.util.test.FakeSettingsProvider;
Paul Jensencf4c2c62015-07-01 14:16:32 -040080import com.android.server.connectivity.NetworkAgentInfo;
Paul Jensend7b6ca92015-05-13 14:05:12 -040081import com.android.server.connectivity.NetworkMonitor;
Paul Jensen232437312016-04-06 09:51:26 -040082import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
Lorenzo Colitti531a3442016-03-01 12:55:58 +090083import com.android.server.net.NetworkPinner;
Paul Jensend7b6ca92015-05-13 14:05:12 -040084
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070085import java.net.InetAddress;
Paul Jensen4e1d3fd2016-04-08 13:56:52 -040086import java.util.ArrayList;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +090087import java.util.Arrays;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +090088import java.util.Objects;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +090089import java.util.concurrent.CountDownLatch;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +090090import java.util.concurrent.LinkedBlockingQueue;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +090091import java.util.concurrent.TimeUnit;
Robert Greenwalt348e98d2015-06-05 17:55:36 -070092import java.util.concurrent.atomic.AtomicBoolean;
Hugo Benichi53d83d52016-11-15 13:42:34 +090093import java.util.function.BooleanSupplier;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070094
95/**
96 * Tests for {@link ConnectivityService}.
Paul Jensend7b6ca92015-05-13 14:05:12 -040097 *
98 * Build, install and run with:
99 * runtest frameworks-services -c com.android.server.ConnectivityServiceTest
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700100 */
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700101public class ConnectivityServiceTest extends AndroidTestCase {
102 private static final String TAG = "ConnectivityServiceTest";
103
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900104 private static final int TIMEOUT_MS = 500;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900105 private static final int TEST_LINGER_DELAY_MS = 120;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900106
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700107 private BroadcastInterceptingContext mServiceContext;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400108 private WrappedConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900109 private WrappedConnectivityManager mCm;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400110 private MockNetworkAgent mWiFiNetworkAgent;
111 private MockNetworkAgent mCellNetworkAgent;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900112 private MockNetworkAgent mEthernetNetworkAgent;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700113
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900114 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
115 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
116 // reflect the state of our test ConnectivityService.
117 private class WrappedConnectivityManager extends ConnectivityManager {
118 private Network mFakeBoundNetwork;
119
120 public synchronized boolean bindProcessToNetwork(Network network) {
121 mFakeBoundNetwork = network;
122 return true;
123 }
124
125 public synchronized Network getBoundNetworkForProcess() {
126 return mFakeBoundNetwork;
127 }
128
129 public WrappedConnectivityManager(Context context, ConnectivityService service) {
130 super(context, service);
131 }
132 }
133
Paul Jensend7b6ca92015-05-13 14:05:12 -0400134 private class MockContext extends BroadcastInterceptingContext {
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900135 private final MockContentResolver mContentResolver;
136
Paul Jensend7b6ca92015-05-13 14:05:12 -0400137 MockContext(Context base) {
138 super(base);
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900139 mContentResolver = new MockContentResolver();
140 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
Paul Jensend7b6ca92015-05-13 14:05:12 -0400141 }
142
143 @Override
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900144 public Object getSystemService(String name) {
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900145 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
146 if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400147 return super.getSystemService(name);
148 }
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900149
150 @Override
151 public ContentResolver getContentResolver() {
152 return mContentResolver;
153 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400154 }
155
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900156 /**
157 * A subclass of HandlerThread that allows callers to wait for it to become idle. waitForIdle
158 * will return immediately if the handler is already idle.
159 */
160 private class IdleableHandlerThread extends HandlerThread {
161 private IdleHandler mIdleHandler;
162
163 public IdleableHandlerThread(String name) {
164 super(name);
165 }
166
167 public void waitForIdle(int timeoutMs) {
168 final ConditionVariable cv = new ConditionVariable();
169 final MessageQueue queue = getLooper().getQueue();
170
171 synchronized (queue) {
172 if (queue.isIdle()) {
173 return;
174 }
175
176 assertNull("BUG: only one idle handler allowed", mIdleHandler);
177 mIdleHandler = new IdleHandler() {
178 public boolean queueIdle() {
Lorenzo Colitti5eaaf742016-03-02 21:47:42 +0900179 synchronized (queue) {
180 cv.open();
181 mIdleHandler = null;
182 return false; // Remove the handler.
183 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900184 }
185 };
186 queue.addIdleHandler(mIdleHandler);
187 }
188
189 if (!cv.block(timeoutMs)) {
190 fail("HandlerThread " + getName() +
191 " did not become idle after " + timeoutMs + " ms");
192 queue.removeIdleHandler(mIdleHandler);
193 }
194 }
195 }
196
197 // Tests that IdleableHandlerThread works as expected.
Hugo Benichicfcc1cb2016-11-04 16:06:34 +0900198 @SmallTest
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900199 public void testIdleableHandlerThread() {
200 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
201
202 // Tests that waitForIdle returns immediately if the service is already idle.
203 for (int i = 0; i < attempts; i++) {
204 mService.waitForIdle();
205 }
206
207 // Bring up a network that we can use to send messages to ConnectivityService.
208 ConditionVariable cv = waitForConnectivityBroadcasts(1);
209 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
210 mWiFiNetworkAgent.connect(false);
211 waitFor(cv);
212 Network n = mWiFiNetworkAgent.getNetwork();
213 assertNotNull(n);
214
215 // Tests that calling waitForIdle waits for messages to be processed.
216 for (int i = 0; i < attempts; i++) {
217 mWiFiNetworkAgent.setSignalStrength(i);
218 mService.waitForIdle();
219 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
220 }
Hugo Benichi5d540d12016-10-17 15:54:51 +0900221 }
222
Hugo Benichicfcc1cb2016-11-04 16:06:34 +0900223 @SmallTest
Hugo Benichi5d540d12016-10-17 15:54:51 +0900224 @FlakyTest(tolerance = 3)
225 public void testNotWaitingForIdleCausesRaceConditions() {
226 // Bring up a network that we can use to send messages to ConnectivityService.
227 ConditionVariable cv = waitForConnectivityBroadcasts(1);
228 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
229 mWiFiNetworkAgent.connect(false);
230 waitFor(cv);
231 Network n = mWiFiNetworkAgent.getNetwork();
232 assertNotNull(n);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900233
234 // Ensure that not calling waitForIdle causes a race condition.
Hugo Benichi5d540d12016-10-17 15:54:51 +0900235 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900236 for (int i = 0; i < attempts; i++) {
237 mWiFiNetworkAgent.setSignalStrength(i);
238 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
239 // We hit a race condition, as expected. Pass the test.
240 return;
241 }
242 }
243
244 // No race? There is a bug in this test.
245 fail("expected race condition at least once in " + attempts + " attempts");
246 }
247
Paul Jensend7b6ca92015-05-13 14:05:12 -0400248 private class MockNetworkAgent {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400249 private final WrappedNetworkMonitor mWrappedNetworkMonitor;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400250 private final NetworkInfo mNetworkInfo;
251 private final NetworkCapabilities mNetworkCapabilities;
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900252 private final IdleableHandlerThread mHandlerThread;
Paul Jensene0988542015-06-25 15:30:08 -0400253 private final ConditionVariable mDisconnected = new ConditionVariable();
Paul Jensen232437312016-04-06 09:51:26 -0400254 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
Calvin On1f64f3f2016-10-11 15:10:46 -0700255 private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
Paul Jensen3d911462015-06-12 06:40:24 -0400256 private int mScore;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400257 private NetworkAgent mNetworkAgent;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900258 private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
259 private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE;
260 private Integer mExpectedKeepaliveSlot = null;
Paul Jensen232437312016-04-06 09:51:26 -0400261 // Contains the redirectUrl from networkStatus(). Before reading, wait for
262 // mNetworkStatusReceived.
263 private String mRedirectUrl;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400264
265 MockNetworkAgent(int transport) {
266 final int type = transportToLegacyType(transport);
267 final String typeName = ConnectivityManager.getNetworkTypeName(type);
268 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
269 mNetworkCapabilities = new NetworkCapabilities();
270 mNetworkCapabilities.addTransportType(transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400271 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900272 case TRANSPORT_ETHERNET:
273 mScore = 70;
274 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400275 case TRANSPORT_WIFI:
Paul Jensen3d911462015-06-12 06:40:24 -0400276 mScore = 60;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400277 break;
278 case TRANSPORT_CELLULAR:
Paul Jensen3d911462015-06-12 06:40:24 -0400279 mScore = 50;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400280 break;
281 default:
282 throw new UnsupportedOperationException("unimplemented network type");
283 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900284 mHandlerThread = new IdleableHandlerThread("Mock-" + typeName);
285 mHandlerThread.start();
286 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
287 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
288 new LinkProperties(), mScore, new NetworkMisc()) {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900289 @Override
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900290 public void unwanted() { mDisconnected.open(); }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900291
292 @Override
293 public void startPacketKeepalive(Message msg) {
294 int slot = msg.arg1;
295 if (mExpectedKeepaliveSlot != null) {
296 assertEquals((int) mExpectedKeepaliveSlot, slot);
297 }
298 onPacketKeepaliveEvent(slot, mStartKeepaliveError);
299 }
300
301 @Override
302 public void stopPacketKeepalive(Message msg) {
303 onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
304 }
Paul Jensen232437312016-04-06 09:51:26 -0400305
306 @Override
307 public void networkStatus(int status, String redirectUrl) {
308 mRedirectUrl = redirectUrl;
309 mNetworkStatusReceived.open();
310 }
Calvin On1f64f3f2016-10-11 15:10:46 -0700311
312 @Override
313 protected void preventAutomaticReconnect() {
314 mPreventReconnectReceived.open();
315 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400316 };
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900317 // Waits for the NetworkAgent to be registered, which includes the creation of the
318 // NetworkMonitor.
319 mService.waitForIdle();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400320 mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor();
Paul Jensen3d911462015-06-12 06:40:24 -0400321 }
322
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900323 public void waitForIdle(int timeoutMs) {
324 mHandlerThread.waitForIdle(timeoutMs);
325 }
326
327 public void waitForIdle() {
328 waitForIdle(TIMEOUT_MS);
329 }
330
Paul Jensen3d911462015-06-12 06:40:24 -0400331 public void adjustScore(int change) {
332 mScore += change;
333 mNetworkAgent.sendNetworkScore(mScore);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400334 }
335
Paul Jensen85cf78e2015-06-25 13:25:07 -0400336 public void addCapability(int capability) {
337 mNetworkCapabilities.addCapability(capability);
338 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
339 }
340
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900341 public void removeCapability(int capability) {
342 mNetworkCapabilities.removeCapability(capability);
343 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
344 }
345
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900346 public void setSignalStrength(int signalStrength) {
347 mNetworkCapabilities.setSignalStrength(signalStrength);
348 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
349 }
350
Paul Jensene0988542015-06-25 15:30:08 -0400351 public void connectWithoutInternet() {
352 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
353 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
354 }
355
Paul Jensend7b6ca92015-05-13 14:05:12 -0400356 /**
Paul Jensene0988542015-06-25 15:30:08 -0400357 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400358 * @param validated Indicate if network should pretend to be validated.
359 */
360 public void connect(boolean validated) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900361 assertEquals("MockNetworkAgents can only be connected once",
362 mNetworkInfo.getDetailedState(), DetailedState.IDLE);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400363 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
364
Paul Jensend7b6ca92015-05-13 14:05:12 -0400365 NetworkCallback callback = null;
366 final ConditionVariable validatedCv = new ConditionVariable();
367 if (validated) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400368 mWrappedNetworkMonitor.gen204ProbeResult = 204;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400369 NetworkRequest request = new NetworkRequest.Builder()
370 .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
371 .build();
372 callback = new NetworkCallback() {
373 public void onCapabilitiesChanged(Network network,
374 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400375 if (network.equals(getNetwork()) &&
376 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400377 validatedCv.open();
378 }
379 }
380 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400381 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400382 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400383 addCapability(NET_CAPABILITY_INTERNET);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400384
Paul Jensene0988542015-06-25 15:30:08 -0400385 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400386
387 if (validated) {
388 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400389 waitFor(validatedCv);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400390 mWrappedNetworkMonitor.gen204ProbeResult = 500;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400391 }
392
393 if (callback != null) mCm.unregisterNetworkCallback(callback);
394 }
395
Paul Jensen232437312016-04-06 09:51:26 -0400396 public void connectWithCaptivePortal(String redirectUrl) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400397 mWrappedNetworkMonitor.gen204ProbeResult = 200;
Paul Jensen232437312016-04-06 09:51:26 -0400398 mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400399 connect(false);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400400 }
401
Paul Jensend7b6ca92015-05-13 14:05:12 -0400402 public void disconnect() {
403 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
404 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
405 }
406
407 public Network getNetwork() {
408 return new Network(mNetworkAgent.netId);
409 }
Paul Jensene0988542015-06-25 15:30:08 -0400410
Calvin On1f64f3f2016-10-11 15:10:46 -0700411 public ConditionVariable getPreventReconnectReceived() {
412 return mPreventReconnectReceived;
413 }
414
Paul Jensene0988542015-06-25 15:30:08 -0400415 public ConditionVariable getDisconnectedCV() {
416 return mDisconnected;
417 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400418
419 public WrappedNetworkMonitor getWrappedNetworkMonitor() {
420 return mWrappedNetworkMonitor;
421 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900422
423 public void sendLinkProperties(LinkProperties lp) {
424 mNetworkAgent.sendLinkProperties(lp);
425 }
426
427 public void setStartKeepaliveError(int error) {
428 mStartKeepaliveError = error;
429 }
430
431 public void setStopKeepaliveError(int error) {
432 mStopKeepaliveError = error;
433 }
434
435 public void setExpectedKeepaliveSlot(Integer slot) {
436 mExpectedKeepaliveSlot = slot;
437 }
Paul Jensen232437312016-04-06 09:51:26 -0400438
439 public String waitForRedirectUrl() {
440 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
441 return mRedirectUrl;
442 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400443 }
444
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900445 /**
446 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
447 * operations have been processed. Before ConnectivityService can add or remove any requests,
448 * the factory must be told to expect those operations by calling expectAddRequests or
449 * expectRemoveRequests.
450 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700451 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400452 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
453 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400454 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700455
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900456 // Used to expect that requests be removed or added on a separate thread, without sleeping.
457 // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then
458 // cause some other thread to add or remove requests, then call waitForRequests(). We can
459 // either expect requests to be added or removed, but not both, because CountDownLatch can
460 // only count in one direction.
461 private CountDownLatch mExpectations;
462
463 // Whether we are currently expecting requests to be added or removed. Valid only if
464 // mExpectations is non-null.
465 private boolean mExpectingAdditions;
466
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700467 public MockNetworkFactory(Looper looper, Context context, String logTag,
468 NetworkCapabilities filter) {
469 super(looper, context, logTag, filter);
470 }
471
472 public int getMyRequestCount() {
473 return getRequestCount();
474 }
475
476 protected void startNetwork() {
477 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400478 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700479 }
480
481 protected void stopNetwork() {
482 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400483 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700484 }
485
486 public boolean getMyStartRequested() {
487 return mNetworkStarted.get();
488 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400489
490 public ConditionVariable getNetworkStartedCV() {
491 mNetworkStartedCV.close();
492 return mNetworkStartedCV;
493 }
494
495 public ConditionVariable getNetworkStoppedCV() {
496 mNetworkStoppedCV.close();
497 return mNetworkStoppedCV;
498 }
499
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900500 @Override
501 protected void handleAddRequest(NetworkRequest request, int score) {
502 // If we're expecting anything, we must be expecting additions.
503 if (mExpectations != null && !mExpectingAdditions) {
504 fail("Can't add requests while expecting requests to be removed");
505 }
506
507 // Add the request.
508 super.handleAddRequest(request, score);
509
510 // Reduce the number of request additions we're waiting for.
511 if (mExpectingAdditions) {
512 assertTrue("Added more requests than expected", mExpectations.getCount() > 0);
513 mExpectations.countDown();
514 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400515 }
516
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900517 @Override
518 protected void handleRemoveRequest(NetworkRequest request) {
519 // If we're expecting anything, we must be expecting removals.
520 if (mExpectations != null && mExpectingAdditions) {
521 fail("Can't remove requests while expecting requests to be added");
522 }
523
524 // Remove the request.
525 super.handleRemoveRequest(request);
526
527 // Reduce the number of request removals we're waiting for.
528 if (!mExpectingAdditions) {
529 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0);
530 mExpectations.countDown();
531 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400532 }
533
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900534 private void assertNoExpectations() {
535 if (mExpectations != null) {
536 fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
537 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400538 }
539
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900540 // Expects that count requests will be added.
541 public void expectAddRequests(final int count) {
542 assertNoExpectations();
543 mExpectingAdditions = true;
544 mExpectations = new CountDownLatch(count);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400545 }
546
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900547 // Expects that count requests will be removed.
548 public void expectRemoveRequests(final int count) {
549 assertNoExpectations();
550 mExpectingAdditions = false;
551 mExpectations = new CountDownLatch(count);
552 }
553
554 // Waits for the expected request additions or removals to happen within a timeout.
555 public void waitForRequests() throws InterruptedException {
556 assertNotNull("Nothing to wait for", mExpectations);
557 mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
558 final long count = mExpectations.getCount();
559 final String msg = count + " requests still not " +
560 (mExpectingAdditions ? "added" : "removed") +
561 " after " + TIMEOUT_MS + " ms";
562 assertEquals(msg, 0, count);
563 mExpectations = null;
564 }
565
566 public void waitForNetworkRequests(final int count) throws InterruptedException {
567 waitForRequests();
568 assertEquals(count, getMyRequestCount());
Paul Jensen0a2823e2015-06-12 10:31:09 -0400569 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700570 }
571
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900572 private class FakeWakeupMessage extends WakeupMessage {
573 private static final int UNREASONABLY_LONG_WAIT = 1000;
574
575 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
576 super(context, handler, cmdName, cmd);
577 }
578
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900579 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
580 int arg1, int arg2, Object obj) {
581 super(context, handler, cmdName, cmd, arg1, arg2, obj);
582 }
583
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900584 @Override
585 public void schedule(long when) {
586 long delayMs = when - SystemClock.elapsedRealtime();
587 if (delayMs < 0) delayMs = 0;
588 if (delayMs > UNREASONABLY_LONG_WAIT) {
589 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
590 "ms into the future: " + delayMs);
591 }
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900592 Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
593 mHandler.sendMessageDelayed(msg, delayMs);
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900594 }
595
596 @Override
597 public void cancel() {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900598 mHandler.removeMessages(mCmd, mObj);
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900599 }
600
601 @Override
602 public void onAlarm() {
603 throw new AssertionError("Should never happen. Update this fake.");
604 }
605 }
606
Paul Jensencf4c2c62015-07-01 14:16:32 -0400607 // NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
608 private class WrappedNetworkMonitor extends NetworkMonitor {
609 // HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
610 public int gen204ProbeResult = 500;
Paul Jensen232437312016-04-06 09:51:26 -0400611 public String gen204ProbeRedirectUrl = null;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400612
613 public WrappedNetworkMonitor(Context context, Handler handler,
Hugo Benichif9fdf872016-07-28 17:53:06 +0900614 NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest,
615 IpConnectivityLog log) {
616 super(context, handler, networkAgentInfo, defaultRequest, log);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400617 }
618
619 @Override
Paul Jensen232437312016-04-06 09:51:26 -0400620 protected CaptivePortalProbeResult isCaptivePortal() {
Calvin On1f64f3f2016-10-11 15:10:46 -0700621 if (!mIsCaptivePortalCheckEnabled) { return new CaptivePortalProbeResult(204); }
Hugo Benichid953bf82016-09-27 09:22:35 +0900622 return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl, null);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400623 }
624 }
625
Erik Kline065ab6e2016-10-02 18:02:14 +0900626 private class WrappedAvoidBadWifiTracker extends AvoidBadWifiTracker {
Hugo Benichi53d83d52016-11-15 13:42:34 +0900627 public volatile boolean configRestrictsAvoidBadWifi;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400628
Erik Kline065ab6e2016-10-02 18:02:14 +0900629 public WrappedAvoidBadWifiTracker(Context c, Handler h, Runnable r) {
630 super(c, h, r);
631 }
632
633 @Override
634 public boolean configRestrictsAvoidBadWifi() {
635 return configRestrictsAvoidBadWifi;
636 }
637 }
638
639 private class WrappedConnectivityService extends ConnectivityService {
640 public WrappedAvoidBadWifiTracker wrappedAvoidBadWifiTracker;
641 private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
642
Paul Jensend7b6ca92015-05-13 14:05:12 -0400643 public WrappedConnectivityService(Context context, INetworkManagementService netManager,
Hugo Benichif9fdf872016-07-28 17:53:06 +0900644 INetworkStatsService statsService, INetworkPolicyManager policyManager,
645 IpConnectivityLog log) {
646 super(context, netManager, statsService, policyManager, log);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900647 mLingerDelayMs = TEST_LINGER_DELAY_MS;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400648 }
649
650 @Override
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900651 protected HandlerThread createHandlerThread() {
652 return new IdleableHandlerThread("WrappedConnectivityService");
653 }
654
655 @Override
Paul Jensend7b6ca92015-05-13 14:05:12 -0400656 protected int getDefaultTcpRwnd() {
657 // Prevent wrapped ConnectivityService from trying to write to SystemProperties.
658 return 0;
659 }
Paul Jensen67b0b072015-06-10 11:22:17 -0400660
661 @Override
662 protected int reserveNetId() {
663 while (true) {
664 final int netId = super.reserveNetId();
665
666 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
667 // can have odd side-effects, like network validations succeeding.
668 final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks();
669 boolean overlaps = false;
670 for (Network network : networks) {
671 if (netId == network.netId) {
672 overlaps = true;
673 break;
674 }
675 }
676 if (overlaps) continue;
677
678 return netId;
679 }
680 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400681
682 @Override
683 public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
684 NetworkAgentInfo nai, NetworkRequest defaultRequest) {
Hugo Benichif9fdf872016-07-28 17:53:06 +0900685 final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(
686 context, handler, nai, defaultRequest, mock(IpConnectivityLog.class));
Paul Jensencf4c2c62015-07-01 14:16:32 -0400687 mLastCreatedNetworkMonitor = monitor;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400688 return monitor;
689 }
690
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900691 @Override
Erik Kline065ab6e2016-10-02 18:02:14 +0900692 public AvoidBadWifiTracker createAvoidBadWifiTracker(
693 Context c, Handler h, Runnable r) {
694 final WrappedAvoidBadWifiTracker tracker = new WrappedAvoidBadWifiTracker(c, h, r);
695 return tracker;
696 }
697
698 public WrappedAvoidBadWifiTracker getAvoidBadWifiTracker() {
699 return (WrappedAvoidBadWifiTracker) mAvoidBadWifiTracker;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900700 }
701
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900702 @Override
Erik Kline065ab6e2016-10-02 18:02:14 +0900703 public WakeupMessage makeWakeupMessage(
704 Context context, Handler handler, String cmdName, int cmd, Object obj) {
705 return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900706 }
707
Paul Jensencf4c2c62015-07-01 14:16:32 -0400708 public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
709 return mLastCreatedNetworkMonitor;
710 }
711
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900712 public void waitForIdle(int timeoutMs) {
713 ((IdleableHandlerThread) mHandlerThread).waitForIdle(timeoutMs);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400714 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900715
716 public void waitForIdle() {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900717 waitForIdle(TIMEOUT_MS);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900718 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400719 }
720
Paul Jensen0a2823e2015-06-12 10:31:09 -0400721 private interface Criteria {
722 public boolean get();
723 }
724
Paul Jensen3d911462015-06-12 06:40:24 -0400725 /**
726 * Wait up to 500ms for {@code criteria.get()} to become true, polling.
727 * Fails if 500ms goes by before {@code criteria.get()} to become true.
728 */
Paul Jensen0a2823e2015-06-12 10:31:09 -0400729 static private void waitFor(Criteria criteria) {
730 int delays = 0;
731 while (!criteria.get()) {
Etan Cohenbf3b1ba2016-10-27 15:05:50 -0700732 sleepFor(50);
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900733 if (++delays == 10) fail();
Paul Jensen0a2823e2015-06-12 10:31:09 -0400734 }
735 }
736
Paul Jensen3d911462015-06-12 06:40:24 -0400737 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900738 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
739 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -0400740 */
741 static private void waitFor(ConditionVariable conditionVariable) {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900742 assertTrue(conditionVariable.block(TIMEOUT_MS));
Paul Jensen3d911462015-06-12 06:40:24 -0400743 }
744
Paul Jensend7b6ca92015-05-13 14:05:12 -0400745 @Override
746 public void setUp() throws Exception {
747 super.setUp();
748
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +0900749 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
750 // http://b/25897652 .
751 if (Looper.myLooper() == null) {
752 Looper.prepare();
753 }
754
Paul Jensend7b6ca92015-05-13 14:05:12 -0400755 mServiceContext = new MockContext(getContext());
Lorenzo Colitti83fa2582015-08-07 12:49:01 +0900756 mService = new WrappedConnectivityService(mServiceContext,
757 mock(INetworkManagementService.class),
758 mock(INetworkStatsService.class),
Hugo Benichif9fdf872016-07-28 17:53:06 +0900759 mock(INetworkPolicyManager.class),
760 mock(IpConnectivityLog.class));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400761
Paul Jensend7b6ca92015-05-13 14:05:12 -0400762 mService.systemReady();
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900763 mCm = new WrappedConnectivityManager(getContext(), mService);
764 mCm.bindProcessToNetwork(null);
Calvin On1f64f3f2016-10-11 15:10:46 -0700765
766 // Ensure that the default setting for Captive Portals is used for most tests
767 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400768 }
769
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +0900770 public void tearDown() throws Exception {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +0900771 setMobileDataAlwaysOn(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +0900772 if (mCellNetworkAgent != null) { mCellNetworkAgent.disconnect(); }
773 if (mWiFiNetworkAgent != null) { mWiFiNetworkAgent.disconnect(); }
774 mCellNetworkAgent = mWiFiNetworkAgent = null;
775 super.tearDown();
776 }
777
Paul Jensend7b6ca92015-05-13 14:05:12 -0400778 private int transportToLegacyType(int transport) {
779 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900780 case TRANSPORT_ETHERNET:
781 return TYPE_ETHERNET;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400782 case TRANSPORT_WIFI:
783 return TYPE_WIFI;
784 case TRANSPORT_CELLULAR:
785 return TYPE_MOBILE;
786 default:
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900787 throw new IllegalStateException("Unknown transport " + transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400788 }
789 }
790
791 private void verifyActiveNetwork(int transport) {
792 // Test getActiveNetworkInfo()
793 assertNotNull(mCm.getActiveNetworkInfo());
794 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
795 // Test getActiveNetwork()
796 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +0000797 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400798 switch (transport) {
799 case TRANSPORT_WIFI:
800 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
801 break;
802 case TRANSPORT_CELLULAR:
803 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
804 break;
805 default:
806 throw new IllegalStateException("Unknown transport" + transport);
807 }
808 // Test getNetworkInfo(Network)
809 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
810 assertEquals(transportToLegacyType(transport), mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
811 // Test getNetworkCapabilities(Network)
812 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
813 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
814 }
815
816 private void verifyNoNetwork() {
817 // Test getActiveNetworkInfo()
818 assertNull(mCm.getActiveNetworkInfo());
819 // Test getActiveNetwork()
820 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +0000821 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400822 // Test getAllNetworks()
823 assertEquals(0, mCm.getAllNetworks().length);
824 }
825
826 /**
827 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
828 * broadcasts are received.
829 */
830 private ConditionVariable waitForConnectivityBroadcasts(final int count) {
831 final ConditionVariable cv = new ConditionVariable();
832 mServiceContext.registerReceiver(new BroadcastReceiver() {
833 private int remaining = count;
834 public void onReceive(Context context, Intent intent) {
835 if (--remaining == 0) {
836 cv.open();
837 mServiceContext.unregisterReceiver(this);
838 }
839 }
840 }, new IntentFilter(CONNECTIVITY_ACTION));
841 return cv;
842 }
843
Hugo Benichicfcc1cb2016-11-04 16:06:34 +0900844 @SmallTest
Paul Jensend7b6ca92015-05-13 14:05:12 -0400845 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400846 verifyNoNetwork();
847 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
848 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
849 assertNull(mCm.getActiveNetworkInfo());
850 assertNull(mCm.getActiveNetwork());
851 // Test bringing up validated cellular.
852 ConditionVariable cv = waitForConnectivityBroadcasts(1);
853 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -0400854 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400855 verifyActiveNetwork(TRANSPORT_CELLULAR);
856 assertEquals(2, mCm.getAllNetworks().length);
857 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
858 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
859 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
860 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
861 // Test bringing up validated WiFi.
862 cv = waitForConnectivityBroadcasts(2);
863 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -0400864 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400865 verifyActiveNetwork(TRANSPORT_WIFI);
866 assertEquals(2, mCm.getAllNetworks().length);
867 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
868 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
869 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
870 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
871 // Test cellular linger timeout.
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900872 waitFor(new Criteria() {
873 public boolean get() { return mCm.getAllNetworks().length == 1; } });
Paul Jensend7b6ca92015-05-13 14:05:12 -0400874 verifyActiveNetwork(TRANSPORT_WIFI);
875 assertEquals(1, mCm.getAllNetworks().length);
876 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
877 // Test WiFi disconnect.
878 cv = waitForConnectivityBroadcasts(1);
879 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400880 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400881 verifyNoNetwork();
882 }
883
Hugo Benichicfcc1cb2016-11-04 16:06:34 +0900884 @SmallTest
Paul Jensend7b6ca92015-05-13 14:05:12 -0400885 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
886 // Test bringing up unvalidated WiFi
887 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
888 ConditionVariable cv = waitForConnectivityBroadcasts(1);
889 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -0400890 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400891 verifyActiveNetwork(TRANSPORT_WIFI);
892 // Test bringing up unvalidated cellular
893 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
894 mCellNetworkAgent.connect(false);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900895 mService.waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400896 verifyActiveNetwork(TRANSPORT_WIFI);
897 // Test cellular disconnect.
898 mCellNetworkAgent.disconnect();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900899 mService.waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400900 verifyActiveNetwork(TRANSPORT_WIFI);
901 // Test bringing up validated cellular
902 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
903 cv = waitForConnectivityBroadcasts(2);
904 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -0400905 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400906 verifyActiveNetwork(TRANSPORT_CELLULAR);
907 // Test cellular disconnect.
908 cv = waitForConnectivityBroadcasts(2);
909 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400910 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400911 verifyActiveNetwork(TRANSPORT_WIFI);
912 // Test WiFi disconnect.
913 cv = waitForConnectivityBroadcasts(1);
914 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400915 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400916 verifyNoNetwork();
917 }
918
Hugo Benichicfcc1cb2016-11-04 16:06:34 +0900919 @SmallTest
Paul Jensend7b6ca92015-05-13 14:05:12 -0400920 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
921 // Test bringing up unvalidated cellular.
922 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
923 ConditionVariable cv = waitForConnectivityBroadcasts(1);
924 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -0400925 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400926 verifyActiveNetwork(TRANSPORT_CELLULAR);
927 // Test bringing up unvalidated WiFi.
928 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
929 cv = waitForConnectivityBroadcasts(2);
930 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -0400931 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400932 verifyActiveNetwork(TRANSPORT_WIFI);
933 // Test WiFi disconnect.
934 cv = waitForConnectivityBroadcasts(2);
935 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400936 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400937 verifyActiveNetwork(TRANSPORT_CELLULAR);
938 // Test cellular disconnect.
939 cv = waitForConnectivityBroadcasts(1);
940 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400941 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400942 verifyNoNetwork();
943 }
944
Hugo Benichicfcc1cb2016-11-04 16:06:34 +0900945 @SmallTest
Paul Jensene0988542015-06-25 15:30:08 -0400946 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400947 // Test bringing up unvalidated WiFi.
Paul Jensene0988542015-06-25 15:30:08 -0400948 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400949 ConditionVariable cv = waitForConnectivityBroadcasts(1);
950 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -0400951 waitFor(cv);
952 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400953 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -0400954 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -0400955 // Test bringing up validated cellular.
956 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -0400957 cv = waitForConnectivityBroadcasts(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400958 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -0400959 waitFor(cv);
960 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400961 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
962 NET_CAPABILITY_VALIDATED));
963 // Test cellular disconnect.
964 cv = waitForConnectivityBroadcasts(2);
965 mCellNetworkAgent.disconnect();
966 waitFor(cv);
967 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -0400968 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -0400969 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -0400970 NET_CAPABILITY_VALIDATED));
971 }
972
Hugo Benichicfcc1cb2016-11-04 16:06:34 +0900973 @SmallTest
Paul Jensen3d911462015-06-12 06:40:24 -0400974 public void testCellularOutscoresWeakWifi() throws Exception {
975 // Test bringing up validated cellular.
976 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
977 ConditionVariable cv = waitForConnectivityBroadcasts(1);
978 mCellNetworkAgent.connect(true);
979 waitFor(cv);
980 verifyActiveNetwork(TRANSPORT_CELLULAR);
981 // Test bringing up validated WiFi.
982 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
983 cv = waitForConnectivityBroadcasts(2);
984 mWiFiNetworkAgent.connect(true);
985 waitFor(cv);
986 verifyActiveNetwork(TRANSPORT_WIFI);
987 // Test WiFi getting really weak.
988 cv = waitForConnectivityBroadcasts(2);
989 mWiFiNetworkAgent.adjustScore(-11);
990 waitFor(cv);
991 verifyActiveNetwork(TRANSPORT_CELLULAR);
992 // Test WiFi restoring signal strength.
993 cv = waitForConnectivityBroadcasts(2);
994 mWiFiNetworkAgent.adjustScore(11);
995 waitFor(cv);
996 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -0400997 }
998
Hugo Benichicfcc1cb2016-11-04 16:06:34 +0900999 @SmallTest
Paul Jensene0988542015-06-25 15:30:08 -04001000 public void testReapingNetwork() throws Exception {
1001 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1002 // Expect it to be torn down immediately because it satisfies no requests.
1003 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1004 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
1005 mWiFiNetworkAgent.connectWithoutInternet();
1006 waitFor(cv);
1007 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1008 // Expect it to be torn down immediately because it satisfies no requests.
1009 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1010 cv = mCellNetworkAgent.getDisconnectedCV();
1011 mCellNetworkAgent.connectWithoutInternet();
1012 waitFor(cv);
1013 // Test bringing up validated WiFi.
1014 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1015 cv = waitForConnectivityBroadcasts(1);
1016 mWiFiNetworkAgent.connect(true);
1017 waitFor(cv);
1018 verifyActiveNetwork(TRANSPORT_WIFI);
1019 // Test bringing up unvalidated cellular.
1020 // Expect it to be torn down because it could never be the highest scoring network
1021 // satisfying the default request even if it validated.
1022 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1023 cv = mCellNetworkAgent.getDisconnectedCV();
1024 mCellNetworkAgent.connect(false);
1025 waitFor(cv);
1026 verifyActiveNetwork(TRANSPORT_WIFI);
1027 cv = mWiFiNetworkAgent.getDisconnectedCV();
1028 mWiFiNetworkAgent.disconnect();
1029 waitFor(cv);
1030 }
1031
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001032 @SmallTest
Paul Jensene0988542015-06-25 15:30:08 -04001033 public void testCellularFallback() throws Exception {
1034 // Test bringing up validated cellular.
1035 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1036 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1037 mCellNetworkAgent.connect(true);
1038 waitFor(cv);
1039 verifyActiveNetwork(TRANSPORT_CELLULAR);
1040 // Test bringing up validated WiFi.
1041 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1042 cv = waitForConnectivityBroadcasts(2);
1043 mWiFiNetworkAgent.connect(true);
1044 waitFor(cv);
1045 verifyActiveNetwork(TRANSPORT_WIFI);
1046 // Reevaluate WiFi (it'll instantly fail DNS).
1047 cv = waitForConnectivityBroadcasts(2);
1048 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1049 NET_CAPABILITY_VALIDATED));
1050 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1051 // Should quickly fall back to Cellular.
1052 waitFor(cv);
1053 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1054 NET_CAPABILITY_VALIDATED));
1055 verifyActiveNetwork(TRANSPORT_CELLULAR);
1056 // Reevaluate cellular (it'll instantly fail DNS).
1057 cv = waitForConnectivityBroadcasts(2);
1058 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1059 NET_CAPABILITY_VALIDATED));
1060 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1061 // Should quickly fall back to WiFi.
1062 waitFor(cv);
1063 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1064 NET_CAPABILITY_VALIDATED));
1065 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1066 NET_CAPABILITY_VALIDATED));
1067 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001068 }
1069
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001070 @SmallTest
Paul Jensene0988542015-06-25 15:30:08 -04001071 public void testWiFiFallback() throws Exception {
1072 // Test bringing up unvalidated WiFi.
1073 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1074 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1075 mWiFiNetworkAgent.connect(false);
1076 waitFor(cv);
1077 verifyActiveNetwork(TRANSPORT_WIFI);
1078 // Test bringing up validated cellular.
1079 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1080 cv = waitForConnectivityBroadcasts(2);
1081 mCellNetworkAgent.connect(true);
1082 waitFor(cv);
1083 verifyActiveNetwork(TRANSPORT_CELLULAR);
1084 // Reevaluate cellular (it'll instantly fail DNS).
1085 cv = waitForConnectivityBroadcasts(2);
1086 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1087 NET_CAPABILITY_VALIDATED));
1088 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1089 // Should quickly fall back to WiFi.
1090 waitFor(cv);
1091 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1092 NET_CAPABILITY_VALIDATED));
1093 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001094 }
1095
Paul Jensen3d911462015-06-12 06:40:24 -04001096 enum CallbackState {
1097 NONE,
1098 AVAILABLE,
Erik Klineacdd6392016-07-07 16:50:58 +09001099 NETWORK_CAPABILITIES,
1100 LINK_PROPERTIES,
Paul Jensen3d911462015-06-12 06:40:24 -04001101 LOSING,
Erik Kline3841a482015-11-25 12:49:38 +09001102 LOST,
1103 UNAVAILABLE
Paul Jensen3d911462015-06-12 06:40:24 -04001104 }
1105
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001106 /**
1107 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1108 * this class receives, by calling expectCallback() exactly once each time a callback is
1109 * received. assertNoCallback may be called at any time.
1110 */
Paul Jensen3d911462015-06-12 06:40:24 -04001111 private class TestNetworkCallback extends NetworkCallback {
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001112 // Chosen to be much less than the linger timeout. This ensures that we can distinguish
1113 // between a LOST callback that arrives immediately and a LOST callback that arrives after
1114 // the linger timeout.
1115 private final static int TIMEOUT_MS = 50;
1116
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001117 private class CallbackInfo {
1118 public final CallbackState state;
1119 public final Network network;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001120 public Object arg;
1121 public CallbackInfo(CallbackState s, Network n, Object o) {
1122 state = s; network = n; arg = o;
1123 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001124 public String toString() { return String.format("%s (%s)", state, network); }
1125 public boolean equals(Object o) {
1126 if (!(o instanceof CallbackInfo)) return false;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001127 // Ignore timeMs, since it's unpredictable.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001128 CallbackInfo other = (CallbackInfo) o;
1129 return state == other.state && Objects.equals(network, other.network);
1130 }
1131 }
1132 private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
1133
Erik Klineacdd6392016-07-07 16:50:58 +09001134 protected void setLastCallback(CallbackState state, Network network, Object o) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001135 mCallbacks.offer(new CallbackInfo(state, network, o));
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001136 }
Paul Jensen3d911462015-06-12 06:40:24 -04001137
Erik Klineacdd6392016-07-07 16:50:58 +09001138 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001139 public void onAvailable(Network network) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001140 setLastCallback(CallbackState.AVAILABLE, network, null);
Paul Jensen3d911462015-06-12 06:40:24 -04001141 }
1142
Erik Klineacdd6392016-07-07 16:50:58 +09001143 @Override
Erik Kline3841a482015-11-25 12:49:38 +09001144 public void onUnavailable() {
1145 setLastCallback(CallbackState.UNAVAILABLE, null, null);
1146 }
1147
1148 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001149 public void onLosing(Network network, int maxMsToLive) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001150 setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
Paul Jensen3d911462015-06-12 06:40:24 -04001151 }
1152
Erik Klineacdd6392016-07-07 16:50:58 +09001153 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001154 public void onLost(Network network) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001155 setLastCallback(CallbackState.LOST, network, null);
1156 }
1157
1158 void expectCallback(CallbackState state, MockNetworkAgent mockAgent, int timeoutMs) {
1159 CallbackInfo expected = new CallbackInfo(
1160 state, (mockAgent != null) ? mockAgent.getNetwork() : null, 0);
1161 CallbackInfo actual;
1162 try {
1163 actual = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
1164 assertEquals("Unexpected callback:", expected, actual);
1165 } catch (InterruptedException e) {
1166 fail("Did not receive expected " + expected + " after " + TIMEOUT_MS + "ms");
1167 actual = null; // Or the compiler can't tell it's never used uninitialized.
1168 }
1169 if (state == CallbackState.LOSING) {
1170 String msg = String.format(
1171 "Invalid linger time value %d, must be between %d and %d",
1172 actual.arg, 0, TEST_LINGER_DELAY_MS);
1173 int maxMsToLive = (Integer) actual.arg;
1174 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= TEST_LINGER_DELAY_MS);
1175 }
Erik Klinea2d29402016-03-16 15:31:39 +09001176 }
1177
1178 void expectCallback(CallbackState state, MockNetworkAgent mockAgent) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001179 expectCallback(state, mockAgent, TIMEOUT_MS);
Paul Jensen3d911462015-06-12 06:40:24 -04001180 }
1181
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001182 void assertNoCallback() {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001183 mService.waitForIdle();
1184 CallbackInfo c = mCallbacks.peek();
1185 assertNull("Unexpected callback: " + c, c);
1186 }
1187 }
1188
1189 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1190 // only be declared in a static or top level type".
1191 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1192 for (TestNetworkCallback c : callbacks) {
1193 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001194 }
1195 }
1196
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001197 @SmallTest
Paul Jensen3d911462015-06-12 06:40:24 -04001198 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001199 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001200 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1201 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001202 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1203 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001204 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1205 .addTransportType(TRANSPORT_WIFI).build();
1206 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1207 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001208 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001209 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1210 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1211
1212 // Test unvalidated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001213 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1214 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1215 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001216 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1217 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001218 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1219 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001220 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001221
Paul Jensen3d911462015-06-12 06:40:24 -04001222 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1223 mCellNetworkAgent.adjustScore(-1);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001224 mService.waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001225 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001226 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1227
Paul Jensen3d911462015-06-12 06:40:24 -04001228 cv = waitForConnectivityBroadcasts(2);
1229 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1230 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001231 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1232 wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001233 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1234 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001235 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001236
Paul Jensen3d911462015-06-12 06:40:24 -04001237 cv = waitForConnectivityBroadcasts(2);
1238 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001239 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1240 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001241 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001242 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001243 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001244
Paul Jensen3d911462015-06-12 06:40:24 -04001245 cv = waitForConnectivityBroadcasts(1);
1246 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001247 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1248 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001249 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001250 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001251
1252 // Test validated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001253 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1254 mCellNetworkAgent.connect(true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001255 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1256 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001257 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001258 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001259
Paul Jensen3d911462015-06-12 06:40:24 -04001260 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1261 mCellNetworkAgent.adjustScore(-1);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001262 mService.waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001263 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001264 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1265
Paul Jensen3d911462015-06-12 06:40:24 -04001266 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1267 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001268 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1269 genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1270 wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1271 cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001272 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001273 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001274
Paul Jensen3d911462015-06-12 06:40:24 -04001275 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001276 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1277 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1278 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001279
Paul Jensen3d911462015-06-12 06:40:24 -04001280 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001281 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1282 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1283 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001284 }
1285
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001286 @SmallTest
1287 public void testMultipleLingering() {
1288 NetworkRequest request = new NetworkRequest.Builder()
1289 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1290 .build();
1291 TestNetworkCallback callback = new TestNetworkCallback();
1292 mCm.registerNetworkCallback(request, callback);
1293
1294 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1295 mCm.registerDefaultNetworkCallback(defaultCallback);
1296
1297 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1298 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1299 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
1300
1301 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1302 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1303 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1304
1305 mCellNetworkAgent.connect(true);
1306 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1307 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1308 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1309
1310 mWiFiNetworkAgent.connect(true);
1311 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1312 // We then get LOSING when wifi validates and cell is outscored.
1313 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1314 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1315 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1316 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1317
1318 mEthernetNetworkAgent.connect(true);
1319 callback.expectCallback(CallbackState.AVAILABLE, mEthernetNetworkAgent);
1320 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
1321 defaultCallback.expectCallback(CallbackState.AVAILABLE, mEthernetNetworkAgent);
1322 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1323
1324 mEthernetNetworkAgent.disconnect();
1325 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1326 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1327 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1328
1329 for (int i = 0; i < 4; i++) {
1330 MockNetworkAgent oldNetwork, newNetwork;
1331 if (i % 2 == 0) {
1332 mWiFiNetworkAgent.adjustScore(-15);
1333 oldNetwork = mWiFiNetworkAgent;
1334 newNetwork = mCellNetworkAgent;
1335 } else {
1336 mWiFiNetworkAgent.adjustScore(15);
1337 oldNetwork = mCellNetworkAgent;
1338 newNetwork = mWiFiNetworkAgent;
1339
1340 }
1341 callback.expectCallback(CallbackState.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001342 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1343 // longer lingering?
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001344 defaultCallback.expectCallback(CallbackState.AVAILABLE, newNetwork);
1345 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
1346 }
1347 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1348
1349 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
1350 // if the network is still up.
1351 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
1352 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1353
1354 // Wifi no longer satisfies our listen, which is for an unmetered network.
1355 // But because its score is 55, it's still up (and the default network).
1356 defaultCallback.assertNoCallback();
1357 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1358
1359 // Disconnect our test networks.
1360 mWiFiNetworkAgent.disconnect();
1361 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1362 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1363 mCellNetworkAgent.disconnect();
1364 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1365
1366 mCm.unregisterNetworkCallback(callback);
1367 mService.waitForIdle();
1368
1369 // Check that a network is only lingered or torn down if it would not satisfy a request even
1370 // if it validated.
1371 request = new NetworkRequest.Builder().clearCapabilities().build();
1372 callback = new TestNetworkCallback();
1373
1374 mCm.registerNetworkCallback(request, callback);
1375
1376 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1377 mCellNetworkAgent.connect(false); // Score: 10
1378 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1379 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1380 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1381
1382 // Bring up wifi with a score of 20.
1383 // Cell stays up because it would satisfy the default request if it validated.
1384 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1385 mWiFiNetworkAgent.connect(false); // Score: 20
1386 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1387 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1388 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1389
1390 mWiFiNetworkAgent.disconnect();
1391 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1392 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1393 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1394 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1395
1396 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001397 // Cell is lingered because it would not satisfy any request, even if it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001398 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1399 mWiFiNetworkAgent.adjustScore(50);
1400 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001401 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001402 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001403 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1404 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1405
1406 // Tear down wifi.
1407 mWiFiNetworkAgent.disconnect();
1408 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1409 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1410 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1411 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1412
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001413 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
1414 // it's arguably correct to linger it, since it was the default network before it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001415 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1416 mWiFiNetworkAgent.connect(true);
1417 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001418 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001419 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1420 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1421
1422 mWiFiNetworkAgent.disconnect();
1423 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001424 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001425 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1426 mCellNetworkAgent.disconnect();
1427 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1428 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001429
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001430 // If a network is lingering, and we add and remove a request from it, resume lingering.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001431 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1432 mCellNetworkAgent.connect(true);
1433 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1434 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1435 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1436 mWiFiNetworkAgent.connect(true);
1437 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1438 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1439 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1440
1441 NetworkRequest cellRequest = new NetworkRequest.Builder()
1442 .addTransportType(TRANSPORT_CELLULAR).build();
1443 NetworkCallback noopCallback = new NetworkCallback();
1444 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001445 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
1446 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001447 mCm.unregisterNetworkCallback(noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001448 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001449
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001450 // Similar to the above: lingering can start even after the lingered request is removed.
1451 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001452 mWiFiNetworkAgent.disconnect();
1453 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001454 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1455 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1456
1457 // Cell is now the default network. Pin it with a cell-specific request.
1458 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
1459 mCm.requestNetwork(cellRequest, noopCallback);
1460
1461 // Now connect wifi, and expect it to become the default network.
1462 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1463 mWiFiNetworkAgent.connect(true);
1464 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1465 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1466 // The default request is lingering on cell, but nothing happens to cell, and we send no
1467 // callbacks for it, because it's kept up by cellRequest.
1468 callback.assertNoCallback();
1469 // Now unregister cellRequest and expect cell to start lingering.
1470 mCm.unregisterNetworkCallback(noopCallback);
1471 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1472
1473 // Let linger run its course.
1474 callback.assertNoCallback();
1475 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent,
1476 TEST_LINGER_DELAY_MS /* timeoutMs */);
1477
1478 // Clean up.
1479 mWiFiNetworkAgent.disconnect();
1480 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1481 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001482
1483 mCm.unregisterNetworkCallback(callback);
1484 mCm.unregisterNetworkCallback(defaultCallback);
1485 }
1486
Paul Jensen85cf78e2015-06-25 13:25:07 -04001487 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04001488 // Verify NOT_RESTRICTED is set appropriately
1489 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
1490 .build().networkCapabilities;
1491 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
1492 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
1493 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04001494 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04001495 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1496 } else {
1497 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1498 }
1499
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001500 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001501 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001502 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
1503 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04001504 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001505 mServiceContext, "testFactory", filter);
1506 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04001507 ConditionVariable cv = testFactory.getNetworkStartedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001508 testFactory.expectAddRequests(1);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001509 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001510 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001511 int expectedRequestCount = 1;
1512 NetworkCallback networkCallback = null;
1513 // For non-INTERNET capabilities we cannot rely on the default request being present, so
1514 // add one.
1515 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04001516 assertFalse(testFactory.getMyStartRequested());
1517 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
1518 networkCallback = new NetworkCallback();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001519 testFactory.expectAddRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001520 mCm.requestNetwork(request, networkCallback);
1521 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001522 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001523 }
Paul Jensen3d911462015-06-12 06:40:24 -04001524 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001525 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1526 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001527
Paul Jensen85cf78e2015-06-25 13:25:07 -04001528 // Now bring in a higher scored network.
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001529 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001530 // Rather than create a validated network which complicates things by registering it's
1531 // own NetworkRequest during startup, just bump up the score to cancel out the
1532 // unvalidated penalty.
1533 testAgent.adjustScore(40);
1534 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001535
1536 // When testAgent connects, ConnectivityService will re-send us all current requests with
1537 // the new score. There are expectedRequestCount such requests, and we must wait for all of
1538 // them.
1539 testFactory.expectAddRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001540 testAgent.connect(false);
1541 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04001542 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001543 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001544 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001545
Paul Jensen85cf78e2015-06-25 13:25:07 -04001546 // Bring in a bunch of requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001547 testFactory.expectAddRequests(10);
1548 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001549 ConnectivityManager.NetworkCallback[] networkCallbacks =
1550 new ConnectivityManager.NetworkCallback[10];
1551 for (int i = 0; i< networkCallbacks.length; i++) {
1552 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
1553 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001554 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001555 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
1556 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04001557 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
1558 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001559
Paul Jensen85cf78e2015-06-25 13:25:07 -04001560 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001561 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001562 for (int i = 0; i < networkCallbacks.length; i++) {
1563 mCm.unregisterNetworkCallback(networkCallbacks[i]);
1564 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04001565 testFactory.waitForNetworkRequests(expectedRequestCount);
1566 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001567
Paul Jensen85cf78e2015-06-25 13:25:07 -04001568 // Drop the higher scored network.
1569 cv = testFactory.getNetworkStartedCV();
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001570 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001571 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001572 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1573 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001574
1575 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001576 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001577 handlerThread.quit();
1578 }
1579
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001580 @SmallTest
Paul Jensen85cf78e2015-06-25 13:25:07 -04001581 public void testNetworkFactoryRequests() throws Exception {
1582 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
1583 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
1584 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
1585 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
1586 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
1587 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
1588 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
1589 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
1590 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
1591 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
1592 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
1593 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
1594 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
1595 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
1596 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
1597 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
1598 }
1599
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001600 @SmallTest
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001601 public void testNoMutableNetworkRequests() throws Exception {
1602 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
1603 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001604 builder.addCapability(NET_CAPABILITY_VALIDATED);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001605 try {
1606 mCm.requestNetwork(builder.build(), new NetworkCallback());
1607 fail();
1608 } catch (IllegalArgumentException expected) {}
1609 try {
1610 mCm.requestNetwork(builder.build(), pendingIntent);
1611 fail();
1612 } catch (IllegalArgumentException expected) {}
1613 builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001614 builder.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001615 try {
1616 mCm.requestNetwork(builder.build(), new NetworkCallback());
1617 fail();
1618 } catch (IllegalArgumentException expected) {}
1619 try {
1620 mCm.requestNetwork(builder.build(), pendingIntent);
1621 fail();
1622 } catch (IllegalArgumentException expected) {}
1623 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001624
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001625 @SmallTest
Paul Jensene0988542015-06-25 15:30:08 -04001626 public void testMMSonWiFi() throws Exception {
1627 // Test bringing up cellular without MMS NetworkRequest gets reaped
1628 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1629 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1630 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
1631 mCellNetworkAgent.connectWithoutInternet();
1632 waitFor(cv);
1633 waitFor(new Criteria() {
1634 public boolean get() { return mCm.getAllNetworks().length == 0; } });
1635 verifyNoNetwork();
1636 // Test bringing up validated WiFi.
1637 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1638 cv = waitForConnectivityBroadcasts(1);
1639 mWiFiNetworkAgent.connect(true);
1640 waitFor(cv);
1641 verifyActiveNetwork(TRANSPORT_WIFI);
1642 // Register MMS NetworkRequest
1643 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1644 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1645 final TestNetworkCallback networkCallback = new TestNetworkCallback();
1646 mCm.requestNetwork(builder.build(), networkCallback);
1647 // Test bringing up unvalidated cellular with MMS
1648 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1649 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04001650 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001651 networkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04001652 verifyActiveNetwork(TRANSPORT_WIFI);
1653 // Test releasing NetworkRequest disconnects cellular with MMS
1654 cv = mCellNetworkAgent.getDisconnectedCV();
1655 mCm.unregisterNetworkCallback(networkCallback);
1656 waitFor(cv);
1657 verifyActiveNetwork(TRANSPORT_WIFI);
1658 }
1659
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001660 @SmallTest
Paul Jensene0988542015-06-25 15:30:08 -04001661 public void testMMSonCell() throws Exception {
1662 // Test bringing up cellular without MMS
1663 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1664 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1665 mCellNetworkAgent.connect(false);
1666 waitFor(cv);
1667 verifyActiveNetwork(TRANSPORT_CELLULAR);
1668 // Register MMS NetworkRequest
1669 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1670 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1671 final TestNetworkCallback networkCallback = new TestNetworkCallback();
1672 mCm.requestNetwork(builder.build(), networkCallback);
1673 // Test bringing up MMS cellular network
Paul Jensene0988542015-06-25 15:30:08 -04001674 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1675 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1676 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001677 networkCallback.expectCallback(CallbackState.AVAILABLE, mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04001678 verifyActiveNetwork(TRANSPORT_CELLULAR);
1679 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
1680 cv = mmsNetworkAgent.getDisconnectedCV();
1681 mCm.unregisterNetworkCallback(networkCallback);
1682 waitFor(cv);
1683 verifyActiveNetwork(TRANSPORT_CELLULAR);
1684 }
1685
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001686 @SmallTest
Paul Jensencf4c2c62015-07-01 14:16:32 -04001687 public void testCaptivePortal() {
1688 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1689 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1690 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1691 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1692
1693 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1694 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1695 .addCapability(NET_CAPABILITY_VALIDATED).build();
1696 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001697
1698 // Bring up a network with a captive portal.
1699 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001700 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04001701 String firstRedirectUrl = "http://example.com/firstPath";
1702 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001703 captivePortalCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04001704 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001705
1706 // Take down network.
1707 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001708 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001709 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001710
1711 // Bring up a network with a captive portal.
1712 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001713 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04001714 String secondRedirectUrl = "http://example.com/secondPath";
1715 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001716 captivePortalCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04001717 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001718
1719 // Make captive portal disappear then revalidate.
1720 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001721 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
1722 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001723 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001724
1725 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001726 validatedCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001727
1728 // Break network connectivity.
1729 // Expect NET_CAPABILITY_VALIDATED onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001730 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
1731 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001732 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001733 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09001734
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001735 @SmallTest
Calvin On1f64f3f2016-10-11 15:10:46 -07001736 public void testAvoidOrIgnoreCaptivePortals() {
1737 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1738 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1739 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1740 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1741
1742 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1743 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1744 .addCapability(NET_CAPABILITY_VALIDATED).build();
1745 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
1746
1747 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
1748 // Bring up a network with a captive portal.
1749 // Expect it to fail to connect and not result in any callbacks.
1750 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1751 String firstRedirectUrl = "http://example.com/firstPath";
1752
1753 ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
1754 ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
1755 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
1756 waitFor(disconnectCv);
1757 waitFor(avoidCv);
1758
1759 assertNoCallbacks(captivePortalCallback, validatedCallback);
1760
1761 // Now test ignore mode.
1762 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE);
1763
1764 // Bring up a network with a captive portal.
1765 // Since we're ignoring captive portals, the network will validate.
1766 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1767 String secondRedirectUrl = "http://example.com/secondPath";
1768 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
1769
1770 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
1771 validatedCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1772 // But there should be no CaptivePortal callback.
1773 captivePortalCallback.assertNoCallback();
1774 }
1775
Etan Cohenddb9ef02015-11-18 10:56:15 -08001776 @SmallTest
1777 public void testInvalidNetworkSpecifier() {
1778 boolean execptionCalled = true;
1779
1780 try {
1781 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1782 builder.setNetworkSpecifier(MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
1783 execptionCalled = false;
1784 } catch (IllegalArgumentException e) {
1785 // do nothing - should get here
1786 }
1787
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001788 assertTrue("NetworkRequest builder with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
Etan Cohenddb9ef02015-11-18 10:56:15 -08001789 execptionCalled);
1790
1791 try {
1792 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
1793 networkCapabilities.addTransportType(TRANSPORT_WIFI)
1794 .setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
1795 mService.requestNetwork(networkCapabilities, null, 0, null,
1796 ConnectivityManager.TYPE_WIFI);
1797 execptionCalled = false;
1798 } catch (IllegalArgumentException e) {
1799 // do nothing - should get here
1800 }
1801
1802 assertTrue("ConnectivityService requestNetwork with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
1803 execptionCalled);
1804 }
1805
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001806 @SmallTest
Erik Klinea2d29402016-03-16 15:31:39 +09001807 public void testRegisterDefaultNetworkCallback() throws Exception {
1808 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
1809 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
1810 defaultNetworkCallback.assertNoCallback();
1811
1812 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
1813 // whenever Wi-Fi is up. Without this, the mobile network agent is
1814 // reaped before any other activity can take place.
1815 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
1816 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1817 .addTransportType(TRANSPORT_CELLULAR).build();
1818 mCm.requestNetwork(cellRequest, cellNetworkCallback);
1819 cellNetworkCallback.assertNoCallback();
1820
1821 // Bring up cell and expect CALLBACK_AVAILABLE.
1822 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1823 mCellNetworkAgent.connect(true);
1824 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1825 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1826
1827 // Bring up wifi and expect CALLBACK_AVAILABLE.
1828 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1829 mWiFiNetworkAgent.connect(true);
1830 cellNetworkCallback.assertNoCallback();
1831 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1832
1833 // Bring down cell. Expect no default network callback, since it wasn't the default.
1834 mCellNetworkAgent.disconnect();
1835 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1836 defaultNetworkCallback.assertNoCallback();
1837
1838 // Bring up cell. Expect no default network callback, since it won't be the default.
1839 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1840 mCellNetworkAgent.connect(true);
1841 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1842 defaultNetworkCallback.assertNoCallback();
1843
1844 // Bring down wifi. Expect the default network callback to notified of LOST wifi
1845 // followed by AVAILABLE cell.
1846 mWiFiNetworkAgent.disconnect();
1847 cellNetworkCallback.assertNoCallback();
1848 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1849 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1850 mCellNetworkAgent.disconnect();
1851 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1852 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1853 }
1854
Erik Klineacdd6392016-07-07 16:50:58 +09001855 private class TestRequestUpdateCallback extends TestNetworkCallback {
1856 @Override
1857 public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
1858 setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
1859 }
1860
1861 @Override
1862 public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
1863 setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
1864 }
1865 }
1866
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001867 @SmallTest
Erik Klineacdd6392016-07-07 16:50:58 +09001868 public void testRequestCallbackUpdates() throws Exception {
1869 // File a network request for mobile.
1870 final TestNetworkCallback cellNetworkCallback = new TestRequestUpdateCallback();
1871 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1872 .addTransportType(TRANSPORT_CELLULAR).build();
1873 mCm.requestNetwork(cellRequest, cellNetworkCallback);
1874
1875 // Bring up the mobile network.
1876 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1877 mCellNetworkAgent.connect(true);
1878
1879 // We should get onAvailable().
1880 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1881 // We should get onCapabilitiesChanged(), when the mobile network successfully validates.
1882 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
1883 cellNetworkCallback.assertNoCallback();
1884
1885 // Update LinkProperties.
1886 final LinkProperties lp = new LinkProperties();
1887 lp.setInterfaceName("foonet_data0");
1888 mCellNetworkAgent.sendLinkProperties(lp);
1889 // We should get onLinkPropertiesChanged().
1890 cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
1891 cellNetworkCallback.assertNoCallback();
1892
1893 // Register a garden variety default network request.
1894 final TestNetworkCallback dfltNetworkCallback = new TestRequestUpdateCallback();
1895 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
1896 // Only onAvailable() is called; no other information is delivered.
1897 dfltNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1898 dfltNetworkCallback.assertNoCallback();
1899
1900 // Request a NetworkCapabilities update; only the requesting callback is notified.
1901 mCm.requestNetworkCapabilities(dfltNetworkCallback);
1902 dfltNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
1903 cellNetworkCallback.assertNoCallback();
1904 dfltNetworkCallback.assertNoCallback();
1905
1906 // Request a LinkProperties update; only the requesting callback is notified.
1907 mCm.requestLinkProperties(dfltNetworkCallback);
1908 dfltNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
1909 cellNetworkCallback.assertNoCallback();
1910 dfltNetworkCallback.assertNoCallback();
1911
1912 mCm.unregisterNetworkCallback(dfltNetworkCallback);
1913 mCm.unregisterNetworkCallback(cellNetworkCallback);
1914 }
1915
Calvin On1f64f3f2016-10-11 15:10:46 -07001916 private void setCaptivePortalMode(int mode) {
1917 ContentResolver cr = mServiceContext.getContentResolver();
1918 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
1919 }
1920
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09001921 private void setMobileDataAlwaysOn(boolean enable) {
1922 ContentResolver cr = mServiceContext.getContentResolver();
1923 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
1924 mService.updateMobileDataAlwaysOn();
1925 mService.waitForIdle();
1926 }
1927
1928 private boolean isForegroundNetwork(MockNetworkAgent network) {
1929 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
1930 assertNotNull(nc);
1931 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
1932 }
1933
1934 @SmallTest
1935 public void testBackgroundNetworks() throws Exception {
1936 // Create a background request. We can't do this ourselves because ConnectivityService
1937 // doesn't have an API for it. So just turn on mobile data always on.
1938 setMobileDataAlwaysOn(true);
1939 final NetworkRequest request = new NetworkRequest.Builder().build();
1940 final NetworkRequest fgRequest = new NetworkRequest.Builder()
1941 .addCapability(NET_CAPABILITY_FOREGROUND).build();
1942 final TestNetworkCallback callback = new TestNetworkCallback();
1943 final TestNetworkCallback fgCallback = new TestNetworkCallback();
1944 mCm.registerNetworkCallback(request, callback);
1945 mCm.registerNetworkCallback(fgRequest, fgCallback);
1946
1947 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1948 mCellNetworkAgent.connect(true);
1949 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1950 fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1951 assertTrue(isForegroundNetwork(mCellNetworkAgent));
1952
1953 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1954 mWiFiNetworkAgent.connect(true);
1955
1956 // When wifi connects, cell lingers.
1957 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1958 fgCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1959 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1960 fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1961 assertTrue(isForegroundNetwork(mCellNetworkAgent));
1962 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1963
1964 // When lingering is complete, cell is still there but is now in the background.
1965 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, TEST_LINGER_DELAY_MS);
1966 callback.assertNoCallback();
1967 assertFalse(isForegroundNetwork(mCellNetworkAgent));
1968 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1969
1970 // File a cell request and check that cell comes into the foreground.
1971 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1972 .addTransportType(TRANSPORT_CELLULAR).build();
1973 final TestNetworkCallback cellCallback = new TestNetworkCallback();
1974 mCm.requestNetwork(cellRequest, cellCallback);
1975 cellCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1976 fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1977 callback.assertNoCallback(); // Because the network is already up.
1978 assertTrue(isForegroundNetwork(mCellNetworkAgent));
1979 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1980
1981 // Release the request. The network immediately goes into the background, since it was not
1982 // lingering.
1983 mCm.unregisterNetworkCallback(cellCallback);
1984 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1985 callback.assertNoCallback();
1986 assertFalse(isForegroundNetwork(mCellNetworkAgent));
1987 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1988
1989 // Disconnect wifi and check that cell is foreground again.
1990 mWiFiNetworkAgent.disconnect();
1991 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1992 fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1993 fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1994 assertTrue(isForegroundNetwork(mCellNetworkAgent));
1995
1996 mCm.unregisterNetworkCallback(callback);
1997 mCm.unregisterNetworkCallback(fgCallback);
1998 }
1999
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002000 @SmallTest
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002001 public void testRequestBenchmark() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002002 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002003 // Benchmarks connecting and switching performance in the presence of a large number of
2004 // NetworkRequests.
2005 // 1. File NUM_REQUESTS requests.
2006 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
2007 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
2008 // and NUM_REQUESTS onAvailable callbacks to fire.
2009 // See how long it took.
2010 final int NUM_REQUESTS = 90;
2011 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
2012 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
2013 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
2014 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
2015
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002016 for (int i = 0; i < NUM_REQUESTS; i++) {
2017 callbacks[i] = new NetworkCallback() {
2018 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
2019 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
2020 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002021 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002022
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002023 final int REGISTER_TIME_LIMIT_MS = 180;
2024 assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
2025 for (NetworkCallback cb : callbacks) {
2026 mCm.registerNetworkCallback(request, cb);
2027 }
2028 });
2029
2030 final int CONNECT_TIME_LIMIT_MS = 40;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002031 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2032 // Don't request that the network validate, because otherwise connect() will block until
2033 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
2034 // and we won't actually measure anything.
2035 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002036
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002037 long onAvailableDispatchingDuration = durationOf(() -> {
2038 if (!awaitLatch(availableLatch, CONNECT_TIME_LIMIT_MS)) {
2039 fail(String.format("Only dispatched %d/%d onAvailable callbacks in %dms",
2040 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
2041 CONNECT_TIME_LIMIT_MS));
2042 }
2043 });
2044 Log.d(TAG, String.format("Connect, %d callbacks: %dms, acceptable %dms",
2045 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS));
2046
2047 final int SWITCH_TIME_LIMIT_MS = 40;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002048 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2049 // Give wifi a high enough score that we'll linger cell when wifi comes up.
2050 mWiFiNetworkAgent.adjustScore(40);
2051 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002052
2053 long onLostDispatchingDuration = durationOf(() -> {
2054 if (!awaitLatch(losingLatch, SWITCH_TIME_LIMIT_MS)) {
2055 fail(String.format("Only dispatched %d/%d onLosing callbacks in %dms",
2056 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, SWITCH_TIME_LIMIT_MS));
2057 }
2058 });
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002059 Log.d(TAG, String.format("Linger, %d callbacks: %dms, acceptable %dms",
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002060 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS));
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002061
2062 final int UNREGISTER_TIME_LIMIT_MS = 10;
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002063 assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
2064 for (NetworkCallback cb : callbacks) {
2065 mCm.unregisterNetworkCallback(cb);
2066 }
2067 });
2068 }
2069
2070 private long durationOf(Runnable fn) {
2071 long startTime = SystemClock.elapsedRealtime();
2072 fn.run();
2073 return SystemClock.elapsedRealtime() - startTime;
2074 }
2075
2076 private void assertTimeLimit(String descr, long timeLimit, Runnable fn) {
2077 long timeTaken = durationOf(fn);
2078 String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002079 Log.d(TAG, msg);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002080 assertTrue(msg, timeTaken <= timeLimit);
2081 }
2082
2083 private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
2084 try {
2085 if (l.await(timeoutMs, TimeUnit.MILLISECONDS)) {
2086 return true;
2087 }
2088 } catch (InterruptedException e) {}
2089 return false;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002090 }
2091
2092 @SmallTest
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002093 public void testMobileDataAlwaysOn() throws Exception {
2094 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2095 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2096 .addTransportType(TRANSPORT_CELLULAR).build();
2097 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
2098
2099 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
2100 handlerThread.start();
2101 NetworkCapabilities filter = new NetworkCapabilities()
2102 .addTransportType(TRANSPORT_CELLULAR)
2103 .addCapability(NET_CAPABILITY_INTERNET);
2104 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
2105 mServiceContext, "testFactory", filter);
2106 testFactory.setScoreFilter(40);
2107
2108 // Register the factory and expect it to start looking for a network.
2109 testFactory.expectAddRequests(1);
2110 testFactory.register();
2111 testFactory.waitForNetworkRequests(1);
2112 assertTrue(testFactory.getMyStartRequested());
2113
2114 // Bring up wifi. The factory stops looking for a network.
2115 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2116 testFactory.expectAddRequests(2); // Because the default request changes score twice.
2117 mWiFiNetworkAgent.connect(true);
2118 testFactory.waitForNetworkRequests(1);
2119 assertFalse(testFactory.getMyStartRequested());
2120
2121 ContentResolver cr = mServiceContext.getContentResolver();
2122
2123 // Turn on mobile data always on. The factory starts looking again.
2124 testFactory.expectAddRequests(1);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002125 setMobileDataAlwaysOn(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002126 testFactory.waitForNetworkRequests(2);
2127 assertTrue(testFactory.getMyStartRequested());
2128
2129 // Bring up cell data and check that the factory stops looking.
2130 assertEquals(1, mCm.getAllNetworks().length);
2131 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2132 testFactory.expectAddRequests(2); // Because the cell request changes score twice.
2133 mCellNetworkAgent.connect(true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002134 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002135 testFactory.waitForNetworkRequests(2);
2136 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
2137
2138 // Check that cell data stays up.
2139 mService.waitForIdle();
2140 verifyActiveNetwork(TRANSPORT_WIFI);
2141 assertEquals(2, mCm.getAllNetworks().length);
2142
2143 // Turn off mobile data always on and expect the request to disappear...
2144 testFactory.expectRemoveRequests(1);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002145 setMobileDataAlwaysOn(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002146 testFactory.waitForNetworkRequests(1);
2147
2148 // ... and cell data to be torn down.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002149 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002150 assertEquals(1, mCm.getAllNetworks().length);
2151
2152 testFactory.unregister();
2153 mCm.unregisterNetworkCallback(cellNetworkCallback);
2154 handlerThread.quit();
2155 }
2156
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002157 @SmallTest
2158 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002159 final ContentResolver cr = mServiceContext.getContentResolver();
Erik Kline065ab6e2016-10-02 18:02:14 +09002160 final WrappedAvoidBadWifiTracker tracker = mService.getAvoidBadWifiTracker();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002161 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
2162
Erik Kline065ab6e2016-10-02 18:02:14 +09002163 tracker.configRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002164 String[] values = new String[] {null, "0", "1"};
2165 for (int i = 0; i < values.length; i++) {
2166 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002167 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002168 mService.waitForIdle();
2169 String msg = String.format("config=false, setting=%s", values[i]);
Hugo Benichi53d83d52016-11-15 13:42:34 +09002170 assertEventuallyTrue(() -> mService.avoidBadWifi(), 50);
Erik Kline065ab6e2016-10-02 18:02:14 +09002171 assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002172 }
2173
Erik Kline065ab6e2016-10-02 18:02:14 +09002174 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002175
2176 Settings.Global.putInt(cr, settingName, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09002177 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002178 mService.waitForIdle();
Hugo Benichi53d83d52016-11-15 13:42:34 +09002179 assertEventuallyTrue(() -> !mService.avoidBadWifi(), 50);
Erik Kline065ab6e2016-10-02 18:02:14 +09002180 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002181
2182 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002183 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002184 mService.waitForIdle();
Hugo Benichi53d83d52016-11-15 13:42:34 +09002185 assertEventuallyTrue(() -> mService.avoidBadWifi(), 50);
Erik Kline065ab6e2016-10-02 18:02:14 +09002186 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002187
2188 Settings.Global.putString(cr, settingName, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09002189 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002190 mService.waitForIdle();
Hugo Benichi53d83d52016-11-15 13:42:34 +09002191 assertEventuallyTrue(() -> !mService.avoidBadWifi(), 50);
Erik Kline065ab6e2016-10-02 18:02:14 +09002192 assertTrue(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002193 }
2194
2195 @SmallTest
2196 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09002197 final ContentResolver cr = mServiceContext.getContentResolver();
2198 final WrappedAvoidBadWifiTracker tracker = mService.getAvoidBadWifiTracker();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002199
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002200 // Pretend we're on a carrier that restricts switching away from bad wifi.
Erik Kline065ab6e2016-10-02 18:02:14 +09002201 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002202
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002203 // File a request for cell to ensure it doesn't go down.
2204 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2205 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2206 .addTransportType(TRANSPORT_CELLULAR).build();
2207 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2208
2209 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2210 mCm.registerDefaultNetworkCallback(defaultCallback);
2211
2212 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
2213 .addTransportType(TRANSPORT_WIFI)
2214 .addCapability(NET_CAPABILITY_VALIDATED)
2215 .build();
2216 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
2217 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
2218
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002219 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09002220 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002221
2222 // Bring up validated cell.
2223 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2224 mCellNetworkAgent.connect(true);
2225 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2226 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2227 Network cellNetwork = mCellNetworkAgent.getNetwork();
2228
2229 // Bring up validated wifi.
2230 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2231 mWiFiNetworkAgent.connect(true);
2232 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2233 validatedWifiCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2234 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2235
2236 // Fail validation on wifi.
2237 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
2238 mCm.reportNetworkConnectivity(wifiNetwork, false);
2239 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2240
2241 // Because avoid bad wifi is off, we don't switch to cellular.
2242 defaultCallback.assertNoCallback();
2243 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2244 NET_CAPABILITY_VALIDATED));
2245 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2246 NET_CAPABILITY_VALIDATED));
2247 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2248
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002249 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
2250 // that we switch back to cell.
Erik Kline065ab6e2016-10-02 18:02:14 +09002251 tracker.configRestrictsAvoidBadWifi = false;
2252 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002253 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2254 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2255
2256 // Switch back to a restrictive carrier.
Erik Kline065ab6e2016-10-02 18:02:14 +09002257 tracker.configRestrictsAvoidBadWifi = true;
2258 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002259 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2260 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2261
2262 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
2263 mCm.setAvoidUnvalidated(wifiNetwork);
2264 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2265 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2266 NET_CAPABILITY_VALIDATED));
2267 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2268 NET_CAPABILITY_VALIDATED));
2269 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2270
2271 // Disconnect and reconnect wifi to clear the one-time switch above.
2272 mWiFiNetworkAgent.disconnect();
2273 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2274 mWiFiNetworkAgent.connect(true);
2275 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2276 validatedWifiCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2277 wifiNetwork = mWiFiNetworkAgent.getNetwork();
2278
2279 // Fail validation on wifi and expect the dialog to appear.
2280 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
2281 mCm.reportNetworkConnectivity(wifiNetwork, false);
2282 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2283
2284 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002285 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002286 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002287
2288 // We now switch to cell.
2289 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2290 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2291 NET_CAPABILITY_VALIDATED));
2292 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2293 NET_CAPABILITY_VALIDATED));
2294 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2295
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002296 // Simulate the user turning the cellular fallback setting off and then on.
2297 // We switch to wifi and then to cell.
2298 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09002299 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002300 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2301 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2302 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002303 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002304 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2305 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2306
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002307 // If cell goes down, we switch to wifi.
2308 mCellNetworkAgent.disconnect();
2309 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2310 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2311 validatedWifiCallback.assertNoCallback();
2312
2313 mCm.unregisterNetworkCallback(cellNetworkCallback);
2314 mCm.unregisterNetworkCallback(validatedWifiCallback);
2315 mCm.unregisterNetworkCallback(defaultCallback);
2316 }
2317
Erik Kline3841a482015-11-25 12:49:38 +09002318 /**
2319 * Validate that a satisfied network request does not trigger onUnavailable() once the
2320 * time-out period expires.
2321 */
2322 @SmallTest
2323 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
2324 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2325 NetworkCapabilities.TRANSPORT_WIFI).build();
2326 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2327 mCm.requestNetwork(nr, networkCallback, 10);
2328
2329 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2330 mWiFiNetworkAgent.connect(false);
2331 networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2332
2333 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07002334 sleepFor(15);
2335 networkCallback.assertNoCallback();
2336 }
2337
2338 /**
2339 * Validate that a satisfied network request followed by a disconnected (lost) network does
2340 * not trigger onUnavailable() once the time-out period expires.
2341 */
2342 @SmallTest
2343 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
2344 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2345 NetworkCapabilities.TRANSPORT_WIFI).build();
2346 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2347 mCm.requestNetwork(nr, networkCallback, 500);
2348
2349 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2350 mWiFiNetworkAgent.connect(false);
2351 networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2352 sleepFor(20);
2353 mWiFiNetworkAgent.disconnect();
2354 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2355
2356 // pass timeout and validate that UNAVAILABLE is not called
2357 sleepFor(600);
Erik Kline3841a482015-11-25 12:49:38 +09002358 networkCallback.assertNoCallback();
2359 }
2360
2361 /**
2362 * Validate that when a time-out is specified for a network request the onUnavailable()
2363 * callback is called when time-out expires. Then validate that if network request is
2364 * (somehow) satisfied - the callback isn't called later.
2365 */
2366 @SmallTest
2367 public void testTimedoutNetworkRequest() {
2368 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2369 NetworkCapabilities.TRANSPORT_WIFI).build();
2370 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2371 mCm.requestNetwork(nr, networkCallback, 10);
2372
2373 // pass timeout and validate that UNAVAILABLE is called
2374 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
2375
2376 // create a network satisfying request - validate that request not triggered
2377 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2378 mWiFiNetworkAgent.connect(false);
2379 networkCallback.assertNoCallback();
2380 }
2381
2382 /**
2383 * Validate that when a network request is unregistered (cancelled) the time-out for that
2384 * request doesn't trigger the onUnavailable() callback.
2385 */
2386 @SmallTest
2387 public void testTimedoutAfterUnregisteredNetworkRequest() {
2388 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2389 NetworkCapabilities.TRANSPORT_WIFI).build();
2390 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2391 mCm.requestNetwork(nr, networkCallback, 10);
2392
2393 // remove request
2394 mCm.unregisterNetworkCallback(networkCallback);
2395
2396 // pass timeout and validate that no callbacks
2397 // Note: doesn't validate that nothing called from CS since even if called the CM already
2398 // unregisters the callback and won't pass it through!
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07002399 sleepFor(15);
Erik Kline3841a482015-11-25 12:49:38 +09002400 networkCallback.assertNoCallback();
2401
2402 // create a network satisfying request - validate that request not triggered
2403 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2404 mWiFiNetworkAgent.connect(false);
2405 networkCallback.assertNoCallback();
2406 }
2407
Hugo Benichi53d83d52016-11-15 13:42:34 +09002408 public void assertEventuallyTrue(BooleanSupplier fn, long maxWaitingTimeMs) throws Exception {
2409 long start = SystemClock.elapsedRealtime();
2410 while (SystemClock.elapsedRealtime() <= start + maxWaitingTimeMs) {
2411 if (fn.getAsBoolean()) {
2412 return;
2413 }
2414 Thread.sleep(10);
2415 }
2416 assertTrue(fn.getAsBoolean());
2417 }
2418
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002419 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
2420
2421 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
2422
2423 private class CallbackValue {
2424 public CallbackType callbackType;
2425 public int error;
2426
2427 public CallbackValue(CallbackType type) {
2428 this.callbackType = type;
2429 this.error = PacketKeepalive.SUCCESS;
2430 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
2431 }
2432
2433 public CallbackValue(CallbackType type, int error) {
2434 this.callbackType = type;
2435 this.error = error;
2436 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
2437 }
2438
2439 @Override
2440 public boolean equals(Object o) {
2441 return o instanceof CallbackValue &&
2442 this.callbackType == ((CallbackValue) o).callbackType &&
2443 this.error == ((CallbackValue) o).error;
2444 }
2445
2446 @Override
2447 public String toString() {
2448 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
2449 }
2450 }
2451
2452 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
2453
2454 @Override
2455 public void onStarted() {
2456 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
2457 }
2458
2459 @Override
2460 public void onStopped() {
2461 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
2462 }
2463
2464 @Override
2465 public void onError(int error) {
2466 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
2467 }
2468
2469 private void expectCallback(CallbackValue callbackValue) {
2470 try {
2471 assertEquals(
2472 callbackValue,
2473 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
2474 } catch (InterruptedException e) {
2475 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
2476 }
2477 }
2478
2479 public void expectStarted() {
2480 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
2481 }
2482
2483 public void expectStopped() {
2484 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
2485 }
2486
2487 public void expectError(int error) {
2488 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
2489 }
2490 }
2491
2492 private Network connectKeepaliveNetwork(LinkProperties lp) {
2493 // Ensure the network is disconnected before we do anything.
2494 if (mWiFiNetworkAgent != null) {
2495 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
2496 }
2497
2498 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2499 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2500 mWiFiNetworkAgent.connect(true);
2501 waitFor(cv);
2502 verifyActiveNetwork(TRANSPORT_WIFI);
2503 mWiFiNetworkAgent.sendLinkProperties(lp);
2504 mService.waitForIdle();
2505 return mWiFiNetworkAgent.getNetwork();
2506 }
2507
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09002508 @SmallTest
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002509 public void testPacketKeepalives() throws Exception {
2510 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
2511 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
2512 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
2513 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
2514 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
2515
2516 LinkProperties lp = new LinkProperties();
2517 lp.setInterfaceName("wlan12");
2518 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
2519 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
2520 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
2521 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
2522
2523 Network notMyNet = new Network(61234);
2524 Network myNet = connectKeepaliveNetwork(lp);
2525
2526 TestKeepaliveCallback callback = new TestKeepaliveCallback();
2527 PacketKeepalive ka;
2528
2529 // Attempt to start keepalives with invalid parameters and check for errors.
2530 ka = mCm.startNattKeepalive(notMyNet, 25, callback, myIPv4, 1234, dstIPv4);
2531 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
2532
2533 ka = mCm.startNattKeepalive(myNet, 19, callback, notMyIPv4, 1234, dstIPv4);
2534 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
2535
2536 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 1234, dstIPv6);
2537 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2538
2539 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv4);
2540 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2541
2542 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv6);
2543 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); // NAT-T is IPv4-only.
2544
2545 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
2546 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
2547
2548 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
2549 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
2550
2551 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2552 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
2553
2554 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2555 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
2556
2557 // Check that a started keepalive can be stopped.
2558 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2559 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2560 callback.expectStarted();
2561 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
2562 ka.stop();
2563 callback.expectStopped();
2564
2565 // Check that deleting the IP address stops the keepalive.
2566 LinkProperties bogusLp = new LinkProperties(lp);
2567 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2568 callback.expectStarted();
2569 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
2570 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
2571 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
2572 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2573 mWiFiNetworkAgent.sendLinkProperties(lp);
2574
2575 // Check that a started keepalive is stopped correctly when the network disconnects.
2576 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2577 callback.expectStarted();
2578 mWiFiNetworkAgent.disconnect();
2579 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
2580
2581 // ... and that stopping it after that has no adverse effects.
2582 assertNull(mCm.getNetworkCapabilities(myNet));
2583 ka.stop();
2584
2585 // Reconnect.
2586 myNet = connectKeepaliveNetwork(lp);
2587 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2588
2589 // Check things work as expected when the keepalive is stopped and the network disconnects.
2590 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2591 callback.expectStarted();
2592 ka.stop();
2593 mWiFiNetworkAgent.disconnect();
2594 mService.waitForIdle();
2595 callback.expectStopped();
2596
2597 // Reconnect.
2598 myNet = connectKeepaliveNetwork(lp);
2599 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2600
2601 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
2602 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
2603 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2604 callback.expectStarted();
2605
2606 // The second one gets slot 2.
2607 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
2608 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
2609 PacketKeepalive ka2 = mCm.startNattKeepalive(myNet, 25, callback2, myIPv4, 6789, dstIPv4);
2610 callback2.expectStarted();
2611
2612 // Now stop the first one and create a third. This also gets slot 1.
2613 ka.stop();
2614 callback.expectStopped();
2615
2616 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
2617 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
2618 PacketKeepalive ka3 = mCm.startNattKeepalive(myNet, 25, callback3, myIPv4, 9876, dstIPv4);
2619 callback3.expectStarted();
2620
2621 ka2.stop();
2622 callback2.expectStopped();
2623
2624 ka3.stop();
2625 callback3.expectStopped();
2626 }
Udam Sainib7c24872016-01-04 12:16:14 -08002627
2628 @SmallTest
2629 public void testGetCaptivePortalServerUrl() throws Exception {
2630 String url = mCm.getCaptivePortalServerUrl();
2631 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
2632 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09002633
2634 private static class TestNetworkPinner extends NetworkPinner {
2635 public static boolean awaitPin(int timeoutMs) {
2636 synchronized(sLock) {
2637 if (sNetwork == null) {
2638 try {
2639 sLock.wait(timeoutMs);
2640 } catch (InterruptedException e) {}
2641 }
2642 return sNetwork != null;
2643 }
2644 }
2645
2646 public static boolean awaitUnpin(int timeoutMs) {
2647 synchronized(sLock) {
2648 if (sNetwork != null) {
2649 try {
2650 sLock.wait(timeoutMs);
2651 } catch (InterruptedException e) {}
2652 }
2653 return sNetwork == null;
2654 }
2655 }
2656 }
2657
2658 private void assertPinnedToWifiWithCellDefault() {
2659 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
2660 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2661 }
2662
2663 private void assertPinnedToWifiWithWifiDefault() {
2664 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
2665 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2666 }
2667
2668 private void assertNotPinnedToWifi() {
2669 assertNull(mCm.getBoundNetworkForProcess());
2670 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2671 }
2672
2673 @SmallTest
2674 public void testNetworkPinner() {
2675 NetworkRequest wifiRequest = new NetworkRequest.Builder()
2676 .addTransportType(TRANSPORT_WIFI)
2677 .build();
2678 assertNull(mCm.getBoundNetworkForProcess());
2679
2680 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2681 assertNull(mCm.getBoundNetworkForProcess());
2682
2683 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2684 mCellNetworkAgent.connect(true);
2685 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2686 mWiFiNetworkAgent.connect(false);
2687
2688 // When wi-fi connects, expect to be pinned.
2689 assertTrue(TestNetworkPinner.awaitPin(100));
2690 assertPinnedToWifiWithCellDefault();
2691
2692 // Disconnect and expect the pin to drop.
2693 mWiFiNetworkAgent.disconnect();
2694 assertTrue(TestNetworkPinner.awaitUnpin(100));
2695 assertNotPinnedToWifi();
2696
2697 // Reconnecting does not cause the pin to come back.
2698 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2699 mWiFiNetworkAgent.connect(false);
2700 assertFalse(TestNetworkPinner.awaitPin(100));
2701 assertNotPinnedToWifi();
2702
2703 // Pinning while connected causes the pin to take effect immediately.
2704 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2705 assertTrue(TestNetworkPinner.awaitPin(100));
2706 assertPinnedToWifiWithCellDefault();
2707
2708 // Explicitly unpin and expect to use the default network again.
2709 TestNetworkPinner.unpin();
2710 assertNotPinnedToWifi();
2711
2712 // Disconnect cell and wifi.
2713 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
2714 mCellNetworkAgent.disconnect();
2715 mWiFiNetworkAgent.disconnect();
2716 waitFor(cv);
2717
2718 // Pinning takes effect even if the pinned network is the default when the pin is set...
2719 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2720 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2721 mWiFiNetworkAgent.connect(false);
2722 assertTrue(TestNetworkPinner.awaitPin(100));
2723 assertPinnedToWifiWithWifiDefault();
2724
2725 // ... and is maintained even when that network is no longer the default.
2726 cv = waitForConnectivityBroadcasts(1);
2727 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2728 mCellNetworkAgent.connect(true);
2729 waitFor(cv);
2730 assertPinnedToWifiWithCellDefault();
2731 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04002732
2733 @SmallTest
2734 public void testNetworkRequestMaximum() {
2735 final int MAX_REQUESTS = 100;
2736 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
2737 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
2738 ArrayList<NetworkCallback> networkCallbacks = new ArrayList<NetworkCallback>();
2739 try {
2740 for (int i = 0; i < MAX_REQUESTS; i++) {
2741 NetworkCallback networkCallback = new NetworkCallback();
2742 mCm.requestNetwork(networkRequest, networkCallback);
2743 networkCallbacks.add(networkCallback);
2744 }
2745 fail("Registering " + MAX_REQUESTS + " NetworkRequests did not throw exception");
2746 } catch (IllegalArgumentException expected) {}
2747 for (NetworkCallback networkCallback : networkCallbacks) {
2748 mCm.unregisterNetworkCallback(networkCallback);
2749 }
2750 networkCallbacks.clear();
2751
2752 try {
2753 for (int i = 0; i < MAX_REQUESTS; i++) {
2754 NetworkCallback networkCallback = new NetworkCallback();
2755 mCm.registerNetworkCallback(networkRequest, networkCallback);
2756 networkCallbacks.add(networkCallback);
2757 }
2758 fail("Registering " + MAX_REQUESTS + " NetworkCallbacks did not throw exception");
2759 } catch (IllegalArgumentException expected) {}
2760 for (NetworkCallback networkCallback : networkCallbacks) {
2761 mCm.unregisterNetworkCallback(networkCallback);
2762 }
2763 networkCallbacks.clear();
2764
2765 ArrayList<PendingIntent> pendingIntents = new ArrayList<PendingIntent>();
2766 try {
2767 for (int i = 0; i < MAX_REQUESTS + 1; i++) {
2768 PendingIntent pendingIntent =
2769 PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
2770 mCm.requestNetwork(networkRequest, pendingIntent);
2771 pendingIntents.add(pendingIntent);
2772 }
2773 fail("Registering " + MAX_REQUESTS +
2774 " PendingIntent NetworkRequests did not throw exception");
2775 } catch (IllegalArgumentException expected) {}
2776 for (PendingIntent pendingIntent : pendingIntents) {
2777 mCm.unregisterNetworkCallback(pendingIntent);
2778 }
2779 pendingIntents.clear();
2780
2781 try {
2782 for (int i = 0; i < MAX_REQUESTS + 1; i++) {
2783 PendingIntent pendingIntent =
2784 PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
2785 mCm.registerNetworkCallback(networkRequest, pendingIntent);
2786 pendingIntents.add(pendingIntent);
2787 }
2788 fail("Registering " + MAX_REQUESTS +
2789 " PendingIntent NetworkCallbacks did not throw exception");
2790 } catch (IllegalArgumentException expected) {}
2791 for (PendingIntent pendingIntent : pendingIntents) {
2792 mCm.unregisterNetworkCallback(pendingIntent);
2793 }
2794 pendingIntents.clear();
2795 mService.waitForIdle(5000);
2796
2797 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
2798 for (int i = 0; i < MAX_REQUESTS; i++) {
2799 NetworkCallback networkCallback = new NetworkCallback();
2800 mCm.requestNetwork(networkRequest, networkCallback);
2801 mCm.unregisterNetworkCallback(networkCallback);
2802 }
2803 mService.waitForIdle();
2804 for (int i = 0; i < MAX_REQUESTS; i++) {
2805 NetworkCallback networkCallback = new NetworkCallback();
2806 mCm.registerNetworkCallback(networkRequest, networkCallback);
2807 mCm.unregisterNetworkCallback(networkCallback);
2808 }
2809 mService.waitForIdle();
2810 for (int i = 0; i < MAX_REQUESTS; i++) {
2811 PendingIntent pendingIntent =
2812 PendingIntent.getBroadcast(mContext, 0, new Intent("b" + i), 0);
2813 mCm.requestNetwork(networkRequest, pendingIntent);
2814 mCm.unregisterNetworkCallback(pendingIntent);
2815 }
2816 mService.waitForIdle();
2817 for (int i = 0; i < MAX_REQUESTS; i++) {
2818 PendingIntent pendingIntent =
2819 PendingIntent.getBroadcast(mContext, 0, new Intent("c" + i), 0);
2820 mCm.registerNetworkCallback(networkRequest, pendingIntent);
2821 mCm.unregisterNetworkCallback(pendingIntent);
2822 }
2823 }
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07002824
2825 /* test utilities */
2826 static private void sleepFor(int ms) {
2827 try {
2828 Thread.sleep(ms);
2829 } catch (InterruptedException e) {
2830 }
2831
2832 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07002833}