blob: 46b64031ee8acb16493dff0a57cdddd1088e039f [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
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001106 private static class CallbackInfo {
1107 public final CallbackState state;
1108 public final Network network;
1109 public final Object arg;
1110 public CallbackInfo(CallbackState s, Network n, Object o) {
1111 state = s; network = n; arg = o;
1112 }
1113 public String toString() {
1114 return String.format("%s (%s)", state, network);
1115 }
1116 @Override
1117 public boolean equals(Object o) {
1118 if (!(o instanceof CallbackInfo)) return false;
1119 // Ignore timeMs, since it's unpredictable.
1120 CallbackInfo other = (CallbackInfo) o;
1121 return (state == other.state) && Objects.equals(network, other.network);
1122 }
1123 @Override
1124 public int hashCode() {
1125 return Objects.hash(state, network);
1126 }
1127 }
1128
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001129 /**
1130 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1131 * this class receives, by calling expectCallback() exactly once each time a callback is
1132 * received. assertNoCallback may be called at any time.
1133 */
Paul Jensen3d911462015-06-12 06:40:24 -04001134 private class TestNetworkCallback extends NetworkCallback {
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001135 // Chosen to be much less than the linger timeout. This ensures that we can distinguish
1136 // between a LOST callback that arrives immediately and a LOST callback that arrives after
1137 // the linger timeout.
1138 private final static int TIMEOUT_MS = 50;
1139
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001140 private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
1141
Erik Klineacdd6392016-07-07 16:50:58 +09001142 protected void setLastCallback(CallbackState state, Network network, Object o) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001143 mCallbacks.offer(new CallbackInfo(state, network, o));
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001144 }
Paul Jensen3d911462015-06-12 06:40:24 -04001145
Erik Klineacdd6392016-07-07 16:50:58 +09001146 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001147 public void onAvailable(Network network) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001148 setLastCallback(CallbackState.AVAILABLE, network, null);
Paul Jensen3d911462015-06-12 06:40:24 -04001149 }
1150
Erik Klineacdd6392016-07-07 16:50:58 +09001151 @Override
Erik Kline3841a482015-11-25 12:49:38 +09001152 public void onUnavailable() {
1153 setLastCallback(CallbackState.UNAVAILABLE, null, null);
1154 }
1155
1156 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001157 public void onLosing(Network network, int maxMsToLive) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001158 setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
Paul Jensen3d911462015-06-12 06:40:24 -04001159 }
1160
Erik Klineacdd6392016-07-07 16:50:58 +09001161 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001162 public void onLost(Network network) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001163 setLastCallback(CallbackState.LOST, network, null);
1164 }
1165
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001166 CallbackInfo nextCallback(int timeoutMs) {
1167 CallbackInfo cb = null;
1168 try {
1169 cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
1170 } catch (InterruptedException e) {
1171 }
1172 if (cb == null) {
1173 // LinkedBlockingQueue.poll() returns null if it timeouts.
1174 fail("Did not receive callback after " + timeoutMs + "ms");
1175 }
1176 return cb;
1177 }
1178
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001179 void expectCallback(CallbackState state, MockNetworkAgent mockAgent, int timeoutMs) {
1180 CallbackInfo expected = new CallbackInfo(
1181 state, (mockAgent != null) ? mockAgent.getNetwork() : null, 0);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001182 CallbackInfo actual = nextCallback(timeoutMs);
1183 assertEquals("Unexpected callback:", expected, actual);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001184 if (state == CallbackState.LOSING) {
1185 String msg = String.format(
1186 "Invalid linger time value %d, must be between %d and %d",
1187 actual.arg, 0, TEST_LINGER_DELAY_MS);
1188 int maxMsToLive = (Integer) actual.arg;
1189 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= TEST_LINGER_DELAY_MS);
1190 }
Erik Klinea2d29402016-03-16 15:31:39 +09001191 }
1192
1193 void expectCallback(CallbackState state, MockNetworkAgent mockAgent) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001194 expectCallback(state, mockAgent, TIMEOUT_MS);
Paul Jensen3d911462015-06-12 06:40:24 -04001195 }
1196
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001197 void assertNoCallback() {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001198 mService.waitForIdle();
1199 CallbackInfo c = mCallbacks.peek();
1200 assertNull("Unexpected callback: " + c, c);
1201 }
1202 }
1203
1204 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1205 // only be declared in a static or top level type".
1206 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1207 for (TestNetworkCallback c : callbacks) {
1208 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001209 }
1210 }
1211
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001212 @SmallTest
Paul Jensen3d911462015-06-12 06:40:24 -04001213 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001214 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001215 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1216 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001217 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1218 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001219 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1220 .addTransportType(TRANSPORT_WIFI).build();
1221 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1222 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001223 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001224 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1225 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1226
1227 // Test unvalidated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001228 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1229 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1230 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001231 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1232 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001233 assertEquals(mCellNetworkAgent.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 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1238 mCellNetworkAgent.adjustScore(-1);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001239 mService.waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001240 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001241 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1242
Paul Jensen3d911462015-06-12 06:40:24 -04001243 cv = waitForConnectivityBroadcasts(2);
1244 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1245 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001246 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1247 wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001248 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1249 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001250 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001251
Paul Jensen3d911462015-06-12 06:40:24 -04001252 cv = waitForConnectivityBroadcasts(2);
1253 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001254 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1255 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001256 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001257 waitFor(cv);
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 cv = waitForConnectivityBroadcasts(1);
1261 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001262 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1263 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001264 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001265 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001266
1267 // Test validated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001268 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1269 mCellNetworkAgent.connect(true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001270 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1271 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001272 assertEquals(mCellNetworkAgent.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 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1276 mCellNetworkAgent.adjustScore(-1);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001277 mService.waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001278 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001279 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1280
Paul Jensen3d911462015-06-12 06:40:24 -04001281 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1282 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001283 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1284 genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1285 wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1286 cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001287 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001288 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001289
Paul Jensen3d911462015-06-12 06:40:24 -04001290 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001291 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1292 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1293 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001294
Paul Jensen3d911462015-06-12 06:40:24 -04001295 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001296 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1297 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1298 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001299 }
1300
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001301 @SmallTest
1302 public void testMultipleLingering() {
1303 NetworkRequest request = new NetworkRequest.Builder()
1304 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1305 .build();
1306 TestNetworkCallback callback = new TestNetworkCallback();
1307 mCm.registerNetworkCallback(request, callback);
1308
1309 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1310 mCm.registerDefaultNetworkCallback(defaultCallback);
1311
1312 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1313 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1314 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
1315
1316 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1317 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1318 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1319
1320 mCellNetworkAgent.connect(true);
1321 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1322 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1323 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1324
1325 mWiFiNetworkAgent.connect(true);
1326 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1327 // We then get LOSING when wifi validates and cell is outscored.
1328 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1329 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1330 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1331 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1332
1333 mEthernetNetworkAgent.connect(true);
1334 callback.expectCallback(CallbackState.AVAILABLE, mEthernetNetworkAgent);
1335 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
1336 defaultCallback.expectCallback(CallbackState.AVAILABLE, mEthernetNetworkAgent);
1337 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1338
1339 mEthernetNetworkAgent.disconnect();
1340 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1341 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1342 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1343
1344 for (int i = 0; i < 4; i++) {
1345 MockNetworkAgent oldNetwork, newNetwork;
1346 if (i % 2 == 0) {
1347 mWiFiNetworkAgent.adjustScore(-15);
1348 oldNetwork = mWiFiNetworkAgent;
1349 newNetwork = mCellNetworkAgent;
1350 } else {
1351 mWiFiNetworkAgent.adjustScore(15);
1352 oldNetwork = mCellNetworkAgent;
1353 newNetwork = mWiFiNetworkAgent;
1354
1355 }
1356 callback.expectCallback(CallbackState.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001357 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1358 // longer lingering?
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001359 defaultCallback.expectCallback(CallbackState.AVAILABLE, newNetwork);
1360 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
1361 }
1362 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1363
1364 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
1365 // if the network is still up.
1366 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
1367 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1368
1369 // Wifi no longer satisfies our listen, which is for an unmetered network.
1370 // But because its score is 55, it's still up (and the default network).
1371 defaultCallback.assertNoCallback();
1372 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1373
1374 // Disconnect our test networks.
1375 mWiFiNetworkAgent.disconnect();
1376 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1377 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1378 mCellNetworkAgent.disconnect();
1379 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1380
1381 mCm.unregisterNetworkCallback(callback);
1382 mService.waitForIdle();
1383
1384 // Check that a network is only lingered or torn down if it would not satisfy a request even
1385 // if it validated.
1386 request = new NetworkRequest.Builder().clearCapabilities().build();
1387 callback = new TestNetworkCallback();
1388
1389 mCm.registerNetworkCallback(request, callback);
1390
1391 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1392 mCellNetworkAgent.connect(false); // Score: 10
1393 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1394 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1395 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1396
1397 // Bring up wifi with a score of 20.
1398 // Cell stays up because it would satisfy the default request if it validated.
1399 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1400 mWiFiNetworkAgent.connect(false); // Score: 20
1401 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1402 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1403 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1404
1405 mWiFiNetworkAgent.disconnect();
1406 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1407 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1408 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1409 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1410
1411 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001412 // Cell is lingered because it would not satisfy any request, even if it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001413 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1414 mWiFiNetworkAgent.adjustScore(50);
1415 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001416 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001417 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001418 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1419 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1420
1421 // Tear down wifi.
1422 mWiFiNetworkAgent.disconnect();
1423 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1424 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1425 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1426 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1427
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001428 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
1429 // it's arguably correct to linger it, since it was the default network before it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001430 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1431 mWiFiNetworkAgent.connect(true);
1432 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001433 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001434 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1435 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1436
1437 mWiFiNetworkAgent.disconnect();
1438 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001439 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001440 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1441 mCellNetworkAgent.disconnect();
1442 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1443 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001444
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001445 // If a network is lingering, and we add and remove a request from it, resume lingering.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001446 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1447 mCellNetworkAgent.connect(true);
1448 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1449 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1450 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1451 mWiFiNetworkAgent.connect(true);
1452 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1453 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1454 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1455
1456 NetworkRequest cellRequest = new NetworkRequest.Builder()
1457 .addTransportType(TRANSPORT_CELLULAR).build();
1458 NetworkCallback noopCallback = new NetworkCallback();
1459 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001460 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
1461 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001462 mCm.unregisterNetworkCallback(noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001463 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001464
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001465 // Similar to the above: lingering can start even after the lingered request is removed.
1466 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001467 mWiFiNetworkAgent.disconnect();
1468 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001469 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1470 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1471
1472 // Cell is now the default network. Pin it with a cell-specific request.
1473 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
1474 mCm.requestNetwork(cellRequest, noopCallback);
1475
1476 // Now connect wifi, and expect it to become the default network.
1477 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1478 mWiFiNetworkAgent.connect(true);
1479 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1480 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1481 // The default request is lingering on cell, but nothing happens to cell, and we send no
1482 // callbacks for it, because it's kept up by cellRequest.
1483 callback.assertNoCallback();
1484 // Now unregister cellRequest and expect cell to start lingering.
1485 mCm.unregisterNetworkCallback(noopCallback);
1486 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1487
1488 // Let linger run its course.
1489 callback.assertNoCallback();
1490 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent,
1491 TEST_LINGER_DELAY_MS /* timeoutMs */);
1492
1493 // Clean up.
1494 mWiFiNetworkAgent.disconnect();
1495 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1496 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001497
1498 mCm.unregisterNetworkCallback(callback);
1499 mCm.unregisterNetworkCallback(defaultCallback);
1500 }
1501
Paul Jensen85cf78e2015-06-25 13:25:07 -04001502 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04001503 // Verify NOT_RESTRICTED is set appropriately
1504 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
1505 .build().networkCapabilities;
1506 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
1507 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
1508 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04001509 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04001510 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1511 } else {
1512 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1513 }
1514
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001515 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001516 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001517 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
1518 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04001519 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001520 mServiceContext, "testFactory", filter);
1521 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04001522 ConditionVariable cv = testFactory.getNetworkStartedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001523 testFactory.expectAddRequests(1);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001524 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001525 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001526 int expectedRequestCount = 1;
1527 NetworkCallback networkCallback = null;
1528 // For non-INTERNET capabilities we cannot rely on the default request being present, so
1529 // add one.
1530 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04001531 assertFalse(testFactory.getMyStartRequested());
1532 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
1533 networkCallback = new NetworkCallback();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001534 testFactory.expectAddRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001535 mCm.requestNetwork(request, networkCallback);
1536 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001537 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001538 }
Paul Jensen3d911462015-06-12 06:40:24 -04001539 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001540 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1541 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001542
Paul Jensen85cf78e2015-06-25 13:25:07 -04001543 // Now bring in a higher scored network.
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001544 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001545 // Rather than create a validated network which complicates things by registering it's
1546 // own NetworkRequest during startup, just bump up the score to cancel out the
1547 // unvalidated penalty.
1548 testAgent.adjustScore(40);
1549 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001550
1551 // When testAgent connects, ConnectivityService will re-send us all current requests with
1552 // the new score. There are expectedRequestCount such requests, and we must wait for all of
1553 // them.
1554 testFactory.expectAddRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001555 testAgent.connect(false);
1556 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04001557 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001558 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001559 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001560
Paul Jensen85cf78e2015-06-25 13:25:07 -04001561 // Bring in a bunch of requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001562 testFactory.expectAddRequests(10);
1563 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001564 ConnectivityManager.NetworkCallback[] networkCallbacks =
1565 new ConnectivityManager.NetworkCallback[10];
1566 for (int i = 0; i< networkCallbacks.length; i++) {
1567 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
1568 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001569 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001570 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
1571 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04001572 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
1573 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001574
Paul Jensen85cf78e2015-06-25 13:25:07 -04001575 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001576 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001577 for (int i = 0; i < networkCallbacks.length; i++) {
1578 mCm.unregisterNetworkCallback(networkCallbacks[i]);
1579 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04001580 testFactory.waitForNetworkRequests(expectedRequestCount);
1581 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001582
Paul Jensen85cf78e2015-06-25 13:25:07 -04001583 // Drop the higher scored network.
1584 cv = testFactory.getNetworkStartedCV();
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001585 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001586 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001587 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1588 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001589
1590 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001591 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001592 handlerThread.quit();
1593 }
1594
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001595 @SmallTest
Paul Jensen85cf78e2015-06-25 13:25:07 -04001596 public void testNetworkFactoryRequests() throws Exception {
1597 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
1598 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
1599 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
1600 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
1601 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
1602 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
1603 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
1604 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
1605 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
1606 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
1607 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
1608 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
1609 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
1610 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
1611 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
1612 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
1613 }
1614
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001615 @SmallTest
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001616 public void testNoMutableNetworkRequests() throws Exception {
1617 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
1618 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001619 builder.addCapability(NET_CAPABILITY_VALIDATED);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001620 try {
1621 mCm.requestNetwork(builder.build(), new NetworkCallback());
1622 fail();
1623 } catch (IllegalArgumentException expected) {}
1624 try {
1625 mCm.requestNetwork(builder.build(), pendingIntent);
1626 fail();
1627 } catch (IllegalArgumentException expected) {}
1628 builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001629 builder.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001630 try {
1631 mCm.requestNetwork(builder.build(), new NetworkCallback());
1632 fail();
1633 } catch (IllegalArgumentException expected) {}
1634 try {
1635 mCm.requestNetwork(builder.build(), pendingIntent);
1636 fail();
1637 } catch (IllegalArgumentException expected) {}
1638 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001639
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001640 @SmallTest
Paul Jensene0988542015-06-25 15:30:08 -04001641 public void testMMSonWiFi() throws Exception {
1642 // Test bringing up cellular without MMS NetworkRequest gets reaped
1643 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1644 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1645 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
1646 mCellNetworkAgent.connectWithoutInternet();
1647 waitFor(cv);
1648 waitFor(new Criteria() {
1649 public boolean get() { return mCm.getAllNetworks().length == 0; } });
1650 verifyNoNetwork();
1651 // Test bringing up validated WiFi.
1652 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1653 cv = waitForConnectivityBroadcasts(1);
1654 mWiFiNetworkAgent.connect(true);
1655 waitFor(cv);
1656 verifyActiveNetwork(TRANSPORT_WIFI);
1657 // Register MMS NetworkRequest
1658 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1659 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1660 final TestNetworkCallback networkCallback = new TestNetworkCallback();
1661 mCm.requestNetwork(builder.build(), networkCallback);
1662 // Test bringing up unvalidated cellular with MMS
1663 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1664 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04001665 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001666 networkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04001667 verifyActiveNetwork(TRANSPORT_WIFI);
1668 // Test releasing NetworkRequest disconnects cellular with MMS
1669 cv = mCellNetworkAgent.getDisconnectedCV();
1670 mCm.unregisterNetworkCallback(networkCallback);
1671 waitFor(cv);
1672 verifyActiveNetwork(TRANSPORT_WIFI);
1673 }
1674
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001675 @SmallTest
Paul Jensene0988542015-06-25 15:30:08 -04001676 public void testMMSonCell() throws Exception {
1677 // Test bringing up cellular without MMS
1678 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1679 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1680 mCellNetworkAgent.connect(false);
1681 waitFor(cv);
1682 verifyActiveNetwork(TRANSPORT_CELLULAR);
1683 // Register MMS NetworkRequest
1684 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1685 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1686 final TestNetworkCallback networkCallback = new TestNetworkCallback();
1687 mCm.requestNetwork(builder.build(), networkCallback);
1688 // Test bringing up MMS cellular network
Paul Jensene0988542015-06-25 15:30:08 -04001689 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1690 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1691 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001692 networkCallback.expectCallback(CallbackState.AVAILABLE, mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04001693 verifyActiveNetwork(TRANSPORT_CELLULAR);
1694 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
1695 cv = mmsNetworkAgent.getDisconnectedCV();
1696 mCm.unregisterNetworkCallback(networkCallback);
1697 waitFor(cv);
1698 verifyActiveNetwork(TRANSPORT_CELLULAR);
1699 }
1700
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001701 @SmallTest
Paul Jensencf4c2c62015-07-01 14:16:32 -04001702 public void testCaptivePortal() {
1703 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1704 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1705 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1706 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1707
1708 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1709 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1710 .addCapability(NET_CAPABILITY_VALIDATED).build();
1711 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001712
1713 // Bring up a network with a captive portal.
1714 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001715 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04001716 String firstRedirectUrl = "http://example.com/firstPath";
1717 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001718 captivePortalCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04001719 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001720
1721 // Take down network.
1722 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001723 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001724 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001725
1726 // Bring up a network with a captive portal.
1727 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001728 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04001729 String secondRedirectUrl = "http://example.com/secondPath";
1730 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001731 captivePortalCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04001732 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001733
1734 // Make captive portal disappear then revalidate.
1735 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001736 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
1737 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001738 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001739
1740 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001741 validatedCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001742
1743 // Break network connectivity.
1744 // Expect NET_CAPABILITY_VALIDATED onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001745 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
1746 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001747 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001748 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09001749
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001750 @SmallTest
Calvin On1f64f3f2016-10-11 15:10:46 -07001751 public void testAvoidOrIgnoreCaptivePortals() {
1752 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1753 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1754 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1755 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1756
1757 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1758 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1759 .addCapability(NET_CAPABILITY_VALIDATED).build();
1760 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
1761
1762 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
1763 // Bring up a network with a captive portal.
1764 // Expect it to fail to connect and not result in any callbacks.
1765 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1766 String firstRedirectUrl = "http://example.com/firstPath";
1767
1768 ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
1769 ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
1770 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
1771 waitFor(disconnectCv);
1772 waitFor(avoidCv);
1773
1774 assertNoCallbacks(captivePortalCallback, validatedCallback);
1775
1776 // Now test ignore mode.
1777 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE);
1778
1779 // Bring up a network with a captive portal.
1780 // Since we're ignoring captive portals, the network will validate.
1781 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1782 String secondRedirectUrl = "http://example.com/secondPath";
1783 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
1784
1785 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
1786 validatedCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1787 // But there should be no CaptivePortal callback.
1788 captivePortalCallback.assertNoCallback();
1789 }
1790
Etan Cohenddb9ef02015-11-18 10:56:15 -08001791 @SmallTest
1792 public void testInvalidNetworkSpecifier() {
1793 boolean execptionCalled = true;
1794
1795 try {
1796 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1797 builder.setNetworkSpecifier(MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
1798 execptionCalled = false;
1799 } catch (IllegalArgumentException e) {
1800 // do nothing - should get here
1801 }
1802
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001803 assertTrue("NetworkRequest builder with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
Etan Cohenddb9ef02015-11-18 10:56:15 -08001804 execptionCalled);
1805
1806 try {
1807 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
1808 networkCapabilities.addTransportType(TRANSPORT_WIFI)
1809 .setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
1810 mService.requestNetwork(networkCapabilities, null, 0, null,
1811 ConnectivityManager.TYPE_WIFI);
1812 execptionCalled = false;
1813 } catch (IllegalArgumentException e) {
1814 // do nothing - should get here
1815 }
1816
1817 assertTrue("ConnectivityService requestNetwork with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
1818 execptionCalled);
1819 }
1820
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001821 @SmallTest
Erik Klinea2d29402016-03-16 15:31:39 +09001822 public void testRegisterDefaultNetworkCallback() throws Exception {
1823 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
1824 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
1825 defaultNetworkCallback.assertNoCallback();
1826
1827 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
1828 // whenever Wi-Fi is up. Without this, the mobile network agent is
1829 // reaped before any other activity can take place.
1830 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
1831 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1832 .addTransportType(TRANSPORT_CELLULAR).build();
1833 mCm.requestNetwork(cellRequest, cellNetworkCallback);
1834 cellNetworkCallback.assertNoCallback();
1835
1836 // Bring up cell and expect CALLBACK_AVAILABLE.
1837 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1838 mCellNetworkAgent.connect(true);
1839 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1840 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1841
1842 // Bring up wifi and expect CALLBACK_AVAILABLE.
1843 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1844 mWiFiNetworkAgent.connect(true);
1845 cellNetworkCallback.assertNoCallback();
1846 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1847
1848 // Bring down cell. Expect no default network callback, since it wasn't the default.
1849 mCellNetworkAgent.disconnect();
1850 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1851 defaultNetworkCallback.assertNoCallback();
1852
1853 // Bring up cell. Expect no default network callback, since it won't be the default.
1854 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1855 mCellNetworkAgent.connect(true);
1856 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1857 defaultNetworkCallback.assertNoCallback();
1858
1859 // Bring down wifi. Expect the default network callback to notified of LOST wifi
1860 // followed by AVAILABLE cell.
1861 mWiFiNetworkAgent.disconnect();
1862 cellNetworkCallback.assertNoCallback();
1863 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1864 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1865 mCellNetworkAgent.disconnect();
1866 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1867 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1868 }
1869
Erik Klineacdd6392016-07-07 16:50:58 +09001870 private class TestRequestUpdateCallback extends TestNetworkCallback {
1871 @Override
1872 public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
1873 setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
1874 }
1875
1876 @Override
1877 public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
1878 setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
1879 }
1880 }
1881
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001882 @SmallTest
Erik Klineacdd6392016-07-07 16:50:58 +09001883 public void testRequestCallbackUpdates() throws Exception {
1884 // File a network request for mobile.
1885 final TestNetworkCallback cellNetworkCallback = new TestRequestUpdateCallback();
1886 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1887 .addTransportType(TRANSPORT_CELLULAR).build();
1888 mCm.requestNetwork(cellRequest, cellNetworkCallback);
1889
1890 // Bring up the mobile network.
1891 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1892 mCellNetworkAgent.connect(true);
1893
1894 // We should get onAvailable().
1895 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1896 // We should get onCapabilitiesChanged(), when the mobile network successfully validates.
1897 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
1898 cellNetworkCallback.assertNoCallback();
1899
1900 // Update LinkProperties.
1901 final LinkProperties lp = new LinkProperties();
1902 lp.setInterfaceName("foonet_data0");
1903 mCellNetworkAgent.sendLinkProperties(lp);
1904 // We should get onLinkPropertiesChanged().
1905 cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
1906 cellNetworkCallback.assertNoCallback();
1907
1908 // Register a garden variety default network request.
1909 final TestNetworkCallback dfltNetworkCallback = new TestRequestUpdateCallback();
1910 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
1911 // Only onAvailable() is called; no other information is delivered.
1912 dfltNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1913 dfltNetworkCallback.assertNoCallback();
1914
1915 // Request a NetworkCapabilities update; only the requesting callback is notified.
1916 mCm.requestNetworkCapabilities(dfltNetworkCallback);
1917 dfltNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
1918 cellNetworkCallback.assertNoCallback();
1919 dfltNetworkCallback.assertNoCallback();
1920
1921 // Request a LinkProperties update; only the requesting callback is notified.
1922 mCm.requestLinkProperties(dfltNetworkCallback);
1923 dfltNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
1924 cellNetworkCallback.assertNoCallback();
1925 dfltNetworkCallback.assertNoCallback();
1926
1927 mCm.unregisterNetworkCallback(dfltNetworkCallback);
1928 mCm.unregisterNetworkCallback(cellNetworkCallback);
1929 }
1930
Calvin On1f64f3f2016-10-11 15:10:46 -07001931 private void setCaptivePortalMode(int mode) {
1932 ContentResolver cr = mServiceContext.getContentResolver();
1933 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
1934 }
1935
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09001936 private void setMobileDataAlwaysOn(boolean enable) {
1937 ContentResolver cr = mServiceContext.getContentResolver();
1938 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
1939 mService.updateMobileDataAlwaysOn();
1940 mService.waitForIdle();
1941 }
1942
1943 private boolean isForegroundNetwork(MockNetworkAgent network) {
1944 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
1945 assertNotNull(nc);
1946 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
1947 }
1948
1949 @SmallTest
1950 public void testBackgroundNetworks() throws Exception {
1951 // Create a background request. We can't do this ourselves because ConnectivityService
1952 // doesn't have an API for it. So just turn on mobile data always on.
1953 setMobileDataAlwaysOn(true);
1954 final NetworkRequest request = new NetworkRequest.Builder().build();
1955 final NetworkRequest fgRequest = new NetworkRequest.Builder()
1956 .addCapability(NET_CAPABILITY_FOREGROUND).build();
1957 final TestNetworkCallback callback = new TestNetworkCallback();
1958 final TestNetworkCallback fgCallback = new TestNetworkCallback();
1959 mCm.registerNetworkCallback(request, callback);
1960 mCm.registerNetworkCallback(fgRequest, fgCallback);
1961
1962 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1963 mCellNetworkAgent.connect(true);
1964 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1965 fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1966 assertTrue(isForegroundNetwork(mCellNetworkAgent));
1967
1968 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1969 mWiFiNetworkAgent.connect(true);
1970
1971 // When wifi connects, cell lingers.
1972 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1973 fgCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1974 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1975 fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1976 assertTrue(isForegroundNetwork(mCellNetworkAgent));
1977 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1978
1979 // When lingering is complete, cell is still there but is now in the background.
1980 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, TEST_LINGER_DELAY_MS);
1981 callback.assertNoCallback();
1982 assertFalse(isForegroundNetwork(mCellNetworkAgent));
1983 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1984
1985 // File a cell request and check that cell comes into the foreground.
1986 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1987 .addTransportType(TRANSPORT_CELLULAR).build();
1988 final TestNetworkCallback cellCallback = new TestNetworkCallback();
1989 mCm.requestNetwork(cellRequest, cellCallback);
1990 cellCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1991 fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1992 callback.assertNoCallback(); // Because the network is already up.
1993 assertTrue(isForegroundNetwork(mCellNetworkAgent));
1994 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1995
1996 // Release the request. The network immediately goes into the background, since it was not
1997 // lingering.
1998 mCm.unregisterNetworkCallback(cellCallback);
1999 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2000 callback.assertNoCallback();
2001 assertFalse(isForegroundNetwork(mCellNetworkAgent));
2002 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2003
2004 // Disconnect wifi and check that cell is foreground again.
2005 mWiFiNetworkAgent.disconnect();
2006 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2007 fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2008 fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2009 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2010
2011 mCm.unregisterNetworkCallback(callback);
2012 mCm.unregisterNetworkCallback(fgCallback);
2013 }
2014
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002015 @SmallTest
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002016 public void testRequestBenchmark() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002017 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002018 // Benchmarks connecting and switching performance in the presence of a large number of
2019 // NetworkRequests.
2020 // 1. File NUM_REQUESTS requests.
2021 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
2022 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
2023 // and NUM_REQUESTS onAvailable callbacks to fire.
2024 // See how long it took.
2025 final int NUM_REQUESTS = 90;
2026 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
2027 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
2028 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
2029 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
2030
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002031 for (int i = 0; i < NUM_REQUESTS; i++) {
2032 callbacks[i] = new NetworkCallback() {
2033 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
2034 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
2035 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002036 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002037
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002038 final int REGISTER_TIME_LIMIT_MS = 180;
2039 assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
2040 for (NetworkCallback cb : callbacks) {
2041 mCm.registerNetworkCallback(request, cb);
2042 }
2043 });
2044
2045 final int CONNECT_TIME_LIMIT_MS = 40;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002046 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2047 // Don't request that the network validate, because otherwise connect() will block until
2048 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
2049 // and we won't actually measure anything.
2050 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002051
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002052 long onAvailableDispatchingDuration = durationOf(() -> {
2053 if (!awaitLatch(availableLatch, CONNECT_TIME_LIMIT_MS)) {
2054 fail(String.format("Only dispatched %d/%d onAvailable callbacks in %dms",
2055 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
2056 CONNECT_TIME_LIMIT_MS));
2057 }
2058 });
2059 Log.d(TAG, String.format("Connect, %d callbacks: %dms, acceptable %dms",
2060 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS));
2061
2062 final int SWITCH_TIME_LIMIT_MS = 40;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002063 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2064 // Give wifi a high enough score that we'll linger cell when wifi comes up.
2065 mWiFiNetworkAgent.adjustScore(40);
2066 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002067
2068 long onLostDispatchingDuration = durationOf(() -> {
2069 if (!awaitLatch(losingLatch, SWITCH_TIME_LIMIT_MS)) {
2070 fail(String.format("Only dispatched %d/%d onLosing callbacks in %dms",
2071 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, SWITCH_TIME_LIMIT_MS));
2072 }
2073 });
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002074 Log.d(TAG, String.format("Linger, %d callbacks: %dms, acceptable %dms",
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002075 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS));
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002076
2077 final int UNREGISTER_TIME_LIMIT_MS = 10;
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002078 assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
2079 for (NetworkCallback cb : callbacks) {
2080 mCm.unregisterNetworkCallback(cb);
2081 }
2082 });
2083 }
2084
2085 private long durationOf(Runnable fn) {
2086 long startTime = SystemClock.elapsedRealtime();
2087 fn.run();
2088 return SystemClock.elapsedRealtime() - startTime;
2089 }
2090
2091 private void assertTimeLimit(String descr, long timeLimit, Runnable fn) {
2092 long timeTaken = durationOf(fn);
2093 String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002094 Log.d(TAG, msg);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002095 assertTrue(msg, timeTaken <= timeLimit);
2096 }
2097
2098 private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
2099 try {
2100 if (l.await(timeoutMs, TimeUnit.MILLISECONDS)) {
2101 return true;
2102 }
2103 } catch (InterruptedException e) {}
2104 return false;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002105 }
2106
2107 @SmallTest
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002108 public void testMobileDataAlwaysOn() throws Exception {
2109 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2110 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2111 .addTransportType(TRANSPORT_CELLULAR).build();
2112 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
2113
2114 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
2115 handlerThread.start();
2116 NetworkCapabilities filter = new NetworkCapabilities()
2117 .addTransportType(TRANSPORT_CELLULAR)
2118 .addCapability(NET_CAPABILITY_INTERNET);
2119 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
2120 mServiceContext, "testFactory", filter);
2121 testFactory.setScoreFilter(40);
2122
2123 // Register the factory and expect it to start looking for a network.
2124 testFactory.expectAddRequests(1);
2125 testFactory.register();
2126 testFactory.waitForNetworkRequests(1);
2127 assertTrue(testFactory.getMyStartRequested());
2128
2129 // Bring up wifi. The factory stops looking for a network.
2130 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2131 testFactory.expectAddRequests(2); // Because the default request changes score twice.
2132 mWiFiNetworkAgent.connect(true);
2133 testFactory.waitForNetworkRequests(1);
2134 assertFalse(testFactory.getMyStartRequested());
2135
2136 ContentResolver cr = mServiceContext.getContentResolver();
2137
2138 // Turn on mobile data always on. The factory starts looking again.
2139 testFactory.expectAddRequests(1);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002140 setMobileDataAlwaysOn(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002141 testFactory.waitForNetworkRequests(2);
2142 assertTrue(testFactory.getMyStartRequested());
2143
2144 // Bring up cell data and check that the factory stops looking.
2145 assertEquals(1, mCm.getAllNetworks().length);
2146 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2147 testFactory.expectAddRequests(2); // Because the cell request changes score twice.
2148 mCellNetworkAgent.connect(true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002149 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002150 testFactory.waitForNetworkRequests(2);
2151 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
2152
2153 // Check that cell data stays up.
2154 mService.waitForIdle();
2155 verifyActiveNetwork(TRANSPORT_WIFI);
2156 assertEquals(2, mCm.getAllNetworks().length);
2157
2158 // Turn off mobile data always on and expect the request to disappear...
2159 testFactory.expectRemoveRequests(1);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002160 setMobileDataAlwaysOn(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002161 testFactory.waitForNetworkRequests(1);
2162
2163 // ... and cell data to be torn down.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002164 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002165 assertEquals(1, mCm.getAllNetworks().length);
2166
2167 testFactory.unregister();
2168 mCm.unregisterNetworkCallback(cellNetworkCallback);
2169 handlerThread.quit();
2170 }
2171
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002172 @SmallTest
2173 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002174 final ContentResolver cr = mServiceContext.getContentResolver();
Erik Kline065ab6e2016-10-02 18:02:14 +09002175 final WrappedAvoidBadWifiTracker tracker = mService.getAvoidBadWifiTracker();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002176 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
2177
Erik Kline065ab6e2016-10-02 18:02:14 +09002178 tracker.configRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002179 String[] values = new String[] {null, "0", "1"};
2180 for (int i = 0; i < values.length; i++) {
2181 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002182 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002183 mService.waitForIdle();
2184 String msg = String.format("config=false, setting=%s", values[i]);
Hugo Benichi53d83d52016-11-15 13:42:34 +09002185 assertEventuallyTrue(() -> mService.avoidBadWifi(), 50);
Erik Kline065ab6e2016-10-02 18:02:14 +09002186 assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002187 }
2188
Erik Kline065ab6e2016-10-02 18:02:14 +09002189 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002190
2191 Settings.Global.putInt(cr, settingName, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09002192 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002193 mService.waitForIdle();
Hugo Benichi53d83d52016-11-15 13:42:34 +09002194 assertEventuallyTrue(() -> !mService.avoidBadWifi(), 50);
Erik Kline065ab6e2016-10-02 18:02:14 +09002195 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002196
2197 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002198 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002199 mService.waitForIdle();
Hugo Benichi53d83d52016-11-15 13:42:34 +09002200 assertEventuallyTrue(() -> mService.avoidBadWifi(), 50);
Erik Kline065ab6e2016-10-02 18:02:14 +09002201 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002202
2203 Settings.Global.putString(cr, settingName, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09002204 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002205 mService.waitForIdle();
Hugo Benichi53d83d52016-11-15 13:42:34 +09002206 assertEventuallyTrue(() -> !mService.avoidBadWifi(), 50);
Erik Kline065ab6e2016-10-02 18:02:14 +09002207 assertTrue(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002208 }
2209
2210 @SmallTest
2211 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09002212 final ContentResolver cr = mServiceContext.getContentResolver();
2213 final WrappedAvoidBadWifiTracker tracker = mService.getAvoidBadWifiTracker();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002214
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002215 // Pretend we're on a carrier that restricts switching away from bad wifi.
Erik Kline065ab6e2016-10-02 18:02:14 +09002216 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002217
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002218 // File a request for cell to ensure it doesn't go down.
2219 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2220 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2221 .addTransportType(TRANSPORT_CELLULAR).build();
2222 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2223
2224 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2225 mCm.registerDefaultNetworkCallback(defaultCallback);
2226
2227 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
2228 .addTransportType(TRANSPORT_WIFI)
2229 .addCapability(NET_CAPABILITY_VALIDATED)
2230 .build();
2231 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
2232 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
2233
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002234 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09002235 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002236
2237 // Bring up validated cell.
2238 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2239 mCellNetworkAgent.connect(true);
2240 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2241 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2242 Network cellNetwork = mCellNetworkAgent.getNetwork();
2243
2244 // Bring up validated wifi.
2245 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2246 mWiFiNetworkAgent.connect(true);
2247 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2248 validatedWifiCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2249 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2250
2251 // Fail validation on wifi.
2252 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
2253 mCm.reportNetworkConnectivity(wifiNetwork, false);
2254 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2255
2256 // Because avoid bad wifi is off, we don't switch to cellular.
2257 defaultCallback.assertNoCallback();
2258 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2259 NET_CAPABILITY_VALIDATED));
2260 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2261 NET_CAPABILITY_VALIDATED));
2262 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2263
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002264 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
2265 // that we switch back to cell.
Erik Kline065ab6e2016-10-02 18:02:14 +09002266 tracker.configRestrictsAvoidBadWifi = false;
2267 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002268 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2269 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2270
2271 // Switch back to a restrictive carrier.
Erik Kline065ab6e2016-10-02 18:02:14 +09002272 tracker.configRestrictsAvoidBadWifi = true;
2273 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002274 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2275 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2276
2277 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
2278 mCm.setAvoidUnvalidated(wifiNetwork);
2279 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2280 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2281 NET_CAPABILITY_VALIDATED));
2282 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2283 NET_CAPABILITY_VALIDATED));
2284 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2285
2286 // Disconnect and reconnect wifi to clear the one-time switch above.
2287 mWiFiNetworkAgent.disconnect();
2288 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2289 mWiFiNetworkAgent.connect(true);
2290 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2291 validatedWifiCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2292 wifiNetwork = mWiFiNetworkAgent.getNetwork();
2293
2294 // Fail validation on wifi and expect the dialog to appear.
2295 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
2296 mCm.reportNetworkConnectivity(wifiNetwork, false);
2297 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2298
2299 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002300 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002301 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002302
2303 // We now switch to cell.
2304 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2305 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2306 NET_CAPABILITY_VALIDATED));
2307 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2308 NET_CAPABILITY_VALIDATED));
2309 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2310
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002311 // Simulate the user turning the cellular fallback setting off and then on.
2312 // We switch to wifi and then to cell.
2313 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09002314 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002315 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2316 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2317 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002318 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002319 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2320 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2321
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002322 // If cell goes down, we switch to wifi.
2323 mCellNetworkAgent.disconnect();
2324 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2325 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2326 validatedWifiCallback.assertNoCallback();
2327
2328 mCm.unregisterNetworkCallback(cellNetworkCallback);
2329 mCm.unregisterNetworkCallback(validatedWifiCallback);
2330 mCm.unregisterNetworkCallback(defaultCallback);
2331 }
2332
Erik Kline3841a482015-11-25 12:49:38 +09002333 /**
2334 * Validate that a satisfied network request does not trigger onUnavailable() once the
2335 * time-out period expires.
2336 */
2337 @SmallTest
2338 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
2339 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2340 NetworkCapabilities.TRANSPORT_WIFI).build();
2341 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2342 mCm.requestNetwork(nr, networkCallback, 10);
2343
2344 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2345 mWiFiNetworkAgent.connect(false);
2346 networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2347
2348 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07002349 sleepFor(15);
2350 networkCallback.assertNoCallback();
2351 }
2352
2353 /**
2354 * Validate that a satisfied network request followed by a disconnected (lost) network does
2355 * not trigger onUnavailable() once the time-out period expires.
2356 */
2357 @SmallTest
2358 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
2359 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2360 NetworkCapabilities.TRANSPORT_WIFI).build();
2361 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2362 mCm.requestNetwork(nr, networkCallback, 500);
2363
2364 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2365 mWiFiNetworkAgent.connect(false);
2366 networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2367 sleepFor(20);
2368 mWiFiNetworkAgent.disconnect();
2369 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2370
2371 // pass timeout and validate that UNAVAILABLE is not called
2372 sleepFor(600);
Erik Kline3841a482015-11-25 12:49:38 +09002373 networkCallback.assertNoCallback();
2374 }
2375
2376 /**
2377 * Validate that when a time-out is specified for a network request the onUnavailable()
2378 * callback is called when time-out expires. Then validate that if network request is
2379 * (somehow) satisfied - the callback isn't called later.
2380 */
2381 @SmallTest
2382 public void testTimedoutNetworkRequest() {
2383 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2384 NetworkCapabilities.TRANSPORT_WIFI).build();
2385 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2386 mCm.requestNetwork(nr, networkCallback, 10);
2387
2388 // pass timeout and validate that UNAVAILABLE is called
2389 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
2390
2391 // create a network satisfying request - validate that request not triggered
2392 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2393 mWiFiNetworkAgent.connect(false);
2394 networkCallback.assertNoCallback();
2395 }
2396
2397 /**
2398 * Validate that when a network request is unregistered (cancelled) the time-out for that
2399 * request doesn't trigger the onUnavailable() callback.
2400 */
2401 @SmallTest
2402 public void testTimedoutAfterUnregisteredNetworkRequest() {
2403 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2404 NetworkCapabilities.TRANSPORT_WIFI).build();
2405 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2406 mCm.requestNetwork(nr, networkCallback, 10);
2407
2408 // remove request
2409 mCm.unregisterNetworkCallback(networkCallback);
2410
2411 // pass timeout and validate that no callbacks
2412 // Note: doesn't validate that nothing called from CS since even if called the CM already
2413 // unregisters the callback and won't pass it through!
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07002414 sleepFor(15);
Erik Kline3841a482015-11-25 12:49:38 +09002415 networkCallback.assertNoCallback();
2416
2417 // create a network satisfying request - validate that request not triggered
2418 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2419 mWiFiNetworkAgent.connect(false);
2420 networkCallback.assertNoCallback();
2421 }
2422
Hugo Benichi53d83d52016-11-15 13:42:34 +09002423 public void assertEventuallyTrue(BooleanSupplier fn, long maxWaitingTimeMs) throws Exception {
2424 long start = SystemClock.elapsedRealtime();
2425 while (SystemClock.elapsedRealtime() <= start + maxWaitingTimeMs) {
2426 if (fn.getAsBoolean()) {
2427 return;
2428 }
2429 Thread.sleep(10);
2430 }
2431 assertTrue(fn.getAsBoolean());
2432 }
2433
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002434 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
2435
2436 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
2437
2438 private class CallbackValue {
2439 public CallbackType callbackType;
2440 public int error;
2441
2442 public CallbackValue(CallbackType type) {
2443 this.callbackType = type;
2444 this.error = PacketKeepalive.SUCCESS;
2445 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
2446 }
2447
2448 public CallbackValue(CallbackType type, int error) {
2449 this.callbackType = type;
2450 this.error = error;
2451 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
2452 }
2453
2454 @Override
2455 public boolean equals(Object o) {
2456 return o instanceof CallbackValue &&
2457 this.callbackType == ((CallbackValue) o).callbackType &&
2458 this.error == ((CallbackValue) o).error;
2459 }
2460
2461 @Override
2462 public String toString() {
2463 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
2464 }
2465 }
2466
2467 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
2468
2469 @Override
2470 public void onStarted() {
2471 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
2472 }
2473
2474 @Override
2475 public void onStopped() {
2476 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
2477 }
2478
2479 @Override
2480 public void onError(int error) {
2481 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
2482 }
2483
2484 private void expectCallback(CallbackValue callbackValue) {
2485 try {
2486 assertEquals(
2487 callbackValue,
2488 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
2489 } catch (InterruptedException e) {
2490 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
2491 }
2492 }
2493
2494 public void expectStarted() {
2495 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
2496 }
2497
2498 public void expectStopped() {
2499 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
2500 }
2501
2502 public void expectError(int error) {
2503 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
2504 }
2505 }
2506
2507 private Network connectKeepaliveNetwork(LinkProperties lp) {
2508 // Ensure the network is disconnected before we do anything.
2509 if (mWiFiNetworkAgent != null) {
2510 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
2511 }
2512
2513 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2514 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2515 mWiFiNetworkAgent.connect(true);
2516 waitFor(cv);
2517 verifyActiveNetwork(TRANSPORT_WIFI);
2518 mWiFiNetworkAgent.sendLinkProperties(lp);
2519 mService.waitForIdle();
2520 return mWiFiNetworkAgent.getNetwork();
2521 }
2522
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09002523 @SmallTest
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002524 public void testPacketKeepalives() throws Exception {
2525 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
2526 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
2527 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
2528 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
2529 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
2530
2531 LinkProperties lp = new LinkProperties();
2532 lp.setInterfaceName("wlan12");
2533 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
2534 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
2535 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
2536 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
2537
2538 Network notMyNet = new Network(61234);
2539 Network myNet = connectKeepaliveNetwork(lp);
2540
2541 TestKeepaliveCallback callback = new TestKeepaliveCallback();
2542 PacketKeepalive ka;
2543
2544 // Attempt to start keepalives with invalid parameters and check for errors.
2545 ka = mCm.startNattKeepalive(notMyNet, 25, callback, myIPv4, 1234, dstIPv4);
2546 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
2547
2548 ka = mCm.startNattKeepalive(myNet, 19, callback, notMyIPv4, 1234, dstIPv4);
2549 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
2550
2551 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 1234, dstIPv6);
2552 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2553
2554 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv4);
2555 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2556
2557 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv6);
2558 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); // NAT-T is IPv4-only.
2559
2560 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
2561 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
2562
2563 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
2564 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
2565
2566 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2567 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
2568
2569 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2570 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
2571
2572 // Check that a started keepalive can be stopped.
2573 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2574 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2575 callback.expectStarted();
2576 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
2577 ka.stop();
2578 callback.expectStopped();
2579
2580 // Check that deleting the IP address stops the keepalive.
2581 LinkProperties bogusLp = new LinkProperties(lp);
2582 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2583 callback.expectStarted();
2584 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
2585 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
2586 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
2587 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2588 mWiFiNetworkAgent.sendLinkProperties(lp);
2589
2590 // Check that a started keepalive is stopped correctly when the network disconnects.
2591 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2592 callback.expectStarted();
2593 mWiFiNetworkAgent.disconnect();
2594 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
2595
2596 // ... and that stopping it after that has no adverse effects.
2597 assertNull(mCm.getNetworkCapabilities(myNet));
2598 ka.stop();
2599
2600 // Reconnect.
2601 myNet = connectKeepaliveNetwork(lp);
2602 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2603
2604 // Check things work as expected when the keepalive is stopped and the network disconnects.
2605 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2606 callback.expectStarted();
2607 ka.stop();
2608 mWiFiNetworkAgent.disconnect();
2609 mService.waitForIdle();
2610 callback.expectStopped();
2611
2612 // Reconnect.
2613 myNet = connectKeepaliveNetwork(lp);
2614 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2615
2616 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
2617 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
2618 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2619 callback.expectStarted();
2620
2621 // The second one gets slot 2.
2622 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
2623 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
2624 PacketKeepalive ka2 = mCm.startNattKeepalive(myNet, 25, callback2, myIPv4, 6789, dstIPv4);
2625 callback2.expectStarted();
2626
2627 // Now stop the first one and create a third. This also gets slot 1.
2628 ka.stop();
2629 callback.expectStopped();
2630
2631 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
2632 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
2633 PacketKeepalive ka3 = mCm.startNattKeepalive(myNet, 25, callback3, myIPv4, 9876, dstIPv4);
2634 callback3.expectStarted();
2635
2636 ka2.stop();
2637 callback2.expectStopped();
2638
2639 ka3.stop();
2640 callback3.expectStopped();
2641 }
Udam Sainib7c24872016-01-04 12:16:14 -08002642
2643 @SmallTest
2644 public void testGetCaptivePortalServerUrl() throws Exception {
2645 String url = mCm.getCaptivePortalServerUrl();
2646 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
2647 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09002648
2649 private static class TestNetworkPinner extends NetworkPinner {
2650 public static boolean awaitPin(int timeoutMs) {
2651 synchronized(sLock) {
2652 if (sNetwork == null) {
2653 try {
2654 sLock.wait(timeoutMs);
2655 } catch (InterruptedException e) {}
2656 }
2657 return sNetwork != null;
2658 }
2659 }
2660
2661 public static boolean awaitUnpin(int timeoutMs) {
2662 synchronized(sLock) {
2663 if (sNetwork != null) {
2664 try {
2665 sLock.wait(timeoutMs);
2666 } catch (InterruptedException e) {}
2667 }
2668 return sNetwork == null;
2669 }
2670 }
2671 }
2672
2673 private void assertPinnedToWifiWithCellDefault() {
2674 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
2675 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2676 }
2677
2678 private void assertPinnedToWifiWithWifiDefault() {
2679 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
2680 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2681 }
2682
2683 private void assertNotPinnedToWifi() {
2684 assertNull(mCm.getBoundNetworkForProcess());
2685 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2686 }
2687
2688 @SmallTest
2689 public void testNetworkPinner() {
2690 NetworkRequest wifiRequest = new NetworkRequest.Builder()
2691 .addTransportType(TRANSPORT_WIFI)
2692 .build();
2693 assertNull(mCm.getBoundNetworkForProcess());
2694
2695 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2696 assertNull(mCm.getBoundNetworkForProcess());
2697
2698 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2699 mCellNetworkAgent.connect(true);
2700 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2701 mWiFiNetworkAgent.connect(false);
2702
2703 // When wi-fi connects, expect to be pinned.
2704 assertTrue(TestNetworkPinner.awaitPin(100));
2705 assertPinnedToWifiWithCellDefault();
2706
2707 // Disconnect and expect the pin to drop.
2708 mWiFiNetworkAgent.disconnect();
2709 assertTrue(TestNetworkPinner.awaitUnpin(100));
2710 assertNotPinnedToWifi();
2711
2712 // Reconnecting does not cause the pin to come back.
2713 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2714 mWiFiNetworkAgent.connect(false);
2715 assertFalse(TestNetworkPinner.awaitPin(100));
2716 assertNotPinnedToWifi();
2717
2718 // Pinning while connected causes the pin to take effect immediately.
2719 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2720 assertTrue(TestNetworkPinner.awaitPin(100));
2721 assertPinnedToWifiWithCellDefault();
2722
2723 // Explicitly unpin and expect to use the default network again.
2724 TestNetworkPinner.unpin();
2725 assertNotPinnedToWifi();
2726
2727 // Disconnect cell and wifi.
2728 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
2729 mCellNetworkAgent.disconnect();
2730 mWiFiNetworkAgent.disconnect();
2731 waitFor(cv);
2732
2733 // Pinning takes effect even if the pinned network is the default when the pin is set...
2734 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2735 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2736 mWiFiNetworkAgent.connect(false);
2737 assertTrue(TestNetworkPinner.awaitPin(100));
2738 assertPinnedToWifiWithWifiDefault();
2739
2740 // ... and is maintained even when that network is no longer the default.
2741 cv = waitForConnectivityBroadcasts(1);
2742 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2743 mCellNetworkAgent.connect(true);
2744 waitFor(cv);
2745 assertPinnedToWifiWithCellDefault();
2746 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04002747
2748 @SmallTest
2749 public void testNetworkRequestMaximum() {
2750 final int MAX_REQUESTS = 100;
2751 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
2752 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
2753 ArrayList<NetworkCallback> networkCallbacks = new ArrayList<NetworkCallback>();
2754 try {
2755 for (int i = 0; i < MAX_REQUESTS; i++) {
2756 NetworkCallback networkCallback = new NetworkCallback();
2757 mCm.requestNetwork(networkRequest, networkCallback);
2758 networkCallbacks.add(networkCallback);
2759 }
2760 fail("Registering " + MAX_REQUESTS + " NetworkRequests did not throw exception");
2761 } catch (IllegalArgumentException expected) {}
2762 for (NetworkCallback networkCallback : networkCallbacks) {
2763 mCm.unregisterNetworkCallback(networkCallback);
2764 }
2765 networkCallbacks.clear();
2766
2767 try {
2768 for (int i = 0; i < MAX_REQUESTS; i++) {
2769 NetworkCallback networkCallback = new NetworkCallback();
2770 mCm.registerNetworkCallback(networkRequest, networkCallback);
2771 networkCallbacks.add(networkCallback);
2772 }
2773 fail("Registering " + MAX_REQUESTS + " NetworkCallbacks did not throw exception");
2774 } catch (IllegalArgumentException expected) {}
2775 for (NetworkCallback networkCallback : networkCallbacks) {
2776 mCm.unregisterNetworkCallback(networkCallback);
2777 }
2778 networkCallbacks.clear();
2779
2780 ArrayList<PendingIntent> pendingIntents = new ArrayList<PendingIntent>();
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.requestNetwork(networkRequest, pendingIntent);
2786 pendingIntents.add(pendingIntent);
2787 }
2788 fail("Registering " + MAX_REQUESTS +
2789 " PendingIntent NetworkRequests did not throw exception");
2790 } catch (IllegalArgumentException expected) {}
2791 for (PendingIntent pendingIntent : pendingIntents) {
2792 mCm.unregisterNetworkCallback(pendingIntent);
2793 }
2794 pendingIntents.clear();
2795
2796 try {
2797 for (int i = 0; i < MAX_REQUESTS + 1; i++) {
2798 PendingIntent pendingIntent =
2799 PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
2800 mCm.registerNetworkCallback(networkRequest, pendingIntent);
2801 pendingIntents.add(pendingIntent);
2802 }
2803 fail("Registering " + MAX_REQUESTS +
2804 " PendingIntent NetworkCallbacks did not throw exception");
2805 } catch (IllegalArgumentException expected) {}
2806 for (PendingIntent pendingIntent : pendingIntents) {
2807 mCm.unregisterNetworkCallback(pendingIntent);
2808 }
2809 pendingIntents.clear();
2810 mService.waitForIdle(5000);
2811
2812 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
2813 for (int i = 0; i < MAX_REQUESTS; i++) {
2814 NetworkCallback networkCallback = new NetworkCallback();
2815 mCm.requestNetwork(networkRequest, networkCallback);
2816 mCm.unregisterNetworkCallback(networkCallback);
2817 }
2818 mService.waitForIdle();
2819 for (int i = 0; i < MAX_REQUESTS; i++) {
2820 NetworkCallback networkCallback = new NetworkCallback();
2821 mCm.registerNetworkCallback(networkRequest, networkCallback);
2822 mCm.unregisterNetworkCallback(networkCallback);
2823 }
2824 mService.waitForIdle();
2825 for (int i = 0; i < MAX_REQUESTS; i++) {
2826 PendingIntent pendingIntent =
2827 PendingIntent.getBroadcast(mContext, 0, new Intent("b" + i), 0);
2828 mCm.requestNetwork(networkRequest, pendingIntent);
2829 mCm.unregisterNetworkCallback(pendingIntent);
2830 }
2831 mService.waitForIdle();
2832 for (int i = 0; i < MAX_REQUESTS; i++) {
2833 PendingIntent pendingIntent =
2834 PendingIntent.getBroadcast(mContext, 0, new Intent("c" + i), 0);
2835 mCm.registerNetworkCallback(networkRequest, pendingIntent);
2836 mCm.unregisterNetworkCallback(pendingIntent);
2837 }
2838 }
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07002839
2840 /* test utilities */
2841 static private void sleepFor(int ms) {
2842 try {
2843 Thread.sleep(ms);
2844 } catch (InterruptedException e) {
2845 }
2846
2847 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07002848}