blob: 4b3f99277e80e037a8f4442a208872739d91afd4 [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 Benichi86e27652016-10-17 15:54:51 +090071import android.test.FlakyTest;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +090072import android.test.mock.MockContentResolver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070073import android.test.suitebuilder.annotation.LargeTest;
Udam Sainib7c24872016-01-04 12:16:14 -080074import android.test.suitebuilder.annotation.SmallTest;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070075import android.util.Log;
76import android.util.LogPrinter;
77
Lorenzo Colittibfecba22016-02-21 01:09:26 +090078import com.android.internal.util.WakeupMessage;
Lorenzo Colitti073e5e92016-10-28 12:56:03 +090079import com.android.internal.util.test.BroadcastInterceptingContext;
Lorenzo Colitti9997f142016-10-28 12:37:38 +090080import com.android.internal.util.test.FakeSettingsProvider;
Paul Jensencf4c2c62015-07-01 14:16:32 -040081import com.android.server.connectivity.NetworkAgentInfo;
Paul Jensend7b6ca92015-05-13 14:05:12 -040082import com.android.server.connectivity.NetworkMonitor;
Paul Jensen232437312016-04-06 09:51:26 -040083import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
Lorenzo Colitti531a3442016-03-01 12:55:58 +090084import com.android.server.net.NetworkPinner;
Paul Jensend7b6ca92015-05-13 14:05:12 -040085
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070086import java.net.InetAddress;
Paul Jensen4e1d3fd2016-04-08 13:56:52 -040087import java.util.ArrayList;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +090088import java.util.Arrays;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +090089import java.util.Objects;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +090090import java.util.concurrent.CountDownLatch;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +090091import java.util.concurrent.LinkedBlockingQueue;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +090092import java.util.concurrent.TimeUnit;
Robert Greenwalt348e98d2015-06-05 17:55:36 -070093import java.util.concurrent.atomic.AtomicBoolean;
Hugo Benichibccd8ad2016-11-15 13:42:34 +090094import java.util.function.BooleanSupplier;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070095
96/**
97 * Tests for {@link ConnectivityService}.
Paul Jensend7b6ca92015-05-13 14:05:12 -040098 *
99 * Build, install and run with:
100 * runtest frameworks-services -c com.android.server.ConnectivityServiceTest
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700101 */
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700102public class ConnectivityServiceTest extends AndroidTestCase {
103 private static final String TAG = "ConnectivityServiceTest";
104
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900105 private static final int TIMEOUT_MS = 500;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900106 private static final int TEST_LINGER_DELAY_MS = 120;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900107
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700108 private BroadcastInterceptingContext mServiceContext;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400109 private WrappedConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900110 private WrappedConnectivityManager mCm;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400111 private MockNetworkAgent mWiFiNetworkAgent;
112 private MockNetworkAgent mCellNetworkAgent;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900113 private MockNetworkAgent mEthernetNetworkAgent;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700114
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900115 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
116 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
117 // reflect the state of our test ConnectivityService.
118 private class WrappedConnectivityManager extends ConnectivityManager {
119 private Network mFakeBoundNetwork;
120
121 public synchronized boolean bindProcessToNetwork(Network network) {
122 mFakeBoundNetwork = network;
123 return true;
124 }
125
126 public synchronized Network getBoundNetworkForProcess() {
127 return mFakeBoundNetwork;
128 }
129
130 public WrappedConnectivityManager(Context context, ConnectivityService service) {
131 super(context, service);
132 }
133 }
134
Paul Jensend7b6ca92015-05-13 14:05:12 -0400135 private class MockContext extends BroadcastInterceptingContext {
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900136 private final MockContentResolver mContentResolver;
137
Paul Jensend7b6ca92015-05-13 14:05:12 -0400138 MockContext(Context base) {
139 super(base);
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900140 mContentResolver = new MockContentResolver();
141 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
Paul Jensend7b6ca92015-05-13 14:05:12 -0400142 }
143
144 @Override
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900145 public Object getSystemService(String name) {
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900146 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
147 if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400148 return super.getSystemService(name);
149 }
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900150
151 @Override
152 public ContentResolver getContentResolver() {
153 return mContentResolver;
154 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400155 }
156
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900157 /**
158 * A subclass of HandlerThread that allows callers to wait for it to become idle. waitForIdle
159 * will return immediately if the handler is already idle.
160 */
161 private class IdleableHandlerThread extends HandlerThread {
162 private IdleHandler mIdleHandler;
163
164 public IdleableHandlerThread(String name) {
165 super(name);
166 }
167
168 public void waitForIdle(int timeoutMs) {
169 final ConditionVariable cv = new ConditionVariable();
170 final MessageQueue queue = getLooper().getQueue();
171
172 synchronized (queue) {
173 if (queue.isIdle()) {
174 return;
175 }
176
177 assertNull("BUG: only one idle handler allowed", mIdleHandler);
178 mIdleHandler = new IdleHandler() {
179 public boolean queueIdle() {
Lorenzo Colitti5eaaf742016-03-02 21:47:42 +0900180 synchronized (queue) {
181 cv.open();
182 mIdleHandler = null;
183 return false; // Remove the handler.
184 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900185 }
186 };
187 queue.addIdleHandler(mIdleHandler);
188 }
189
190 if (!cv.block(timeoutMs)) {
191 fail("HandlerThread " + getName() +
192 " did not become idle after " + timeoutMs + " ms");
193 queue.removeIdleHandler(mIdleHandler);
194 }
195 }
196 }
197
198 // Tests that IdleableHandlerThread works as expected.
199 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 Benichi86e27652016-10-17 15:54:51 +0900221 }
222
223 @FlakyTest(tolerance = 3)
224 public void testNotWaitingForIdleCausesRaceConditions() {
225 // Bring up a network that we can use to send messages to ConnectivityService.
226 ConditionVariable cv = waitForConnectivityBroadcasts(1);
227 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
228 mWiFiNetworkAgent.connect(false);
229 waitFor(cv);
230 Network n = mWiFiNetworkAgent.getNetwork();
231 assertNotNull(n);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900232
233 // Ensure that not calling waitForIdle causes a race condition.
Hugo Benichi86e27652016-10-17 15:54:51 +0900234 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900235 for (int i = 0; i < attempts; i++) {
236 mWiFiNetworkAgent.setSignalStrength(i);
237 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
238 // We hit a race condition, as expected. Pass the test.
239 return;
240 }
241 }
242
243 // No race? There is a bug in this test.
244 fail("expected race condition at least once in " + attempts + " attempts");
245 }
246
Paul Jensend7b6ca92015-05-13 14:05:12 -0400247 private class MockNetworkAgent {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400248 private final WrappedNetworkMonitor mWrappedNetworkMonitor;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400249 private final NetworkInfo mNetworkInfo;
250 private final NetworkCapabilities mNetworkCapabilities;
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900251 private final IdleableHandlerThread mHandlerThread;
Paul Jensene0988542015-06-25 15:30:08 -0400252 private final ConditionVariable mDisconnected = new ConditionVariable();
Paul Jensen232437312016-04-06 09:51:26 -0400253 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
Calvin On4bc78eb2016-10-11 15:10:46 -0700254 private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
Paul Jensen3d911462015-06-12 06:40:24 -0400255 private int mScore;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400256 private NetworkAgent mNetworkAgent;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900257 private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
258 private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE;
259 private Integer mExpectedKeepaliveSlot = null;
Paul Jensen232437312016-04-06 09:51:26 -0400260 // Contains the redirectUrl from networkStatus(). Before reading, wait for
261 // mNetworkStatusReceived.
262 private String mRedirectUrl;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400263
264 MockNetworkAgent(int transport) {
265 final int type = transportToLegacyType(transport);
266 final String typeName = ConnectivityManager.getNetworkTypeName(type);
267 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
268 mNetworkCapabilities = new NetworkCapabilities();
269 mNetworkCapabilities.addTransportType(transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400270 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900271 case TRANSPORT_ETHERNET:
272 mScore = 70;
273 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400274 case TRANSPORT_WIFI:
Paul Jensen3d911462015-06-12 06:40:24 -0400275 mScore = 60;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400276 break;
277 case TRANSPORT_CELLULAR:
Paul Jensen3d911462015-06-12 06:40:24 -0400278 mScore = 50;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400279 break;
280 default:
281 throw new UnsupportedOperationException("unimplemented network type");
282 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900283 mHandlerThread = new IdleableHandlerThread("Mock-" + typeName);
284 mHandlerThread.start();
285 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
286 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
287 new LinkProperties(), mScore, new NetworkMisc()) {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900288 @Override
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900289 public void unwanted() { mDisconnected.open(); }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900290
291 @Override
292 public void startPacketKeepalive(Message msg) {
293 int slot = msg.arg1;
294 if (mExpectedKeepaliveSlot != null) {
295 assertEquals((int) mExpectedKeepaliveSlot, slot);
296 }
297 onPacketKeepaliveEvent(slot, mStartKeepaliveError);
298 }
299
300 @Override
301 public void stopPacketKeepalive(Message msg) {
302 onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
303 }
Paul Jensen232437312016-04-06 09:51:26 -0400304
305 @Override
306 public void networkStatus(int status, String redirectUrl) {
307 mRedirectUrl = redirectUrl;
308 mNetworkStatusReceived.open();
309 }
Calvin On4bc78eb2016-10-11 15:10:46 -0700310
311 @Override
312 protected void preventAutomaticReconnect() {
313 mPreventReconnectReceived.open();
314 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400315 };
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900316 // Waits for the NetworkAgent to be registered, which includes the creation of the
317 // NetworkMonitor.
318 mService.waitForIdle();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400319 mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor();
Paul Jensen3d911462015-06-12 06:40:24 -0400320 }
321
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900322 public void waitForIdle(int timeoutMs) {
323 mHandlerThread.waitForIdle(timeoutMs);
324 }
325
326 public void waitForIdle() {
327 waitForIdle(TIMEOUT_MS);
328 }
329
Paul Jensen3d911462015-06-12 06:40:24 -0400330 public void adjustScore(int change) {
331 mScore += change;
332 mNetworkAgent.sendNetworkScore(mScore);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400333 }
334
Paul Jensen85cf78e2015-06-25 13:25:07 -0400335 public void addCapability(int capability) {
336 mNetworkCapabilities.addCapability(capability);
337 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
338 }
339
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900340 public void removeCapability(int capability) {
341 mNetworkCapabilities.removeCapability(capability);
342 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
343 }
344
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900345 public void setSignalStrength(int signalStrength) {
346 mNetworkCapabilities.setSignalStrength(signalStrength);
347 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
348 }
349
Paul Jensene0988542015-06-25 15:30:08 -0400350 public void connectWithoutInternet() {
351 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
352 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
353 }
354
Paul Jensend7b6ca92015-05-13 14:05:12 -0400355 /**
Paul Jensene0988542015-06-25 15:30:08 -0400356 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400357 * @param validated Indicate if network should pretend to be validated.
358 */
359 public void connect(boolean validated) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900360 assertEquals("MockNetworkAgents can only be connected once",
361 mNetworkInfo.getDetailedState(), DetailedState.IDLE);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400362 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
363
Paul Jensend7b6ca92015-05-13 14:05:12 -0400364 NetworkCallback callback = null;
365 final ConditionVariable validatedCv = new ConditionVariable();
366 if (validated) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400367 mWrappedNetworkMonitor.gen204ProbeResult = 204;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400368 NetworkRequest request = new NetworkRequest.Builder()
369 .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
370 .build();
371 callback = new NetworkCallback() {
372 public void onCapabilitiesChanged(Network network,
373 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400374 if (network.equals(getNetwork()) &&
375 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400376 validatedCv.open();
377 }
378 }
379 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400380 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400381 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400382 addCapability(NET_CAPABILITY_INTERNET);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400383
Paul Jensene0988542015-06-25 15:30:08 -0400384 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400385
386 if (validated) {
387 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400388 waitFor(validatedCv);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400389 mWrappedNetworkMonitor.gen204ProbeResult = 500;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400390 }
391
392 if (callback != null) mCm.unregisterNetworkCallback(callback);
393 }
394
Paul Jensen232437312016-04-06 09:51:26 -0400395 public void connectWithCaptivePortal(String redirectUrl) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400396 mWrappedNetworkMonitor.gen204ProbeResult = 200;
Paul Jensen232437312016-04-06 09:51:26 -0400397 mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400398 connect(false);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400399 }
400
Paul Jensend7b6ca92015-05-13 14:05:12 -0400401 public void disconnect() {
402 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
403 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
404 }
405
406 public Network getNetwork() {
407 return new Network(mNetworkAgent.netId);
408 }
Paul Jensene0988542015-06-25 15:30:08 -0400409
Calvin On4bc78eb2016-10-11 15:10:46 -0700410 public ConditionVariable getPreventReconnectReceived() {
411 return mPreventReconnectReceived;
412 }
413
Paul Jensene0988542015-06-25 15:30:08 -0400414 public ConditionVariable getDisconnectedCV() {
415 return mDisconnected;
416 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400417
418 public WrappedNetworkMonitor getWrappedNetworkMonitor() {
419 return mWrappedNetworkMonitor;
420 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900421
422 public void sendLinkProperties(LinkProperties lp) {
423 mNetworkAgent.sendLinkProperties(lp);
424 }
425
426 public void setStartKeepaliveError(int error) {
427 mStartKeepaliveError = error;
428 }
429
430 public void setStopKeepaliveError(int error) {
431 mStopKeepaliveError = error;
432 }
433
434 public void setExpectedKeepaliveSlot(Integer slot) {
435 mExpectedKeepaliveSlot = slot;
436 }
Paul Jensen232437312016-04-06 09:51:26 -0400437
438 public String waitForRedirectUrl() {
439 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
440 return mRedirectUrl;
441 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400442 }
443
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900444 /**
445 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
446 * operations have been processed. Before ConnectivityService can add or remove any requests,
447 * the factory must be told to expect those operations by calling expectAddRequests or
448 * expectRemoveRequests.
449 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700450 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400451 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
452 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400453 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700454
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900455 // Used to expect that requests be removed or added on a separate thread, without sleeping.
456 // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then
457 // cause some other thread to add or remove requests, then call waitForRequests(). We can
458 // either expect requests to be added or removed, but not both, because CountDownLatch can
459 // only count in one direction.
460 private CountDownLatch mExpectations;
461
462 // Whether we are currently expecting requests to be added or removed. Valid only if
463 // mExpectations is non-null.
464 private boolean mExpectingAdditions;
465
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700466 public MockNetworkFactory(Looper looper, Context context, String logTag,
467 NetworkCapabilities filter) {
468 super(looper, context, logTag, filter);
469 }
470
471 public int getMyRequestCount() {
472 return getRequestCount();
473 }
474
475 protected void startNetwork() {
476 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400477 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700478 }
479
480 protected void stopNetwork() {
481 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400482 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700483 }
484
485 public boolean getMyStartRequested() {
486 return mNetworkStarted.get();
487 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400488
489 public ConditionVariable getNetworkStartedCV() {
490 mNetworkStartedCV.close();
491 return mNetworkStartedCV;
492 }
493
494 public ConditionVariable getNetworkStoppedCV() {
495 mNetworkStoppedCV.close();
496 return mNetworkStoppedCV;
497 }
498
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900499 @Override
500 protected void handleAddRequest(NetworkRequest request, int score) {
501 // If we're expecting anything, we must be expecting additions.
502 if (mExpectations != null && !mExpectingAdditions) {
503 fail("Can't add requests while expecting requests to be removed");
504 }
505
506 // Add the request.
507 super.handleAddRequest(request, score);
508
509 // Reduce the number of request additions we're waiting for.
510 if (mExpectingAdditions) {
511 assertTrue("Added more requests than expected", mExpectations.getCount() > 0);
512 mExpectations.countDown();
513 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400514 }
515
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900516 @Override
517 protected void handleRemoveRequest(NetworkRequest request) {
518 // If we're expecting anything, we must be expecting removals.
519 if (mExpectations != null && mExpectingAdditions) {
520 fail("Can't remove requests while expecting requests to be added");
521 }
522
523 // Remove the request.
524 super.handleRemoveRequest(request);
525
526 // Reduce the number of request removals we're waiting for.
527 if (!mExpectingAdditions) {
528 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0);
529 mExpectations.countDown();
530 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400531 }
532
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900533 private void assertNoExpectations() {
534 if (mExpectations != null) {
535 fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
536 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400537 }
538
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900539 // Expects that count requests will be added.
540 public void expectAddRequests(final int count) {
541 assertNoExpectations();
542 mExpectingAdditions = true;
543 mExpectations = new CountDownLatch(count);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400544 }
545
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900546 // Expects that count requests will be removed.
547 public void expectRemoveRequests(final int count) {
548 assertNoExpectations();
549 mExpectingAdditions = false;
550 mExpectations = new CountDownLatch(count);
551 }
552
553 // Waits for the expected request additions or removals to happen within a timeout.
554 public void waitForRequests() throws InterruptedException {
555 assertNotNull("Nothing to wait for", mExpectations);
556 mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
557 final long count = mExpectations.getCount();
558 final String msg = count + " requests still not " +
559 (mExpectingAdditions ? "added" : "removed") +
560 " after " + TIMEOUT_MS + " ms";
561 assertEquals(msg, 0, count);
562 mExpectations = null;
563 }
564
565 public void waitForNetworkRequests(final int count) throws InterruptedException {
566 waitForRequests();
567 assertEquals(count, getMyRequestCount());
Paul Jensen0a2823e2015-06-12 10:31:09 -0400568 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700569 }
570
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900571 private class FakeWakeupMessage extends WakeupMessage {
572 private static final int UNREASONABLY_LONG_WAIT = 1000;
573
574 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
575 super(context, handler, cmdName, cmd);
576 }
577
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900578 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
579 int arg1, int arg2, Object obj) {
580 super(context, handler, cmdName, cmd, arg1, arg2, obj);
581 }
582
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900583 @Override
584 public void schedule(long when) {
585 long delayMs = when - SystemClock.elapsedRealtime();
586 if (delayMs < 0) delayMs = 0;
587 if (delayMs > UNREASONABLY_LONG_WAIT) {
588 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
589 "ms into the future: " + delayMs);
590 }
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900591 Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
592 mHandler.sendMessageDelayed(msg, delayMs);
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900593 }
594
595 @Override
596 public void cancel() {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900597 mHandler.removeMessages(mCmd, mObj);
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900598 }
599
600 @Override
601 public void onAlarm() {
602 throw new AssertionError("Should never happen. Update this fake.");
603 }
604 }
605
Paul Jensencf4c2c62015-07-01 14:16:32 -0400606 // NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
607 private class WrappedNetworkMonitor extends NetworkMonitor {
608 // HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
609 public int gen204ProbeResult = 500;
Paul Jensen232437312016-04-06 09:51:26 -0400610 public String gen204ProbeRedirectUrl = null;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400611
612 public WrappedNetworkMonitor(Context context, Handler handler,
Hugo Benichif9fdf872016-07-28 17:53:06 +0900613 NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest,
614 IpConnectivityLog log) {
615 super(context, handler, networkAgentInfo, defaultRequest, log);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400616 }
617
618 @Override
Paul Jensen232437312016-04-06 09:51:26 -0400619 protected CaptivePortalProbeResult isCaptivePortal() {
Calvin On4bc78eb2016-10-11 15:10:46 -0700620 if (!mIsCaptivePortalCheckEnabled) { return new CaptivePortalProbeResult(204); }
Hugo Benichid953bf82016-09-27 09:22:35 +0900621 return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl, null);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400622 }
623 }
624
Erik Kline065ab6e2016-10-02 18:02:14 +0900625 private class WrappedAvoidBadWifiTracker extends AvoidBadWifiTracker {
Hugo Benichibccd8ad2016-11-15 13:42:34 +0900626 public volatile boolean configRestrictsAvoidBadWifi;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400627
Erik Kline065ab6e2016-10-02 18:02:14 +0900628 public WrappedAvoidBadWifiTracker(Context c, Handler h, Runnable r) {
629 super(c, h, r);
630 }
631
632 @Override
633 public boolean configRestrictsAvoidBadWifi() {
634 return configRestrictsAvoidBadWifi;
635 }
636 }
637
638 private class WrappedConnectivityService extends ConnectivityService {
639 public WrappedAvoidBadWifiTracker wrappedAvoidBadWifiTracker;
640 private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
641
Paul Jensend7b6ca92015-05-13 14:05:12 -0400642 public WrappedConnectivityService(Context context, INetworkManagementService netManager,
Hugo Benichif9fdf872016-07-28 17:53:06 +0900643 INetworkStatsService statsService, INetworkPolicyManager policyManager,
644 IpConnectivityLog log) {
645 super(context, netManager, statsService, policyManager, log);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900646 mLingerDelayMs = TEST_LINGER_DELAY_MS;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400647 }
648
649 @Override
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900650 protected HandlerThread createHandlerThread() {
651 return new IdleableHandlerThread("WrappedConnectivityService");
652 }
653
654 @Override
Paul Jensend7b6ca92015-05-13 14:05:12 -0400655 protected int getDefaultTcpRwnd() {
656 // Prevent wrapped ConnectivityService from trying to write to SystemProperties.
657 return 0;
658 }
Paul Jensen67b0b072015-06-10 11:22:17 -0400659
660 @Override
661 protected int reserveNetId() {
662 while (true) {
663 final int netId = super.reserveNetId();
664
665 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
666 // can have odd side-effects, like network validations succeeding.
667 final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks();
668 boolean overlaps = false;
669 for (Network network : networks) {
670 if (netId == network.netId) {
671 overlaps = true;
672 break;
673 }
674 }
675 if (overlaps) continue;
676
677 return netId;
678 }
679 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400680
681 @Override
682 public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
683 NetworkAgentInfo nai, NetworkRequest defaultRequest) {
Hugo Benichif9fdf872016-07-28 17:53:06 +0900684 final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(
685 context, handler, nai, defaultRequest, mock(IpConnectivityLog.class));
Paul Jensencf4c2c62015-07-01 14:16:32 -0400686 mLastCreatedNetworkMonitor = monitor;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400687 return monitor;
688 }
689
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900690 @Override
Erik Kline065ab6e2016-10-02 18:02:14 +0900691 public AvoidBadWifiTracker createAvoidBadWifiTracker(
692 Context c, Handler h, Runnable r) {
693 final WrappedAvoidBadWifiTracker tracker = new WrappedAvoidBadWifiTracker(c, h, r);
694 return tracker;
695 }
696
697 public WrappedAvoidBadWifiTracker getAvoidBadWifiTracker() {
698 return (WrappedAvoidBadWifiTracker) mAvoidBadWifiTracker;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900699 }
700
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900701 @Override
Erik Kline065ab6e2016-10-02 18:02:14 +0900702 public WakeupMessage makeWakeupMessage(
703 Context context, Handler handler, String cmdName, int cmd, Object obj) {
704 return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900705 }
706
Paul Jensencf4c2c62015-07-01 14:16:32 -0400707 public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
708 return mLastCreatedNetworkMonitor;
709 }
710
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900711 public void waitForIdle(int timeoutMs) {
712 ((IdleableHandlerThread) mHandlerThread).waitForIdle(timeoutMs);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400713 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900714
715 public void waitForIdle() {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900716 waitForIdle(TIMEOUT_MS);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900717 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400718 }
719
Paul Jensen0a2823e2015-06-12 10:31:09 -0400720 private interface Criteria {
721 public boolean get();
722 }
723
Paul Jensen3d911462015-06-12 06:40:24 -0400724 /**
725 * Wait up to 500ms for {@code criteria.get()} to become true, polling.
726 * Fails if 500ms goes by before {@code criteria.get()} to become true.
727 */
Paul Jensen0a2823e2015-06-12 10:31:09 -0400728 static private void waitFor(Criteria criteria) {
729 int delays = 0;
730 while (!criteria.get()) {
Etan Cohen4fde1672016-10-27 15:05:50 -0700731 sleepFor(50);
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900732 if (++delays == 10) fail();
Paul Jensen0a2823e2015-06-12 10:31:09 -0400733 }
734 }
735
Paul Jensen3d911462015-06-12 06:40:24 -0400736 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900737 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
738 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -0400739 */
740 static private void waitFor(ConditionVariable conditionVariable) {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900741 assertTrue(conditionVariable.block(TIMEOUT_MS));
Paul Jensen3d911462015-06-12 06:40:24 -0400742 }
743
Paul Jensend7b6ca92015-05-13 14:05:12 -0400744 @Override
745 public void setUp() throws Exception {
746 super.setUp();
747
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +0900748 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
749 // http://b/25897652 .
750 if (Looper.myLooper() == null) {
751 Looper.prepare();
752 }
753
Paul Jensend7b6ca92015-05-13 14:05:12 -0400754 mServiceContext = new MockContext(getContext());
Lorenzo Colitti83fa2582015-08-07 12:49:01 +0900755 mService = new WrappedConnectivityService(mServiceContext,
756 mock(INetworkManagementService.class),
757 mock(INetworkStatsService.class),
Hugo Benichif9fdf872016-07-28 17:53:06 +0900758 mock(INetworkPolicyManager.class),
759 mock(IpConnectivityLog.class));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400760
Paul Jensend7b6ca92015-05-13 14:05:12 -0400761 mService.systemReady();
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900762 mCm = new WrappedConnectivityManager(getContext(), mService);
763 mCm.bindProcessToNetwork(null);
Calvin On4bc78eb2016-10-11 15:10:46 -0700764
765 // Ensure that the default setting for Captive Portals is used for most tests
766 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400767 }
768
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +0900769 public void tearDown() throws Exception {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +0900770 setMobileDataAlwaysOn(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +0900771 if (mCellNetworkAgent != null) { mCellNetworkAgent.disconnect(); }
772 if (mWiFiNetworkAgent != null) { mWiFiNetworkAgent.disconnect(); }
773 mCellNetworkAgent = mWiFiNetworkAgent = null;
774 super.tearDown();
775 }
776
Paul Jensend7b6ca92015-05-13 14:05:12 -0400777 private int transportToLegacyType(int transport) {
778 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900779 case TRANSPORT_ETHERNET:
780 return TYPE_ETHERNET;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400781 case TRANSPORT_WIFI:
782 return TYPE_WIFI;
783 case TRANSPORT_CELLULAR:
784 return TYPE_MOBILE;
785 default:
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900786 throw new IllegalStateException("Unknown transport " + transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400787 }
788 }
789
790 private void verifyActiveNetwork(int transport) {
791 // Test getActiveNetworkInfo()
792 assertNotNull(mCm.getActiveNetworkInfo());
793 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
794 // Test getActiveNetwork()
795 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +0000796 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400797 switch (transport) {
798 case TRANSPORT_WIFI:
799 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
800 break;
801 case TRANSPORT_CELLULAR:
802 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
803 break;
804 default:
805 throw new IllegalStateException("Unknown transport" + transport);
806 }
807 // Test getNetworkInfo(Network)
808 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
809 assertEquals(transportToLegacyType(transport), mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
810 // Test getNetworkCapabilities(Network)
811 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
812 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
813 }
814
815 private void verifyNoNetwork() {
816 // Test getActiveNetworkInfo()
817 assertNull(mCm.getActiveNetworkInfo());
818 // Test getActiveNetwork()
819 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +0000820 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400821 // Test getAllNetworks()
822 assertEquals(0, mCm.getAllNetworks().length);
823 }
824
825 /**
826 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
827 * broadcasts are received.
828 */
829 private ConditionVariable waitForConnectivityBroadcasts(final int count) {
830 final ConditionVariable cv = new ConditionVariable();
831 mServiceContext.registerReceiver(new BroadcastReceiver() {
832 private int remaining = count;
833 public void onReceive(Context context, Intent intent) {
834 if (--remaining == 0) {
835 cv.open();
836 mServiceContext.unregisterReceiver(this);
837 }
838 }
839 }, new IntentFilter(CONNECTIVITY_ACTION));
840 return cv;
841 }
842
843 @LargeTest
844 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400845 verifyNoNetwork();
846 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
847 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
848 assertNull(mCm.getActiveNetworkInfo());
849 assertNull(mCm.getActiveNetwork());
850 // Test bringing up validated cellular.
851 ConditionVariable cv = waitForConnectivityBroadcasts(1);
852 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -0400853 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400854 verifyActiveNetwork(TRANSPORT_CELLULAR);
855 assertEquals(2, mCm.getAllNetworks().length);
856 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
857 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
858 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
859 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
860 // Test bringing up validated WiFi.
861 cv = waitForConnectivityBroadcasts(2);
862 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -0400863 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400864 verifyActiveNetwork(TRANSPORT_WIFI);
865 assertEquals(2, mCm.getAllNetworks().length);
866 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
867 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
868 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
869 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
870 // Test cellular linger timeout.
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900871 waitFor(new Criteria() {
872 public boolean get() { return mCm.getAllNetworks().length == 1; } });
Paul Jensend7b6ca92015-05-13 14:05:12 -0400873 verifyActiveNetwork(TRANSPORT_WIFI);
874 assertEquals(1, mCm.getAllNetworks().length);
875 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
876 // Test WiFi disconnect.
877 cv = waitForConnectivityBroadcasts(1);
878 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400879 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400880 verifyNoNetwork();
881 }
882
883 @LargeTest
884 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
885 // Test bringing up unvalidated WiFi
886 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
887 ConditionVariable cv = waitForConnectivityBroadcasts(1);
888 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -0400889 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400890 verifyActiveNetwork(TRANSPORT_WIFI);
891 // Test bringing up unvalidated cellular
892 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
893 mCellNetworkAgent.connect(false);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900894 mService.waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400895 verifyActiveNetwork(TRANSPORT_WIFI);
896 // Test cellular disconnect.
897 mCellNetworkAgent.disconnect();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900898 mService.waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400899 verifyActiveNetwork(TRANSPORT_WIFI);
900 // Test bringing up validated cellular
901 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
902 cv = waitForConnectivityBroadcasts(2);
903 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -0400904 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400905 verifyActiveNetwork(TRANSPORT_CELLULAR);
906 // Test cellular disconnect.
907 cv = waitForConnectivityBroadcasts(2);
908 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400909 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400910 verifyActiveNetwork(TRANSPORT_WIFI);
911 // Test WiFi disconnect.
912 cv = waitForConnectivityBroadcasts(1);
913 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400914 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400915 verifyNoNetwork();
916 }
917
918 @LargeTest
919 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
920 // Test bringing up unvalidated cellular.
921 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
922 ConditionVariable cv = waitForConnectivityBroadcasts(1);
923 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -0400924 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400925 verifyActiveNetwork(TRANSPORT_CELLULAR);
926 // Test bringing up unvalidated WiFi.
927 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
928 cv = waitForConnectivityBroadcasts(2);
929 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -0400930 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400931 verifyActiveNetwork(TRANSPORT_WIFI);
932 // Test WiFi disconnect.
933 cv = waitForConnectivityBroadcasts(2);
934 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400935 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400936 verifyActiveNetwork(TRANSPORT_CELLULAR);
937 // Test cellular disconnect.
938 cv = waitForConnectivityBroadcasts(1);
939 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400940 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400941 verifyNoNetwork();
942 }
943
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700944 @LargeTest
Paul Jensene0988542015-06-25 15:30:08 -0400945 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400946 // Test bringing up unvalidated WiFi.
Paul Jensene0988542015-06-25 15:30:08 -0400947 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400948 ConditionVariable cv = waitForConnectivityBroadcasts(1);
949 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -0400950 waitFor(cv);
951 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400952 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -0400953 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -0400954 // Test bringing up validated cellular.
955 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -0400956 cv = waitForConnectivityBroadcasts(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400957 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -0400958 waitFor(cv);
959 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400960 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
961 NET_CAPABILITY_VALIDATED));
962 // Test cellular disconnect.
963 cv = waitForConnectivityBroadcasts(2);
964 mCellNetworkAgent.disconnect();
965 waitFor(cv);
966 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -0400967 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -0400968 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -0400969 NET_CAPABILITY_VALIDATED));
970 }
971
972 @LargeTest
Paul Jensen3d911462015-06-12 06:40:24 -0400973 public void testCellularOutscoresWeakWifi() throws Exception {
974 // Test bringing up validated cellular.
975 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
976 ConditionVariable cv = waitForConnectivityBroadcasts(1);
977 mCellNetworkAgent.connect(true);
978 waitFor(cv);
979 verifyActiveNetwork(TRANSPORT_CELLULAR);
980 // Test bringing up validated WiFi.
981 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
982 cv = waitForConnectivityBroadcasts(2);
983 mWiFiNetworkAgent.connect(true);
984 waitFor(cv);
985 verifyActiveNetwork(TRANSPORT_WIFI);
986 // Test WiFi getting really weak.
987 cv = waitForConnectivityBroadcasts(2);
988 mWiFiNetworkAgent.adjustScore(-11);
989 waitFor(cv);
990 verifyActiveNetwork(TRANSPORT_CELLULAR);
991 // Test WiFi restoring signal strength.
992 cv = waitForConnectivityBroadcasts(2);
993 mWiFiNetworkAgent.adjustScore(11);
994 waitFor(cv);
995 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -0400996 }
997
Paul Jensene0988542015-06-25 15:30:08 -0400998 @LargeTest
999 public void testReapingNetwork() throws Exception {
1000 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1001 // Expect it to be torn down immediately because it satisfies no requests.
1002 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1003 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
1004 mWiFiNetworkAgent.connectWithoutInternet();
1005 waitFor(cv);
1006 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1007 // Expect it to be torn down immediately because it satisfies no requests.
1008 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1009 cv = mCellNetworkAgent.getDisconnectedCV();
1010 mCellNetworkAgent.connectWithoutInternet();
1011 waitFor(cv);
1012 // Test bringing up validated WiFi.
1013 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1014 cv = waitForConnectivityBroadcasts(1);
1015 mWiFiNetworkAgent.connect(true);
1016 waitFor(cv);
1017 verifyActiveNetwork(TRANSPORT_WIFI);
1018 // Test bringing up unvalidated cellular.
1019 // Expect it to be torn down because it could never be the highest scoring network
1020 // satisfying the default request even if it validated.
1021 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1022 cv = mCellNetworkAgent.getDisconnectedCV();
1023 mCellNetworkAgent.connect(false);
1024 waitFor(cv);
1025 verifyActiveNetwork(TRANSPORT_WIFI);
1026 cv = mWiFiNetworkAgent.getDisconnectedCV();
1027 mWiFiNetworkAgent.disconnect();
1028 waitFor(cv);
1029 }
1030
1031 @LargeTest
1032 public void testCellularFallback() throws Exception {
1033 // Test bringing up validated cellular.
1034 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1035 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1036 mCellNetworkAgent.connect(true);
1037 waitFor(cv);
1038 verifyActiveNetwork(TRANSPORT_CELLULAR);
1039 // Test bringing up validated WiFi.
1040 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1041 cv = waitForConnectivityBroadcasts(2);
1042 mWiFiNetworkAgent.connect(true);
1043 waitFor(cv);
1044 verifyActiveNetwork(TRANSPORT_WIFI);
1045 // Reevaluate WiFi (it'll instantly fail DNS).
1046 cv = waitForConnectivityBroadcasts(2);
1047 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1048 NET_CAPABILITY_VALIDATED));
1049 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1050 // Should quickly fall back to Cellular.
1051 waitFor(cv);
1052 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1053 NET_CAPABILITY_VALIDATED));
1054 verifyActiveNetwork(TRANSPORT_CELLULAR);
1055 // Reevaluate cellular (it'll instantly fail DNS).
1056 cv = waitForConnectivityBroadcasts(2);
1057 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1058 NET_CAPABILITY_VALIDATED));
1059 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1060 // Should quickly fall back to WiFi.
1061 waitFor(cv);
1062 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1063 NET_CAPABILITY_VALIDATED));
1064 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1065 NET_CAPABILITY_VALIDATED));
1066 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001067 }
1068
1069 @LargeTest
1070 public void testWiFiFallback() throws Exception {
1071 // Test bringing up unvalidated WiFi.
1072 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1073 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1074 mWiFiNetworkAgent.connect(false);
1075 waitFor(cv);
1076 verifyActiveNetwork(TRANSPORT_WIFI);
1077 // Test bringing up validated cellular.
1078 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1079 cv = waitForConnectivityBroadcasts(2);
1080 mCellNetworkAgent.connect(true);
1081 waitFor(cv);
1082 verifyActiveNetwork(TRANSPORT_CELLULAR);
1083 // Reevaluate cellular (it'll instantly fail DNS).
1084 cv = waitForConnectivityBroadcasts(2);
1085 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1086 NET_CAPABILITY_VALIDATED));
1087 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1088 // Should quickly fall back to WiFi.
1089 waitFor(cv);
1090 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1091 NET_CAPABILITY_VALIDATED));
1092 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001093 }
1094
Paul Jensen3d911462015-06-12 06:40:24 -04001095 enum CallbackState {
1096 NONE,
1097 AVAILABLE,
Erik Klineacdd6392016-07-07 16:50:58 +09001098 NETWORK_CAPABILITIES,
1099 LINK_PROPERTIES,
Paul Jensen3d911462015-06-12 06:40:24 -04001100 LOSING,
Erik Klinee9e251f2015-11-25 12:49:38 +09001101 LOST,
1102 UNAVAILABLE
Paul Jensen3d911462015-06-12 06:40:24 -04001103 }
1104
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001105 private static class CallbackInfo {
1106 public final CallbackState state;
1107 public final Network network;
1108 public final Object arg;
1109 public CallbackInfo(CallbackState s, Network n, Object o) {
1110 state = s; network = n; arg = o;
1111 }
1112 public String toString() {
1113 return String.format("%s (%s)", state, network);
1114 }
1115 @Override
1116 public boolean equals(Object o) {
1117 if (!(o instanceof CallbackInfo)) return false;
1118 // Ignore timeMs, since it's unpredictable.
1119 CallbackInfo other = (CallbackInfo) o;
1120 return (state == other.state) && Objects.equals(network, other.network);
1121 }
1122 @Override
1123 public int hashCode() {
1124 return Objects.hash(state, network);
1125 }
1126 }
1127
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001128 /**
1129 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1130 * this class receives, by calling expectCallback() exactly once each time a callback is
1131 * received. assertNoCallback may be called at any time.
1132 */
Paul Jensen3d911462015-06-12 06:40:24 -04001133 private class TestNetworkCallback extends NetworkCallback {
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001134 // Chosen to be much less than the linger timeout. This ensures that we can distinguish
1135 // between a LOST callback that arrives immediately and a LOST callback that arrives after
1136 // the linger timeout.
1137 private final static int TIMEOUT_MS = 50;
1138
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001139 private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
1140
Erik Klineacdd6392016-07-07 16:50:58 +09001141 protected void setLastCallback(CallbackState state, Network network, Object o) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001142 mCallbacks.offer(new CallbackInfo(state, network, o));
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001143 }
Paul Jensen3d911462015-06-12 06:40:24 -04001144
Erik Klineacdd6392016-07-07 16:50:58 +09001145 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001146 public void onAvailable(Network network) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001147 setLastCallback(CallbackState.AVAILABLE, network, null);
Paul Jensen3d911462015-06-12 06:40:24 -04001148 }
1149
Erik Klineacdd6392016-07-07 16:50:58 +09001150 @Override
Erik Klinee9e251f2015-11-25 12:49:38 +09001151 public void onUnavailable() {
1152 setLastCallback(CallbackState.UNAVAILABLE, null, null);
1153 }
1154
1155 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001156 public void onLosing(Network network, int maxMsToLive) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001157 setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
Paul Jensen3d911462015-06-12 06:40:24 -04001158 }
1159
Erik Klineacdd6392016-07-07 16:50:58 +09001160 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001161 public void onLost(Network network) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001162 setLastCallback(CallbackState.LOST, network, null);
1163 }
1164
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001165 CallbackInfo nextCallback(int timeoutMs) {
1166 CallbackInfo cb = null;
1167 try {
1168 cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
1169 } catch (InterruptedException e) {
1170 }
1171 if (cb == null) {
1172 // LinkedBlockingQueue.poll() returns null if it timeouts.
1173 fail("Did not receive callback after " + timeoutMs + "ms");
1174 }
1175 return cb;
1176 }
1177
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001178 void expectCallback(CallbackState state, MockNetworkAgent mockAgent, int timeoutMs) {
1179 CallbackInfo expected = new CallbackInfo(
1180 state, (mockAgent != null) ? mockAgent.getNetwork() : null, 0);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001181 CallbackInfo actual = nextCallback(timeoutMs);
1182 assertEquals("Unexpected callback:", expected, actual);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001183 if (state == CallbackState.LOSING) {
1184 String msg = String.format(
1185 "Invalid linger time value %d, must be between %d and %d",
1186 actual.arg, 0, TEST_LINGER_DELAY_MS);
1187 int maxMsToLive = (Integer) actual.arg;
1188 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= TEST_LINGER_DELAY_MS);
1189 }
Erik Klinea2d29402016-03-16 15:31:39 +09001190 }
1191
1192 void expectCallback(CallbackState state, MockNetworkAgent mockAgent) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001193 expectCallback(state, mockAgent, TIMEOUT_MS);
Paul Jensen3d911462015-06-12 06:40:24 -04001194 }
1195
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001196 void assertNoCallback() {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001197 mService.waitForIdle();
1198 CallbackInfo c = mCallbacks.peek();
1199 assertNull("Unexpected callback: " + c, c);
1200 }
1201 }
1202
1203 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1204 // only be declared in a static or top level type".
1205 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1206 for (TestNetworkCallback c : callbacks) {
1207 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001208 }
1209 }
1210
1211 @LargeTest
1212 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001213 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001214 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1215 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001216 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1217 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001218 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1219 .addTransportType(TRANSPORT_WIFI).build();
1220 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1221 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001222 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001223 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1224 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1225
1226 // Test unvalidated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001227 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1228 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1229 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001230 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1231 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001232 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1233 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001234 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001235
Paul Jensen3d911462015-06-12 06:40:24 -04001236 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1237 mCellNetworkAgent.adjustScore(-1);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001238 mService.waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001239 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001240 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1241
Paul Jensen3d911462015-06-12 06:40:24 -04001242 cv = waitForConnectivityBroadcasts(2);
1243 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1244 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001245 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1246 wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001247 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1248 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001249 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001250
Paul Jensen3d911462015-06-12 06:40:24 -04001251 cv = waitForConnectivityBroadcasts(2);
1252 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001253 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1254 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001255 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001256 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001257 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001258
Paul Jensen3d911462015-06-12 06:40:24 -04001259 cv = waitForConnectivityBroadcasts(1);
1260 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001261 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1262 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001263 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001264 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001265
1266 // Test validated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001267 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1268 mCellNetworkAgent.connect(true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001269 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1270 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001271 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001272 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001273
Paul Jensen3d911462015-06-12 06:40:24 -04001274 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1275 mCellNetworkAgent.adjustScore(-1);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001276 mService.waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001277 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001278 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1279
Paul Jensen3d911462015-06-12 06:40:24 -04001280 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1281 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001282 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1283 genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1284 wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1285 cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001286 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001287 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001288
Paul Jensen3d911462015-06-12 06:40:24 -04001289 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001290 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1291 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1292 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001293
Paul Jensen3d911462015-06-12 06:40:24 -04001294 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001295 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1296 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1297 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001298 }
1299
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001300 @SmallTest
1301 public void testMultipleLingering() {
1302 NetworkRequest request = new NetworkRequest.Builder()
1303 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1304 .build();
1305 TestNetworkCallback callback = new TestNetworkCallback();
1306 mCm.registerNetworkCallback(request, callback);
1307
1308 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1309 mCm.registerDefaultNetworkCallback(defaultCallback);
1310
1311 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1312 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1313 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
1314
1315 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1316 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1317 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1318
1319 mCellNetworkAgent.connect(true);
1320 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1321 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1322 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1323
1324 mWiFiNetworkAgent.connect(true);
1325 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1326 // We then get LOSING when wifi validates and cell is outscored.
1327 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1328 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1329 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1330 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1331
1332 mEthernetNetworkAgent.connect(true);
1333 callback.expectCallback(CallbackState.AVAILABLE, mEthernetNetworkAgent);
1334 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
1335 defaultCallback.expectCallback(CallbackState.AVAILABLE, mEthernetNetworkAgent);
1336 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1337
1338 mEthernetNetworkAgent.disconnect();
1339 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1340 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1341 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1342
1343 for (int i = 0; i < 4; i++) {
1344 MockNetworkAgent oldNetwork, newNetwork;
1345 if (i % 2 == 0) {
1346 mWiFiNetworkAgent.adjustScore(-15);
1347 oldNetwork = mWiFiNetworkAgent;
1348 newNetwork = mCellNetworkAgent;
1349 } else {
1350 mWiFiNetworkAgent.adjustScore(15);
1351 oldNetwork = mCellNetworkAgent;
1352 newNetwork = mWiFiNetworkAgent;
1353
1354 }
1355 callback.expectCallback(CallbackState.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001356 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1357 // longer lingering?
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001358 defaultCallback.expectCallback(CallbackState.AVAILABLE, newNetwork);
1359 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
1360 }
1361 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1362
1363 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
1364 // if the network is still up.
1365 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
1366 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1367
1368 // Wifi no longer satisfies our listen, which is for an unmetered network.
1369 // But because its score is 55, it's still up (and the default network).
1370 defaultCallback.assertNoCallback();
1371 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1372
1373 // Disconnect our test networks.
1374 mWiFiNetworkAgent.disconnect();
1375 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1376 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1377 mCellNetworkAgent.disconnect();
1378 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1379
1380 mCm.unregisterNetworkCallback(callback);
1381 mService.waitForIdle();
1382
1383 // Check that a network is only lingered or torn down if it would not satisfy a request even
1384 // if it validated.
1385 request = new NetworkRequest.Builder().clearCapabilities().build();
1386 callback = new TestNetworkCallback();
1387
1388 mCm.registerNetworkCallback(request, callback);
1389
1390 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1391 mCellNetworkAgent.connect(false); // Score: 10
1392 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1393 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1394 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1395
1396 // Bring up wifi with a score of 20.
1397 // Cell stays up because it would satisfy the default request if it validated.
1398 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1399 mWiFiNetworkAgent.connect(false); // Score: 20
1400 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1401 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1402 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1403
1404 mWiFiNetworkAgent.disconnect();
1405 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1406 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1407 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1408 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1409
1410 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001411 // Cell is lingered because it would not satisfy any request, even if it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001412 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1413 mWiFiNetworkAgent.adjustScore(50);
1414 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001415 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001416 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001417 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1418 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1419
1420 // Tear down wifi.
1421 mWiFiNetworkAgent.disconnect();
1422 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1423 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1424 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1425 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1426
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001427 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
1428 // it's arguably correct to linger it, since it was the default network before it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001429 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1430 mWiFiNetworkAgent.connect(true);
1431 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001432 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001433 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1434 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1435
1436 mWiFiNetworkAgent.disconnect();
1437 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001438 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001439 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1440 mCellNetworkAgent.disconnect();
1441 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1442 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001443
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001444 // If a network is lingering, and we add and remove a request from it, resume lingering.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001445 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1446 mCellNetworkAgent.connect(true);
1447 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1448 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1449 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1450 mWiFiNetworkAgent.connect(true);
1451 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1452 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1453 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1454
1455 NetworkRequest cellRequest = new NetworkRequest.Builder()
1456 .addTransportType(TRANSPORT_CELLULAR).build();
1457 NetworkCallback noopCallback = new NetworkCallback();
1458 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001459 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
1460 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001461 mCm.unregisterNetworkCallback(noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001462 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001463
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001464 // Similar to the above: lingering can start even after the lingered request is removed.
1465 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001466 mWiFiNetworkAgent.disconnect();
1467 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001468 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1469 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1470
1471 // Cell is now the default network. Pin it with a cell-specific request.
1472 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
1473 mCm.requestNetwork(cellRequest, noopCallback);
1474
1475 // Now connect wifi, and expect it to become the default network.
1476 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1477 mWiFiNetworkAgent.connect(true);
1478 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1479 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1480 // The default request is lingering on cell, but nothing happens to cell, and we send no
1481 // callbacks for it, because it's kept up by cellRequest.
1482 callback.assertNoCallback();
1483 // Now unregister cellRequest and expect cell to start lingering.
1484 mCm.unregisterNetworkCallback(noopCallback);
1485 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1486
1487 // Let linger run its course.
1488 callback.assertNoCallback();
1489 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent,
1490 TEST_LINGER_DELAY_MS /* timeoutMs */);
1491
1492 // Clean up.
1493 mWiFiNetworkAgent.disconnect();
1494 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1495 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001496
1497 mCm.unregisterNetworkCallback(callback);
1498 mCm.unregisterNetworkCallback(defaultCallback);
1499 }
1500
Paul Jensen85cf78e2015-06-25 13:25:07 -04001501 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04001502 // Verify NOT_RESTRICTED is set appropriately
1503 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
1504 .build().networkCapabilities;
1505 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
1506 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
1507 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04001508 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04001509 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1510 } else {
1511 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1512 }
1513
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001514 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001515 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001516 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
1517 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04001518 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001519 mServiceContext, "testFactory", filter);
1520 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04001521 ConditionVariable cv = testFactory.getNetworkStartedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001522 testFactory.expectAddRequests(1);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001523 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001524 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001525 int expectedRequestCount = 1;
1526 NetworkCallback networkCallback = null;
1527 // For non-INTERNET capabilities we cannot rely on the default request being present, so
1528 // add one.
1529 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04001530 assertFalse(testFactory.getMyStartRequested());
1531 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
1532 networkCallback = new NetworkCallback();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001533 testFactory.expectAddRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001534 mCm.requestNetwork(request, networkCallback);
1535 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001536 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001537 }
Paul Jensen3d911462015-06-12 06:40:24 -04001538 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001539 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1540 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001541
Paul Jensen85cf78e2015-06-25 13:25:07 -04001542 // Now bring in a higher scored network.
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001543 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001544 // Rather than create a validated network which complicates things by registering it's
1545 // own NetworkRequest during startup, just bump up the score to cancel out the
1546 // unvalidated penalty.
1547 testAgent.adjustScore(40);
1548 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001549
1550 // When testAgent connects, ConnectivityService will re-send us all current requests with
1551 // the new score. There are expectedRequestCount such requests, and we must wait for all of
1552 // them.
1553 testFactory.expectAddRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001554 testAgent.connect(false);
1555 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04001556 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001557 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001558 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001559
Paul Jensen85cf78e2015-06-25 13:25:07 -04001560 // Bring in a bunch of requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001561 testFactory.expectAddRequests(10);
1562 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001563 ConnectivityManager.NetworkCallback[] networkCallbacks =
1564 new ConnectivityManager.NetworkCallback[10];
1565 for (int i = 0; i< networkCallbacks.length; i++) {
1566 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
1567 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001568 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001569 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
1570 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04001571 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
1572 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001573
Paul Jensen85cf78e2015-06-25 13:25:07 -04001574 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001575 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001576 for (int i = 0; i < networkCallbacks.length; i++) {
1577 mCm.unregisterNetworkCallback(networkCallbacks[i]);
1578 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04001579 testFactory.waitForNetworkRequests(expectedRequestCount);
1580 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001581
Paul Jensen85cf78e2015-06-25 13:25:07 -04001582 // Drop the higher scored network.
1583 cv = testFactory.getNetworkStartedCV();
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001584 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001585 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001586 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1587 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001588
1589 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001590 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001591 handlerThread.quit();
1592 }
1593
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001594 @LargeTest
Paul Jensen85cf78e2015-06-25 13:25:07 -04001595 public void testNetworkFactoryRequests() throws Exception {
1596 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
1597 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
1598 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
1599 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
1600 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
1601 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
1602 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
1603 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
1604 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
1605 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
1606 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
1607 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
1608 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
1609 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
1610 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
1611 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
1612 }
1613
1614 @LargeTest
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001615 public void testNoMutableNetworkRequests() throws Exception {
1616 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
1617 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001618 builder.addCapability(NET_CAPABILITY_VALIDATED);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001619 try {
1620 mCm.requestNetwork(builder.build(), new NetworkCallback());
1621 fail();
1622 } catch (IllegalArgumentException expected) {}
1623 try {
1624 mCm.requestNetwork(builder.build(), pendingIntent);
1625 fail();
1626 } catch (IllegalArgumentException expected) {}
1627 builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001628 builder.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001629 try {
1630 mCm.requestNetwork(builder.build(), new NetworkCallback());
1631 fail();
1632 } catch (IllegalArgumentException expected) {}
1633 try {
1634 mCm.requestNetwork(builder.build(), pendingIntent);
1635 fail();
1636 } catch (IllegalArgumentException expected) {}
1637 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001638
Paul Jensene0988542015-06-25 15:30:08 -04001639 @LargeTest
1640 public void testMMSonWiFi() throws Exception {
1641 // Test bringing up cellular without MMS NetworkRequest gets reaped
1642 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1643 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1644 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
1645 mCellNetworkAgent.connectWithoutInternet();
1646 waitFor(cv);
1647 waitFor(new Criteria() {
1648 public boolean get() { return mCm.getAllNetworks().length == 0; } });
1649 verifyNoNetwork();
1650 // Test bringing up validated WiFi.
1651 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1652 cv = waitForConnectivityBroadcasts(1);
1653 mWiFiNetworkAgent.connect(true);
1654 waitFor(cv);
1655 verifyActiveNetwork(TRANSPORT_WIFI);
1656 // Register MMS NetworkRequest
1657 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1658 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1659 final TestNetworkCallback networkCallback = new TestNetworkCallback();
1660 mCm.requestNetwork(builder.build(), networkCallback);
1661 // Test bringing up unvalidated cellular with MMS
1662 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1663 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04001664 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001665 networkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04001666 verifyActiveNetwork(TRANSPORT_WIFI);
1667 // Test releasing NetworkRequest disconnects cellular with MMS
1668 cv = mCellNetworkAgent.getDisconnectedCV();
1669 mCm.unregisterNetworkCallback(networkCallback);
1670 waitFor(cv);
1671 verifyActiveNetwork(TRANSPORT_WIFI);
1672 }
1673
1674 @LargeTest
1675 public void testMMSonCell() throws Exception {
1676 // Test bringing up cellular without MMS
1677 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1678 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1679 mCellNetworkAgent.connect(false);
1680 waitFor(cv);
1681 verifyActiveNetwork(TRANSPORT_CELLULAR);
1682 // Register MMS NetworkRequest
1683 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1684 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1685 final TestNetworkCallback networkCallback = new TestNetworkCallback();
1686 mCm.requestNetwork(builder.build(), networkCallback);
1687 // Test bringing up MMS cellular network
Paul Jensene0988542015-06-25 15:30:08 -04001688 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1689 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1690 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001691 networkCallback.expectCallback(CallbackState.AVAILABLE, mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04001692 verifyActiveNetwork(TRANSPORT_CELLULAR);
1693 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
1694 cv = mmsNetworkAgent.getDisconnectedCV();
1695 mCm.unregisterNetworkCallback(networkCallback);
1696 waitFor(cv);
1697 verifyActiveNetwork(TRANSPORT_CELLULAR);
1698 }
1699
Paul Jensencf4c2c62015-07-01 14:16:32 -04001700 @LargeTest
1701 public void testCaptivePortal() {
1702 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1703 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1704 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1705 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1706
1707 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1708 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1709 .addCapability(NET_CAPABILITY_VALIDATED).build();
1710 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001711
1712 // Bring up a network with a captive portal.
1713 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001714 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04001715 String firstRedirectUrl = "http://example.com/firstPath";
1716 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001717 captivePortalCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04001718 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001719
1720 // Take down network.
1721 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001722 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001723 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001724
1725 // Bring up a network with a captive portal.
1726 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001727 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04001728 String secondRedirectUrl = "http://example.com/secondPath";
1729 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001730 captivePortalCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04001731 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001732
1733 // Make captive portal disappear then revalidate.
1734 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001735 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
1736 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001737 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001738
1739 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001740 validatedCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001741
1742 // Break network connectivity.
1743 // Expect NET_CAPABILITY_VALIDATED onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001744 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
1745 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001746 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001747 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09001748
Calvin On4bc78eb2016-10-11 15:10:46 -07001749 @LargeTest
1750 public void testAvoidOrIgnoreCaptivePortals() {
1751 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1752 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1753 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1754 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1755
1756 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1757 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1758 .addCapability(NET_CAPABILITY_VALIDATED).build();
1759 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
1760
1761 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
1762 // Bring up a network with a captive portal.
1763 // Expect it to fail to connect and not result in any callbacks.
1764 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1765 String firstRedirectUrl = "http://example.com/firstPath";
1766
1767 ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
1768 ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
1769 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
1770 waitFor(disconnectCv);
1771 waitFor(avoidCv);
1772
1773 assertNoCallbacks(captivePortalCallback, validatedCallback);
1774
1775 // Now test ignore mode.
1776 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE);
1777
1778 // Bring up a network with a captive portal.
1779 // Since we're ignoring captive portals, the network will validate.
1780 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1781 String secondRedirectUrl = "http://example.com/secondPath";
1782 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
1783
1784 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
1785 validatedCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1786 // But there should be no CaptivePortal callback.
1787 captivePortalCallback.assertNoCallback();
1788 }
1789
Etan Cohenddb9ef02015-11-18 10:56:15 -08001790 @SmallTest
1791 public void testInvalidNetworkSpecifier() {
1792 boolean execptionCalled = true;
1793
1794 try {
1795 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1796 builder.setNetworkSpecifier(MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
1797 execptionCalled = false;
1798 } catch (IllegalArgumentException e) {
1799 // do nothing - should get here
1800 }
1801
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001802 assertTrue("NetworkRequest builder with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
Etan Cohenddb9ef02015-11-18 10:56:15 -08001803 execptionCalled);
1804
1805 try {
1806 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
1807 networkCapabilities.addTransportType(TRANSPORT_WIFI)
1808 .setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
1809 mService.requestNetwork(networkCapabilities, null, 0, null,
1810 ConnectivityManager.TYPE_WIFI);
1811 execptionCalled = false;
1812 } catch (IllegalArgumentException e) {
1813 // do nothing - should get here
1814 }
1815
1816 assertTrue("ConnectivityService requestNetwork with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
1817 execptionCalled);
1818 }
1819
Erik Klinea2d29402016-03-16 15:31:39 +09001820 @LargeTest
1821 public void testRegisterDefaultNetworkCallback() throws Exception {
1822 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
1823 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
1824 defaultNetworkCallback.assertNoCallback();
1825
1826 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
1827 // whenever Wi-Fi is up. Without this, the mobile network agent is
1828 // reaped before any other activity can take place.
1829 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
1830 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1831 .addTransportType(TRANSPORT_CELLULAR).build();
1832 mCm.requestNetwork(cellRequest, cellNetworkCallback);
1833 cellNetworkCallback.assertNoCallback();
1834
1835 // Bring up cell and expect CALLBACK_AVAILABLE.
1836 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1837 mCellNetworkAgent.connect(true);
1838 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1839 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1840
1841 // Bring up wifi and expect CALLBACK_AVAILABLE.
1842 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1843 mWiFiNetworkAgent.connect(true);
1844 cellNetworkCallback.assertNoCallback();
1845 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1846
1847 // Bring down cell. Expect no default network callback, since it wasn't the default.
1848 mCellNetworkAgent.disconnect();
1849 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1850 defaultNetworkCallback.assertNoCallback();
1851
1852 // Bring up cell. Expect no default network callback, since it won't be the default.
1853 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1854 mCellNetworkAgent.connect(true);
1855 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1856 defaultNetworkCallback.assertNoCallback();
1857
1858 // Bring down wifi. Expect the default network callback to notified of LOST wifi
1859 // followed by AVAILABLE cell.
1860 mWiFiNetworkAgent.disconnect();
1861 cellNetworkCallback.assertNoCallback();
1862 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1863 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1864 mCellNetworkAgent.disconnect();
1865 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1866 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1867 }
1868
Erik Klineacdd6392016-07-07 16:50:58 +09001869 private class TestRequestUpdateCallback extends TestNetworkCallback {
1870 @Override
1871 public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
1872 setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
1873 }
1874
1875 @Override
1876 public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
1877 setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
1878 }
1879 }
1880
1881 @LargeTest
1882 public void testRequestCallbackUpdates() throws Exception {
1883 // File a network request for mobile.
1884 final TestNetworkCallback cellNetworkCallback = new TestRequestUpdateCallback();
1885 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1886 .addTransportType(TRANSPORT_CELLULAR).build();
1887 mCm.requestNetwork(cellRequest, cellNetworkCallback);
1888
1889 // Bring up the mobile network.
1890 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1891 mCellNetworkAgent.connect(true);
1892
1893 // We should get onAvailable().
1894 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1895 // We should get onCapabilitiesChanged(), when the mobile network successfully validates.
1896 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
1897 cellNetworkCallback.assertNoCallback();
1898
1899 // Update LinkProperties.
1900 final LinkProperties lp = new LinkProperties();
1901 lp.setInterfaceName("foonet_data0");
1902 mCellNetworkAgent.sendLinkProperties(lp);
1903 // We should get onLinkPropertiesChanged().
1904 cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
1905 cellNetworkCallback.assertNoCallback();
1906
1907 // Register a garden variety default network request.
1908 final TestNetworkCallback dfltNetworkCallback = new TestRequestUpdateCallback();
1909 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
1910 // Only onAvailable() is called; no other information is delivered.
1911 dfltNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1912 dfltNetworkCallback.assertNoCallback();
1913
1914 // Request a NetworkCapabilities update; only the requesting callback is notified.
1915 mCm.requestNetworkCapabilities(dfltNetworkCallback);
1916 dfltNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
1917 cellNetworkCallback.assertNoCallback();
1918 dfltNetworkCallback.assertNoCallback();
1919
1920 // Request a LinkProperties update; only the requesting callback is notified.
1921 mCm.requestLinkProperties(dfltNetworkCallback);
1922 dfltNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
1923 cellNetworkCallback.assertNoCallback();
1924 dfltNetworkCallback.assertNoCallback();
1925
1926 mCm.unregisterNetworkCallback(dfltNetworkCallback);
1927 mCm.unregisterNetworkCallback(cellNetworkCallback);
1928 }
1929
Calvin On4bc78eb2016-10-11 15:10:46 -07001930 private void setCaptivePortalMode(int mode) {
1931 ContentResolver cr = mServiceContext.getContentResolver();
1932 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
1933 }
1934
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09001935 private void setMobileDataAlwaysOn(boolean enable) {
1936 ContentResolver cr = mServiceContext.getContentResolver();
1937 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
1938 mService.updateMobileDataAlwaysOn();
1939 mService.waitForIdle();
1940 }
1941
1942 private boolean isForegroundNetwork(MockNetworkAgent network) {
1943 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
1944 assertNotNull(nc);
1945 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
1946 }
1947
1948 @SmallTest
1949 public void testBackgroundNetworks() throws Exception {
1950 // Create a background request. We can't do this ourselves because ConnectivityService
1951 // doesn't have an API for it. So just turn on mobile data always on.
1952 setMobileDataAlwaysOn(true);
1953 final NetworkRequest request = new NetworkRequest.Builder().build();
1954 final NetworkRequest fgRequest = new NetworkRequest.Builder()
1955 .addCapability(NET_CAPABILITY_FOREGROUND).build();
1956 final TestNetworkCallback callback = new TestNetworkCallback();
1957 final TestNetworkCallback fgCallback = new TestNetworkCallback();
1958 mCm.registerNetworkCallback(request, callback);
1959 mCm.registerNetworkCallback(fgRequest, fgCallback);
1960
1961 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1962 mCellNetworkAgent.connect(true);
1963 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1964 fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1965 assertTrue(isForegroundNetwork(mCellNetworkAgent));
1966
1967 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1968 mWiFiNetworkAgent.connect(true);
1969
1970 // When wifi connects, cell lingers.
1971 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1972 fgCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1973 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1974 fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1975 assertTrue(isForegroundNetwork(mCellNetworkAgent));
1976 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1977
1978 // When lingering is complete, cell is still there but is now in the background.
1979 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, TEST_LINGER_DELAY_MS);
1980 callback.assertNoCallback();
1981 assertFalse(isForegroundNetwork(mCellNetworkAgent));
1982 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1983
1984 // File a cell request and check that cell comes into the foreground.
1985 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1986 .addTransportType(TRANSPORT_CELLULAR).build();
1987 final TestNetworkCallback cellCallback = new TestNetworkCallback();
1988 mCm.requestNetwork(cellRequest, cellCallback);
1989 cellCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1990 fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1991 callback.assertNoCallback(); // Because the network is already up.
1992 assertTrue(isForegroundNetwork(mCellNetworkAgent));
1993 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1994
1995 // Release the request. The network immediately goes into the background, since it was not
1996 // lingering.
1997 mCm.unregisterNetworkCallback(cellCallback);
1998 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1999 callback.assertNoCallback();
2000 assertFalse(isForegroundNetwork(mCellNetworkAgent));
2001 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2002
2003 // Disconnect wifi and check that cell is foreground again.
2004 mWiFiNetworkAgent.disconnect();
2005 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2006 fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2007 fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2008 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2009
2010 mCm.unregisterNetworkCallback(callback);
2011 mCm.unregisterNetworkCallback(fgCallback);
2012 }
2013
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002014 @SmallTest
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002015 public void testRequestBenchmark() throws Exception {
Hugo Benichide7002e2016-11-15 11:25:52 +09002016 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002017 // Benchmarks connecting and switching performance in the presence of a large number of
2018 // NetworkRequests.
2019 // 1. File NUM_REQUESTS requests.
2020 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
2021 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
2022 // and NUM_REQUESTS onAvailable callbacks to fire.
2023 // See how long it took.
2024 final int NUM_REQUESTS = 90;
2025 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
2026 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
2027 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
2028 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
2029
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002030 for (int i = 0; i < NUM_REQUESTS; i++) {
2031 callbacks[i] = new NetworkCallback() {
2032 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
2033 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
2034 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002035 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002036
Hugo Benichide7002e2016-11-15 11:25:52 +09002037 final int REGISTER_TIME_LIMIT_MS = 180;
2038 assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
2039 for (NetworkCallback cb : callbacks) {
2040 mCm.registerNetworkCallback(request, cb);
2041 }
2042 });
2043
2044 final int CONNECT_TIME_LIMIT_MS = 40;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002045 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2046 // Don't request that the network validate, because otherwise connect() will block until
2047 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
2048 // and we won't actually measure anything.
2049 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002050
Hugo Benichide7002e2016-11-15 11:25:52 +09002051 long onAvailableDispatchingDuration = durationOf(() -> {
2052 if (!awaitLatch(availableLatch, CONNECT_TIME_LIMIT_MS)) {
2053 fail(String.format("Only dispatched %d/%d onAvailable callbacks in %dms",
2054 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
2055 CONNECT_TIME_LIMIT_MS));
2056 }
2057 });
2058 Log.d(TAG, String.format("Connect, %d callbacks: %dms, acceptable %dms",
2059 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS));
2060
2061 final int SWITCH_TIME_LIMIT_MS = 40;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002062 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2063 // Give wifi a high enough score that we'll linger cell when wifi comes up.
2064 mWiFiNetworkAgent.adjustScore(40);
2065 mWiFiNetworkAgent.connect(false);
Hugo Benichide7002e2016-11-15 11:25:52 +09002066
2067 long onLostDispatchingDuration = durationOf(() -> {
2068 if (!awaitLatch(losingLatch, SWITCH_TIME_LIMIT_MS)) {
2069 fail(String.format("Only dispatched %d/%d onLosing callbacks in %dms",
2070 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, SWITCH_TIME_LIMIT_MS));
2071 }
2072 });
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002073 Log.d(TAG, String.format("Linger, %d callbacks: %dms, acceptable %dms",
Hugo Benichide7002e2016-11-15 11:25:52 +09002074 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS));
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002075
2076 final int UNREGISTER_TIME_LIMIT_MS = 10;
Hugo Benichide7002e2016-11-15 11:25:52 +09002077 assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
2078 for (NetworkCallback cb : callbacks) {
2079 mCm.unregisterNetworkCallback(cb);
2080 }
2081 });
2082 }
2083
2084 private long durationOf(Runnable fn) {
2085 long startTime = SystemClock.elapsedRealtime();
2086 fn.run();
2087 return SystemClock.elapsedRealtime() - startTime;
2088 }
2089
2090 private void assertTimeLimit(String descr, long timeLimit, Runnable fn) {
2091 long timeTaken = durationOf(fn);
2092 String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002093 Log.d(TAG, msg);
Hugo Benichide7002e2016-11-15 11:25:52 +09002094 assertTrue(msg, timeTaken <= timeLimit);
2095 }
2096
2097 private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
2098 try {
2099 if (l.await(timeoutMs, TimeUnit.MILLISECONDS)) {
2100 return true;
2101 }
2102 } catch (InterruptedException e) {}
2103 return false;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002104 }
2105
2106 @SmallTest
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002107 public void testMobileDataAlwaysOn() throws Exception {
2108 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2109 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2110 .addTransportType(TRANSPORT_CELLULAR).build();
2111 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
2112
2113 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
2114 handlerThread.start();
2115 NetworkCapabilities filter = new NetworkCapabilities()
2116 .addTransportType(TRANSPORT_CELLULAR)
2117 .addCapability(NET_CAPABILITY_INTERNET);
2118 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
2119 mServiceContext, "testFactory", filter);
2120 testFactory.setScoreFilter(40);
2121
2122 // Register the factory and expect it to start looking for a network.
2123 testFactory.expectAddRequests(1);
2124 testFactory.register();
2125 testFactory.waitForNetworkRequests(1);
2126 assertTrue(testFactory.getMyStartRequested());
2127
2128 // Bring up wifi. The factory stops looking for a network.
2129 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2130 testFactory.expectAddRequests(2); // Because the default request changes score twice.
2131 mWiFiNetworkAgent.connect(true);
2132 testFactory.waitForNetworkRequests(1);
2133 assertFalse(testFactory.getMyStartRequested());
2134
2135 ContentResolver cr = mServiceContext.getContentResolver();
2136
2137 // Turn on mobile data always on. The factory starts looking again.
2138 testFactory.expectAddRequests(1);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002139 setMobileDataAlwaysOn(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002140 testFactory.waitForNetworkRequests(2);
2141 assertTrue(testFactory.getMyStartRequested());
2142
2143 // Bring up cell data and check that the factory stops looking.
2144 assertEquals(1, mCm.getAllNetworks().length);
2145 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2146 testFactory.expectAddRequests(2); // Because the cell request changes score twice.
2147 mCellNetworkAgent.connect(true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002148 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002149 testFactory.waitForNetworkRequests(2);
2150 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
2151
2152 // Check that cell data stays up.
2153 mService.waitForIdle();
2154 verifyActiveNetwork(TRANSPORT_WIFI);
2155 assertEquals(2, mCm.getAllNetworks().length);
2156
2157 // Turn off mobile data always on and expect the request to disappear...
2158 testFactory.expectRemoveRequests(1);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002159 setMobileDataAlwaysOn(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002160 testFactory.waitForNetworkRequests(1);
2161
2162 // ... and cell data to be torn down.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002163 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002164 assertEquals(1, mCm.getAllNetworks().length);
2165
2166 testFactory.unregister();
2167 mCm.unregisterNetworkCallback(cellNetworkCallback);
2168 handlerThread.quit();
2169 }
2170
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002171 @SmallTest
2172 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002173 final ContentResolver cr = mServiceContext.getContentResolver();
Erik Kline065ab6e2016-10-02 18:02:14 +09002174 final WrappedAvoidBadWifiTracker tracker = mService.getAvoidBadWifiTracker();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002175 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
2176
Erik Kline065ab6e2016-10-02 18:02:14 +09002177 tracker.configRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002178 String[] values = new String[] {null, "0", "1"};
2179 for (int i = 0; i < values.length; i++) {
2180 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002181 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002182 mService.waitForIdle();
2183 String msg = String.format("config=false, setting=%s", values[i]);
Hugo Benichibccd8ad2016-11-15 13:42:34 +09002184 assertEventuallyTrue(() -> mService.avoidBadWifi(), 50);
Erik Kline065ab6e2016-10-02 18:02:14 +09002185 assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002186 }
2187
Erik Kline065ab6e2016-10-02 18:02:14 +09002188 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002189
2190 Settings.Global.putInt(cr, settingName, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09002191 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002192 mService.waitForIdle();
Hugo Benichibccd8ad2016-11-15 13:42:34 +09002193 assertEventuallyTrue(() -> !mService.avoidBadWifi(), 50);
Erik Kline065ab6e2016-10-02 18:02:14 +09002194 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002195
2196 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002197 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002198 mService.waitForIdle();
Hugo Benichibccd8ad2016-11-15 13:42:34 +09002199 assertEventuallyTrue(() -> mService.avoidBadWifi(), 50);
Erik Kline065ab6e2016-10-02 18:02:14 +09002200 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002201
2202 Settings.Global.putString(cr, settingName, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09002203 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002204 mService.waitForIdle();
Hugo Benichibccd8ad2016-11-15 13:42:34 +09002205 assertEventuallyTrue(() -> !mService.avoidBadWifi(), 50);
Erik Kline065ab6e2016-10-02 18:02:14 +09002206 assertTrue(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002207 }
2208
2209 @SmallTest
2210 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09002211 final ContentResolver cr = mServiceContext.getContentResolver();
2212 final WrappedAvoidBadWifiTracker tracker = mService.getAvoidBadWifiTracker();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002213
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002214 // Pretend we're on a carrier that restricts switching away from bad wifi.
Erik Kline065ab6e2016-10-02 18:02:14 +09002215 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002216
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002217 // File a request for cell to ensure it doesn't go down.
2218 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2219 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2220 .addTransportType(TRANSPORT_CELLULAR).build();
2221 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2222
2223 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2224 mCm.registerDefaultNetworkCallback(defaultCallback);
2225
2226 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
2227 .addTransportType(TRANSPORT_WIFI)
2228 .addCapability(NET_CAPABILITY_VALIDATED)
2229 .build();
2230 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
2231 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
2232
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002233 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09002234 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002235
2236 // Bring up validated cell.
2237 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2238 mCellNetworkAgent.connect(true);
2239 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2240 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2241 Network cellNetwork = mCellNetworkAgent.getNetwork();
2242
2243 // Bring up validated wifi.
2244 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2245 mWiFiNetworkAgent.connect(true);
2246 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2247 validatedWifiCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2248 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2249
2250 // Fail validation on wifi.
2251 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
2252 mCm.reportNetworkConnectivity(wifiNetwork, false);
2253 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2254
2255 // Because avoid bad wifi is off, we don't switch to cellular.
2256 defaultCallback.assertNoCallback();
2257 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2258 NET_CAPABILITY_VALIDATED));
2259 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2260 NET_CAPABILITY_VALIDATED));
2261 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2262
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002263 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
2264 // that we switch back to cell.
Erik Kline065ab6e2016-10-02 18:02:14 +09002265 tracker.configRestrictsAvoidBadWifi = false;
2266 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002267 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2268 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2269
2270 // Switch back to a restrictive carrier.
Erik Kline065ab6e2016-10-02 18:02:14 +09002271 tracker.configRestrictsAvoidBadWifi = true;
2272 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002273 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2274 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2275
2276 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
2277 mCm.setAvoidUnvalidated(wifiNetwork);
2278 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2279 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2280 NET_CAPABILITY_VALIDATED));
2281 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2282 NET_CAPABILITY_VALIDATED));
2283 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2284
2285 // Disconnect and reconnect wifi to clear the one-time switch above.
2286 mWiFiNetworkAgent.disconnect();
2287 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2288 mWiFiNetworkAgent.connect(true);
2289 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2290 validatedWifiCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2291 wifiNetwork = mWiFiNetworkAgent.getNetwork();
2292
2293 // Fail validation on wifi and expect the dialog to appear.
2294 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
2295 mCm.reportNetworkConnectivity(wifiNetwork, false);
2296 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2297
2298 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002299 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002300 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002301
2302 // We now switch to cell.
2303 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2304 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2305 NET_CAPABILITY_VALIDATED));
2306 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2307 NET_CAPABILITY_VALIDATED));
2308 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2309
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002310 // Simulate the user turning the cellular fallback setting off and then on.
2311 // We switch to wifi and then to cell.
2312 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09002313 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002314 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2315 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2316 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002317 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002318 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2319 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2320
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002321 // If cell goes down, we switch to wifi.
2322 mCellNetworkAgent.disconnect();
2323 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2324 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2325 validatedWifiCallback.assertNoCallback();
2326
2327 mCm.unregisterNetworkCallback(cellNetworkCallback);
2328 mCm.unregisterNetworkCallback(validatedWifiCallback);
2329 mCm.unregisterNetworkCallback(defaultCallback);
2330 }
2331
Erik Klinee9e251f2015-11-25 12:49:38 +09002332 /**
2333 * Validate that a satisfied network request does not trigger onUnavailable() once the
2334 * time-out period expires.
2335 */
2336 @SmallTest
2337 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
2338 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2339 NetworkCapabilities.TRANSPORT_WIFI).build();
2340 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2341 mCm.requestNetwork(nr, networkCallback, 10);
2342
2343 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2344 mWiFiNetworkAgent.connect(false);
2345 networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2346
2347 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohen4fde1672016-10-27 15:05:50 -07002348 sleepFor(15);
2349 networkCallback.assertNoCallback();
2350 }
2351
2352 /**
2353 * Validate that a satisfied network request followed by a disconnected (lost) network does
2354 * not trigger onUnavailable() once the time-out period expires.
2355 */
2356 @SmallTest
2357 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
2358 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2359 NetworkCapabilities.TRANSPORT_WIFI).build();
2360 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2361 mCm.requestNetwork(nr, networkCallback, 500);
2362
2363 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2364 mWiFiNetworkAgent.connect(false);
2365 networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2366 sleepFor(20);
2367 mWiFiNetworkAgent.disconnect();
2368 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2369
2370 // pass timeout and validate that UNAVAILABLE is not called
2371 sleepFor(600);
Erik Klinee9e251f2015-11-25 12:49:38 +09002372 networkCallback.assertNoCallback();
2373 }
2374
2375 /**
2376 * Validate that when a time-out is specified for a network request the onUnavailable()
2377 * callback is called when time-out expires. Then validate that if network request is
2378 * (somehow) satisfied - the callback isn't called later.
2379 */
2380 @SmallTest
2381 public void testTimedoutNetworkRequest() {
2382 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2383 NetworkCapabilities.TRANSPORT_WIFI).build();
2384 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2385 mCm.requestNetwork(nr, networkCallback, 10);
2386
2387 // pass timeout and validate that UNAVAILABLE is called
2388 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
2389
2390 // create a network satisfying request - validate that request not triggered
2391 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2392 mWiFiNetworkAgent.connect(false);
2393 networkCallback.assertNoCallback();
2394 }
2395
2396 /**
2397 * Validate that when a network request is unregistered (cancelled) the time-out for that
2398 * request doesn't trigger the onUnavailable() callback.
2399 */
2400 @SmallTest
2401 public void testTimedoutAfterUnregisteredNetworkRequest() {
2402 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2403 NetworkCapabilities.TRANSPORT_WIFI).build();
2404 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2405 mCm.requestNetwork(nr, networkCallback, 10);
2406
2407 // remove request
2408 mCm.unregisterNetworkCallback(networkCallback);
2409
2410 // pass timeout and validate that no callbacks
2411 // Note: doesn't validate that nothing called from CS since even if called the CM already
2412 // unregisters the callback and won't pass it through!
Etan Cohen4fde1672016-10-27 15:05:50 -07002413 sleepFor(15);
Erik Klinee9e251f2015-11-25 12:49:38 +09002414 networkCallback.assertNoCallback();
2415
2416 // create a network satisfying request - validate that request not triggered
2417 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2418 mWiFiNetworkAgent.connect(false);
2419 networkCallback.assertNoCallback();
2420 }
2421
Hugo Benichibccd8ad2016-11-15 13:42:34 +09002422 public void assertEventuallyTrue(BooleanSupplier fn, long maxWaitingTimeMs) throws Exception {
2423 long start = SystemClock.elapsedRealtime();
2424 while (SystemClock.elapsedRealtime() <= start + maxWaitingTimeMs) {
2425 if (fn.getAsBoolean()) {
2426 return;
2427 }
2428 Thread.sleep(10);
2429 }
2430 assertTrue(fn.getAsBoolean());
2431 }
2432
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002433 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
2434
2435 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
2436
2437 private class CallbackValue {
2438 public CallbackType callbackType;
2439 public int error;
2440
2441 public CallbackValue(CallbackType type) {
2442 this.callbackType = type;
2443 this.error = PacketKeepalive.SUCCESS;
2444 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
2445 }
2446
2447 public CallbackValue(CallbackType type, int error) {
2448 this.callbackType = type;
2449 this.error = error;
2450 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
2451 }
2452
2453 @Override
2454 public boolean equals(Object o) {
2455 return o instanceof CallbackValue &&
2456 this.callbackType == ((CallbackValue) o).callbackType &&
2457 this.error == ((CallbackValue) o).error;
2458 }
2459
2460 @Override
2461 public String toString() {
2462 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
2463 }
2464 }
2465
2466 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
2467
2468 @Override
2469 public void onStarted() {
2470 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
2471 }
2472
2473 @Override
2474 public void onStopped() {
2475 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
2476 }
2477
2478 @Override
2479 public void onError(int error) {
2480 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
2481 }
2482
2483 private void expectCallback(CallbackValue callbackValue) {
2484 try {
2485 assertEquals(
2486 callbackValue,
2487 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
2488 } catch (InterruptedException e) {
2489 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
2490 }
2491 }
2492
2493 public void expectStarted() {
2494 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
2495 }
2496
2497 public void expectStopped() {
2498 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
2499 }
2500
2501 public void expectError(int error) {
2502 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
2503 }
2504 }
2505
2506 private Network connectKeepaliveNetwork(LinkProperties lp) {
2507 // Ensure the network is disconnected before we do anything.
2508 if (mWiFiNetworkAgent != null) {
2509 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
2510 }
2511
2512 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2513 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2514 mWiFiNetworkAgent.connect(true);
2515 waitFor(cv);
2516 verifyActiveNetwork(TRANSPORT_WIFI);
2517 mWiFiNetworkAgent.sendLinkProperties(lp);
2518 mService.waitForIdle();
2519 return mWiFiNetworkAgent.getNetwork();
2520 }
2521
2522 public void testPacketKeepalives() throws Exception {
2523 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
2524 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
2525 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
2526 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
2527 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
2528
2529 LinkProperties lp = new LinkProperties();
2530 lp.setInterfaceName("wlan12");
2531 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
2532 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
2533 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
2534 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
2535
2536 Network notMyNet = new Network(61234);
2537 Network myNet = connectKeepaliveNetwork(lp);
2538
2539 TestKeepaliveCallback callback = new TestKeepaliveCallback();
2540 PacketKeepalive ka;
2541
2542 // Attempt to start keepalives with invalid parameters and check for errors.
2543 ka = mCm.startNattKeepalive(notMyNet, 25, callback, myIPv4, 1234, dstIPv4);
2544 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
2545
2546 ka = mCm.startNattKeepalive(myNet, 19, callback, notMyIPv4, 1234, dstIPv4);
2547 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
2548
2549 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 1234, dstIPv6);
2550 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2551
2552 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv4);
2553 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2554
2555 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv6);
2556 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); // NAT-T is IPv4-only.
2557
2558 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
2559 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
2560
2561 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
2562 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
2563
2564 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2565 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
2566
2567 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2568 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
2569
2570 // Check that a started keepalive can be stopped.
2571 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2572 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2573 callback.expectStarted();
2574 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
2575 ka.stop();
2576 callback.expectStopped();
2577
2578 // Check that deleting the IP address stops the keepalive.
2579 LinkProperties bogusLp = new LinkProperties(lp);
2580 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2581 callback.expectStarted();
2582 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
2583 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
2584 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
2585 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2586 mWiFiNetworkAgent.sendLinkProperties(lp);
2587
2588 // Check that a started keepalive is stopped correctly when the network disconnects.
2589 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2590 callback.expectStarted();
2591 mWiFiNetworkAgent.disconnect();
2592 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
2593
2594 // ... and that stopping it after that has no adverse effects.
2595 assertNull(mCm.getNetworkCapabilities(myNet));
2596 ka.stop();
2597
2598 // Reconnect.
2599 myNet = connectKeepaliveNetwork(lp);
2600 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2601
2602 // Check things work as expected when the keepalive is stopped and the network disconnects.
2603 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2604 callback.expectStarted();
2605 ka.stop();
2606 mWiFiNetworkAgent.disconnect();
2607 mService.waitForIdle();
2608 callback.expectStopped();
2609
2610 // Reconnect.
2611 myNet = connectKeepaliveNetwork(lp);
2612 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2613
2614 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
2615 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
2616 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2617 callback.expectStarted();
2618
2619 // The second one gets slot 2.
2620 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
2621 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
2622 PacketKeepalive ka2 = mCm.startNattKeepalive(myNet, 25, callback2, myIPv4, 6789, dstIPv4);
2623 callback2.expectStarted();
2624
2625 // Now stop the first one and create a third. This also gets slot 1.
2626 ka.stop();
2627 callback.expectStopped();
2628
2629 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
2630 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
2631 PacketKeepalive ka3 = mCm.startNattKeepalive(myNet, 25, callback3, myIPv4, 9876, dstIPv4);
2632 callback3.expectStarted();
2633
2634 ka2.stop();
2635 callback2.expectStopped();
2636
2637 ka3.stop();
2638 callback3.expectStopped();
2639 }
Udam Sainib7c24872016-01-04 12:16:14 -08002640
2641 @SmallTest
2642 public void testGetCaptivePortalServerUrl() throws Exception {
2643 String url = mCm.getCaptivePortalServerUrl();
2644 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
2645 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09002646
2647 private static class TestNetworkPinner extends NetworkPinner {
2648 public static boolean awaitPin(int timeoutMs) {
2649 synchronized(sLock) {
2650 if (sNetwork == null) {
2651 try {
2652 sLock.wait(timeoutMs);
2653 } catch (InterruptedException e) {}
2654 }
2655 return sNetwork != null;
2656 }
2657 }
2658
2659 public static boolean awaitUnpin(int timeoutMs) {
2660 synchronized(sLock) {
2661 if (sNetwork != null) {
2662 try {
2663 sLock.wait(timeoutMs);
2664 } catch (InterruptedException e) {}
2665 }
2666 return sNetwork == null;
2667 }
2668 }
2669 }
2670
2671 private void assertPinnedToWifiWithCellDefault() {
2672 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
2673 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2674 }
2675
2676 private void assertPinnedToWifiWithWifiDefault() {
2677 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
2678 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2679 }
2680
2681 private void assertNotPinnedToWifi() {
2682 assertNull(mCm.getBoundNetworkForProcess());
2683 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2684 }
2685
2686 @SmallTest
2687 public void testNetworkPinner() {
2688 NetworkRequest wifiRequest = new NetworkRequest.Builder()
2689 .addTransportType(TRANSPORT_WIFI)
2690 .build();
2691 assertNull(mCm.getBoundNetworkForProcess());
2692
2693 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2694 assertNull(mCm.getBoundNetworkForProcess());
2695
2696 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2697 mCellNetworkAgent.connect(true);
2698 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2699 mWiFiNetworkAgent.connect(false);
2700
2701 // When wi-fi connects, expect to be pinned.
2702 assertTrue(TestNetworkPinner.awaitPin(100));
2703 assertPinnedToWifiWithCellDefault();
2704
2705 // Disconnect and expect the pin to drop.
2706 mWiFiNetworkAgent.disconnect();
2707 assertTrue(TestNetworkPinner.awaitUnpin(100));
2708 assertNotPinnedToWifi();
2709
2710 // Reconnecting does not cause the pin to come back.
2711 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2712 mWiFiNetworkAgent.connect(false);
2713 assertFalse(TestNetworkPinner.awaitPin(100));
2714 assertNotPinnedToWifi();
2715
2716 // Pinning while connected causes the pin to take effect immediately.
2717 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2718 assertTrue(TestNetworkPinner.awaitPin(100));
2719 assertPinnedToWifiWithCellDefault();
2720
2721 // Explicitly unpin and expect to use the default network again.
2722 TestNetworkPinner.unpin();
2723 assertNotPinnedToWifi();
2724
2725 // Disconnect cell and wifi.
2726 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
2727 mCellNetworkAgent.disconnect();
2728 mWiFiNetworkAgent.disconnect();
2729 waitFor(cv);
2730
2731 // Pinning takes effect even if the pinned network is the default when the pin is set...
2732 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2733 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2734 mWiFiNetworkAgent.connect(false);
2735 assertTrue(TestNetworkPinner.awaitPin(100));
2736 assertPinnedToWifiWithWifiDefault();
2737
2738 // ... and is maintained even when that network is no longer the default.
2739 cv = waitForConnectivityBroadcasts(1);
2740 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2741 mCellNetworkAgent.connect(true);
2742 waitFor(cv);
2743 assertPinnedToWifiWithCellDefault();
2744 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04002745
2746 @SmallTest
2747 public void testNetworkRequestMaximum() {
2748 final int MAX_REQUESTS = 100;
2749 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
2750 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
2751 ArrayList<NetworkCallback> networkCallbacks = new ArrayList<NetworkCallback>();
2752 try {
2753 for (int i = 0; i < MAX_REQUESTS; i++) {
2754 NetworkCallback networkCallback = new NetworkCallback();
2755 mCm.requestNetwork(networkRequest, networkCallback);
2756 networkCallbacks.add(networkCallback);
2757 }
2758 fail("Registering " + MAX_REQUESTS + " NetworkRequests did not throw exception");
2759 } catch (IllegalArgumentException expected) {}
2760 for (NetworkCallback networkCallback : networkCallbacks) {
2761 mCm.unregisterNetworkCallback(networkCallback);
2762 }
2763 networkCallbacks.clear();
2764
2765 try {
2766 for (int i = 0; i < MAX_REQUESTS; i++) {
2767 NetworkCallback networkCallback = new NetworkCallback();
2768 mCm.registerNetworkCallback(networkRequest, networkCallback);
2769 networkCallbacks.add(networkCallback);
2770 }
2771 fail("Registering " + MAX_REQUESTS + " NetworkCallbacks did not throw exception");
2772 } catch (IllegalArgumentException expected) {}
2773 for (NetworkCallback networkCallback : networkCallbacks) {
2774 mCm.unregisterNetworkCallback(networkCallback);
2775 }
2776 networkCallbacks.clear();
2777
2778 ArrayList<PendingIntent> pendingIntents = new ArrayList<PendingIntent>();
2779 try {
2780 for (int i = 0; i < MAX_REQUESTS + 1; i++) {
2781 PendingIntent pendingIntent =
2782 PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
2783 mCm.requestNetwork(networkRequest, pendingIntent);
2784 pendingIntents.add(pendingIntent);
2785 }
2786 fail("Registering " + MAX_REQUESTS +
2787 " PendingIntent NetworkRequests did not throw exception");
2788 } catch (IllegalArgumentException expected) {}
2789 for (PendingIntent pendingIntent : pendingIntents) {
2790 mCm.unregisterNetworkCallback(pendingIntent);
2791 }
2792 pendingIntents.clear();
2793
2794 try {
2795 for (int i = 0; i < MAX_REQUESTS + 1; i++) {
2796 PendingIntent pendingIntent =
2797 PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
2798 mCm.registerNetworkCallback(networkRequest, pendingIntent);
2799 pendingIntents.add(pendingIntent);
2800 }
2801 fail("Registering " + MAX_REQUESTS +
2802 " PendingIntent NetworkCallbacks did not throw exception");
2803 } catch (IllegalArgumentException expected) {}
2804 for (PendingIntent pendingIntent : pendingIntents) {
2805 mCm.unregisterNetworkCallback(pendingIntent);
2806 }
2807 pendingIntents.clear();
2808 mService.waitForIdle(5000);
2809
2810 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
2811 for (int i = 0; i < MAX_REQUESTS; i++) {
2812 NetworkCallback networkCallback = new NetworkCallback();
2813 mCm.requestNetwork(networkRequest, networkCallback);
2814 mCm.unregisterNetworkCallback(networkCallback);
2815 }
2816 mService.waitForIdle();
2817 for (int i = 0; i < MAX_REQUESTS; i++) {
2818 NetworkCallback networkCallback = new NetworkCallback();
2819 mCm.registerNetworkCallback(networkRequest, networkCallback);
2820 mCm.unregisterNetworkCallback(networkCallback);
2821 }
2822 mService.waitForIdle();
2823 for (int i = 0; i < MAX_REQUESTS; i++) {
2824 PendingIntent pendingIntent =
2825 PendingIntent.getBroadcast(mContext, 0, new Intent("b" + i), 0);
2826 mCm.requestNetwork(networkRequest, pendingIntent);
2827 mCm.unregisterNetworkCallback(pendingIntent);
2828 }
2829 mService.waitForIdle();
2830 for (int i = 0; i < MAX_REQUESTS; i++) {
2831 PendingIntent pendingIntent =
2832 PendingIntent.getBroadcast(mContext, 0, new Intent("c" + i), 0);
2833 mCm.registerNetworkCallback(networkRequest, pendingIntent);
2834 mCm.unregisterNetworkCallback(pendingIntent);
2835 }
2836 }
Etan Cohen4fde1672016-10-27 15:05:50 -07002837
2838 /* test utilities */
2839 static private void sleepFor(int ms) {
2840 try {
2841 Thread.sleep(ms);
2842 } catch (InterruptedException e) {
2843 }
2844
2845 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07002846}