blob: 51c89079e81d1087e7d9dc90af4da7a6fbb86c45 [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
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090026import static org.mockito.Mockito.anyBoolean;
27import static org.mockito.Mockito.anyInt;
28import static org.mockito.Mockito.eq;
Jeff Sharkey3671b1e2013-01-31 17:22:26 -080029import static org.mockito.Mockito.mock;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090030import static org.mockito.Mockito.spy;
31import static org.mockito.Mockito.when;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070032
Lorenzo Colitti73b209382016-09-15 22:18:09 +090033import android.app.NotificationManager;
Paul Jensenbb2e0e92015-06-16 15:11:58 -040034import android.app.PendingIntent;
Paul Jensend7b6ca92015-05-13 14:05:12 -040035import android.content.BroadcastReceiver;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +090036import android.content.ContentResolver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070037import android.content.Context;
Paul Jensend7b6ca92015-05-13 14:05:12 -040038import android.content.ContextWrapper;
39import android.content.Intent;
40import android.content.IntentFilter;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090041import android.content.res.Resources;
Paul Jensend7b6ca92015-05-13 14:05:12 -040042import android.net.ConnectivityManager;
43import android.net.ConnectivityManager.NetworkCallback;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +090044import android.net.ConnectivityManager.PacketKeepalive;
45import android.net.ConnectivityManager.PacketKeepaliveCallback;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070046import android.net.INetworkPolicyManager;
47import android.net.INetworkStatsService;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +090048import android.net.IpPrefix;
49import android.net.LinkAddress;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070050import android.net.LinkProperties;
Etan Cohena7434272017-04-03 12:17:51 -070051import android.net.MatchAllNetworkSpecifier;
Paul Jensend7b6ca92015-05-13 14:05:12 -040052import android.net.Network;
53import android.net.NetworkAgent;
54import android.net.NetworkCapabilities;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070055import android.net.NetworkConfig;
Robert Greenwalt348e98d2015-06-05 17:55:36 -070056import android.net.NetworkFactory;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070057import android.net.NetworkInfo;
58import android.net.NetworkInfo.DetailedState;
Paul Jensend7b6ca92015-05-13 14:05:12 -040059import android.net.NetworkMisc;
60import android.net.NetworkRequest;
Etan Cohena7434272017-04-03 12:17:51 -070061import android.net.NetworkSpecifier;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070062import android.net.RouteInfo;
Etan Cohena7434272017-04-03 12:17:51 -070063import android.net.StringNetworkSpecifier;
Hugo Benichif9fdf872016-07-28 17:53:06 +090064import android.net.metrics.IpConnectivityLog;
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +090065import android.net.util.MultinetworkPolicyTracker;
Paul Jensend7b6ca92015-05-13 14:05:12 -040066import android.os.ConditionVariable;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070067import android.os.Handler;
Robert Greenwalt348e98d2015-06-05 17:55:36 -070068import android.os.HandlerThread;
Etan Cohenddb9ef02015-11-18 10:56:15 -080069import android.os.IBinder;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070070import android.os.INetworkManagementService;
Lorenzo Colittie58961a2015-08-07 20:17:27 +090071import android.os.Looper;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +090072import android.os.Message;
Lorenzo Colittie58961a2015-08-07 20:17:27 +090073import android.os.MessageQueue;
Etan Cohenddb9ef02015-11-18 10:56:15 -080074import android.os.Messenger;
Lorenzo Colittie58961a2015-08-07 20:17:27 +090075import android.os.MessageQueue.IdleHandler;
Etan Cohena7434272017-04-03 12:17:51 -070076import android.os.Parcel;
77import android.os.Parcelable;
Robin Leed2baf792016-03-24 12:07:00 +000078import android.os.Process;
Lorenzo Colittibfecba22016-02-21 01:09:26 +090079import android.os.SystemClock;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +090080import android.provider.Settings;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070081import android.test.AndroidTestCase;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +090082import android.test.mock.MockContentResolver;
Udam Sainib7c24872016-01-04 12:16:14 -080083import android.test.suitebuilder.annotation.SmallTest;
Etan Cohena7434272017-04-03 12:17:51 -070084import android.text.TextUtils;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070085import android.util.Log;
86import android.util.LogPrinter;
87
Lorenzo Colittibfecba22016-02-21 01:09:26 +090088import com.android.internal.util.WakeupMessage;
Lorenzo Colitti3c295b52016-10-28 12:56:03 +090089import com.android.internal.util.test.BroadcastInterceptingContext;
Lorenzo Colittib8df76e42016-10-28 12:37:38 +090090import com.android.internal.util.test.FakeSettingsProvider;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090091import com.android.server.connectivity.MockableSystemProperties;
Paul Jensencf4c2c62015-07-01 14:16:32 -040092import com.android.server.connectivity.NetworkAgentInfo;
Paul Jensend7b6ca92015-05-13 14:05:12 -040093import com.android.server.connectivity.NetworkMonitor;
Paul Jensen232437312016-04-06 09:51:26 -040094import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
Lorenzo Colitti531a3442016-03-01 12:55:58 +090095import com.android.server.net.NetworkPinner;
Paul Jensend7b6ca92015-05-13 14:05:12 -040096
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090097import org.mockito.Mock;
98import org.mockito.MockitoAnnotations;
99import org.mockito.Spy;
100
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700101import java.net.InetAddress;
Paul Jensen4e1d3fd2016-04-08 13:56:52 -0400102import java.util.ArrayList;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900103import java.util.Arrays;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +0900104import java.util.Objects;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900105import java.util.concurrent.CountDownLatch;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900106import java.util.concurrent.LinkedBlockingQueue;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900107import java.util.concurrent.TimeUnit;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700108import java.util.concurrent.atomic.AtomicBoolean;
Hugo Benichi53d83d52016-11-15 13:42:34 +0900109import java.util.function.BooleanSupplier;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700110
111/**
112 * Tests for {@link ConnectivityService}.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400113 *
114 * Build, install and run with:
115 * runtest frameworks-services -c com.android.server.ConnectivityServiceTest
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700116 */
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700117public class ConnectivityServiceTest extends AndroidTestCase {
118 private static final String TAG = "ConnectivityServiceTest";
119
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900120 private static final int TIMEOUT_MS = 500;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900121 private static final int TEST_LINGER_DELAY_MS = 120;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900122
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700123 private BroadcastInterceptingContext mServiceContext;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400124 private WrappedConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900125 private WrappedConnectivityManager mCm;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400126 private MockNetworkAgent mWiFiNetworkAgent;
127 private MockNetworkAgent mCellNetworkAgent;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900128 private MockNetworkAgent mEthernetNetworkAgent;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700129
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900130 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
131 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
132 // reflect the state of our test ConnectivityService.
133 private class WrappedConnectivityManager extends ConnectivityManager {
134 private Network mFakeBoundNetwork;
135
136 public synchronized boolean bindProcessToNetwork(Network network) {
137 mFakeBoundNetwork = network;
138 return true;
139 }
140
141 public synchronized Network getBoundNetworkForProcess() {
142 return mFakeBoundNetwork;
143 }
144
145 public WrappedConnectivityManager(Context context, ConnectivityService service) {
146 super(context, service);
147 }
148 }
149
Paul Jensend7b6ca92015-05-13 14:05:12 -0400150 private class MockContext extends BroadcastInterceptingContext {
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900151 private final MockContentResolver mContentResolver;
152
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900153 @Spy private Resources mResources;
154
Paul Jensend7b6ca92015-05-13 14:05:12 -0400155 MockContext(Context base) {
156 super(base);
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900157
158 mResources = spy(base.getResources());
159 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
160 thenReturn(new String[] {
161 "wifi,1,1,1,-1,true",
162 "mobile,0,0,0,-1,true",
163 "mobile_mms,2,0,2,60000,true",
164 });
165
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900166 mContentResolver = new MockContentResolver();
167 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
Paul Jensend7b6ca92015-05-13 14:05:12 -0400168 }
169
170 @Override
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900171 public Object getSystemService(String name) {
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900172 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
173 if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400174 return super.getSystemService(name);
175 }
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900176
177 @Override
178 public ContentResolver getContentResolver() {
179 return mContentResolver;
180 }
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900181
182 @Override
183 public Resources getResources() {
184 return mResources;
185 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400186 }
187
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900188 /**
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900189 * Block until the given handler becomes idle, or until timeoutMs has passed.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900190 */
Lorenzo Colittiae3ce812017-01-25 23:09:07 +0900191 private static void waitForIdleHandler(HandlerThread handlerThread, int timeoutMs) {
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900192 final ConditionVariable cv = new ConditionVariable();
Lorenzo Colittiae3ce812017-01-25 23:09:07 +0900193 final Handler handler = new Handler(handlerThread.getLooper());
194 handler.post(() -> cv.open());
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900195 if (!cv.block(timeoutMs)) {
Lorenzo Colittiae3ce812017-01-25 23:09:07 +0900196 fail("HandlerThread " + handlerThread.getName() +
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900197 " did not become idle after " + timeoutMs + " ms");
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900198 }
199 }
200
Hugo Benichicfcc1cb2016-11-04 16:06:34 +0900201 @SmallTest
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900202 public void testWaitForIdle() {
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900203 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
204
205 // Tests that waitForIdle returns immediately if the service is already idle.
206 for (int i = 0; i < attempts; i++) {
207 mService.waitForIdle();
208 }
209
210 // Bring up a network that we can use to send messages to ConnectivityService.
211 ConditionVariable cv = waitForConnectivityBroadcasts(1);
212 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
213 mWiFiNetworkAgent.connect(false);
214 waitFor(cv);
215 Network n = mWiFiNetworkAgent.getNetwork();
216 assertNotNull(n);
217
218 // Tests that calling waitForIdle waits for messages to be processed.
219 for (int i = 0; i < attempts; i++) {
220 mWiFiNetworkAgent.setSignalStrength(i);
221 mService.waitForIdle();
222 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
223 }
Hugo Benichi5d540d12016-10-17 15:54:51 +0900224 }
225
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900226 // This test has an inherent race condition in it, and cannot be enabled for continuous testing
227 // or presubmit tests. It is kept for manual runs and documentation purposes.
228 public void verifyThatNotWaitingForIdleCausesRaceConditions() {
Hugo Benichi5d540d12016-10-17 15:54:51 +0900229 // Bring up a network that we can use to send messages to ConnectivityService.
230 ConditionVariable cv = waitForConnectivityBroadcasts(1);
231 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
232 mWiFiNetworkAgent.connect(false);
233 waitFor(cv);
234 Network n = mWiFiNetworkAgent.getNetwork();
235 assertNotNull(n);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900236
237 // Ensure that not calling waitForIdle causes a race condition.
Hugo Benichi5d540d12016-10-17 15:54:51 +0900238 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900239 for (int i = 0; i < attempts; i++) {
240 mWiFiNetworkAgent.setSignalStrength(i);
241 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
242 // We hit a race condition, as expected. Pass the test.
243 return;
244 }
245 }
246
247 // No race? There is a bug in this test.
248 fail("expected race condition at least once in " + attempts + " attempts");
249 }
250
Paul Jensend7b6ca92015-05-13 14:05:12 -0400251 private class MockNetworkAgent {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400252 private final WrappedNetworkMonitor mWrappedNetworkMonitor;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400253 private final NetworkInfo mNetworkInfo;
254 private final NetworkCapabilities mNetworkCapabilities;
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900255 private final HandlerThread mHandlerThread;
Paul Jensene0988542015-06-25 15:30:08 -0400256 private final ConditionVariable mDisconnected = new ConditionVariable();
Paul Jensen232437312016-04-06 09:51:26 -0400257 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
Calvin On1f64f3f2016-10-11 15:10:46 -0700258 private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
Paul Jensen3d911462015-06-12 06:40:24 -0400259 private int mScore;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400260 private NetworkAgent mNetworkAgent;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900261 private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
262 private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE;
263 private Integer mExpectedKeepaliveSlot = null;
Paul Jensen232437312016-04-06 09:51:26 -0400264 // Contains the redirectUrl from networkStatus(). Before reading, wait for
265 // mNetworkStatusReceived.
266 private String mRedirectUrl;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400267
268 MockNetworkAgent(int transport) {
269 final int type = transportToLegacyType(transport);
270 final String typeName = ConnectivityManager.getNetworkTypeName(type);
271 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
272 mNetworkCapabilities = new NetworkCapabilities();
273 mNetworkCapabilities.addTransportType(transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400274 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900275 case TRANSPORT_ETHERNET:
276 mScore = 70;
277 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400278 case TRANSPORT_WIFI:
Paul Jensen3d911462015-06-12 06:40:24 -0400279 mScore = 60;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400280 break;
281 case TRANSPORT_CELLULAR:
Paul Jensen3d911462015-06-12 06:40:24 -0400282 mScore = 50;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400283 break;
284 default:
285 throw new UnsupportedOperationException("unimplemented network type");
286 }
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900287 mHandlerThread = new HandlerThread("Mock-" + typeName);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900288 mHandlerThread.start();
289 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
290 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
291 new LinkProperties(), mScore, new NetworkMisc()) {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900292 @Override
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900293 public void unwanted() { mDisconnected.open(); }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900294
295 @Override
296 public void startPacketKeepalive(Message msg) {
297 int slot = msg.arg1;
298 if (mExpectedKeepaliveSlot != null) {
299 assertEquals((int) mExpectedKeepaliveSlot, slot);
300 }
301 onPacketKeepaliveEvent(slot, mStartKeepaliveError);
302 }
303
304 @Override
305 public void stopPacketKeepalive(Message msg) {
306 onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
307 }
Paul Jensen232437312016-04-06 09:51:26 -0400308
309 @Override
310 public void networkStatus(int status, String redirectUrl) {
311 mRedirectUrl = redirectUrl;
312 mNetworkStatusReceived.open();
313 }
Calvin On1f64f3f2016-10-11 15:10:46 -0700314
315 @Override
316 protected void preventAutomaticReconnect() {
317 mPreventReconnectReceived.open();
318 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400319 };
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900320 // Waits for the NetworkAgent to be registered, which includes the creation of the
321 // NetworkMonitor.
322 mService.waitForIdle();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400323 mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor();
Paul Jensen3d911462015-06-12 06:40:24 -0400324 }
325
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900326 public void waitForIdle(int timeoutMs) {
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900327 waitForIdleHandler(mHandlerThread, timeoutMs);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900328 }
329
330 public void waitForIdle() {
331 waitForIdle(TIMEOUT_MS);
332 }
333
Paul Jensen3d911462015-06-12 06:40:24 -0400334 public void adjustScore(int change) {
335 mScore += change;
336 mNetworkAgent.sendNetworkScore(mScore);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400337 }
338
Paul Jensen85cf78e2015-06-25 13:25:07 -0400339 public void addCapability(int capability) {
340 mNetworkCapabilities.addCapability(capability);
341 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
342 }
343
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900344 public void removeCapability(int capability) {
345 mNetworkCapabilities.removeCapability(capability);
346 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
347 }
348
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900349 public void setSignalStrength(int signalStrength) {
350 mNetworkCapabilities.setSignalStrength(signalStrength);
351 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
352 }
353
Etan Cohena7434272017-04-03 12:17:51 -0700354 public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
355 mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
Lorenzo Colitti6556a222017-04-03 17:46:35 +0900356 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
357 }
358
Paul Jensene0988542015-06-25 15:30:08 -0400359 public void connectWithoutInternet() {
360 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
361 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
362 }
363
Paul Jensend7b6ca92015-05-13 14:05:12 -0400364 /**
Paul Jensene0988542015-06-25 15:30:08 -0400365 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400366 * @param validated Indicate if network should pretend to be validated.
367 */
368 public void connect(boolean validated) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900369 assertEquals("MockNetworkAgents can only be connected once",
370 mNetworkInfo.getDetailedState(), DetailedState.IDLE);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400371 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
372
Paul Jensend7b6ca92015-05-13 14:05:12 -0400373 NetworkCallback callback = null;
374 final ConditionVariable validatedCv = new ConditionVariable();
375 if (validated) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400376 mWrappedNetworkMonitor.gen204ProbeResult = 204;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400377 NetworkRequest request = new NetworkRequest.Builder()
378 .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
379 .build();
380 callback = new NetworkCallback() {
381 public void onCapabilitiesChanged(Network network,
382 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400383 if (network.equals(getNetwork()) &&
384 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400385 validatedCv.open();
386 }
387 }
388 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400389 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400390 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400391 addCapability(NET_CAPABILITY_INTERNET);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400392
Paul Jensene0988542015-06-25 15:30:08 -0400393 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400394
395 if (validated) {
396 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400397 waitFor(validatedCv);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400398 mWrappedNetworkMonitor.gen204ProbeResult = 500;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400399 }
400
401 if (callback != null) mCm.unregisterNetworkCallback(callback);
402 }
403
Paul Jensen232437312016-04-06 09:51:26 -0400404 public void connectWithCaptivePortal(String redirectUrl) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400405 mWrappedNetworkMonitor.gen204ProbeResult = 200;
Paul Jensen232437312016-04-06 09:51:26 -0400406 mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400407 connect(false);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400408 }
409
Erik Kline1d3db322017-02-28 16:20:20 +0900410 public void suspend() {
411 mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null);
412 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
413 }
414
Paul Jensend7b6ca92015-05-13 14:05:12 -0400415 public void disconnect() {
416 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
417 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
418 }
419
420 public Network getNetwork() {
421 return new Network(mNetworkAgent.netId);
422 }
Paul Jensene0988542015-06-25 15:30:08 -0400423
Calvin On1f64f3f2016-10-11 15:10:46 -0700424 public ConditionVariable getPreventReconnectReceived() {
425 return mPreventReconnectReceived;
426 }
427
Paul Jensene0988542015-06-25 15:30:08 -0400428 public ConditionVariable getDisconnectedCV() {
429 return mDisconnected;
430 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400431
432 public WrappedNetworkMonitor getWrappedNetworkMonitor() {
433 return mWrappedNetworkMonitor;
434 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900435
436 public void sendLinkProperties(LinkProperties lp) {
437 mNetworkAgent.sendLinkProperties(lp);
438 }
439
440 public void setStartKeepaliveError(int error) {
441 mStartKeepaliveError = error;
442 }
443
444 public void setStopKeepaliveError(int error) {
445 mStopKeepaliveError = error;
446 }
447
448 public void setExpectedKeepaliveSlot(Integer slot) {
449 mExpectedKeepaliveSlot = slot;
450 }
Paul Jensen232437312016-04-06 09:51:26 -0400451
452 public String waitForRedirectUrl() {
453 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
454 return mRedirectUrl;
455 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400456 }
457
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900458 /**
459 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
460 * operations have been processed. Before ConnectivityService can add or remove any requests,
461 * the factory must be told to expect those operations by calling expectAddRequests or
462 * expectRemoveRequests.
463 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700464 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400465 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
466 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400467 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700468
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900469 // Used to expect that requests be removed or added on a separate thread, without sleeping.
470 // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then
471 // cause some other thread to add or remove requests, then call waitForRequests(). We can
472 // either expect requests to be added or removed, but not both, because CountDownLatch can
473 // only count in one direction.
474 private CountDownLatch mExpectations;
475
476 // Whether we are currently expecting requests to be added or removed. Valid only if
477 // mExpectations is non-null.
478 private boolean mExpectingAdditions;
479
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700480 public MockNetworkFactory(Looper looper, Context context, String logTag,
481 NetworkCapabilities filter) {
482 super(looper, context, logTag, filter);
483 }
484
485 public int getMyRequestCount() {
486 return getRequestCount();
487 }
488
489 protected void startNetwork() {
490 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400491 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700492 }
493
494 protected void stopNetwork() {
495 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400496 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700497 }
498
499 public boolean getMyStartRequested() {
500 return mNetworkStarted.get();
501 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400502
503 public ConditionVariable getNetworkStartedCV() {
504 mNetworkStartedCV.close();
505 return mNetworkStartedCV;
506 }
507
508 public ConditionVariable getNetworkStoppedCV() {
509 mNetworkStoppedCV.close();
510 return mNetworkStoppedCV;
511 }
512
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900513 @Override
514 protected void handleAddRequest(NetworkRequest request, int score) {
515 // If we're expecting anything, we must be expecting additions.
516 if (mExpectations != null && !mExpectingAdditions) {
517 fail("Can't add requests while expecting requests to be removed");
518 }
519
520 // Add the request.
521 super.handleAddRequest(request, score);
522
523 // Reduce the number of request additions we're waiting for.
524 if (mExpectingAdditions) {
525 assertTrue("Added more requests than expected", mExpectations.getCount() > 0);
526 mExpectations.countDown();
527 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400528 }
529
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900530 @Override
531 protected void handleRemoveRequest(NetworkRequest request) {
532 // If we're expecting anything, we must be expecting removals.
533 if (mExpectations != null && mExpectingAdditions) {
534 fail("Can't remove requests while expecting requests to be added");
535 }
536
537 // Remove the request.
538 super.handleRemoveRequest(request);
539
540 // Reduce the number of request removals we're waiting for.
541 if (!mExpectingAdditions) {
542 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0);
543 mExpectations.countDown();
544 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400545 }
546
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900547 private void assertNoExpectations() {
548 if (mExpectations != null) {
549 fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
550 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400551 }
552
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900553 // Expects that count requests will be added.
554 public void expectAddRequests(final int count) {
555 assertNoExpectations();
556 mExpectingAdditions = true;
557 mExpectations = new CountDownLatch(count);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400558 }
559
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900560 // Expects that count requests will be removed.
561 public void expectRemoveRequests(final int count) {
562 assertNoExpectations();
563 mExpectingAdditions = false;
564 mExpectations = new CountDownLatch(count);
565 }
566
567 // Waits for the expected request additions or removals to happen within a timeout.
568 public void waitForRequests() throws InterruptedException {
569 assertNotNull("Nothing to wait for", mExpectations);
570 mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
571 final long count = mExpectations.getCount();
572 final String msg = count + " requests still not " +
573 (mExpectingAdditions ? "added" : "removed") +
574 " after " + TIMEOUT_MS + " ms";
575 assertEquals(msg, 0, count);
576 mExpectations = null;
577 }
578
579 public void waitForNetworkRequests(final int count) throws InterruptedException {
580 waitForRequests();
581 assertEquals(count, getMyRequestCount());
Paul Jensen0a2823e2015-06-12 10:31:09 -0400582 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700583 }
584
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900585 private class FakeWakeupMessage extends WakeupMessage {
586 private static final int UNREASONABLY_LONG_WAIT = 1000;
587
588 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
589 super(context, handler, cmdName, cmd);
590 }
591
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900592 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
593 int arg1, int arg2, Object obj) {
594 super(context, handler, cmdName, cmd, arg1, arg2, obj);
595 }
596
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900597 @Override
598 public void schedule(long when) {
599 long delayMs = when - SystemClock.elapsedRealtime();
600 if (delayMs < 0) delayMs = 0;
601 if (delayMs > UNREASONABLY_LONG_WAIT) {
602 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
603 "ms into the future: " + delayMs);
604 }
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900605 Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
606 mHandler.sendMessageDelayed(msg, delayMs);
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900607 }
608
609 @Override
610 public void cancel() {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900611 mHandler.removeMessages(mCmd, mObj);
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900612 }
613
614 @Override
615 public void onAlarm() {
616 throw new AssertionError("Should never happen. Update this fake.");
617 }
618 }
619
Paul Jensencf4c2c62015-07-01 14:16:32 -0400620 // NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
621 private class WrappedNetworkMonitor extends NetworkMonitor {
622 // HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
623 public int gen204ProbeResult = 500;
Paul Jensen232437312016-04-06 09:51:26 -0400624 public String gen204ProbeRedirectUrl = null;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400625
626 public WrappedNetworkMonitor(Context context, Handler handler,
Hugo Benichif9fdf872016-07-28 17:53:06 +0900627 NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest,
628 IpConnectivityLog log) {
629 super(context, handler, networkAgentInfo, defaultRequest, log);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400630 }
631
632 @Override
Paul Jensen232437312016-04-06 09:51:26 -0400633 protected CaptivePortalProbeResult isCaptivePortal() {
Calvin On1f64f3f2016-10-11 15:10:46 -0700634 if (!mIsCaptivePortalCheckEnabled) { return new CaptivePortalProbeResult(204); }
Hugo Benichid953bf82016-09-27 09:22:35 +0900635 return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl, null);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400636 }
637 }
638
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900639 private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
Hugo Benichi53d83d52016-11-15 13:42:34 +0900640 public volatile boolean configRestrictsAvoidBadWifi;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400641
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900642 public WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
Erik Kline065ab6e2016-10-02 18:02:14 +0900643 super(c, h, r);
644 }
645
646 @Override
647 public boolean configRestrictsAvoidBadWifi() {
648 return configRestrictsAvoidBadWifi;
649 }
650 }
651
652 private class WrappedConnectivityService extends ConnectivityService {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900653 public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
Erik Kline065ab6e2016-10-02 18:02:14 +0900654 private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900655 private MockableSystemProperties mSystemProperties;
Erik Kline065ab6e2016-10-02 18:02:14 +0900656
Paul Jensend7b6ca92015-05-13 14:05:12 -0400657 public WrappedConnectivityService(Context context, INetworkManagementService netManager,
Hugo Benichif9fdf872016-07-28 17:53:06 +0900658 INetworkStatsService statsService, INetworkPolicyManager policyManager,
659 IpConnectivityLog log) {
660 super(context, netManager, statsService, policyManager, log);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900661 mLingerDelayMs = TEST_LINGER_DELAY_MS;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400662 }
663
664 @Override
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900665 protected MockableSystemProperties getSystemProperties() {
666 // Minimal approach to overriding system properties: let most calls fall through to real
667 // device values, and only override ones values that are important to this test.
668 mSystemProperties = spy(new MockableSystemProperties());
669 when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
670 when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
671 return mSystemProperties;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400672 }
Paul Jensen67b0b072015-06-10 11:22:17 -0400673
674 @Override
675 protected int reserveNetId() {
676 while (true) {
677 final int netId = super.reserveNetId();
678
679 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
680 // can have odd side-effects, like network validations succeeding.
681 final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks();
682 boolean overlaps = false;
683 for (Network network : networks) {
684 if (netId == network.netId) {
685 overlaps = true;
686 break;
687 }
688 }
689 if (overlaps) continue;
690
691 return netId;
692 }
693 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400694
695 @Override
696 public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
697 NetworkAgentInfo nai, NetworkRequest defaultRequest) {
Hugo Benichif9fdf872016-07-28 17:53:06 +0900698 final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(
699 context, handler, nai, defaultRequest, mock(IpConnectivityLog.class));
Paul Jensencf4c2c62015-07-01 14:16:32 -0400700 mLastCreatedNetworkMonitor = monitor;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400701 return monitor;
702 }
703
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900704 @Override
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900705 public MultinetworkPolicyTracker createMultinetworkPolicyTracker(
Erik Kline065ab6e2016-10-02 18:02:14 +0900706 Context c, Handler h, Runnable r) {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900707 final WrappedMultinetworkPolicyTracker tracker = new WrappedMultinetworkPolicyTracker(c, h, r);
Erik Kline065ab6e2016-10-02 18:02:14 +0900708 return tracker;
709 }
710
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900711 public WrappedMultinetworkPolicyTracker getMultinetworkPolicyTracker() {
712 return (WrappedMultinetworkPolicyTracker) mMultinetworkPolicyTracker;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900713 }
714
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900715 @Override
Erik Kline065ab6e2016-10-02 18:02:14 +0900716 public WakeupMessage makeWakeupMessage(
717 Context context, Handler handler, String cmdName, int cmd, Object obj) {
718 return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900719 }
720
Paul Jensencf4c2c62015-07-01 14:16:32 -0400721 public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
722 return mLastCreatedNetworkMonitor;
723 }
724
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900725 public void waitForIdle(int timeoutMs) {
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900726 waitForIdleHandler(mHandlerThread, timeoutMs);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400727 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900728
729 public void waitForIdle() {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900730 waitForIdle(TIMEOUT_MS);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900731 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400732 }
733
Paul Jensen3d911462015-06-12 06:40:24 -0400734 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900735 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
736 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -0400737 */
738 static private void waitFor(ConditionVariable conditionVariable) {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900739 assertTrue(conditionVariable.block(TIMEOUT_MS));
Paul Jensen3d911462015-06-12 06:40:24 -0400740 }
741
Paul Jensend7b6ca92015-05-13 14:05:12 -0400742 @Override
743 public void setUp() throws Exception {
744 super.setUp();
745
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +0900746 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
747 // http://b/25897652 .
748 if (Looper.myLooper() == null) {
749 Looper.prepare();
750 }
751
Paul Jensend7b6ca92015-05-13 14:05:12 -0400752 mServiceContext = new MockContext(getContext());
Lorenzo Colitti83fa2582015-08-07 12:49:01 +0900753 mService = new WrappedConnectivityService(mServiceContext,
754 mock(INetworkManagementService.class),
755 mock(INetworkStatsService.class),
Hugo Benichif9fdf872016-07-28 17:53:06 +0900756 mock(INetworkPolicyManager.class),
757 mock(IpConnectivityLog.class));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400758
Paul Jensend7b6ca92015-05-13 14:05:12 -0400759 mService.systemReady();
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900760 mCm = new WrappedConnectivityManager(getContext(), mService);
761 mCm.bindProcessToNetwork(null);
Calvin On1f64f3f2016-10-11 15:10:46 -0700762
763 // Ensure that the default setting for Captive Portals is used for most tests
764 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400765 }
766
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +0900767 public void tearDown() throws Exception {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +0900768 setMobileDataAlwaysOn(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +0900769 if (mCellNetworkAgent != null) { mCellNetworkAgent.disconnect(); }
770 if (mWiFiNetworkAgent != null) { mWiFiNetworkAgent.disconnect(); }
771 mCellNetworkAgent = mWiFiNetworkAgent = null;
772 super.tearDown();
773 }
774
Paul Jensend7b6ca92015-05-13 14:05:12 -0400775 private int transportToLegacyType(int transport) {
776 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900777 case TRANSPORT_ETHERNET:
778 return TYPE_ETHERNET;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400779 case TRANSPORT_WIFI:
780 return TYPE_WIFI;
781 case TRANSPORT_CELLULAR:
782 return TYPE_MOBILE;
783 default:
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900784 throw new IllegalStateException("Unknown transport " + transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400785 }
786 }
787
788 private void verifyActiveNetwork(int transport) {
789 // Test getActiveNetworkInfo()
790 assertNotNull(mCm.getActiveNetworkInfo());
791 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
792 // Test getActiveNetwork()
793 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +0000794 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400795 switch (transport) {
796 case TRANSPORT_WIFI:
797 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
798 break;
799 case TRANSPORT_CELLULAR:
800 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
801 break;
802 default:
803 throw new IllegalStateException("Unknown transport" + transport);
804 }
805 // Test getNetworkInfo(Network)
806 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
807 assertEquals(transportToLegacyType(transport), mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
808 // Test getNetworkCapabilities(Network)
809 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
810 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
811 }
812
813 private void verifyNoNetwork() {
814 // Test getActiveNetworkInfo()
815 assertNull(mCm.getActiveNetworkInfo());
816 // Test getActiveNetwork()
817 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +0000818 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400819 // Test getAllNetworks()
820 assertEquals(0, mCm.getAllNetworks().length);
821 }
822
823 /**
824 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
825 * broadcasts are received.
826 */
827 private ConditionVariable waitForConnectivityBroadcasts(final int count) {
828 final ConditionVariable cv = new ConditionVariable();
829 mServiceContext.registerReceiver(new BroadcastReceiver() {
830 private int remaining = count;
831 public void onReceive(Context context, Intent intent) {
832 if (--remaining == 0) {
833 cv.open();
834 mServiceContext.unregisterReceiver(this);
835 }
836 }
837 }, new IntentFilter(CONNECTIVITY_ACTION));
838 return cv;
839 }
840
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900841 public void testNetworkTypes() {
842 // Ensure that our mocks for the networkAttributes config variable work as expected. If they
843 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
844 // will fail. Failing here is much easier to debug.
845 assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
846 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
847 }
848
Hugo Benichicfcc1cb2016-11-04 16:06:34 +0900849 @SmallTest
Paul Jensend7b6ca92015-05-13 14:05:12 -0400850 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400851 verifyNoNetwork();
852 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
853 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
854 assertNull(mCm.getActiveNetworkInfo());
855 assertNull(mCm.getActiveNetwork());
856 // Test bringing up validated cellular.
857 ConditionVariable cv = waitForConnectivityBroadcasts(1);
858 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -0400859 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400860 verifyActiveNetwork(TRANSPORT_CELLULAR);
861 assertEquals(2, mCm.getAllNetworks().length);
862 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
863 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
864 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
865 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
866 // Test bringing up validated WiFi.
867 cv = waitForConnectivityBroadcasts(2);
868 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -0400869 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400870 verifyActiveNetwork(TRANSPORT_WIFI);
871 assertEquals(2, mCm.getAllNetworks().length);
872 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
873 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
874 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
875 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
876 // Test cellular linger timeout.
Lorenzo Colittid2706122017-01-30 17:45:49 +0900877 waitFor(mCellNetworkAgent.getDisconnectedCV());
878 mService.waitForIdle();
879 assertEquals(1, mCm.getAllNetworks().length);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400880 verifyActiveNetwork(TRANSPORT_WIFI);
881 assertEquals(1, mCm.getAllNetworks().length);
882 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
883 // Test WiFi disconnect.
884 cv = waitForConnectivityBroadcasts(1);
885 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400886 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400887 verifyNoNetwork();
888 }
889
Hugo Benichicfcc1cb2016-11-04 16:06:34 +0900890 @SmallTest
Paul Jensend7b6ca92015-05-13 14:05:12 -0400891 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
892 // Test bringing up unvalidated WiFi
893 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
894 ConditionVariable cv = waitForConnectivityBroadcasts(1);
895 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -0400896 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400897 verifyActiveNetwork(TRANSPORT_WIFI);
898 // Test bringing up unvalidated cellular
899 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
900 mCellNetworkAgent.connect(false);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900901 mService.waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400902 verifyActiveNetwork(TRANSPORT_WIFI);
903 // Test cellular disconnect.
904 mCellNetworkAgent.disconnect();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900905 mService.waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400906 verifyActiveNetwork(TRANSPORT_WIFI);
907 // Test bringing up validated cellular
908 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
909 cv = waitForConnectivityBroadcasts(2);
910 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -0400911 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400912 verifyActiveNetwork(TRANSPORT_CELLULAR);
913 // Test cellular disconnect.
914 cv = waitForConnectivityBroadcasts(2);
915 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400916 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400917 verifyActiveNetwork(TRANSPORT_WIFI);
918 // Test WiFi disconnect.
919 cv = waitForConnectivityBroadcasts(1);
920 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400921 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400922 verifyNoNetwork();
923 }
924
Hugo Benichicfcc1cb2016-11-04 16:06:34 +0900925 @SmallTest
Paul Jensend7b6ca92015-05-13 14:05:12 -0400926 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
927 // Test bringing up unvalidated cellular.
928 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
929 ConditionVariable cv = waitForConnectivityBroadcasts(1);
930 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -0400931 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400932 verifyActiveNetwork(TRANSPORT_CELLULAR);
933 // Test bringing up unvalidated WiFi.
934 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
935 cv = waitForConnectivityBroadcasts(2);
936 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -0400937 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400938 verifyActiveNetwork(TRANSPORT_WIFI);
939 // Test WiFi disconnect.
940 cv = waitForConnectivityBroadcasts(2);
941 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400942 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400943 verifyActiveNetwork(TRANSPORT_CELLULAR);
944 // Test cellular disconnect.
945 cv = waitForConnectivityBroadcasts(1);
946 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -0400947 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400948 verifyNoNetwork();
949 }
950
Hugo Benichicfcc1cb2016-11-04 16:06:34 +0900951 @SmallTest
Paul Jensene0988542015-06-25 15:30:08 -0400952 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400953 // Test bringing up unvalidated WiFi.
Paul Jensene0988542015-06-25 15:30:08 -0400954 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400955 ConditionVariable cv = waitForConnectivityBroadcasts(1);
956 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -0400957 waitFor(cv);
958 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400959 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -0400960 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -0400961 // Test bringing up validated cellular.
962 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -0400963 cv = waitForConnectivityBroadcasts(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400964 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -0400965 waitFor(cv);
966 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400967 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
968 NET_CAPABILITY_VALIDATED));
969 // Test cellular disconnect.
970 cv = waitForConnectivityBroadcasts(2);
971 mCellNetworkAgent.disconnect();
972 waitFor(cv);
973 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -0400974 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -0400975 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -0400976 NET_CAPABILITY_VALIDATED));
977 }
978
Hugo Benichicfcc1cb2016-11-04 16:06:34 +0900979 @SmallTest
Paul Jensen3d911462015-06-12 06:40:24 -0400980 public void testCellularOutscoresWeakWifi() throws Exception {
981 // Test bringing up validated cellular.
982 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
983 ConditionVariable cv = waitForConnectivityBroadcasts(1);
984 mCellNetworkAgent.connect(true);
985 waitFor(cv);
986 verifyActiveNetwork(TRANSPORT_CELLULAR);
987 // Test bringing up validated WiFi.
988 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
989 cv = waitForConnectivityBroadcasts(2);
990 mWiFiNetworkAgent.connect(true);
991 waitFor(cv);
992 verifyActiveNetwork(TRANSPORT_WIFI);
993 // Test WiFi getting really weak.
994 cv = waitForConnectivityBroadcasts(2);
995 mWiFiNetworkAgent.adjustScore(-11);
996 waitFor(cv);
997 verifyActiveNetwork(TRANSPORT_CELLULAR);
998 // Test WiFi restoring signal strength.
999 cv = waitForConnectivityBroadcasts(2);
1000 mWiFiNetworkAgent.adjustScore(11);
1001 waitFor(cv);
1002 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001003 }
1004
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001005 @SmallTest
Paul Jensene0988542015-06-25 15:30:08 -04001006 public void testReapingNetwork() throws Exception {
1007 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1008 // Expect it to be torn down immediately because it satisfies no requests.
1009 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1010 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
1011 mWiFiNetworkAgent.connectWithoutInternet();
1012 waitFor(cv);
1013 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1014 // Expect it to be torn down immediately because it satisfies no requests.
1015 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1016 cv = mCellNetworkAgent.getDisconnectedCV();
1017 mCellNetworkAgent.connectWithoutInternet();
1018 waitFor(cv);
1019 // Test bringing up validated WiFi.
1020 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1021 cv = waitForConnectivityBroadcasts(1);
1022 mWiFiNetworkAgent.connect(true);
1023 waitFor(cv);
1024 verifyActiveNetwork(TRANSPORT_WIFI);
1025 // Test bringing up unvalidated cellular.
1026 // Expect it to be torn down because it could never be the highest scoring network
1027 // satisfying the default request even if it validated.
1028 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1029 cv = mCellNetworkAgent.getDisconnectedCV();
1030 mCellNetworkAgent.connect(false);
1031 waitFor(cv);
1032 verifyActiveNetwork(TRANSPORT_WIFI);
1033 cv = mWiFiNetworkAgent.getDisconnectedCV();
1034 mWiFiNetworkAgent.disconnect();
1035 waitFor(cv);
1036 }
1037
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001038 @SmallTest
Paul Jensene0988542015-06-25 15:30:08 -04001039 public void testCellularFallback() throws Exception {
1040 // Test bringing up validated cellular.
1041 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1042 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1043 mCellNetworkAgent.connect(true);
1044 waitFor(cv);
1045 verifyActiveNetwork(TRANSPORT_CELLULAR);
1046 // Test bringing up validated WiFi.
1047 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1048 cv = waitForConnectivityBroadcasts(2);
1049 mWiFiNetworkAgent.connect(true);
1050 waitFor(cv);
1051 verifyActiveNetwork(TRANSPORT_WIFI);
1052 // Reevaluate WiFi (it'll instantly fail DNS).
1053 cv = waitForConnectivityBroadcasts(2);
1054 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1055 NET_CAPABILITY_VALIDATED));
1056 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1057 // Should quickly fall back to Cellular.
1058 waitFor(cv);
1059 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1060 NET_CAPABILITY_VALIDATED));
1061 verifyActiveNetwork(TRANSPORT_CELLULAR);
1062 // Reevaluate cellular (it'll instantly fail DNS).
1063 cv = waitForConnectivityBroadcasts(2);
1064 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1065 NET_CAPABILITY_VALIDATED));
1066 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1067 // Should quickly fall back to WiFi.
1068 waitFor(cv);
1069 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1070 NET_CAPABILITY_VALIDATED));
1071 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1072 NET_CAPABILITY_VALIDATED));
1073 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001074 }
1075
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001076 @SmallTest
Paul Jensene0988542015-06-25 15:30:08 -04001077 public void testWiFiFallback() throws Exception {
1078 // Test bringing up unvalidated WiFi.
1079 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1080 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1081 mWiFiNetworkAgent.connect(false);
1082 waitFor(cv);
1083 verifyActiveNetwork(TRANSPORT_WIFI);
1084 // Test bringing up validated cellular.
1085 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1086 cv = waitForConnectivityBroadcasts(2);
1087 mCellNetworkAgent.connect(true);
1088 waitFor(cv);
1089 verifyActiveNetwork(TRANSPORT_CELLULAR);
1090 // Reevaluate cellular (it'll instantly fail DNS).
1091 cv = waitForConnectivityBroadcasts(2);
1092 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1093 NET_CAPABILITY_VALIDATED));
1094 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1095 // Should quickly fall back to WiFi.
1096 waitFor(cv);
1097 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1098 NET_CAPABILITY_VALIDATED));
1099 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001100 }
1101
Paul Jensen3d911462015-06-12 06:40:24 -04001102 enum CallbackState {
1103 NONE,
1104 AVAILABLE,
Erik Klineacdd6392016-07-07 16:50:58 +09001105 NETWORK_CAPABILITIES,
1106 LINK_PROPERTIES,
Erik Kline1d3db322017-02-28 16:20:20 +09001107 SUSPENDED,
Paul Jensen3d911462015-06-12 06:40:24 -04001108 LOSING,
Erik Kline3841a482015-11-25 12:49:38 +09001109 LOST,
1110 UNAVAILABLE
Paul Jensen3d911462015-06-12 06:40:24 -04001111 }
1112
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001113 private static class CallbackInfo {
1114 public final CallbackState state;
1115 public final Network network;
1116 public final Object arg;
1117 public CallbackInfo(CallbackState s, Network n, Object o) {
1118 state = s; network = n; arg = o;
1119 }
1120 public String toString() {
Erik Kline1d3db322017-02-28 16:20:20 +09001121 return String.format("%s (%s) (%s)", state, network, arg);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001122 }
1123 @Override
1124 public boolean equals(Object o) {
1125 if (!(o instanceof CallbackInfo)) return false;
1126 // Ignore timeMs, since it's unpredictable.
1127 CallbackInfo other = (CallbackInfo) o;
1128 return (state == other.state) && Objects.equals(network, other.network);
1129 }
1130 @Override
1131 public int hashCode() {
1132 return Objects.hash(state, network);
1133 }
1134 }
1135
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001136 /**
1137 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1138 * this class receives, by calling expectCallback() exactly once each time a callback is
1139 * received. assertNoCallback may be called at any time.
1140 */
Paul Jensen3d911462015-06-12 06:40:24 -04001141 private class TestNetworkCallback extends NetworkCallback {
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001142 // Chosen to be much less than the linger timeout. This ensures that we can distinguish
1143 // between a LOST callback that arrives immediately and a LOST callback that arrives after
1144 // the linger timeout.
Hugo Benichidfb559a2016-12-20 14:57:49 +09001145 private final static int TIMEOUT_MS = 100;
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001146
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001147 private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
1148
Erik Klineacdd6392016-07-07 16:50:58 +09001149 protected void setLastCallback(CallbackState state, Network network, Object o) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001150 mCallbacks.offer(new CallbackInfo(state, network, o));
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001151 }
Paul Jensen3d911462015-06-12 06:40:24 -04001152
Erik Klineacdd6392016-07-07 16:50:58 +09001153 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001154 public void onAvailable(Network network) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001155 setLastCallback(CallbackState.AVAILABLE, network, null);
Paul Jensen3d911462015-06-12 06:40:24 -04001156 }
1157
Erik Klineacdd6392016-07-07 16:50:58 +09001158 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001159 public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
1160 setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
1161 }
1162
1163 @Override
1164 public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
1165 setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
1166 }
1167
1168 @Override
Erik Kline3841a482015-11-25 12:49:38 +09001169 public void onUnavailable() {
1170 setLastCallback(CallbackState.UNAVAILABLE, null, null);
1171 }
1172
1173 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001174 public void onNetworkSuspended(Network network) {
1175 setLastCallback(CallbackState.SUSPENDED, network, null);
1176 }
1177
1178 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001179 public void onLosing(Network network, int maxMsToLive) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001180 setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
Paul Jensen3d911462015-06-12 06:40:24 -04001181 }
1182
Erik Klineacdd6392016-07-07 16:50:58 +09001183 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001184 public void onLost(Network network) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001185 setLastCallback(CallbackState.LOST, network, null);
1186 }
1187
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001188 CallbackInfo nextCallback(int timeoutMs) {
1189 CallbackInfo cb = null;
1190 try {
1191 cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
1192 } catch (InterruptedException e) {
1193 }
1194 if (cb == null) {
1195 // LinkedBlockingQueue.poll() returns null if it timeouts.
1196 fail("Did not receive callback after " + timeoutMs + "ms");
1197 }
1198 return cb;
1199 }
1200
Erik Kline1d3db322017-02-28 16:20:20 +09001201 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs) {
1202 final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null;
1203 CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001204 CallbackInfo actual = nextCallback(timeoutMs);
1205 assertEquals("Unexpected callback:", expected, actual);
Erik Kline1d3db322017-02-28 16:20:20 +09001206
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001207 if (state == CallbackState.LOSING) {
1208 String msg = String.format(
1209 "Invalid linger time value %d, must be between %d and %d",
1210 actual.arg, 0, TEST_LINGER_DELAY_MS);
1211 int maxMsToLive = (Integer) actual.arg;
1212 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= TEST_LINGER_DELAY_MS);
1213 }
Erik Kline1d3db322017-02-28 16:20:20 +09001214
1215 return actual;
Erik Klinea2d29402016-03-16 15:31:39 +09001216 }
1217
Erik Kline1d3db322017-02-28 16:20:20 +09001218 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) {
1219 return expectCallback(state, agent, TIMEOUT_MS);
1220 }
1221
1222 void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended, int timeoutMs) {
1223 expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
Erik Klinec75d4fa2017-02-15 19:59:17 +09001224 if (expectSuspended) {
1225 expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001226 }
Erik Klinec75d4fa2017-02-15 19:59:17 +09001227 expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
1228 expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001229 }
1230
1231 void expectAvailableCallbacks(MockNetworkAgent agent) {
1232 expectAvailableCallbacks(agent, false, TIMEOUT_MS);
1233 }
1234
1235 void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent) {
1236 expectAvailableCallbacks(agent, true, TIMEOUT_MS);
1237 }
1238
1239 void expectAvailableAndValidatedCallbacks(MockNetworkAgent agent) {
Erik Klinec75d4fa2017-02-15 19:59:17 +09001240 expectAvailableCallbacks(agent, false, TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001241 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1242 }
1243
1244 void expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
1245 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
1246 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1247 assertTrue(nc.hasCapability(capability));
1248 }
1249
1250 void expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
1251 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
1252 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1253 assertFalse(nc.hasCapability(capability));
Paul Jensen3d911462015-06-12 06:40:24 -04001254 }
1255
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001256 void assertNoCallback() {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001257 mService.waitForIdle();
1258 CallbackInfo c = mCallbacks.peek();
1259 assertNull("Unexpected callback: " + c, c);
1260 }
1261 }
1262
1263 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1264 // only be declared in a static or top level type".
1265 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1266 for (TestNetworkCallback c : callbacks) {
1267 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001268 }
1269 }
1270
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001271 @SmallTest
Paul Jensen3d911462015-06-12 06:40:24 -04001272 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001273 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001274 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1275 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001276 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1277 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001278 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1279 .addTransportType(TRANSPORT_WIFI).build();
1280 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1281 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001282 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001283 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1284 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1285
1286 // Test unvalidated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001287 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1288 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1289 mCellNetworkAgent.connect(false);
Erik Kline1d3db322017-02-28 16:20:20 +09001290 genericNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent);
1291 cellNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001292 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1293 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001294 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001295
Paul Jensen3d911462015-06-12 06:40:24 -04001296 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1297 mCellNetworkAgent.adjustScore(-1);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001298 mService.waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001299 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001300 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1301
Paul Jensen3d911462015-06-12 06:40:24 -04001302 cv = waitForConnectivityBroadcasts(2);
1303 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1304 mWiFiNetworkAgent.connect(false);
Erik Kline1d3db322017-02-28 16:20:20 +09001305 genericNetworkCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
1306 wifiNetworkCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001307 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1308 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001309 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001310
Paul Jensen3d911462015-06-12 06:40:24 -04001311 cv = waitForConnectivityBroadcasts(2);
1312 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001313 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1314 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001315 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001316 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001317 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001318
Paul Jensen3d911462015-06-12 06:40:24 -04001319 cv = waitForConnectivityBroadcasts(1);
1320 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001321 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1322 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001323 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001324 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001325
1326 // Test validated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001327 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1328 mCellNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09001329 genericNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
1330 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001331 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001332 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001333
Paul Jensen3d911462015-06-12 06:40:24 -04001334 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1335 mCellNetworkAgent.adjustScore(-1);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001336 mService.waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001337 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001338 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1339
Paul Jensen3d911462015-06-12 06:40:24 -04001340 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1341 mWiFiNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09001342 genericNetworkCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001343 genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001344 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
1345 wifiNetworkCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001346 cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001347 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001348 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001349
Paul Jensen3d911462015-06-12 06:40:24 -04001350 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001351 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1352 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1353 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001354
Paul Jensen3d911462015-06-12 06:40:24 -04001355 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001356 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1357 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1358 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001359 }
1360
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001361 @SmallTest
1362 public void testMultipleLingering() {
1363 NetworkRequest request = new NetworkRequest.Builder()
1364 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1365 .build();
1366 TestNetworkCallback callback = new TestNetworkCallback();
1367 mCm.registerNetworkCallback(request, callback);
1368
1369 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1370 mCm.registerDefaultNetworkCallback(defaultCallback);
1371
1372 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1373 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1374 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
1375
1376 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1377 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1378 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1379
1380 mCellNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09001381 callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
1382 defaultCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001383 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1384
1385 mWiFiNetworkAgent.connect(true);
1386 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1387 // We then get LOSING when wifi validates and cell is outscored.
Erik Kline1d3db322017-02-28 16:20:20 +09001388 callback.expectAvailableCallbacks(mWiFiNetworkAgent);
1389 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001390 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001391 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
1392 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001393 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1394
1395 mEthernetNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09001396 callback.expectAvailableCallbacks(mEthernetNetworkAgent);
1397 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001398 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001399 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
1400 defaultCallback.expectAvailableAndValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001401 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1402
1403 mEthernetNetworkAgent.disconnect();
1404 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1405 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001406 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001407
1408 for (int i = 0; i < 4; i++) {
1409 MockNetworkAgent oldNetwork, newNetwork;
1410 if (i % 2 == 0) {
1411 mWiFiNetworkAgent.adjustScore(-15);
1412 oldNetwork = mWiFiNetworkAgent;
1413 newNetwork = mCellNetworkAgent;
1414 } else {
1415 mWiFiNetworkAgent.adjustScore(15);
1416 oldNetwork = mCellNetworkAgent;
1417 newNetwork = mWiFiNetworkAgent;
1418
1419 }
1420 callback.expectCallback(CallbackState.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001421 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1422 // longer lingering?
Erik Kline1d3db322017-02-28 16:20:20 +09001423 defaultCallback.expectAvailableCallbacks(newNetwork);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001424 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
1425 }
1426 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1427
1428 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
1429 // if the network is still up.
1430 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
Erik Kline1d3db322017-02-28 16:20:20 +09001431 // We expect a notification about the capabilities change, and nothing else.
1432 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
1433 defaultCallback.assertNoCallback();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001434 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1435
1436 // Wifi no longer satisfies our listen, which is for an unmetered network.
1437 // But because its score is 55, it's still up (and the default network).
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001438 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1439
1440 // Disconnect our test networks.
1441 mWiFiNetworkAgent.disconnect();
1442 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001443 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001444 mCellNetworkAgent.disconnect();
1445 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1446
1447 mCm.unregisterNetworkCallback(callback);
1448 mService.waitForIdle();
1449
1450 // Check that a network is only lingered or torn down if it would not satisfy a request even
1451 // if it validated.
1452 request = new NetworkRequest.Builder().clearCapabilities().build();
1453 callback = new TestNetworkCallback();
1454
1455 mCm.registerNetworkCallback(request, callback);
1456
1457 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1458 mCellNetworkAgent.connect(false); // Score: 10
Erik Kline1d3db322017-02-28 16:20:20 +09001459 callback.expectAvailableCallbacks(mCellNetworkAgent);
1460 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001461 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1462
1463 // Bring up wifi with a score of 20.
1464 // Cell stays up because it would satisfy the default request if it validated.
1465 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1466 mWiFiNetworkAgent.connect(false); // Score: 20
Erik Kline1d3db322017-02-28 16:20:20 +09001467 callback.expectAvailableCallbacks(mWiFiNetworkAgent);
1468 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001469 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1470
1471 mWiFiNetworkAgent.disconnect();
1472 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1473 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001474 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001475 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1476
1477 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001478 // Cell is lingered because it would not satisfy any request, even if it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001479 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1480 mWiFiNetworkAgent.adjustScore(50);
1481 mWiFiNetworkAgent.connect(false); // Score: 70
Erik Kline1d3db322017-02-28 16:20:20 +09001482 callback.expectAvailableCallbacks(mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001483 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001484 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001485 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1486
1487 // Tear down wifi.
1488 mWiFiNetworkAgent.disconnect();
1489 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1490 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001491 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001492 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1493
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001494 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
1495 // it's arguably correct to linger it, since it was the default network before it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001496 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1497 mWiFiNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09001498 callback.expectAvailableCallbacks(mWiFiNetworkAgent);
1499 // TODO: Investigate sending validated before losing.
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001500 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001501 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
1502 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001503 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1504
1505 mWiFiNetworkAgent.disconnect();
1506 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001507 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001508 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001509 mCellNetworkAgent.disconnect();
1510 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1511 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001512
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001513 // If a network is lingering, and we add and remove a request from it, resume lingering.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001514 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1515 mCellNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09001516 callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
1517 defaultCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001518 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1519 mWiFiNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09001520 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
1521 callback.expectAvailableCallbacks(mWiFiNetworkAgent);
1522 // TODO: Investigate sending validated before losing.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001523 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001524 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001525
1526 NetworkRequest cellRequest = new NetworkRequest.Builder()
1527 .addTransportType(TRANSPORT_CELLULAR).build();
1528 NetworkCallback noopCallback = new NetworkCallback();
1529 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001530 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
1531 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001532 mCm.unregisterNetworkCallback(noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001533 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001534
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001535 // Similar to the above: lingering can start even after the lingered request is removed.
1536 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001537 mWiFiNetworkAgent.disconnect();
1538 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001539 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001540 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001541
1542 // Cell is now the default network. Pin it with a cell-specific request.
1543 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
1544 mCm.requestNetwork(cellRequest, noopCallback);
1545
1546 // Now connect wifi, and expect it to become the default network.
1547 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1548 mWiFiNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09001549 callback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
1550 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001551 // The default request is lingering on cell, but nothing happens to cell, and we send no
1552 // callbacks for it, because it's kept up by cellRequest.
1553 callback.assertNoCallback();
1554 // Now unregister cellRequest and expect cell to start lingering.
1555 mCm.unregisterNetworkCallback(noopCallback);
1556 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1557
1558 // Let linger run its course.
1559 callback.assertNoCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09001560 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
1561 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001562
1563 // Clean up.
1564 mWiFiNetworkAgent.disconnect();
1565 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1566 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001567
1568 mCm.unregisterNetworkCallback(callback);
1569 mCm.unregisterNetworkCallback(defaultCallback);
1570 }
1571
Paul Jensen85cf78e2015-06-25 13:25:07 -04001572 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04001573 // Verify NOT_RESTRICTED is set appropriately
1574 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
1575 .build().networkCapabilities;
1576 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
1577 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
1578 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04001579 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04001580 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1581 } else {
1582 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1583 }
1584
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001585 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001586 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001587 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
1588 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04001589 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001590 mServiceContext, "testFactory", filter);
1591 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04001592 ConditionVariable cv = testFactory.getNetworkStartedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001593 testFactory.expectAddRequests(1);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001594 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001595 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001596 int expectedRequestCount = 1;
1597 NetworkCallback networkCallback = null;
1598 // For non-INTERNET capabilities we cannot rely on the default request being present, so
1599 // add one.
1600 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04001601 assertFalse(testFactory.getMyStartRequested());
1602 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
1603 networkCallback = new NetworkCallback();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001604 testFactory.expectAddRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001605 mCm.requestNetwork(request, networkCallback);
1606 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001607 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001608 }
Paul Jensen3d911462015-06-12 06:40:24 -04001609 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001610 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1611 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001612
Paul Jensen85cf78e2015-06-25 13:25:07 -04001613 // Now bring in a higher scored network.
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001614 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001615 // Rather than create a validated network which complicates things by registering it's
1616 // own NetworkRequest during startup, just bump up the score to cancel out the
1617 // unvalidated penalty.
1618 testAgent.adjustScore(40);
1619 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001620
1621 // When testAgent connects, ConnectivityService will re-send us all current requests with
1622 // the new score. There are expectedRequestCount such requests, and we must wait for all of
1623 // them.
1624 testFactory.expectAddRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001625 testAgent.connect(false);
1626 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04001627 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001628 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001629 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001630
Paul Jensen85cf78e2015-06-25 13:25:07 -04001631 // Bring in a bunch of requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001632 testFactory.expectAddRequests(10);
1633 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001634 ConnectivityManager.NetworkCallback[] networkCallbacks =
1635 new ConnectivityManager.NetworkCallback[10];
1636 for (int i = 0; i< networkCallbacks.length; i++) {
1637 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
1638 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001639 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001640 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
1641 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04001642 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
1643 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001644
Paul Jensen85cf78e2015-06-25 13:25:07 -04001645 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001646 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001647 for (int i = 0; i < networkCallbacks.length; i++) {
1648 mCm.unregisterNetworkCallback(networkCallbacks[i]);
1649 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04001650 testFactory.waitForNetworkRequests(expectedRequestCount);
1651 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001652
Paul Jensen85cf78e2015-06-25 13:25:07 -04001653 // Drop the higher scored network.
1654 cv = testFactory.getNetworkStartedCV();
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001655 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001656 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001657 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1658 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001659
1660 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001661 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001662 handlerThread.quit();
1663 }
1664
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001665 @SmallTest
Paul Jensen85cf78e2015-06-25 13:25:07 -04001666 public void testNetworkFactoryRequests() throws Exception {
1667 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
1668 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
1669 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
1670 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
1671 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
1672 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
1673 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
1674 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
1675 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
1676 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
1677 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
1678 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
1679 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
1680 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
1681 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
1682 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
1683 }
1684
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001685 @SmallTest
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001686 public void testNoMutableNetworkRequests() throws Exception {
1687 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
1688 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001689 builder.addCapability(NET_CAPABILITY_VALIDATED);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001690 try {
1691 mCm.requestNetwork(builder.build(), new NetworkCallback());
1692 fail();
1693 } catch (IllegalArgumentException expected) {}
1694 try {
1695 mCm.requestNetwork(builder.build(), pendingIntent);
1696 fail();
1697 } catch (IllegalArgumentException expected) {}
1698 builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001699 builder.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04001700 try {
1701 mCm.requestNetwork(builder.build(), new NetworkCallback());
1702 fail();
1703 } catch (IllegalArgumentException expected) {}
1704 try {
1705 mCm.requestNetwork(builder.build(), pendingIntent);
1706 fail();
1707 } catch (IllegalArgumentException expected) {}
1708 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001709
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001710 @SmallTest
Paul Jensene0988542015-06-25 15:30:08 -04001711 public void testMMSonWiFi() throws Exception {
1712 // Test bringing up cellular without MMS NetworkRequest gets reaped
1713 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1714 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1715 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
1716 mCellNetworkAgent.connectWithoutInternet();
1717 waitFor(cv);
Lorenzo Colittid2706122017-01-30 17:45:49 +09001718 mService.waitForIdle();
1719 assertEquals(0, mCm.getAllNetworks().length);
Paul Jensene0988542015-06-25 15:30:08 -04001720 verifyNoNetwork();
1721 // Test bringing up validated WiFi.
1722 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1723 cv = waitForConnectivityBroadcasts(1);
1724 mWiFiNetworkAgent.connect(true);
1725 waitFor(cv);
1726 verifyActiveNetwork(TRANSPORT_WIFI);
1727 // Register MMS NetworkRequest
1728 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1729 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1730 final TestNetworkCallback networkCallback = new TestNetworkCallback();
1731 mCm.requestNetwork(builder.build(), networkCallback);
1732 // Test bringing up unvalidated cellular with MMS
1733 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1734 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04001735 mCellNetworkAgent.connectWithoutInternet();
Erik Kline1d3db322017-02-28 16:20:20 +09001736 networkCallback.expectAvailableCallbacks(mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04001737 verifyActiveNetwork(TRANSPORT_WIFI);
1738 // Test releasing NetworkRequest disconnects cellular with MMS
1739 cv = mCellNetworkAgent.getDisconnectedCV();
1740 mCm.unregisterNetworkCallback(networkCallback);
1741 waitFor(cv);
1742 verifyActiveNetwork(TRANSPORT_WIFI);
1743 }
1744
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001745 @SmallTest
Paul Jensene0988542015-06-25 15:30:08 -04001746 public void testMMSonCell() throws Exception {
1747 // Test bringing up cellular without MMS
1748 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1749 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1750 mCellNetworkAgent.connect(false);
1751 waitFor(cv);
1752 verifyActiveNetwork(TRANSPORT_CELLULAR);
1753 // Register MMS NetworkRequest
1754 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1755 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1756 final TestNetworkCallback networkCallback = new TestNetworkCallback();
1757 mCm.requestNetwork(builder.build(), networkCallback);
1758 // Test bringing up MMS cellular network
Paul Jensene0988542015-06-25 15:30:08 -04001759 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1760 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1761 mmsNetworkAgent.connectWithoutInternet();
Erik Kline1d3db322017-02-28 16:20:20 +09001762 networkCallback.expectAvailableCallbacks(mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04001763 verifyActiveNetwork(TRANSPORT_CELLULAR);
1764 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
1765 cv = mmsNetworkAgent.getDisconnectedCV();
1766 mCm.unregisterNetworkCallback(networkCallback);
1767 waitFor(cv);
1768 verifyActiveNetwork(TRANSPORT_CELLULAR);
1769 }
1770
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001771 @SmallTest
Paul Jensencf4c2c62015-07-01 14:16:32 -04001772 public void testCaptivePortal() {
1773 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1774 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1775 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1776 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1777
1778 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1779 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1780 .addCapability(NET_CAPABILITY_VALIDATED).build();
1781 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001782
1783 // Bring up a network with a captive portal.
1784 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001785 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04001786 String firstRedirectUrl = "http://example.com/firstPath";
1787 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
Erik Kline1d3db322017-02-28 16:20:20 +09001788 captivePortalCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04001789 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001790
1791 // Take down network.
1792 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001793 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001794 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001795
1796 // Bring up a network with a captive portal.
1797 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001798 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04001799 String secondRedirectUrl = "http://example.com/secondPath";
1800 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
Erik Kline1d3db322017-02-28 16:20:20 +09001801 captivePortalCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04001802 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001803
1804 // Make captive portal disappear then revalidate.
1805 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001806 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
1807 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001808 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001809
1810 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Erik Kline1d3db322017-02-28 16:20:20 +09001811 validatedCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
1812 // TODO: Investigate only sending available callbacks.
1813 validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001814
1815 // Break network connectivity.
1816 // Expect NET_CAPABILITY_VALIDATED onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001817 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
1818 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001819 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001820 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09001821
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001822 @SmallTest
Calvin On1f64f3f2016-10-11 15:10:46 -07001823 public void testAvoidOrIgnoreCaptivePortals() {
1824 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1825 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1826 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1827 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1828
1829 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1830 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1831 .addCapability(NET_CAPABILITY_VALIDATED).build();
1832 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
1833
1834 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
1835 // Bring up a network with a captive portal.
1836 // Expect it to fail to connect and not result in any callbacks.
1837 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1838 String firstRedirectUrl = "http://example.com/firstPath";
1839
1840 ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
1841 ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
1842 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
1843 waitFor(disconnectCv);
1844 waitFor(avoidCv);
1845
1846 assertNoCallbacks(captivePortalCallback, validatedCallback);
1847
1848 // Now test ignore mode.
1849 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE);
1850
1851 // Bring up a network with a captive portal.
1852 // Since we're ignoring captive portals, the network will validate.
1853 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1854 String secondRedirectUrl = "http://example.com/secondPath";
1855 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
1856
1857 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Erik Kline1d3db322017-02-28 16:20:20 +09001858 validatedCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Calvin On1f64f3f2016-10-11 15:10:46 -07001859 // But there should be no CaptivePortal callback.
1860 captivePortalCallback.assertNoCallback();
1861 }
1862
Lorenzo Colitti6556a222017-04-03 17:46:35 +09001863 private NetworkRequest.Builder newWifiRequestBuilder() {
1864 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
1865 }
1866
1867 @SmallTest
1868 public void testNetworkSpecifier() {
Lorenzo Colitti6556a222017-04-03 17:46:35 +09001869 NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
Etan Cohena7434272017-04-03 12:17:51 -07001870 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09001871 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
Etan Cohena7434272017-04-03 12:17:51 -07001872 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
1873 (NetworkSpecifier) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09001874 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier("foo").build();
Etan Cohena7434272017-04-03 12:17:51 -07001875 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
1876 new StringNetworkSpecifier("bar")).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09001877
1878 TestNetworkCallback cEmpty1 = new TestNetworkCallback();
1879 TestNetworkCallback cEmpty2 = new TestNetworkCallback();
1880 TestNetworkCallback cEmpty3 = new TestNetworkCallback();
Etan Cohena7434272017-04-03 12:17:51 -07001881 TestNetworkCallback cEmpty4 = new TestNetworkCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09001882 TestNetworkCallback cFoo = new TestNetworkCallback();
1883 TestNetworkCallback cBar = new TestNetworkCallback();
1884 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
1885 cEmpty1, cEmpty2, cEmpty3 };
1886
1887 mCm.registerNetworkCallback(rEmpty1, cEmpty1);
1888 mCm.registerNetworkCallback(rEmpty2, cEmpty2);
1889 mCm.registerNetworkCallback(rEmpty3, cEmpty3);
Etan Cohena7434272017-04-03 12:17:51 -07001890 mCm.registerNetworkCallback(rEmpty4, cEmpty4);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09001891 mCm.registerNetworkCallback(rFoo, cFoo);
1892 mCm.registerNetworkCallback(rBar, cBar);
1893
1894 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1895 mWiFiNetworkAgent.connect(false);
1896 cEmpty1.expectAvailableCallbacks(mWiFiNetworkAgent);
1897 cEmpty2.expectAvailableCallbacks(mWiFiNetworkAgent);
1898 cEmpty3.expectAvailableCallbacks(mWiFiNetworkAgent);
Etan Cohena7434272017-04-03 12:17:51 -07001899 cEmpty4.expectAvailableCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09001900 assertNoCallbacks(cFoo, cBar);
1901
Etan Cohena7434272017-04-03 12:17:51 -07001902 mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("foo"));
Lorenzo Colitti6556a222017-04-03 17:46:35 +09001903 cFoo.expectAvailableCallbacks(mWiFiNetworkAgent);
1904 for (TestNetworkCallback c: emptyCallbacks) {
1905 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
1906 }
1907 cFoo.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
1908 cFoo.assertNoCallback();
1909
Etan Cohena7434272017-04-03 12:17:51 -07001910 mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("bar"));
Lorenzo Colitti6556a222017-04-03 17:46:35 +09001911 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1912 cBar.expectAvailableCallbacks(mWiFiNetworkAgent);
1913 for (TestNetworkCallback c: emptyCallbacks) {
1914 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
1915 }
1916 cBar.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
1917 cBar.assertNoCallback();
1918
1919 mWiFiNetworkAgent.setNetworkSpecifier(null);
1920 cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1921 for (TestNetworkCallback c: emptyCallbacks) {
1922 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
1923 }
1924
1925 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cFoo, cBar);
1926 }
1927
Etan Cohenddb9ef02015-11-18 10:56:15 -08001928 @SmallTest
1929 public void testInvalidNetworkSpecifier() {
Etan Cohenddb9ef02015-11-18 10:56:15 -08001930 try {
1931 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Etan Cohena7434272017-04-03 12:17:51 -07001932 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
1933 fail("NetworkRequest builder with MatchAllNetworkSpecifier");
1934 } catch (IllegalArgumentException expected) {
1935 // expected
Etan Cohenddb9ef02015-11-18 10:56:15 -08001936 }
1937
Etan Cohenddb9ef02015-11-18 10:56:15 -08001938 try {
1939 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
1940 networkCapabilities.addTransportType(TRANSPORT_WIFI)
Etan Cohena7434272017-04-03 12:17:51 -07001941 .setNetworkSpecifier(new MatchAllNetworkSpecifier());
Etan Cohenddb9ef02015-11-18 10:56:15 -08001942 mService.requestNetwork(networkCapabilities, null, 0, null,
1943 ConnectivityManager.TYPE_WIFI);
Etan Cohena7434272017-04-03 12:17:51 -07001944 fail("ConnectivityService requestNetwork with MatchAllNetworkSpecifier");
1945 } catch (IllegalArgumentException expected) {
1946 // expected
Etan Cohenddb9ef02015-11-18 10:56:15 -08001947 }
1948
Etan Cohena7434272017-04-03 12:17:51 -07001949 class NonParcelableSpecifier extends NetworkSpecifier {
1950 public boolean satisfiedBy(NetworkSpecifier other) { return false; }
1951 };
1952 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
1953 @Override public int describeContents() { return 0; }
1954 @Override public void writeToParcel(Parcel p, int flags) {}
1955 }
1956 NetworkRequest.Builder builder;
1957
1958 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
1959 try {
1960 builder.setNetworkSpecifier(new NonParcelableSpecifier());
1961 Parcel parcelW = Parcel.obtain();
1962 builder.build().writeToParcel(parcelW, 0);
1963 fail("Parceling a non-parcelable specifier did not throw an exception");
1964 } catch (Exception e) {
1965 // expected
1966 }
1967
1968 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
1969 builder.setNetworkSpecifier(new ParcelableSpecifier());
1970 NetworkRequest nr = builder.build();
1971 assertNotNull(nr);
1972
1973 try {
1974 Parcel parcelW = Parcel.obtain();
1975 nr.writeToParcel(parcelW, 0);
1976 byte[] bytes = parcelW.marshall();
1977 parcelW.recycle();
1978
1979 Parcel parcelR = Parcel.obtain();
1980 parcelR.unmarshall(bytes, 0, bytes.length);
1981 parcelR.setDataPosition(0);
1982 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
1983 fail("Unparceling a non-framework NetworkSpecifier did not throw an exception");
1984 } catch (Exception e) {
1985 // expected
1986 }
Etan Cohenddb9ef02015-11-18 10:56:15 -08001987 }
1988
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09001989 @SmallTest
Erik Klinea2d29402016-03-16 15:31:39 +09001990 public void testRegisterDefaultNetworkCallback() throws Exception {
1991 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
1992 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
1993 defaultNetworkCallback.assertNoCallback();
1994
1995 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
1996 // whenever Wi-Fi is up. Without this, the mobile network agent is
1997 // reaped before any other activity can take place.
1998 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
1999 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2000 .addTransportType(TRANSPORT_CELLULAR).build();
2001 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2002 cellNetworkCallback.assertNoCallback();
2003
2004 // Bring up cell and expect CALLBACK_AVAILABLE.
2005 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2006 mCellNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09002007 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
2008 defaultNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002009
2010 // Bring up wifi and expect CALLBACK_AVAILABLE.
2011 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2012 mWiFiNetworkAgent.connect(true);
2013 cellNetworkCallback.assertNoCallback();
Erik Kline1d3db322017-02-28 16:20:20 +09002014 defaultNetworkCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002015
2016 // Bring down cell. Expect no default network callback, since it wasn't the default.
2017 mCellNetworkAgent.disconnect();
2018 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2019 defaultNetworkCallback.assertNoCallback();
2020
2021 // Bring up cell. Expect no default network callback, since it won't be the default.
2022 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2023 mCellNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09002024 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002025 defaultNetworkCallback.assertNoCallback();
2026
2027 // Bring down wifi. Expect the default network callback to notified of LOST wifi
2028 // followed by AVAILABLE cell.
2029 mWiFiNetworkAgent.disconnect();
2030 cellNetworkCallback.assertNoCallback();
2031 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002032 defaultNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002033 mCellNetworkAgent.disconnect();
2034 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2035 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2036 }
2037
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09002038 @SmallTest
Erik Kline1d3db322017-02-28 16:20:20 +09002039 public void testAdditionalStateCallbacks() throws Exception {
Erik Klineacdd6392016-07-07 16:50:58 +09002040 // File a network request for mobile.
Erik Kline1d3db322017-02-28 16:20:20 +09002041 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09002042 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2043 .addTransportType(TRANSPORT_CELLULAR).build();
2044 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2045
2046 // Bring up the mobile network.
2047 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2048 mCellNetworkAgent.connect(true);
2049
Erik Kline1d3db322017-02-28 16:20:20 +09002050 // We should get onAvailable(), onCapabilitiesChanged(), and
2051 // onLinkPropertiesChanged() in rapid succession. Additionally, we
2052 // should get onCapabilitiesChanged() when the mobile network validates.
2053 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09002054 cellNetworkCallback.assertNoCallback();
2055
2056 // Update LinkProperties.
2057 final LinkProperties lp = new LinkProperties();
2058 lp.setInterfaceName("foonet_data0");
2059 mCellNetworkAgent.sendLinkProperties(lp);
2060 // We should get onLinkPropertiesChanged().
2061 cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
2062 cellNetworkCallback.assertNoCallback();
2063
Erik Kline1d3db322017-02-28 16:20:20 +09002064 // Suspend the network.
2065 mCellNetworkAgent.suspend();
2066 cellNetworkCallback.expectCallback(CallbackState.SUSPENDED, mCellNetworkAgent);
2067 cellNetworkCallback.assertNoCallback();
2068
Erik Klineacdd6392016-07-07 16:50:58 +09002069 // Register a garden variety default network request.
Erik Kline1d3db322017-02-28 16:20:20 +09002070 final TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09002071 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09002072 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
2073 // as well as onNetworkSuspended() in rapid succession.
2074 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09002075 dfltNetworkCallback.assertNoCallback();
2076
Erik Klineacdd6392016-07-07 16:50:58 +09002077 mCm.unregisterNetworkCallback(dfltNetworkCallback);
2078 mCm.unregisterNetworkCallback(cellNetworkCallback);
2079 }
2080
Calvin On1f64f3f2016-10-11 15:10:46 -07002081 private void setCaptivePortalMode(int mode) {
2082 ContentResolver cr = mServiceContext.getContentResolver();
2083 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
2084 }
2085
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002086 private void setMobileDataAlwaysOn(boolean enable) {
2087 ContentResolver cr = mServiceContext.getContentResolver();
2088 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
2089 mService.updateMobileDataAlwaysOn();
2090 mService.waitForIdle();
2091 }
2092
2093 private boolean isForegroundNetwork(MockNetworkAgent network) {
2094 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
2095 assertNotNull(nc);
2096 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
2097 }
2098
2099 @SmallTest
2100 public void testBackgroundNetworks() throws Exception {
2101 // Create a background request. We can't do this ourselves because ConnectivityService
2102 // doesn't have an API for it. So just turn on mobile data always on.
2103 setMobileDataAlwaysOn(true);
2104 final NetworkRequest request = new NetworkRequest.Builder().build();
2105 final NetworkRequest fgRequest = new NetworkRequest.Builder()
2106 .addCapability(NET_CAPABILITY_FOREGROUND).build();
2107 final TestNetworkCallback callback = new TestNetworkCallback();
2108 final TestNetworkCallback fgCallback = new TestNetworkCallback();
2109 mCm.registerNetworkCallback(request, callback);
2110 mCm.registerNetworkCallback(fgRequest, fgCallback);
2111
2112 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2113 mCellNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09002114 callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
2115 fgCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002116 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2117
2118 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2119 mWiFiNetworkAgent.connect(true);
2120
2121 // When wifi connects, cell lingers.
Erik Kline1d3db322017-02-28 16:20:20 +09002122 callback.expectAvailableCallbacks(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002123 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002124 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2125 fgCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002126 fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002127 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002128 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2129 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2130
2131 // When lingering is complete, cell is still there but is now in the background.
Hugo Benichidfb559a2016-12-20 14:57:49 +09002132 mService.waitForIdle();
2133 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2134 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09002135 // Expect a network capabilities update sans FOREGROUND.
2136 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002137 assertFalse(isForegroundNetwork(mCellNetworkAgent));
2138 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2139
2140 // File a cell request and check that cell comes into the foreground.
2141 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2142 .addTransportType(TRANSPORT_CELLULAR).build();
2143 final TestNetworkCallback cellCallback = new TestNetworkCallback();
2144 mCm.requestNetwork(cellRequest, cellCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09002145 // NOTE: This request causes the network's capabilities to change. This
2146 // is currently delivered before the onAvailable() callbacks.
2147 // TODO: Fix this.
2148 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
2149 cellCallback.expectAvailableCallbacks(mCellNetworkAgent);
2150 fgCallback.expectAvailableCallbacks(mCellNetworkAgent);
2151 // Expect a network capabilities update with FOREGROUND, because the most recent
2152 // request causes its state to change.
2153 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002154 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2155 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2156
2157 // Release the request. The network immediately goes into the background, since it was not
2158 // lingering.
2159 mCm.unregisterNetworkCallback(cellCallback);
2160 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002161 // Expect a network capabilities update sans FOREGROUND.
2162 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002163 assertFalse(isForegroundNetwork(mCellNetworkAgent));
2164 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2165
2166 // Disconnect wifi and check that cell is foreground again.
2167 mWiFiNetworkAgent.disconnect();
2168 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2169 fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002170 fgCallback.expectAvailableCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002171 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2172
2173 mCm.unregisterNetworkCallback(callback);
2174 mCm.unregisterNetworkCallback(fgCallback);
2175 }
2176
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002177 @SmallTest
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002178 public void testRequestBenchmark() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002179 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002180 // Benchmarks connecting and switching performance in the presence of a large number of
2181 // NetworkRequests.
2182 // 1. File NUM_REQUESTS requests.
2183 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
2184 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
2185 // and NUM_REQUESTS onAvailable callbacks to fire.
2186 // See how long it took.
2187 final int NUM_REQUESTS = 90;
2188 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
2189 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
2190 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
2191 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
2192
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002193 for (int i = 0; i < NUM_REQUESTS; i++) {
2194 callbacks[i] = new NetworkCallback() {
2195 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
2196 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
2197 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002198 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002199
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002200 final int REGISTER_TIME_LIMIT_MS = 180;
2201 assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
2202 for (NetworkCallback cb : callbacks) {
2203 mCm.registerNetworkCallback(request, cb);
2204 }
2205 });
2206
2207 final int CONNECT_TIME_LIMIT_MS = 40;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002208 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2209 // Don't request that the network validate, because otherwise connect() will block until
2210 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
2211 // and we won't actually measure anything.
2212 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002213
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002214 long onAvailableDispatchingDuration = durationOf(() -> {
2215 if (!awaitLatch(availableLatch, CONNECT_TIME_LIMIT_MS)) {
2216 fail(String.format("Only dispatched %d/%d onAvailable callbacks in %dms",
2217 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
2218 CONNECT_TIME_LIMIT_MS));
2219 }
2220 });
2221 Log.d(TAG, String.format("Connect, %d callbacks: %dms, acceptable %dms",
2222 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS));
2223
2224 final int SWITCH_TIME_LIMIT_MS = 40;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002225 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2226 // Give wifi a high enough score that we'll linger cell when wifi comes up.
2227 mWiFiNetworkAgent.adjustScore(40);
2228 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002229
2230 long onLostDispatchingDuration = durationOf(() -> {
2231 if (!awaitLatch(losingLatch, SWITCH_TIME_LIMIT_MS)) {
2232 fail(String.format("Only dispatched %d/%d onLosing callbacks in %dms",
2233 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, SWITCH_TIME_LIMIT_MS));
2234 }
2235 });
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002236 Log.d(TAG, String.format("Linger, %d callbacks: %dms, acceptable %dms",
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002237 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS));
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002238
2239 final int UNREGISTER_TIME_LIMIT_MS = 10;
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002240 assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
2241 for (NetworkCallback cb : callbacks) {
2242 mCm.unregisterNetworkCallback(cb);
2243 }
2244 });
2245 }
2246
2247 private long durationOf(Runnable fn) {
2248 long startTime = SystemClock.elapsedRealtime();
2249 fn.run();
2250 return SystemClock.elapsedRealtime() - startTime;
2251 }
2252
2253 private void assertTimeLimit(String descr, long timeLimit, Runnable fn) {
2254 long timeTaken = durationOf(fn);
2255 String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002256 Log.d(TAG, msg);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002257 assertTrue(msg, timeTaken <= timeLimit);
2258 }
2259
2260 private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
2261 try {
2262 if (l.await(timeoutMs, TimeUnit.MILLISECONDS)) {
2263 return true;
2264 }
2265 } catch (InterruptedException e) {}
2266 return false;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002267 }
2268
2269 @SmallTest
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002270 public void testMobileDataAlwaysOn() throws Exception {
2271 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2272 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2273 .addTransportType(TRANSPORT_CELLULAR).build();
2274 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
2275
2276 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
2277 handlerThread.start();
2278 NetworkCapabilities filter = new NetworkCapabilities()
2279 .addTransportType(TRANSPORT_CELLULAR)
2280 .addCapability(NET_CAPABILITY_INTERNET);
2281 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
2282 mServiceContext, "testFactory", filter);
2283 testFactory.setScoreFilter(40);
2284
2285 // Register the factory and expect it to start looking for a network.
2286 testFactory.expectAddRequests(1);
2287 testFactory.register();
2288 testFactory.waitForNetworkRequests(1);
2289 assertTrue(testFactory.getMyStartRequested());
2290
2291 // Bring up wifi. The factory stops looking for a network.
2292 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2293 testFactory.expectAddRequests(2); // Because the default request changes score twice.
2294 mWiFiNetworkAgent.connect(true);
2295 testFactory.waitForNetworkRequests(1);
2296 assertFalse(testFactory.getMyStartRequested());
2297
2298 ContentResolver cr = mServiceContext.getContentResolver();
2299
2300 // Turn on mobile data always on. The factory starts looking again.
2301 testFactory.expectAddRequests(1);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002302 setMobileDataAlwaysOn(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002303 testFactory.waitForNetworkRequests(2);
2304 assertTrue(testFactory.getMyStartRequested());
2305
2306 // Bring up cell data and check that the factory stops looking.
2307 assertEquals(1, mCm.getAllNetworks().length);
2308 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2309 testFactory.expectAddRequests(2); // Because the cell request changes score twice.
2310 mCellNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09002311 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002312 testFactory.waitForNetworkRequests(2);
2313 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
2314
2315 // Check that cell data stays up.
2316 mService.waitForIdle();
2317 verifyActiveNetwork(TRANSPORT_WIFI);
2318 assertEquals(2, mCm.getAllNetworks().length);
2319
2320 // Turn off mobile data always on and expect the request to disappear...
2321 testFactory.expectRemoveRequests(1);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002322 setMobileDataAlwaysOn(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002323 testFactory.waitForNetworkRequests(1);
2324
2325 // ... and cell data to be torn down.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002326 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002327 assertEquals(1, mCm.getAllNetworks().length);
2328
2329 testFactory.unregister();
2330 mCm.unregisterNetworkCallback(cellNetworkCallback);
2331 handlerThread.quit();
2332 }
2333
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002334 @SmallTest
2335 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002336 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09002337 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002338 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
2339
Erik Kline065ab6e2016-10-02 18:02:14 +09002340 tracker.configRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002341 String[] values = new String[] {null, "0", "1"};
2342 for (int i = 0; i < values.length; i++) {
2343 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002344 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002345 mService.waitForIdle();
2346 String msg = String.format("config=false, setting=%s", values[i]);
Lorenzo Colitti30145d72017-01-27 18:46:03 +09002347 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09002348 assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002349 }
2350
Erik Kline065ab6e2016-10-02 18:02:14 +09002351 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002352
2353 Settings.Global.putInt(cr, settingName, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09002354 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002355 mService.waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09002356 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09002357 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002358
2359 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002360 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002361 mService.waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09002362 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09002363 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002364
2365 Settings.Global.putString(cr, settingName, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09002366 tracker.reevaluate();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002367 mService.waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09002368 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09002369 assertTrue(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002370 }
2371
2372 @SmallTest
2373 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09002374 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09002375 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002376
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002377 // Pretend we're on a carrier that restricts switching away from bad wifi.
Erik Kline065ab6e2016-10-02 18:02:14 +09002378 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002379
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002380 // File a request for cell to ensure it doesn't go down.
2381 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2382 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2383 .addTransportType(TRANSPORT_CELLULAR).build();
2384 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2385
2386 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2387 mCm.registerDefaultNetworkCallback(defaultCallback);
2388
2389 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
2390 .addTransportType(TRANSPORT_WIFI)
2391 .addCapability(NET_CAPABILITY_VALIDATED)
2392 .build();
2393 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
2394 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
2395
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002396 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09002397 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002398
2399 // Bring up validated cell.
2400 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2401 mCellNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09002402 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
2403 defaultCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002404 Network cellNetwork = mCellNetworkAgent.getNetwork();
2405
2406 // Bring up validated wifi.
2407 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2408 mWiFiNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09002409 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
2410 validatedWifiCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
2411 validatedWifiCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002412 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2413
2414 // Fail validation on wifi.
2415 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
2416 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09002417 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002418 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2419
2420 // Because avoid bad wifi is off, we don't switch to cellular.
2421 defaultCallback.assertNoCallback();
2422 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2423 NET_CAPABILITY_VALIDATED));
2424 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2425 NET_CAPABILITY_VALIDATED));
2426 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2427
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002428 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
2429 // that we switch back to cell.
Erik Kline065ab6e2016-10-02 18:02:14 +09002430 tracker.configRestrictsAvoidBadWifi = false;
2431 tracker.reevaluate();
Erik Kline1d3db322017-02-28 16:20:20 +09002432 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002433 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2434
2435 // Switch back to a restrictive carrier.
Erik Kline065ab6e2016-10-02 18:02:14 +09002436 tracker.configRestrictsAvoidBadWifi = true;
2437 tracker.reevaluate();
Erik Kline1d3db322017-02-28 16:20:20 +09002438 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002439 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2440
2441 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
2442 mCm.setAvoidUnvalidated(wifiNetwork);
Erik Kline1d3db322017-02-28 16:20:20 +09002443 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002444 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2445 NET_CAPABILITY_VALIDATED));
2446 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2447 NET_CAPABILITY_VALIDATED));
2448 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2449
2450 // Disconnect and reconnect wifi to clear the one-time switch above.
2451 mWiFiNetworkAgent.disconnect();
2452 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2453 mWiFiNetworkAgent.connect(true);
Erik Kline1d3db322017-02-28 16:20:20 +09002454 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
2455 validatedWifiCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
2456 validatedWifiCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002457 wifiNetwork = mWiFiNetworkAgent.getNetwork();
2458
2459 // Fail validation on wifi and expect the dialog to appear.
2460 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
2461 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09002462 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002463 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2464
2465 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002466 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002467 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002468
2469 // We now switch to cell.
Erik Kline1d3db322017-02-28 16:20:20 +09002470 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002471 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2472 NET_CAPABILITY_VALIDATED));
2473 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2474 NET_CAPABILITY_VALIDATED));
2475 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2476
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002477 // Simulate the user turning the cellular fallback setting off and then on.
2478 // We switch to wifi and then to cell.
2479 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09002480 tracker.reevaluate();
Erik Kline1d3db322017-02-28 16:20:20 +09002481 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002482 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2483 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002484 tracker.reevaluate();
Erik Kline1d3db322017-02-28 16:20:20 +09002485 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002486 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2487
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002488 // If cell goes down, we switch to wifi.
2489 mCellNetworkAgent.disconnect();
2490 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002491 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002492 validatedWifiCallback.assertNoCallback();
2493
2494 mCm.unregisterNetworkCallback(cellNetworkCallback);
2495 mCm.unregisterNetworkCallback(validatedWifiCallback);
2496 mCm.unregisterNetworkCallback(defaultCallback);
2497 }
2498
Erik Kline3841a482015-11-25 12:49:38 +09002499 /**
2500 * Validate that a satisfied network request does not trigger onUnavailable() once the
2501 * time-out period expires.
2502 */
2503 @SmallTest
2504 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
2505 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2506 NetworkCapabilities.TRANSPORT_WIFI).build();
2507 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09002508 final int timeoutMs = 150;
2509 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09002510
2511 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2512 mWiFiNetworkAgent.connect(false);
Erik Kline1d3db322017-02-28 16:20:20 +09002513 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09002514
2515 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07002516 networkCallback.assertNoCallback();
2517 }
2518
2519 /**
2520 * Validate that a satisfied network request followed by a disconnected (lost) network does
2521 * not trigger onUnavailable() once the time-out period expires.
2522 */
2523 @SmallTest
2524 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
2525 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2526 NetworkCapabilities.TRANSPORT_WIFI).build();
2527 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09002528 final int requestTimeoutMs = 100;
2529 mCm.requestNetwork(nr, networkCallback, requestTimeoutMs);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07002530
2531 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2532 mWiFiNetworkAgent.connect(false);
Hugo Benichidfb559a2016-12-20 14:57:49 +09002533 final int assertTimeoutMs = 150;
Erik Kline1d3db322017-02-28 16:20:20 +09002534 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, assertTimeoutMs);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07002535 sleepFor(20);
2536 mWiFiNetworkAgent.disconnect();
2537 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2538
2539 // pass timeout and validate that UNAVAILABLE is not called
Hugo Benichidfb559a2016-12-20 14:57:49 +09002540 sleepFor(100);
Erik Kline3841a482015-11-25 12:49:38 +09002541 networkCallback.assertNoCallback();
2542 }
2543
2544 /**
2545 * Validate that when a time-out is specified for a network request the onUnavailable()
2546 * callback is called when time-out expires. Then validate that if network request is
2547 * (somehow) satisfied - the callback isn't called later.
2548 */
2549 @SmallTest
2550 public void testTimedoutNetworkRequest() {
2551 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2552 NetworkCapabilities.TRANSPORT_WIFI).build();
2553 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09002554 final int timeoutMs = 10;
2555 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09002556
2557 // pass timeout and validate that UNAVAILABLE is called
2558 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
2559
2560 // create a network satisfying request - validate that request not triggered
2561 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2562 mWiFiNetworkAgent.connect(false);
2563 networkCallback.assertNoCallback();
2564 }
2565
2566 /**
2567 * Validate that when a network request is unregistered (cancelled) the time-out for that
2568 * request doesn't trigger the onUnavailable() callback.
2569 */
2570 @SmallTest
2571 public void testTimedoutAfterUnregisteredNetworkRequest() {
2572 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2573 NetworkCapabilities.TRANSPORT_WIFI).build();
2574 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09002575 final int timeoutMs = 10;
2576 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09002577
2578 // remove request
2579 mCm.unregisterNetworkCallback(networkCallback);
2580
2581 // pass timeout and validate that no callbacks
2582 // Note: doesn't validate that nothing called from CS since even if called the CM already
2583 // unregisters the callback and won't pass it through!
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07002584 sleepFor(15);
Erik Kline3841a482015-11-25 12:49:38 +09002585 networkCallback.assertNoCallback();
2586
2587 // create a network satisfying request - validate that request not triggered
2588 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2589 mWiFiNetworkAgent.connect(false);
2590 networkCallback.assertNoCallback();
2591 }
2592
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002593 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
2594
2595 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
2596
2597 private class CallbackValue {
2598 public CallbackType callbackType;
2599 public int error;
2600
2601 public CallbackValue(CallbackType type) {
2602 this.callbackType = type;
2603 this.error = PacketKeepalive.SUCCESS;
2604 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
2605 }
2606
2607 public CallbackValue(CallbackType type, int error) {
2608 this.callbackType = type;
2609 this.error = error;
2610 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
2611 }
2612
2613 @Override
2614 public boolean equals(Object o) {
2615 return o instanceof CallbackValue &&
2616 this.callbackType == ((CallbackValue) o).callbackType &&
2617 this.error == ((CallbackValue) o).error;
2618 }
2619
2620 @Override
2621 public String toString() {
2622 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
2623 }
2624 }
2625
2626 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
2627
2628 @Override
2629 public void onStarted() {
2630 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
2631 }
2632
2633 @Override
2634 public void onStopped() {
2635 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
2636 }
2637
2638 @Override
2639 public void onError(int error) {
2640 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
2641 }
2642
2643 private void expectCallback(CallbackValue callbackValue) {
2644 try {
2645 assertEquals(
2646 callbackValue,
2647 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
2648 } catch (InterruptedException e) {
2649 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
2650 }
2651 }
2652
2653 public void expectStarted() {
2654 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
2655 }
2656
2657 public void expectStopped() {
2658 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
2659 }
2660
2661 public void expectError(int error) {
2662 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
2663 }
2664 }
2665
2666 private Network connectKeepaliveNetwork(LinkProperties lp) {
2667 // Ensure the network is disconnected before we do anything.
2668 if (mWiFiNetworkAgent != null) {
2669 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
2670 }
2671
2672 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2673 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2674 mWiFiNetworkAgent.connect(true);
2675 waitFor(cv);
2676 verifyActiveNetwork(TRANSPORT_WIFI);
2677 mWiFiNetworkAgent.sendLinkProperties(lp);
2678 mService.waitForIdle();
2679 return mWiFiNetworkAgent.getNetwork();
2680 }
2681
Hugo Benichicfcc1cb2016-11-04 16:06:34 +09002682 @SmallTest
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002683 public void testPacketKeepalives() throws Exception {
2684 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
2685 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
2686 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
2687 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
2688 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
2689
2690 LinkProperties lp = new LinkProperties();
2691 lp.setInterfaceName("wlan12");
2692 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
2693 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
2694 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
2695 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
2696
2697 Network notMyNet = new Network(61234);
2698 Network myNet = connectKeepaliveNetwork(lp);
2699
2700 TestKeepaliveCallback callback = new TestKeepaliveCallback();
2701 PacketKeepalive ka;
2702
2703 // Attempt to start keepalives with invalid parameters and check for errors.
2704 ka = mCm.startNattKeepalive(notMyNet, 25, callback, myIPv4, 1234, dstIPv4);
2705 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
2706
2707 ka = mCm.startNattKeepalive(myNet, 19, callback, notMyIPv4, 1234, dstIPv4);
2708 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
2709
2710 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 1234, dstIPv6);
2711 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2712
2713 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv4);
2714 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2715
2716 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv6);
2717 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); // NAT-T is IPv4-only.
2718
2719 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
2720 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
2721
2722 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
2723 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
2724
2725 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2726 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
2727
2728 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2729 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
2730
2731 // Check that a started keepalive can be stopped.
2732 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2733 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2734 callback.expectStarted();
2735 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
2736 ka.stop();
2737 callback.expectStopped();
2738
2739 // Check that deleting the IP address stops the keepalive.
2740 LinkProperties bogusLp = new LinkProperties(lp);
2741 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2742 callback.expectStarted();
2743 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
2744 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
2745 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
2746 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2747 mWiFiNetworkAgent.sendLinkProperties(lp);
2748
2749 // Check that a started keepalive is stopped correctly when the network disconnects.
2750 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2751 callback.expectStarted();
2752 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09002753 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002754 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
2755
2756 // ... and that stopping it after that has no adverse effects.
Lorenzo Colitti30145d72017-01-27 18:46:03 +09002757 mService.waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09002758 final Network myNetAlias = myNet;
Lorenzo Colitti30145d72017-01-27 18:46:03 +09002759 assertNull(mCm.getNetworkCapabilities(myNetAlias));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002760 ka.stop();
2761
2762 // Reconnect.
2763 myNet = connectKeepaliveNetwork(lp);
2764 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2765
2766 // Check things work as expected when the keepalive is stopped and the network disconnects.
2767 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2768 callback.expectStarted();
2769 ka.stop();
2770 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09002771 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002772 mService.waitForIdle();
2773 callback.expectStopped();
2774
2775 // Reconnect.
2776 myNet = connectKeepaliveNetwork(lp);
2777 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2778
2779 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
2780 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
2781 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2782 callback.expectStarted();
2783
2784 // The second one gets slot 2.
2785 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
2786 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
2787 PacketKeepalive ka2 = mCm.startNattKeepalive(myNet, 25, callback2, myIPv4, 6789, dstIPv4);
2788 callback2.expectStarted();
2789
2790 // Now stop the first one and create a third. This also gets slot 1.
2791 ka.stop();
2792 callback.expectStopped();
2793
2794 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
2795 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
2796 PacketKeepalive ka3 = mCm.startNattKeepalive(myNet, 25, callback3, myIPv4, 9876, dstIPv4);
2797 callback3.expectStarted();
2798
2799 ka2.stop();
2800 callback2.expectStopped();
2801
2802 ka3.stop();
2803 callback3.expectStopped();
2804 }
Udam Sainib7c24872016-01-04 12:16:14 -08002805
2806 @SmallTest
2807 public void testGetCaptivePortalServerUrl() throws Exception {
2808 String url = mCm.getCaptivePortalServerUrl();
2809 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
2810 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09002811
2812 private static class TestNetworkPinner extends NetworkPinner {
2813 public static boolean awaitPin(int timeoutMs) {
2814 synchronized(sLock) {
2815 if (sNetwork == null) {
2816 try {
2817 sLock.wait(timeoutMs);
2818 } catch (InterruptedException e) {}
2819 }
2820 return sNetwork != null;
2821 }
2822 }
2823
2824 public static boolean awaitUnpin(int timeoutMs) {
2825 synchronized(sLock) {
2826 if (sNetwork != null) {
2827 try {
2828 sLock.wait(timeoutMs);
2829 } catch (InterruptedException e) {}
2830 }
2831 return sNetwork == null;
2832 }
2833 }
2834 }
2835
2836 private void assertPinnedToWifiWithCellDefault() {
2837 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
2838 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2839 }
2840
2841 private void assertPinnedToWifiWithWifiDefault() {
2842 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
2843 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2844 }
2845
2846 private void assertNotPinnedToWifi() {
2847 assertNull(mCm.getBoundNetworkForProcess());
2848 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2849 }
2850
2851 @SmallTest
2852 public void testNetworkPinner() {
2853 NetworkRequest wifiRequest = new NetworkRequest.Builder()
2854 .addTransportType(TRANSPORT_WIFI)
2855 .build();
2856 assertNull(mCm.getBoundNetworkForProcess());
2857
2858 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2859 assertNull(mCm.getBoundNetworkForProcess());
2860
2861 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2862 mCellNetworkAgent.connect(true);
2863 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2864 mWiFiNetworkAgent.connect(false);
2865
2866 // When wi-fi connects, expect to be pinned.
2867 assertTrue(TestNetworkPinner.awaitPin(100));
2868 assertPinnedToWifiWithCellDefault();
2869
2870 // Disconnect and expect the pin to drop.
2871 mWiFiNetworkAgent.disconnect();
2872 assertTrue(TestNetworkPinner.awaitUnpin(100));
2873 assertNotPinnedToWifi();
2874
2875 // Reconnecting does not cause the pin to come back.
2876 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2877 mWiFiNetworkAgent.connect(false);
2878 assertFalse(TestNetworkPinner.awaitPin(100));
2879 assertNotPinnedToWifi();
2880
2881 // Pinning while connected causes the pin to take effect immediately.
2882 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2883 assertTrue(TestNetworkPinner.awaitPin(100));
2884 assertPinnedToWifiWithCellDefault();
2885
2886 // Explicitly unpin and expect to use the default network again.
2887 TestNetworkPinner.unpin();
2888 assertNotPinnedToWifi();
2889
2890 // Disconnect cell and wifi.
2891 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
2892 mCellNetworkAgent.disconnect();
2893 mWiFiNetworkAgent.disconnect();
2894 waitFor(cv);
2895
2896 // Pinning takes effect even if the pinned network is the default when the pin is set...
2897 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2898 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2899 mWiFiNetworkAgent.connect(false);
2900 assertTrue(TestNetworkPinner.awaitPin(100));
2901 assertPinnedToWifiWithWifiDefault();
2902
2903 // ... and is maintained even when that network is no longer the default.
2904 cv = waitForConnectivityBroadcasts(1);
2905 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2906 mCellNetworkAgent.connect(true);
2907 waitFor(cv);
2908 assertPinnedToWifiWithCellDefault();
2909 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04002910
2911 @SmallTest
2912 public void testNetworkRequestMaximum() {
2913 final int MAX_REQUESTS = 100;
2914 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
2915 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
2916 ArrayList<NetworkCallback> networkCallbacks = new ArrayList<NetworkCallback>();
2917 try {
2918 for (int i = 0; i < MAX_REQUESTS; i++) {
2919 NetworkCallback networkCallback = new NetworkCallback();
2920 mCm.requestNetwork(networkRequest, networkCallback);
2921 networkCallbacks.add(networkCallback);
2922 }
2923 fail("Registering " + MAX_REQUESTS + " NetworkRequests did not throw exception");
2924 } catch (IllegalArgumentException expected) {}
2925 for (NetworkCallback networkCallback : networkCallbacks) {
2926 mCm.unregisterNetworkCallback(networkCallback);
2927 }
2928 networkCallbacks.clear();
2929
2930 try {
2931 for (int i = 0; i < MAX_REQUESTS; i++) {
2932 NetworkCallback networkCallback = new NetworkCallback();
2933 mCm.registerNetworkCallback(networkRequest, networkCallback);
2934 networkCallbacks.add(networkCallback);
2935 }
2936 fail("Registering " + MAX_REQUESTS + " NetworkCallbacks did not throw exception");
2937 } catch (IllegalArgumentException expected) {}
2938 for (NetworkCallback networkCallback : networkCallbacks) {
2939 mCm.unregisterNetworkCallback(networkCallback);
2940 }
2941 networkCallbacks.clear();
2942
2943 ArrayList<PendingIntent> pendingIntents = new ArrayList<PendingIntent>();
2944 try {
2945 for (int i = 0; i < MAX_REQUESTS + 1; i++) {
2946 PendingIntent pendingIntent =
2947 PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
2948 mCm.requestNetwork(networkRequest, pendingIntent);
2949 pendingIntents.add(pendingIntent);
2950 }
2951 fail("Registering " + MAX_REQUESTS +
2952 " PendingIntent NetworkRequests did not throw exception");
2953 } catch (IllegalArgumentException expected) {}
2954 for (PendingIntent pendingIntent : pendingIntents) {
2955 mCm.unregisterNetworkCallback(pendingIntent);
2956 }
2957 pendingIntents.clear();
2958
2959 try {
2960 for (int i = 0; i < MAX_REQUESTS + 1; i++) {
2961 PendingIntent pendingIntent =
2962 PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
2963 mCm.registerNetworkCallback(networkRequest, pendingIntent);
2964 pendingIntents.add(pendingIntent);
2965 }
2966 fail("Registering " + MAX_REQUESTS +
2967 " PendingIntent NetworkCallbacks did not throw exception");
2968 } catch (IllegalArgumentException expected) {}
2969 for (PendingIntent pendingIntent : pendingIntents) {
2970 mCm.unregisterNetworkCallback(pendingIntent);
2971 }
2972 pendingIntents.clear();
2973 mService.waitForIdle(5000);
2974
2975 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
2976 for (int i = 0; i < MAX_REQUESTS; i++) {
2977 NetworkCallback networkCallback = new NetworkCallback();
2978 mCm.requestNetwork(networkRequest, networkCallback);
2979 mCm.unregisterNetworkCallback(networkCallback);
2980 }
2981 mService.waitForIdle();
2982 for (int i = 0; i < MAX_REQUESTS; i++) {
2983 NetworkCallback networkCallback = new NetworkCallback();
2984 mCm.registerNetworkCallback(networkRequest, networkCallback);
2985 mCm.unregisterNetworkCallback(networkCallback);
2986 }
2987 mService.waitForIdle();
2988 for (int i = 0; i < MAX_REQUESTS; i++) {
2989 PendingIntent pendingIntent =
2990 PendingIntent.getBroadcast(mContext, 0, new Intent("b" + i), 0);
2991 mCm.requestNetwork(networkRequest, pendingIntent);
2992 mCm.unregisterNetworkCallback(pendingIntent);
2993 }
2994 mService.waitForIdle();
2995 for (int i = 0; i < MAX_REQUESTS; i++) {
2996 PendingIntent pendingIntent =
2997 PendingIntent.getBroadcast(mContext, 0, new Intent("c" + i), 0);
2998 mCm.registerNetworkCallback(networkRequest, pendingIntent);
2999 mCm.unregisterNetworkCallback(pendingIntent);
3000 }
3001 }
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003002
3003 /* test utilities */
Hugo Benichidfb559a2016-12-20 14:57:49 +09003004 // TODO: eliminate all usages of sleepFor and replace by proper timeouts/waitForIdle.
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003005 static private void sleepFor(int ms) {
3006 try {
3007 Thread.sleep(ms);
3008 } catch (InterruptedException e) {
3009 }
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003010 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07003011}