blob: 4733deba6d17c8feeed1aa0cd3a3f07663c537a0 [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;
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +090022import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
23import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
Hugo Benichi16f0a942017-06-20 14:07:59 +090024import static android.net.ConnectivityManager.TYPE_NONE;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070025import static android.net.ConnectivityManager.TYPE_WIFI;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060026import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
27import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
28import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
29import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
30import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
31import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
32import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
33import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
34import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
35import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
36import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
37import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
38import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
39import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
40import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
41import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
42import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
43import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
44import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
45import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
46import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
Chalard Jean0b214af2018-01-12 17:22:49 +090047import static android.net.NetworkCapabilities.TRANSPORT_VPN;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060048import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
49import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
50
51import static com.android.internal.util.TestUtils.waitForIdleHandler;
Lorenzo Colitti83fa2582015-08-07 12:49:01 +090052
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090053import static org.junit.Assert.assertEquals;
54import static org.junit.Assert.assertFalse;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090055import static org.junit.Assert.assertNotNull;
56import static org.junit.Assert.assertNull;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060057import static org.junit.Assert.assertTrue;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090058import static org.junit.Assert.fail;
Erik Klinee89953b2018-01-11 16:11:10 +090059import static org.mockito.Matchers.anyBoolean;
60import static org.mockito.Matchers.anyInt;
61import static org.mockito.Matchers.anyString;
62import static org.mockito.Mockito.any;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060063import static org.mockito.Mockito.atLeastOnce;
Jeff Sharkey3671b1e2013-01-31 17:22:26 -080064import static org.mockito.Mockito.mock;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060065import static org.mockito.Mockito.never;
66import static org.mockito.Mockito.reset;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090067import static org.mockito.Mockito.spy;
Erik Klinee89953b2018-01-11 16:11:10 +090068import static org.mockito.Mockito.times;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060069import static org.mockito.Mockito.verify;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090070import static org.mockito.Mockito.when;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070071
Erik Klinee89953b2018-01-11 16:11:10 +090072
Lorenzo Colitti73b209382016-09-15 22:18:09 +090073import android.app.NotificationManager;
Paul Jensenbb2e0e92015-06-16 15:11:58 -040074import android.app.PendingIntent;
Paul Jensend7b6ca92015-05-13 14:05:12 -040075import android.content.BroadcastReceiver;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +090076import android.content.ContentResolver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070077import android.content.Context;
Paul Jensend7b6ca92015-05-13 14:05:12 -040078import android.content.Intent;
79import android.content.IntentFilter;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090080import android.content.res.Resources;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +090081import android.net.CaptivePortal;
Paul Jensend7b6ca92015-05-13 14:05:12 -040082import android.net.ConnectivityManager;
83import android.net.ConnectivityManager.NetworkCallback;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +090084import android.net.ConnectivityManager.PacketKeepalive;
85import android.net.ConnectivityManager.PacketKeepaliveCallback;
Hugo Benichicb883232017-05-11 13:16:17 +090086import android.net.ConnectivityManager.TooManyRequestsException;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070087import android.net.INetworkPolicyManager;
88import android.net.INetworkStatsService;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +090089import android.net.IpPrefix;
90import android.net.LinkAddress;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070091import android.net.LinkProperties;
Etan Cohena7434272017-04-03 12:17:51 -070092import android.net.MatchAllNetworkSpecifier;
Paul Jensend7b6ca92015-05-13 14:05:12 -040093import android.net.Network;
94import android.net.NetworkAgent;
95import android.net.NetworkCapabilities;
Robert Greenwalt348e98d2015-06-05 17:55:36 -070096import android.net.NetworkFactory;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070097import android.net.NetworkInfo;
98import android.net.NetworkInfo.DetailedState;
Paul Jensend7b6ca92015-05-13 14:05:12 -040099import android.net.NetworkMisc;
100import android.net.NetworkRequest;
Etan Cohena7434272017-04-03 12:17:51 -0700101import android.net.NetworkSpecifier;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100102import android.net.NetworkUtils;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700103import android.net.RouteInfo;
Etan Cohena7434272017-04-03 12:17:51 -0700104import android.net.StringNetworkSpecifier;
Chalard Jean0b214af2018-01-12 17:22:49 +0900105import android.net.UidRange;
Hugo Benichif9fdf872016-07-28 17:53:06 +0900106import android.net.metrics.IpConnectivityLog;
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900107import android.net.util.MultinetworkPolicyTracker;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400108import android.os.ConditionVariable;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700109import android.os.Handler;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700110import android.os.HandlerThread;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700111import android.os.INetworkManagementService;
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900112import android.os.Looper;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900113import android.os.Message;
Etan Cohena7434272017-04-03 12:17:51 -0700114import android.os.Parcel;
115import android.os.Parcelable;
Robin Leed2baf792016-03-24 12:07:00 +0000116import android.os.Process;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900117import android.os.SystemClock;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900118import android.os.UserHandle;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900119import android.provider.Settings;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900120import android.support.test.InstrumentationRegistry;
121import android.support.test.filters.SmallTest;
122import android.support.test.runner.AndroidJUnit4;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900123import android.test.mock.MockContentResolver;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100124import android.util.ArraySet;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700125import android.util.Log;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700126
Erik Klinee89953b2018-01-11 16:11:10 +0900127import com.android.internal.util.ArrayUtils;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900128import com.android.internal.util.WakeupMessage;
Lorenzo Colitti3c295b52016-10-28 12:56:03 +0900129import com.android.internal.util.test.BroadcastInterceptingContext;
Lorenzo Colittib8df76e42016-10-28 12:37:38 +0900130import com.android.internal.util.test.FakeSettingsProvider;
Hugo Benichi64901e52017-10-19 14:42:40 +0900131import com.android.server.connectivity.DefaultNetworkMetrics;
132import com.android.server.connectivity.IpConnectivityMetrics;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900133import com.android.server.connectivity.MockableSystemProperties;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400134import com.android.server.connectivity.NetworkAgentInfo;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400135import com.android.server.connectivity.NetworkMonitor;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900136import com.android.server.net.NetworkPinner;
Hugo Benichi938ab4f2017-02-11 17:04:43 +0900137import com.android.server.net.NetworkPolicyManagerInternal;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400138
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900139import org.junit.After;
140import org.junit.Before;
Hugo Benichi849b81b2017-05-25 13:42:31 +0900141import org.junit.Ignore;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900142import org.junit.Test;
143import org.junit.runner.RunWith;
Erik Klinee89953b2018-01-11 16:11:10 +0900144import org.mockito.ArgumentCaptor;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900145import org.mockito.Mock;
146import org.mockito.MockitoAnnotations;
147import org.mockito.Spy;
148
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700149import java.net.InetAddress;
Paul Jensen4e1d3fd2016-04-08 13:56:52 -0400150import java.util.ArrayList;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900151import java.util.Arrays;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100152import java.util.Collection;
153import java.util.List;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +0900154import java.util.Objects;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100155import java.util.Set;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900156import java.util.concurrent.CountDownLatch;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900157import java.util.concurrent.LinkedBlockingQueue;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900158import java.util.concurrent.TimeUnit;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700159import java.util.concurrent.atomic.AtomicBoolean;
Hugo Benichi16f0a942017-06-20 14:07:59 +0900160import java.util.function.Predicate;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700161
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900162
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700163/**
164 * Tests for {@link ConnectivityService}.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400165 *
166 * Build, install and run with:
Hugo Benichibb91c572017-05-22 10:44:02 +0900167 * runtest frameworks-net -c com.android.server.ConnectivityServiceTest
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700168 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900169@RunWith(AndroidJUnit4.class)
170@SmallTest
171public class ConnectivityServiceTest {
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700172 private static final String TAG = "ConnectivityServiceTest";
173
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900174 private static final int TIMEOUT_MS = 500;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900175 private static final int TEST_LINGER_DELAY_MS = 120;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900176
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900177 private MockContext mServiceContext;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400178 private WrappedConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900179 private WrappedConnectivityManager mCm;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400180 private MockNetworkAgent mWiFiNetworkAgent;
181 private MockNetworkAgent mCellNetworkAgent;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900182 private MockNetworkAgent mEthernetNetworkAgent;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900183 private Context mContext;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700184
Hugo Benichi64901e52017-10-19 14:42:40 +0900185 @Mock IpConnectivityMetrics.Logger mMetricsService;
186 @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
Erik Klinee89953b2018-01-11 16:11:10 +0900187 @Mock INetworkManagementService mNetworkManagementService;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600188 @Mock INetworkStatsService mStatsService;
Hugo Benichi64901e52017-10-19 14:42:40 +0900189
Erik Klinee89953b2018-01-11 16:11:10 +0900190 private ArgumentCaptor<String[]> mStringArrayCaptor = ArgumentCaptor.forClass(String[].class);
191
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900192 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
193 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
194 // reflect the state of our test ConnectivityService.
195 private class WrappedConnectivityManager extends ConnectivityManager {
196 private Network mFakeBoundNetwork;
197
198 public synchronized boolean bindProcessToNetwork(Network network) {
199 mFakeBoundNetwork = network;
200 return true;
201 }
202
203 public synchronized Network getBoundNetworkForProcess() {
204 return mFakeBoundNetwork;
205 }
206
207 public WrappedConnectivityManager(Context context, ConnectivityService service) {
208 super(context, service);
209 }
210 }
211
Paul Jensend7b6ca92015-05-13 14:05:12 -0400212 private class MockContext extends BroadcastInterceptingContext {
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900213 private final MockContentResolver mContentResolver;
214
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900215 @Spy private Resources mResources;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900216 private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900217
Paul Jensend7b6ca92015-05-13 14:05:12 -0400218 MockContext(Context base) {
219 super(base);
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900220
221 mResources = spy(base.getResources());
222 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
223 thenReturn(new String[] {
224 "wifi,1,1,1,-1,true",
225 "mobile,0,0,0,-1,true",
226 "mobile_mms,2,0,2,60000,true",
227 });
228
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900229 mContentResolver = new MockContentResolver();
230 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
Paul Jensend7b6ca92015-05-13 14:05:12 -0400231 }
232
233 @Override
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900234 public void startActivityAsUser(Intent intent, UserHandle handle) {
235 mStartedActivities.offer(intent);
236 }
237
238 public Intent expectStartActivityIntent(int timeoutMs) {
239 Intent intent = null;
240 try {
241 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
242 } catch (InterruptedException e) {}
243 assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
244 return intent;
245 }
246
247 public void expectNoStartActivityIntent(int timeoutMs) {
248 try {
249 assertNull("Received unexpected Intent to start activity",
250 mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
251 } catch (InterruptedException e) {}
252 }
253
254 @Override
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900255 public Object getSystemService(String name) {
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900256 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
257 if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400258 return super.getSystemService(name);
259 }
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900260
261 @Override
262 public ContentResolver getContentResolver() {
263 return mContentResolver;
264 }
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900265
266 @Override
267 public Resources getResources() {
268 return mResources;
269 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400270 }
271
Hugo Benichi669f0232017-06-29 22:58:39 +0900272 public void waitForIdle(int timeoutMsAsInt) {
273 long timeoutMs = timeoutMsAsInt;
Hugo Benichibb91c572017-05-22 10:44:02 +0900274 waitForIdleHandler(mService.mHandlerThread, timeoutMs);
275 waitForIdle(mCellNetworkAgent, timeoutMs);
276 waitForIdle(mWiFiNetworkAgent, timeoutMs);
277 waitForIdle(mEthernetNetworkAgent, timeoutMs);
278 waitForIdleHandler(mService.mHandlerThread, timeoutMs);
279 }
280
Hugo Benichi669f0232017-06-29 22:58:39 +0900281 public void waitForIdle(MockNetworkAgent agent, long timeoutMs) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900282 if (agent == null) {
283 return;
284 }
285 waitForIdleHandler(agent.mHandlerThread, timeoutMs);
286 }
287
288 private void waitForIdle() {
289 waitForIdle(TIMEOUT_MS);
290 }
291
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900292 @Test
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900293 public void testWaitForIdle() {
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900294 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
295
296 // Tests that waitForIdle returns immediately if the service is already idle.
297 for (int i = 0; i < attempts; i++) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900298 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900299 }
300
301 // Bring up a network that we can use to send messages to ConnectivityService.
302 ConditionVariable cv = waitForConnectivityBroadcasts(1);
303 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
304 mWiFiNetworkAgent.connect(false);
305 waitFor(cv);
306 Network n = mWiFiNetworkAgent.getNetwork();
307 assertNotNull(n);
308
309 // Tests that calling waitForIdle waits for messages to be processed.
310 for (int i = 0; i < attempts; i++) {
311 mWiFiNetworkAgent.setSignalStrength(i);
Hugo Benichibb91c572017-05-22 10:44:02 +0900312 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900313 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
314 }
Hugo Benichi5d540d12016-10-17 15:54:51 +0900315 }
316
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900317 // This test has an inherent race condition in it, and cannot be enabled for continuous testing
318 // or presubmit tests. It is kept for manual runs and documentation purposes.
319 public void verifyThatNotWaitingForIdleCausesRaceConditions() {
Hugo Benichi5d540d12016-10-17 15:54:51 +0900320 // Bring up a network that we can use to send messages to ConnectivityService.
321 ConditionVariable cv = waitForConnectivityBroadcasts(1);
322 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
323 mWiFiNetworkAgent.connect(false);
324 waitFor(cv);
325 Network n = mWiFiNetworkAgent.getNetwork();
326 assertNotNull(n);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900327
328 // Ensure that not calling waitForIdle causes a race condition.
Hugo Benichi5d540d12016-10-17 15:54:51 +0900329 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900330 for (int i = 0; i < attempts; i++) {
331 mWiFiNetworkAgent.setSignalStrength(i);
332 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
333 // We hit a race condition, as expected. Pass the test.
334 return;
335 }
336 }
337
338 // No race? There is a bug in this test.
339 fail("expected race condition at least once in " + attempts + " attempts");
340 }
341
Paul Jensend7b6ca92015-05-13 14:05:12 -0400342 private class MockNetworkAgent {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400343 private final WrappedNetworkMonitor mWrappedNetworkMonitor;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400344 private final NetworkInfo mNetworkInfo;
345 private final NetworkCapabilities mNetworkCapabilities;
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900346 private final HandlerThread mHandlerThread;
Paul Jensene0988542015-06-25 15:30:08 -0400347 private final ConditionVariable mDisconnected = new ConditionVariable();
Paul Jensen232437312016-04-06 09:51:26 -0400348 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
Calvin On1f64f3f2016-10-11 15:10:46 -0700349 private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
Paul Jensen3d911462015-06-12 06:40:24 -0400350 private int mScore;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400351 private NetworkAgent mNetworkAgent;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900352 private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
353 private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE;
354 private Integer mExpectedKeepaliveSlot = null;
Paul Jensen232437312016-04-06 09:51:26 -0400355 // Contains the redirectUrl from networkStatus(). Before reading, wait for
356 // mNetworkStatusReceived.
357 private String mRedirectUrl;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400358
359 MockNetworkAgent(int transport) {
Rubin Xu1bb5c082017-09-05 18:40:49 +0100360 this(transport, new LinkProperties());
361 }
362
363 MockNetworkAgent(int transport, LinkProperties linkProperties) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400364 final int type = transportToLegacyType(transport);
Chalard Jean0b214af2018-01-12 17:22:49 +0900365 final String typeName = ConnectivityManager.getNetworkTypeName(transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400366 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
367 mNetworkCapabilities = new NetworkCapabilities();
368 mNetworkCapabilities.addTransportType(transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400369 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900370 case TRANSPORT_ETHERNET:
371 mScore = 70;
372 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400373 case TRANSPORT_WIFI:
Paul Jensen3d911462015-06-12 06:40:24 -0400374 mScore = 60;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400375 break;
376 case TRANSPORT_CELLULAR:
Paul Jensen3d911462015-06-12 06:40:24 -0400377 mScore = 50;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400378 break;
Hugo Benichi16f0a942017-06-20 14:07:59 +0900379 case TRANSPORT_WIFI_AWARE:
380 mScore = 20;
381 break;
Chalard Jean0b214af2018-01-12 17:22:49 +0900382 case TRANSPORT_VPN:
383 mScore = 0;
384 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400385 default:
386 throw new UnsupportedOperationException("unimplemented network type");
387 }
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900388 mHandlerThread = new HandlerThread("Mock-" + typeName);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900389 mHandlerThread.start();
390 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
391 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
Rubin Xu1bb5c082017-09-05 18:40:49 +0100392 linkProperties, mScore, new NetworkMisc()) {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900393 @Override
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900394 public void unwanted() { mDisconnected.open(); }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900395
396 @Override
397 public void startPacketKeepalive(Message msg) {
398 int slot = msg.arg1;
399 if (mExpectedKeepaliveSlot != null) {
400 assertEquals((int) mExpectedKeepaliveSlot, slot);
401 }
402 onPacketKeepaliveEvent(slot, mStartKeepaliveError);
403 }
404
405 @Override
406 public void stopPacketKeepalive(Message msg) {
407 onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
408 }
Paul Jensen232437312016-04-06 09:51:26 -0400409
410 @Override
411 public void networkStatus(int status, String redirectUrl) {
412 mRedirectUrl = redirectUrl;
413 mNetworkStatusReceived.open();
414 }
Calvin On1f64f3f2016-10-11 15:10:46 -0700415
416 @Override
417 protected void preventAutomaticReconnect() {
418 mPreventReconnectReceived.open();
419 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400420 };
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900421 // Waits for the NetworkAgent to be registered, which includes the creation of the
422 // NetworkMonitor.
Hugo Benichibb91c572017-05-22 10:44:02 +0900423 waitForIdle();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400424 mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor();
Paul Jensen3d911462015-06-12 06:40:24 -0400425 }
426
427 public void adjustScore(int change) {
428 mScore += change;
429 mNetworkAgent.sendNetworkScore(mScore);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400430 }
431
Lorenzo Colitti02cc8392017-05-17 01:28:09 +0900432 public void explicitlySelected(boolean acceptUnvalidated) {
433 mNetworkAgent.explicitlySelected(acceptUnvalidated);
434 }
435
Paul Jensen85cf78e2015-06-25 13:25:07 -0400436 public void addCapability(int capability) {
437 mNetworkCapabilities.addCapability(capability);
438 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
439 }
440
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900441 public void removeCapability(int capability) {
442 mNetworkCapabilities.removeCapability(capability);
443 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
444 }
445
Chalard Jean0b214af2018-01-12 17:22:49 +0900446 public void setUids(Set<UidRange> uids) {
447 mNetworkCapabilities.setUids(uids);
448 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
449 }
450
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900451 public void setSignalStrength(int signalStrength) {
452 mNetworkCapabilities.setSignalStrength(signalStrength);
453 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
454 }
455
Etan Cohena7434272017-04-03 12:17:51 -0700456 public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
457 mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
Lorenzo Colitti6556a222017-04-03 17:46:35 +0900458 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
459 }
460
Paul Jensene0988542015-06-25 15:30:08 -0400461 public void connectWithoutInternet() {
462 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
463 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
464 }
465
Paul Jensend7b6ca92015-05-13 14:05:12 -0400466 /**
Paul Jensene0988542015-06-25 15:30:08 -0400467 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400468 * @param validated Indicate if network should pretend to be validated.
469 */
470 public void connect(boolean validated) {
Hugo Benichi16f0a942017-06-20 14:07:59 +0900471 connect(validated, true);
472 }
473
474 /**
475 * Transition this NetworkAgent to CONNECTED state.
476 * @param validated Indicate if network should pretend to be validated.
477 * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
478 */
479 public void connect(boolean validated, boolean hasInternet) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900480 assertEquals("MockNetworkAgents can only be connected once",
481 mNetworkInfo.getDetailedState(), DetailedState.IDLE);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400482 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
483
Paul Jensend7b6ca92015-05-13 14:05:12 -0400484 NetworkCallback callback = null;
485 final ConditionVariable validatedCv = new ConditionVariable();
486 if (validated) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400487 mWrappedNetworkMonitor.gen204ProbeResult = 204;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400488 NetworkRequest request = new NetworkRequest.Builder()
489 .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
490 .build();
491 callback = new NetworkCallback() {
492 public void onCapabilitiesChanged(Network network,
493 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400494 if (network.equals(getNetwork()) &&
495 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400496 validatedCv.open();
497 }
498 }
499 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400500 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400501 }
Hugo Benichi16f0a942017-06-20 14:07:59 +0900502 if (hasInternet) {
503 addCapability(NET_CAPABILITY_INTERNET);
504 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400505
Paul Jensene0988542015-06-25 15:30:08 -0400506 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400507
508 if (validated) {
509 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400510 waitFor(validatedCv);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400511 mWrappedNetworkMonitor.gen204ProbeResult = 500;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400512 }
513
514 if (callback != null) mCm.unregisterNetworkCallback(callback);
515 }
516
Paul Jensen232437312016-04-06 09:51:26 -0400517 public void connectWithCaptivePortal(String redirectUrl) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400518 mWrappedNetworkMonitor.gen204ProbeResult = 200;
Paul Jensen232437312016-04-06 09:51:26 -0400519 mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400520 connect(false);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400521 }
522
Erik Kline1d3db322017-02-28 16:20:20 +0900523 public void suspend() {
524 mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null);
525 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
526 }
527
Paul Jensend7b6ca92015-05-13 14:05:12 -0400528 public void disconnect() {
529 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
530 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
531 }
532
533 public Network getNetwork() {
534 return new Network(mNetworkAgent.netId);
535 }
Paul Jensene0988542015-06-25 15:30:08 -0400536
Calvin On1f64f3f2016-10-11 15:10:46 -0700537 public ConditionVariable getPreventReconnectReceived() {
538 return mPreventReconnectReceived;
539 }
540
Paul Jensene0988542015-06-25 15:30:08 -0400541 public ConditionVariable getDisconnectedCV() {
542 return mDisconnected;
543 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400544
545 public WrappedNetworkMonitor getWrappedNetworkMonitor() {
546 return mWrappedNetworkMonitor;
547 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900548
549 public void sendLinkProperties(LinkProperties lp) {
550 mNetworkAgent.sendLinkProperties(lp);
551 }
552
553 public void setStartKeepaliveError(int error) {
554 mStartKeepaliveError = error;
555 }
556
557 public void setStopKeepaliveError(int error) {
558 mStopKeepaliveError = error;
559 }
560
561 public void setExpectedKeepaliveSlot(Integer slot) {
562 mExpectedKeepaliveSlot = slot;
563 }
Paul Jensen232437312016-04-06 09:51:26 -0400564
565 public String waitForRedirectUrl() {
566 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
567 return mRedirectUrl;
568 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400569 }
570
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900571 /**
572 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
573 * operations have been processed. Before ConnectivityService can add or remove any requests,
574 * the factory must be told to expect those operations by calling expectAddRequests or
575 * expectRemoveRequests.
576 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700577 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400578 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
579 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400580 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700581
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900582 // Used to expect that requests be removed or added on a separate thread, without sleeping.
583 // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then
584 // cause some other thread to add or remove requests, then call waitForRequests(). We can
585 // either expect requests to be added or removed, but not both, because CountDownLatch can
586 // only count in one direction.
587 private CountDownLatch mExpectations;
588
589 // Whether we are currently expecting requests to be added or removed. Valid only if
590 // mExpectations is non-null.
591 private boolean mExpectingAdditions;
592
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700593 public MockNetworkFactory(Looper looper, Context context, String logTag,
594 NetworkCapabilities filter) {
595 super(looper, context, logTag, filter);
596 }
597
598 public int getMyRequestCount() {
599 return getRequestCount();
600 }
601
602 protected void startNetwork() {
603 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400604 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700605 }
606
607 protected void stopNetwork() {
608 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400609 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700610 }
611
612 public boolean getMyStartRequested() {
613 return mNetworkStarted.get();
614 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400615
616 public ConditionVariable getNetworkStartedCV() {
617 mNetworkStartedCV.close();
618 return mNetworkStartedCV;
619 }
620
621 public ConditionVariable getNetworkStoppedCV() {
622 mNetworkStoppedCV.close();
623 return mNetworkStoppedCV;
624 }
625
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900626 @Override
627 protected void handleAddRequest(NetworkRequest request, int score) {
628 // If we're expecting anything, we must be expecting additions.
629 if (mExpectations != null && !mExpectingAdditions) {
630 fail("Can't add requests while expecting requests to be removed");
631 }
632
633 // Add the request.
634 super.handleAddRequest(request, score);
635
636 // Reduce the number of request additions we're waiting for.
637 if (mExpectingAdditions) {
638 assertTrue("Added more requests than expected", mExpectations.getCount() > 0);
639 mExpectations.countDown();
640 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400641 }
642
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900643 @Override
644 protected void handleRemoveRequest(NetworkRequest request) {
645 // If we're expecting anything, we must be expecting removals.
646 if (mExpectations != null && mExpectingAdditions) {
647 fail("Can't remove requests while expecting requests to be added");
648 }
649
650 // Remove the request.
651 super.handleRemoveRequest(request);
652
653 // Reduce the number of request removals we're waiting for.
654 if (!mExpectingAdditions) {
655 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0);
656 mExpectations.countDown();
657 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400658 }
659
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900660 private void assertNoExpectations() {
661 if (mExpectations != null) {
662 fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
663 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400664 }
665
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900666 // Expects that count requests will be added.
667 public void expectAddRequests(final int count) {
668 assertNoExpectations();
669 mExpectingAdditions = true;
670 mExpectations = new CountDownLatch(count);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400671 }
672
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900673 // Expects that count requests will be removed.
674 public void expectRemoveRequests(final int count) {
675 assertNoExpectations();
676 mExpectingAdditions = false;
677 mExpectations = new CountDownLatch(count);
678 }
679
680 // Waits for the expected request additions or removals to happen within a timeout.
681 public void waitForRequests() throws InterruptedException {
682 assertNotNull("Nothing to wait for", mExpectations);
683 mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
684 final long count = mExpectations.getCount();
685 final String msg = count + " requests still not " +
686 (mExpectingAdditions ? "added" : "removed") +
687 " after " + TIMEOUT_MS + " ms";
688 assertEquals(msg, 0, count);
689 mExpectations = null;
690 }
691
692 public void waitForNetworkRequests(final int count) throws InterruptedException {
693 waitForRequests();
694 assertEquals(count, getMyRequestCount());
Paul Jensen0a2823e2015-06-12 10:31:09 -0400695 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700696 }
697
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900698 private class FakeWakeupMessage extends WakeupMessage {
699 private static final int UNREASONABLY_LONG_WAIT = 1000;
700
701 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
702 super(context, handler, cmdName, cmd);
703 }
704
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900705 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
706 int arg1, int arg2, Object obj) {
707 super(context, handler, cmdName, cmd, arg1, arg2, obj);
708 }
709
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900710 @Override
711 public void schedule(long when) {
712 long delayMs = when - SystemClock.elapsedRealtime();
713 if (delayMs < 0) delayMs = 0;
714 if (delayMs > UNREASONABLY_LONG_WAIT) {
715 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
716 "ms into the future: " + delayMs);
717 }
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900718 Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
719 mHandler.sendMessageDelayed(msg, delayMs);
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900720 }
721
722 @Override
723 public void cancel() {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900724 mHandler.removeMessages(mCmd, mObj);
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900725 }
726
727 @Override
728 public void onAlarm() {
729 throw new AssertionError("Should never happen. Update this fake.");
730 }
731 }
732
Paul Jensencf4c2c62015-07-01 14:16:32 -0400733 // NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
734 private class WrappedNetworkMonitor extends NetworkMonitor {
735 // HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
736 public int gen204ProbeResult = 500;
Paul Jensen232437312016-04-06 09:51:26 -0400737 public String gen204ProbeRedirectUrl = null;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400738
739 public WrappedNetworkMonitor(Context context, Handler handler,
Hugo Benichif9fdf872016-07-28 17:53:06 +0900740 NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest,
741 IpConnectivityLog log) {
Hugo Benichic894b122017-07-31 12:58:20 +0900742 super(context, handler, networkAgentInfo, defaultRequest, log,
743 NetworkMonitor.NetworkMonitorSettings.DEFAULT);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400744 }
745
746 @Override
Paul Jensen232437312016-04-06 09:51:26 -0400747 protected CaptivePortalProbeResult isCaptivePortal() {
Calvin On1f64f3f2016-10-11 15:10:46 -0700748 if (!mIsCaptivePortalCheckEnabled) { return new CaptivePortalProbeResult(204); }
Hugo Benichid953bf82016-09-27 09:22:35 +0900749 return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl, null);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400750 }
751 }
752
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900753 private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
Hugo Benichi53d83d52016-11-15 13:42:34 +0900754 public volatile boolean configRestrictsAvoidBadWifi;
Lorenzo Colitti2de49252017-01-24 18:08:41 +0900755 public volatile int configMeteredMultipathPreference;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400756
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900757 public WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
Erik Kline065ab6e2016-10-02 18:02:14 +0900758 super(c, h, r);
759 }
760
761 @Override
762 public boolean configRestrictsAvoidBadWifi() {
763 return configRestrictsAvoidBadWifi;
764 }
Lorenzo Colitti2de49252017-01-24 18:08:41 +0900765
766 @Override
767 public int configMeteredMultipathPreference() {
768 return configMeteredMultipathPreference;
769 }
Erik Kline065ab6e2016-10-02 18:02:14 +0900770 }
771
772 private class WrappedConnectivityService extends ConnectivityService {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900773 public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
Erik Kline065ab6e2016-10-02 18:02:14 +0900774 private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900775 private MockableSystemProperties mSystemProperties;
Erik Kline065ab6e2016-10-02 18:02:14 +0900776
Paul Jensend7b6ca92015-05-13 14:05:12 -0400777 public WrappedConnectivityService(Context context, INetworkManagementService netManager,
Hugo Benichif9fdf872016-07-28 17:53:06 +0900778 INetworkStatsService statsService, INetworkPolicyManager policyManager,
779 IpConnectivityLog log) {
780 super(context, netManager, statsService, policyManager, log);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900781 mLingerDelayMs = TEST_LINGER_DELAY_MS;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400782 }
783
784 @Override
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900785 protected MockableSystemProperties getSystemProperties() {
786 // Minimal approach to overriding system properties: let most calls fall through to real
787 // device values, and only override ones values that are important to this test.
788 mSystemProperties = spy(new MockableSystemProperties());
789 when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
790 when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
791 return mSystemProperties;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400792 }
Paul Jensen67b0b072015-06-10 11:22:17 -0400793
794 @Override
795 protected int reserveNetId() {
796 while (true) {
797 final int netId = super.reserveNetId();
798
799 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
800 // can have odd side-effects, like network validations succeeding.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900801 Context context = InstrumentationRegistry.getContext();
802 final Network[] networks = ConnectivityManager.from(context).getAllNetworks();
Paul Jensen67b0b072015-06-10 11:22:17 -0400803 boolean overlaps = false;
804 for (Network network : networks) {
805 if (netId == network.netId) {
806 overlaps = true;
807 break;
808 }
809 }
810 if (overlaps) continue;
811
812 return netId;
813 }
814 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400815
816 @Override
817 public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
818 NetworkAgentInfo nai, NetworkRequest defaultRequest) {
Hugo Benichif9fdf872016-07-28 17:53:06 +0900819 final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(
820 context, handler, nai, defaultRequest, mock(IpConnectivityLog.class));
Paul Jensencf4c2c62015-07-01 14:16:32 -0400821 mLastCreatedNetworkMonitor = monitor;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400822 return monitor;
823 }
824
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900825 @Override
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900826 public MultinetworkPolicyTracker createMultinetworkPolicyTracker(
Erik Kline065ab6e2016-10-02 18:02:14 +0900827 Context c, Handler h, Runnable r) {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900828 final WrappedMultinetworkPolicyTracker tracker = new WrappedMultinetworkPolicyTracker(c, h, r);
Erik Kline065ab6e2016-10-02 18:02:14 +0900829 return tracker;
830 }
831
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900832 public WrappedMultinetworkPolicyTracker getMultinetworkPolicyTracker() {
833 return (WrappedMultinetworkPolicyTracker) mMultinetworkPolicyTracker;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900834 }
835
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900836 @Override
Erik Kline065ab6e2016-10-02 18:02:14 +0900837 public WakeupMessage makeWakeupMessage(
838 Context context, Handler handler, String cmdName, int cmd, Object obj) {
839 return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900840 }
841
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +0900842 @Override
843 public boolean hasService(String name) {
844 // Currenty, the only relevant service that ConnectivityService checks for is
845 // ETHERNET_SERVICE.
846 return Context.ETHERNET_SERVICE.equals(name);
847 }
848
Hugo Benichi64901e52017-10-19 14:42:40 +0900849 @Override
850 protected IpConnectivityMetrics.Logger metricsLogger() {
851 return mMetricsService;
852 }
853
Paul Jensencf4c2c62015-07-01 14:16:32 -0400854 public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
855 return mLastCreatedNetworkMonitor;
856 }
857
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900858 public void waitForIdle(int timeoutMs) {
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900859 waitForIdleHandler(mHandlerThread, timeoutMs);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400860 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900861
862 public void waitForIdle() {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900863 waitForIdle(TIMEOUT_MS);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900864 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400865 }
866
Paul Jensen3d911462015-06-12 06:40:24 -0400867 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900868 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
869 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -0400870 */
871 static private void waitFor(ConditionVariable conditionVariable) {
Hugo Benichi16f0a942017-06-20 14:07:59 +0900872 if (conditionVariable.block(TIMEOUT_MS)) {
873 return;
874 }
875 fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
Paul Jensen3d911462015-06-12 06:40:24 -0400876 }
877
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900878 @Before
Paul Jensend7b6ca92015-05-13 14:05:12 -0400879 public void setUp() throws Exception {
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900880 mContext = InstrumentationRegistry.getContext();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400881
Hugo Benichi64901e52017-10-19 14:42:40 +0900882 MockitoAnnotations.initMocks(this);
883 when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
884
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +0900885 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
886 // http://b/25897652 .
887 if (Looper.myLooper() == null) {
888 Looper.prepare();
889 }
890
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900891 mServiceContext = new MockContext(InstrumentationRegistry.getContext());
Hugo Benichi938ab4f2017-02-11 17:04:43 +0900892 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
893 LocalServices.addService(
894 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
Lorenzo Colitti83fa2582015-08-07 12:49:01 +0900895 mService = new WrappedConnectivityService(mServiceContext,
Erik Klinee89953b2018-01-11 16:11:10 +0900896 mNetworkManagementService,
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600897 mStatsService,
Hugo Benichif9fdf872016-07-28 17:53:06 +0900898 mock(INetworkPolicyManager.class),
899 mock(IpConnectivityLog.class));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400900
Paul Jensend7b6ca92015-05-13 14:05:12 -0400901 mService.systemReady();
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900902 mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900903 mCm.bindProcessToNetwork(null);
Calvin On1f64f3f2016-10-11 15:10:46 -0700904
905 // Ensure that the default setting for Captive Portals is used for most tests
906 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +0900907 setMobileDataAlwaysOn(false);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400908 }
909
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900910 @After
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +0900911 public void tearDown() throws Exception {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +0900912 setMobileDataAlwaysOn(false);
Hugo Benichibb91c572017-05-22 10:44:02 +0900913 if (mCellNetworkAgent != null) {
914 mCellNetworkAgent.disconnect();
915 mCellNetworkAgent = null;
916 }
917 if (mWiFiNetworkAgent != null) {
918 mWiFiNetworkAgent.disconnect();
919 mWiFiNetworkAgent = null;
920 }
921 if (mEthernetNetworkAgent != null) {
922 mEthernetNetworkAgent.disconnect();
923 mEthernetNetworkAgent = null;
924 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +0900925 }
926
Hugo Benichibb91c572017-05-22 10:44:02 +0900927 private static int transportToLegacyType(int transport) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400928 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900929 case TRANSPORT_ETHERNET:
930 return TYPE_ETHERNET;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400931 case TRANSPORT_WIFI:
932 return TYPE_WIFI;
933 case TRANSPORT_CELLULAR:
934 return TYPE_MOBILE;
935 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +0900936 return TYPE_NONE;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400937 }
938 }
939
940 private void verifyActiveNetwork(int transport) {
941 // Test getActiveNetworkInfo()
942 assertNotNull(mCm.getActiveNetworkInfo());
943 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
944 // Test getActiveNetwork()
945 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +0000946 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Hugo Benichi16f0a942017-06-20 14:07:59 +0900947 if (!NetworkCapabilities.isValidTransport(transport)) {
948 throw new IllegalStateException("Unknown transport " + transport);
949 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400950 switch (transport) {
951 case TRANSPORT_WIFI:
952 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
953 break;
954 case TRANSPORT_CELLULAR:
955 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
956 break;
957 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +0900958 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400959 }
960 // Test getNetworkInfo(Network)
961 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
Hugo Benichibb91c572017-05-22 10:44:02 +0900962 assertEquals(transportToLegacyType(transport),
963 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
Paul Jensend7b6ca92015-05-13 14:05:12 -0400964 // Test getNetworkCapabilities(Network)
965 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
966 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
967 }
968
969 private void verifyNoNetwork() {
Hugo Benichic1014502017-07-19 10:10:52 +0900970 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400971 // Test getActiveNetworkInfo()
972 assertNull(mCm.getActiveNetworkInfo());
973 // Test getActiveNetwork()
974 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +0000975 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400976 // Test getAllNetworks()
Hugo Benichifed512a2017-06-26 10:06:49 +0900977 assertEmpty(mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -0400978 }
979
980 /**
981 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
982 * broadcasts are received.
983 */
984 private ConditionVariable waitForConnectivityBroadcasts(final int count) {
985 final ConditionVariable cv = new ConditionVariable();
986 mServiceContext.registerReceiver(new BroadcastReceiver() {
987 private int remaining = count;
988 public void onReceive(Context context, Intent intent) {
989 if (--remaining == 0) {
990 cv.open();
991 mServiceContext.unregisterReceiver(this);
992 }
993 }
994 }, new IntentFilter(CONNECTIVITY_ACTION));
995 return cv;
996 }
997
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900998 @Test
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900999 public void testNetworkTypes() {
1000 // Ensure that our mocks for the networkAttributes config variable work as expected. If they
1001 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
1002 // will fail. Failing here is much easier to debug.
1003 assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
1004 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001005 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
1006 assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
1007
1008 // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
1009 // mocks, this assert exercises the ConnectivityService code path that ensures that
1010 // TYPE_ETHERNET is supported if the ethernet service is running.
1011 assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001012 }
1013
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001014 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001015 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001016 verifyNoNetwork();
1017 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1018 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1019 assertNull(mCm.getActiveNetworkInfo());
1020 assertNull(mCm.getActiveNetwork());
1021 // Test bringing up validated cellular.
1022 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1023 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001024 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001025 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichifed512a2017-06-26 10:06:49 +09001026 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001027 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1028 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1029 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
1030 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
1031 // Test bringing up validated WiFi.
1032 cv = waitForConnectivityBroadcasts(2);
1033 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001034 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001035 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001036 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001037 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1038 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1039 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
1040 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
1041 // Test cellular linger timeout.
Lorenzo Colittid2706122017-01-30 17:45:49 +09001042 waitFor(mCellNetworkAgent.getDisconnectedCV());
Hugo Benichibb91c572017-05-22 10:44:02 +09001043 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09001044 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001045 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001046 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001047 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
1048 // Test WiFi disconnect.
1049 cv = waitForConnectivityBroadcasts(1);
1050 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001051 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001052 verifyNoNetwork();
1053 }
1054
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001055 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001056 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
1057 // Test bringing up unvalidated WiFi
1058 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1059 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1060 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001061 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001062 verifyActiveNetwork(TRANSPORT_WIFI);
1063 // Test bringing up unvalidated cellular
1064 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1065 mCellNetworkAgent.connect(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001066 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001067 verifyActiveNetwork(TRANSPORT_WIFI);
1068 // Test cellular disconnect.
1069 mCellNetworkAgent.disconnect();
Hugo Benichibb91c572017-05-22 10:44:02 +09001070 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001071 verifyActiveNetwork(TRANSPORT_WIFI);
1072 // Test bringing up validated cellular
1073 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1074 cv = waitForConnectivityBroadcasts(2);
1075 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001076 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001077 verifyActiveNetwork(TRANSPORT_CELLULAR);
1078 // Test cellular disconnect.
1079 cv = waitForConnectivityBroadcasts(2);
1080 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001081 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001082 verifyActiveNetwork(TRANSPORT_WIFI);
1083 // Test WiFi disconnect.
1084 cv = waitForConnectivityBroadcasts(1);
1085 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001086 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001087 verifyNoNetwork();
1088 }
1089
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001090 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001091 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
1092 // Test bringing up unvalidated cellular.
1093 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1094 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1095 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001096 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001097 verifyActiveNetwork(TRANSPORT_CELLULAR);
1098 // Test bringing up unvalidated WiFi.
1099 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1100 cv = waitForConnectivityBroadcasts(2);
1101 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001102 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001103 verifyActiveNetwork(TRANSPORT_WIFI);
1104 // Test WiFi disconnect.
1105 cv = waitForConnectivityBroadcasts(2);
1106 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001107 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001108 verifyActiveNetwork(TRANSPORT_CELLULAR);
1109 // Test cellular disconnect.
1110 cv = waitForConnectivityBroadcasts(1);
1111 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001112 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001113 verifyNoNetwork();
1114 }
1115
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001116 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001117 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04001118 // Test bringing up unvalidated WiFi.
Paul Jensene0988542015-06-25 15:30:08 -04001119 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001120 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1121 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -04001122 waitFor(cv);
1123 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001124 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001125 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -04001126 // Test bringing up validated cellular.
1127 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001128 cv = waitForConnectivityBroadcasts(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001129 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -04001130 waitFor(cv);
1131 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001132 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1133 NET_CAPABILITY_VALIDATED));
1134 // Test cellular disconnect.
1135 cv = waitForConnectivityBroadcasts(2);
1136 mCellNetworkAgent.disconnect();
1137 waitFor(cv);
1138 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001139 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001140 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001141 NET_CAPABILITY_VALIDATED));
1142 }
1143
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001144 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001145 public void testCellularOutscoresWeakWifi() throws Exception {
1146 // Test bringing up validated cellular.
1147 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1148 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1149 mCellNetworkAgent.connect(true);
1150 waitFor(cv);
1151 verifyActiveNetwork(TRANSPORT_CELLULAR);
1152 // Test bringing up validated WiFi.
1153 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1154 cv = waitForConnectivityBroadcasts(2);
1155 mWiFiNetworkAgent.connect(true);
1156 waitFor(cv);
1157 verifyActiveNetwork(TRANSPORT_WIFI);
1158 // Test WiFi getting really weak.
1159 cv = waitForConnectivityBroadcasts(2);
1160 mWiFiNetworkAgent.adjustScore(-11);
1161 waitFor(cv);
1162 verifyActiveNetwork(TRANSPORT_CELLULAR);
1163 // Test WiFi restoring signal strength.
1164 cv = waitForConnectivityBroadcasts(2);
1165 mWiFiNetworkAgent.adjustScore(11);
1166 waitFor(cv);
1167 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001168 }
1169
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001170 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001171 public void testReapingNetwork() throws Exception {
1172 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1173 // Expect it to be torn down immediately because it satisfies no requests.
1174 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1175 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
1176 mWiFiNetworkAgent.connectWithoutInternet();
1177 waitFor(cv);
1178 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1179 // Expect it to be torn down immediately because it satisfies no requests.
1180 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1181 cv = mCellNetworkAgent.getDisconnectedCV();
1182 mCellNetworkAgent.connectWithoutInternet();
1183 waitFor(cv);
1184 // Test bringing up validated WiFi.
1185 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1186 cv = waitForConnectivityBroadcasts(1);
1187 mWiFiNetworkAgent.connect(true);
1188 waitFor(cv);
1189 verifyActiveNetwork(TRANSPORT_WIFI);
1190 // Test bringing up unvalidated cellular.
1191 // Expect it to be torn down because it could never be the highest scoring network
1192 // satisfying the default request even if it validated.
1193 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1194 cv = mCellNetworkAgent.getDisconnectedCV();
1195 mCellNetworkAgent.connect(false);
1196 waitFor(cv);
1197 verifyActiveNetwork(TRANSPORT_WIFI);
1198 cv = mWiFiNetworkAgent.getDisconnectedCV();
1199 mWiFiNetworkAgent.disconnect();
1200 waitFor(cv);
1201 }
1202
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001203 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001204 public void testCellularFallback() throws Exception {
1205 // Test bringing up validated cellular.
1206 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1207 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1208 mCellNetworkAgent.connect(true);
1209 waitFor(cv);
1210 verifyActiveNetwork(TRANSPORT_CELLULAR);
1211 // Test bringing up validated WiFi.
1212 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1213 cv = waitForConnectivityBroadcasts(2);
1214 mWiFiNetworkAgent.connect(true);
1215 waitFor(cv);
1216 verifyActiveNetwork(TRANSPORT_WIFI);
1217 // Reevaluate WiFi (it'll instantly fail DNS).
1218 cv = waitForConnectivityBroadcasts(2);
1219 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1220 NET_CAPABILITY_VALIDATED));
1221 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1222 // Should quickly fall back to Cellular.
1223 waitFor(cv);
1224 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1225 NET_CAPABILITY_VALIDATED));
1226 verifyActiveNetwork(TRANSPORT_CELLULAR);
1227 // Reevaluate cellular (it'll instantly fail DNS).
1228 cv = waitForConnectivityBroadcasts(2);
1229 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1230 NET_CAPABILITY_VALIDATED));
1231 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1232 // Should quickly fall back to WiFi.
1233 waitFor(cv);
1234 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1235 NET_CAPABILITY_VALIDATED));
1236 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1237 NET_CAPABILITY_VALIDATED));
1238 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001239 }
1240
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001241 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001242 public void testWiFiFallback() throws Exception {
1243 // Test bringing up unvalidated WiFi.
1244 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1245 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1246 mWiFiNetworkAgent.connect(false);
1247 waitFor(cv);
1248 verifyActiveNetwork(TRANSPORT_WIFI);
1249 // Test bringing up validated cellular.
1250 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1251 cv = waitForConnectivityBroadcasts(2);
1252 mCellNetworkAgent.connect(true);
1253 waitFor(cv);
1254 verifyActiveNetwork(TRANSPORT_CELLULAR);
1255 // Reevaluate cellular (it'll instantly fail DNS).
1256 cv = waitForConnectivityBroadcasts(2);
1257 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1258 NET_CAPABILITY_VALIDATED));
1259 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1260 // Should quickly fall back to WiFi.
1261 waitFor(cv);
1262 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1263 NET_CAPABILITY_VALIDATED));
1264 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001265 }
1266
Paul Jensen3d911462015-06-12 06:40:24 -04001267 enum CallbackState {
1268 NONE,
1269 AVAILABLE,
Erik Klineacdd6392016-07-07 16:50:58 +09001270 NETWORK_CAPABILITIES,
1271 LINK_PROPERTIES,
Erik Kline1d3db322017-02-28 16:20:20 +09001272 SUSPENDED,
Paul Jensen3d911462015-06-12 06:40:24 -04001273 LOSING,
Erik Kline3841a482015-11-25 12:49:38 +09001274 LOST,
1275 UNAVAILABLE
Paul Jensen3d911462015-06-12 06:40:24 -04001276 }
1277
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001278 private static class CallbackInfo {
1279 public final CallbackState state;
1280 public final Network network;
1281 public final Object arg;
1282 public CallbackInfo(CallbackState s, Network n, Object o) {
1283 state = s; network = n; arg = o;
1284 }
1285 public String toString() {
Erik Kline1d3db322017-02-28 16:20:20 +09001286 return String.format("%s (%s) (%s)", state, network, arg);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001287 }
1288 @Override
1289 public boolean equals(Object o) {
1290 if (!(o instanceof CallbackInfo)) return false;
1291 // Ignore timeMs, since it's unpredictable.
1292 CallbackInfo other = (CallbackInfo) o;
1293 return (state == other.state) && Objects.equals(network, other.network);
1294 }
1295 @Override
1296 public int hashCode() {
1297 return Objects.hash(state, network);
1298 }
1299 }
1300
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001301 /**
1302 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1303 * this class receives, by calling expectCallback() exactly once each time a callback is
1304 * received. assertNoCallback may be called at any time.
1305 */
Paul Jensen3d911462015-06-12 06:40:24 -04001306 private class TestNetworkCallback extends NetworkCallback {
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001307 // Chosen to be much less than the linger timeout. This ensures that we can distinguish
1308 // between a LOST callback that arrives immediately and a LOST callback that arrives after
1309 // the linger timeout.
Hugo Benichidfb559a2016-12-20 14:57:49 +09001310 private final static int TIMEOUT_MS = 100;
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001311
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001312 private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
1313
Erik Klineacdd6392016-07-07 16:50:58 +09001314 protected void setLastCallback(CallbackState state, Network network, Object o) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001315 mCallbacks.offer(new CallbackInfo(state, network, o));
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001316 }
Paul Jensen3d911462015-06-12 06:40:24 -04001317
Erik Klineacdd6392016-07-07 16:50:58 +09001318 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001319 public void onAvailable(Network network) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001320 setLastCallback(CallbackState.AVAILABLE, network, null);
Paul Jensen3d911462015-06-12 06:40:24 -04001321 }
1322
Erik Klineacdd6392016-07-07 16:50:58 +09001323 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001324 public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
1325 setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
1326 }
1327
1328 @Override
1329 public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
1330 setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
1331 }
1332
1333 @Override
Erik Kline3841a482015-11-25 12:49:38 +09001334 public void onUnavailable() {
1335 setLastCallback(CallbackState.UNAVAILABLE, null, null);
1336 }
1337
1338 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001339 public void onNetworkSuspended(Network network) {
1340 setLastCallback(CallbackState.SUSPENDED, network, null);
1341 }
1342
1343 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001344 public void onLosing(Network network, int maxMsToLive) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001345 setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
Paul Jensen3d911462015-06-12 06:40:24 -04001346 }
1347
Erik Klineacdd6392016-07-07 16:50:58 +09001348 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001349 public void onLost(Network network) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001350 setLastCallback(CallbackState.LOST, network, null);
1351 }
1352
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001353 CallbackInfo nextCallback(int timeoutMs) {
1354 CallbackInfo cb = null;
1355 try {
1356 cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
1357 } catch (InterruptedException e) {
1358 }
1359 if (cb == null) {
1360 // LinkedBlockingQueue.poll() returns null if it timeouts.
1361 fail("Did not receive callback after " + timeoutMs + "ms");
1362 }
1363 return cb;
1364 }
1365
Erik Kline1d3db322017-02-28 16:20:20 +09001366 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs) {
1367 final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null;
1368 CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001369 CallbackInfo actual = nextCallback(timeoutMs);
1370 assertEquals("Unexpected callback:", expected, actual);
Erik Kline1d3db322017-02-28 16:20:20 +09001371
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001372 if (state == CallbackState.LOSING) {
1373 String msg = String.format(
1374 "Invalid linger time value %d, must be between %d and %d",
1375 actual.arg, 0, TEST_LINGER_DELAY_MS);
1376 int maxMsToLive = (Integer) actual.arg;
1377 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= TEST_LINGER_DELAY_MS);
1378 }
Erik Kline1d3db322017-02-28 16:20:20 +09001379
1380 return actual;
Erik Klinea2d29402016-03-16 15:31:39 +09001381 }
1382
Erik Kline1d3db322017-02-28 16:20:20 +09001383 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) {
1384 return expectCallback(state, agent, TIMEOUT_MS);
1385 }
1386
Hugo Benichi16f0a942017-06-20 14:07:59 +09001387 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) {
1388 return expectCallbackLike(fn, TIMEOUT_MS);
1389 }
1390
1391 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs) {
1392 int timeLeft = timeoutMs;
1393 while (timeLeft > 0) {
1394 long start = SystemClock.elapsedRealtime();
1395 CallbackInfo info = nextCallback(timeLeft);
1396 if (fn.test(info)) {
1397 return info;
1398 }
1399 timeLeft -= (SystemClock.elapsedRealtime() - start);
1400 }
1401 fail("Did not receive expected callback after " + timeoutMs + "ms");
1402 return null;
1403 }
1404
Lorenzo Colitti27334542018-01-12 16:22:21 +09001405 // Expects onAvailable and the callbacks that follow it. These are:
1406 // - onSuspended, iff the network was suspended when the callbacks fire.
1407 // - onCapabilitiesChanged.
1408 // - onLinkPropertiesChanged.
1409 //
1410 // @param agent the network to expect the callbacks on.
1411 // @param expectSuspended whether to expect a SUSPENDED callback.
1412 // @param expectValidated the expected value of the VALIDATED capability in the
1413 // onCapabilitiesChanged callback.
1414 // @param timeoutMs how long to wait for the callbacks.
1415 void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended,
1416 boolean expectValidated, int timeoutMs) {
Erik Kline1d3db322017-02-28 16:20:20 +09001417 expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
Erik Klinec75d4fa2017-02-15 19:59:17 +09001418 if (expectSuspended) {
1419 expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001420 }
Lorenzo Colitti27334542018-01-12 16:22:21 +09001421 if (expectValidated) {
1422 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1423 } else {
1424 expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, agent);
1425 }
Erik Klinec75d4fa2017-02-15 19:59:17 +09001426 expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001427 }
1428
Lorenzo Colitti27334542018-01-12 16:22:21 +09001429 // Expects the available callbacks (validated), plus onSuspended.
1430 void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) {
1431 expectAvailableCallbacks(agent, true, expectValidated, TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001432 }
1433
Lorenzo Colitti27334542018-01-12 16:22:21 +09001434 void expectAvailableCallbacksValidated(MockNetworkAgent agent) {
1435 expectAvailableCallbacks(agent, false, true, TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001436 }
1437
Lorenzo Colitti27334542018-01-12 16:22:21 +09001438 void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) {
1439 expectAvailableCallbacks(agent, false, false, TIMEOUT_MS);
1440 }
1441
1442 // Expects the available callbacks (where the onCapabilitiesChanged must contain the
1443 // VALIDATED capability), plus another onCapabilitiesChanged which is identical to the
1444 // one we just sent.
1445 // TODO: this is likely a bug. Fix it and remove this method.
1446 void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) {
1447 expectCallback(CallbackState.AVAILABLE, agent, TIMEOUT_MS);
1448 NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1449 expectCallback(CallbackState.LINK_PROPERTIES, agent, TIMEOUT_MS);
1450 NetworkCapabilities nc2 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1451 assertEquals(nc1, nc2);
1452 }
1453
1454 // Expects the available callbacks where the onCapabilitiesChanged must not have validated,
1455 // then expects another onCapabilitiesChanged that has the validated bit set. This is used
1456 // when a network connects and satisfies a callback, and then immediately validates.
1457 void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) {
1458 expectAvailableCallbacksUnvalidated(agent);
Erik Kline1d3db322017-02-28 16:20:20 +09001459 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1460 }
1461
Lorenzo Colitti27334542018-01-12 16:22:21 +09001462 NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
Erik Kline1d3db322017-02-28 16:20:20 +09001463 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
1464 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1465 assertTrue(nc.hasCapability(capability));
Lorenzo Colitti27334542018-01-12 16:22:21 +09001466 return nc;
Erik Kline1d3db322017-02-28 16:20:20 +09001467 }
1468
Lorenzo Colitti27334542018-01-12 16:22:21 +09001469 NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
Erik Kline1d3db322017-02-28 16:20:20 +09001470 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
1471 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1472 assertFalse(nc.hasCapability(capability));
Lorenzo Colitti27334542018-01-12 16:22:21 +09001473 return nc;
Paul Jensen3d911462015-06-12 06:40:24 -04001474 }
1475
Chalard Jean0b214af2018-01-12 17:22:49 +09001476 void expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent) {
1477 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
1478 assertTrue(fn.test((NetworkCapabilities) cbi.arg));
1479 }
1480
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001481 void assertNoCallback() {
Hugo Benichibb91c572017-05-22 10:44:02 +09001482 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001483 CallbackInfo c = mCallbacks.peek();
1484 assertNull("Unexpected callback: " + c, c);
1485 }
1486 }
1487
1488 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1489 // only be declared in a static or top level type".
1490 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1491 for (TestNetworkCallback c : callbacks) {
1492 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001493 }
1494 }
1495
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001496 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001497 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001498 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001499 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1500 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001501 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1502 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001503 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1504 .addTransportType(TRANSPORT_WIFI).build();
1505 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1506 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001507 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001508 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1509 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1510
1511 // Test unvalidated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001512 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1513 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1514 mCellNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001515 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1516 cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001517 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1518 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001519 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001520
Paul Jensen3d911462015-06-12 06:40:24 -04001521 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1522 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001523 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001524 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001525 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1526
Paul Jensen3d911462015-06-12 06:40:24 -04001527 cv = waitForConnectivityBroadcasts(2);
1528 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1529 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001530 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1531 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001532 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1533 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001534 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001535
Paul Jensen3d911462015-06-12 06:40:24 -04001536 cv = waitForConnectivityBroadcasts(2);
1537 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001538 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1539 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001540 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001541 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001542 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001543
Paul Jensen3d911462015-06-12 06:40:24 -04001544 cv = waitForConnectivityBroadcasts(1);
1545 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001546 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1547 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001548 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001549 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001550
1551 // Test validated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001552 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1553 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001554 genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1555 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001556 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001557 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001558
Paul Jensen3d911462015-06-12 06:40:24 -04001559 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1560 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001561 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001562 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001563 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1564
Paul Jensen3d911462015-06-12 06:40:24 -04001565 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1566 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001567 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001568 genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001569 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001570 wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001571 cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001572 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001573 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001574
Paul Jensen3d911462015-06-12 06:40:24 -04001575 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001576 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1577 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1578 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001579
Paul Jensen3d911462015-06-12 06:40:24 -04001580 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001581 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1582 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1583 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001584 }
1585
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001586 @Test
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001587 public void testMultipleLingering() {
1588 NetworkRequest request = new NetworkRequest.Builder()
1589 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1590 .build();
1591 TestNetworkCallback callback = new TestNetworkCallback();
1592 mCm.registerNetworkCallback(request, callback);
1593
1594 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1595 mCm.registerDefaultNetworkCallback(defaultCallback);
1596
1597 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1598 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1599 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
1600
1601 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1602 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1603 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1604
1605 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001606 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1607 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001608 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1609
1610 mWiFiNetworkAgent.connect(true);
1611 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1612 // We then get LOSING when wifi validates and cell is outscored.
Lorenzo Colitti27334542018-01-12 16:22:21 +09001613 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001614 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001615 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001616 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001617 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001618 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1619
1620 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001621 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001622 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001623 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001624 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001625 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001626 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1627
1628 mEthernetNetworkAgent.disconnect();
1629 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1630 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001631 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001632
1633 for (int i = 0; i < 4; i++) {
1634 MockNetworkAgent oldNetwork, newNetwork;
1635 if (i % 2 == 0) {
1636 mWiFiNetworkAgent.adjustScore(-15);
1637 oldNetwork = mWiFiNetworkAgent;
1638 newNetwork = mCellNetworkAgent;
1639 } else {
1640 mWiFiNetworkAgent.adjustScore(15);
1641 oldNetwork = mCellNetworkAgent;
1642 newNetwork = mWiFiNetworkAgent;
1643
1644 }
1645 callback.expectCallback(CallbackState.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001646 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1647 // longer lingering?
Lorenzo Colitti27334542018-01-12 16:22:21 +09001648 defaultCallback.expectAvailableCallbacksValidated(newNetwork);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001649 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
1650 }
1651 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1652
1653 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
1654 // if the network is still up.
1655 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
Erik Kline1d3db322017-02-28 16:20:20 +09001656 // We expect a notification about the capabilities change, and nothing else.
1657 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
1658 defaultCallback.assertNoCallback();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001659 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1660
1661 // Wifi no longer satisfies our listen, which is for an unmetered network.
1662 // But because its score is 55, it's still up (and the default network).
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001663 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1664
1665 // Disconnect our test networks.
1666 mWiFiNetworkAgent.disconnect();
1667 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001668 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001669 mCellNetworkAgent.disconnect();
1670 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1671
1672 mCm.unregisterNetworkCallback(callback);
Hugo Benichibb91c572017-05-22 10:44:02 +09001673 waitForIdle();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001674
1675 // Check that a network is only lingered or torn down if it would not satisfy a request even
1676 // if it validated.
1677 request = new NetworkRequest.Builder().clearCapabilities().build();
1678 callback = new TestNetworkCallback();
1679
1680 mCm.registerNetworkCallback(request, callback);
1681
1682 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1683 mCellNetworkAgent.connect(false); // Score: 10
Lorenzo Colitti27334542018-01-12 16:22:21 +09001684 callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1685 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001686 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1687
1688 // Bring up wifi with a score of 20.
1689 // Cell stays up because it would satisfy the default request if it validated.
1690 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1691 mWiFiNetworkAgent.connect(false); // Score: 20
Lorenzo Colitti27334542018-01-12 16:22:21 +09001692 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1693 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001694 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1695
1696 mWiFiNetworkAgent.disconnect();
1697 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1698 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001699 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001700 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1701
1702 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001703 // Cell is lingered because it would not satisfy any request, even if it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001704 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1705 mWiFiNetworkAgent.adjustScore(50);
1706 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti27334542018-01-12 16:22:21 +09001707 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001708 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001709 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001710 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1711
1712 // Tear down wifi.
1713 mWiFiNetworkAgent.disconnect();
1714 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1715 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001716 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001717 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1718
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001719 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
1720 // it's arguably correct to linger it, since it was the default network before it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001721 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1722 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001723 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001724 // TODO: Investigate sending validated before losing.
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001725 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001726 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001727 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001728 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1729
1730 mWiFiNetworkAgent.disconnect();
1731 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001732 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001733 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001734 mCellNetworkAgent.disconnect();
1735 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1736 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001737
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001738 // If a network is lingering, and we add and remove a request from it, resume lingering.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001739 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1740 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001741 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1742 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001743 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1744 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001745 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
1746 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001747 // TODO: Investigate sending validated before losing.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001748 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001749 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001750
1751 NetworkRequest cellRequest = new NetworkRequest.Builder()
1752 .addTransportType(TRANSPORT_CELLULAR).build();
1753 NetworkCallback noopCallback = new NetworkCallback();
1754 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001755 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
1756 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001757 mCm.unregisterNetworkCallback(noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001758 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001759
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001760 // Similar to the above: lingering can start even after the lingered request is removed.
1761 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001762 mWiFiNetworkAgent.disconnect();
1763 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001764 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001765 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001766
1767 // Cell is now the default network. Pin it with a cell-specific request.
1768 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
1769 mCm.requestNetwork(cellRequest, noopCallback);
1770
1771 // Now connect wifi, and expect it to become the default network.
1772 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1773 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001774 callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
1775 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001776 // The default request is lingering on cell, but nothing happens to cell, and we send no
1777 // callbacks for it, because it's kept up by cellRequest.
1778 callback.assertNoCallback();
1779 // Now unregister cellRequest and expect cell to start lingering.
1780 mCm.unregisterNetworkCallback(noopCallback);
1781 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1782
1783 // Let linger run its course.
1784 callback.assertNoCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09001785 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
1786 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001787
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001788 // Register a TRACK_DEFAULT request and check that it does not affect lingering.
1789 TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
1790 mCm.registerDefaultNetworkCallback(trackDefaultCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001791 trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001792 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
1793 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001794 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001795 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
1796 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001797 trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
1798 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001799
1800 // Let linger run its course.
1801 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
1802
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001803 // Clean up.
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001804 mEthernetNetworkAgent.disconnect();
1805 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1806 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1807 trackDefaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001808
1809 mCm.unregisterNetworkCallback(callback);
1810 mCm.unregisterNetworkCallback(defaultCallback);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001811 mCm.unregisterNetworkCallback(trackDefaultCallback);
1812 }
1813
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001814 @Test
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001815 public void testExplicitlySelected() {
1816 NetworkRequest request = new NetworkRequest.Builder()
1817 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
1818 .build();
1819 TestNetworkCallback callback = new TestNetworkCallback();
1820 mCm.registerNetworkCallback(request, callback);
1821
1822 // Bring up validated cell.
1823 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1824 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001825 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001826
1827 // Bring up unvalidated wifi with explicitlySelected=true.
1828 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1829 mWiFiNetworkAgent.explicitlySelected(false);
1830 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001831 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001832
1833 // Cell Remains the default.
1834 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1835
1836 // Lower wifi's score to below than cell, and check that it doesn't disconnect because
1837 // it's explicitly selected.
1838 mWiFiNetworkAgent.adjustScore(-40);
1839 mWiFiNetworkAgent.adjustScore(40);
1840 callback.assertNoCallback();
1841
1842 // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
1843 // wifi even though it's unvalidated.
1844 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
1845 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1846 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1847
1848 // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
1849 mWiFiNetworkAgent.disconnect();
1850 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1851 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1852 mWiFiNetworkAgent.explicitlySelected(false);
1853 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001854 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001855
1856 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
1857 // network to disconnect.
1858 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
1859 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1860
1861 // Reconnect, again with explicitlySelected=true, but this time validate.
1862 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1863 mWiFiNetworkAgent.explicitlySelected(false);
1864 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001865 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001866 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1867 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
1868 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1869
1870 // BUG: the network will no longer linger, even though it's validated and outscored.
1871 // TODO: fix this.
1872 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
1873 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001874 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001875 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1876 callback.assertNoCallback();
1877
1878 // Clean up.
1879 mWiFiNetworkAgent.disconnect();
1880 mCellNetworkAgent.disconnect();
1881 mEthernetNetworkAgent.disconnect();
1882
1883 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1884 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1885 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001886 }
1887
Paul Jensen85cf78e2015-06-25 13:25:07 -04001888 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04001889 // Verify NOT_RESTRICTED is set appropriately
1890 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
1891 .build().networkCapabilities;
1892 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
1893 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
1894 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04001895 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04001896 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1897 } else {
1898 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1899 }
1900
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001901 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001902 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001903 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
1904 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04001905 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001906 mServiceContext, "testFactory", filter);
1907 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04001908 ConditionVariable cv = testFactory.getNetworkStartedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001909 testFactory.expectAddRequests(1);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001910 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001911 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001912 int expectedRequestCount = 1;
1913 NetworkCallback networkCallback = null;
1914 // For non-INTERNET capabilities we cannot rely on the default request being present, so
1915 // add one.
1916 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04001917 assertFalse(testFactory.getMyStartRequested());
1918 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
1919 networkCallback = new NetworkCallback();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001920 testFactory.expectAddRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001921 mCm.requestNetwork(request, networkCallback);
1922 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001923 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001924 }
Paul Jensen3d911462015-06-12 06:40:24 -04001925 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001926 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1927 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001928
Paul Jensen85cf78e2015-06-25 13:25:07 -04001929 // Now bring in a higher scored network.
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001930 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001931 // Rather than create a validated network which complicates things by registering it's
1932 // own NetworkRequest during startup, just bump up the score to cancel out the
1933 // unvalidated penalty.
1934 testAgent.adjustScore(40);
1935 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001936
1937 // When testAgent connects, ConnectivityService will re-send us all current requests with
1938 // the new score. There are expectedRequestCount such requests, and we must wait for all of
1939 // them.
1940 testFactory.expectAddRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001941 testAgent.connect(false);
1942 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04001943 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001944 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001945 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001946
Paul Jensen85cf78e2015-06-25 13:25:07 -04001947 // Bring in a bunch of requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001948 testFactory.expectAddRequests(10);
1949 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001950 ConnectivityManager.NetworkCallback[] networkCallbacks =
1951 new ConnectivityManager.NetworkCallback[10];
1952 for (int i = 0; i< networkCallbacks.length; i++) {
1953 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
1954 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001955 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001956 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
1957 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04001958 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
1959 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001960
Paul Jensen85cf78e2015-06-25 13:25:07 -04001961 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001962 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001963 for (int i = 0; i < networkCallbacks.length; i++) {
1964 mCm.unregisterNetworkCallback(networkCallbacks[i]);
1965 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04001966 testFactory.waitForNetworkRequests(expectedRequestCount);
1967 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001968
Paul Jensen85cf78e2015-06-25 13:25:07 -04001969 // Drop the higher scored network.
1970 cv = testFactory.getNetworkStartedCV();
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001971 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001972 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04001973 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1974 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001975
1976 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04001977 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001978 handlerThread.quit();
1979 }
1980
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001981 @Test
Paul Jensen85cf78e2015-06-25 13:25:07 -04001982 public void testNetworkFactoryRequests() throws Exception {
1983 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
1984 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
1985 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
1986 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
1987 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
1988 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
1989 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
1990 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
1991 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
1992 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
1993 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
1994 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
1995 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
1996 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
1997 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
1998 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
1999 }
2000
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002001 @Test
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002002 public void testNoMutableNetworkRequests() throws Exception {
2003 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
Hugo Benichi16f0a942017-06-20 14:07:59 +09002004 NetworkRequest request1 = new NetworkRequest.Builder()
2005 .addCapability(NET_CAPABILITY_VALIDATED)
2006 .build();
2007 NetworkRequest request2 = new NetworkRequest.Builder()
2008 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
2009 .build();
2010
2011 Class<IllegalArgumentException> expected = IllegalArgumentException.class;
2012 assertException(() -> { mCm.requestNetwork(request1, new NetworkCallback()); }, expected);
2013 assertException(() -> { mCm.requestNetwork(request1, pendingIntent); }, expected);
2014 assertException(() -> { mCm.requestNetwork(request2, new NetworkCallback()); }, expected);
2015 assertException(() -> { mCm.requestNetwork(request2, pendingIntent); }, expected);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002016 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002017
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002018 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002019 public void testMMSonWiFi() throws Exception {
2020 // Test bringing up cellular without MMS NetworkRequest gets reaped
2021 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2022 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2023 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
2024 mCellNetworkAgent.connectWithoutInternet();
2025 waitFor(cv);
Hugo Benichibb91c572017-05-22 10:44:02 +09002026 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09002027 assertEmpty(mCm.getAllNetworks());
Paul Jensene0988542015-06-25 15:30:08 -04002028 verifyNoNetwork();
Hugo Benichibb91c572017-05-22 10:44:02 +09002029
Paul Jensene0988542015-06-25 15:30:08 -04002030 // Test bringing up validated WiFi.
2031 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2032 cv = waitForConnectivityBroadcasts(1);
2033 mWiFiNetworkAgent.connect(true);
2034 waitFor(cv);
2035 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002036
Paul Jensene0988542015-06-25 15:30:08 -04002037 // Register MMS NetworkRequest
2038 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2039 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2040 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2041 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002042
Paul Jensene0988542015-06-25 15:30:08 -04002043 // Test bringing up unvalidated cellular with MMS
2044 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2045 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002046 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002047 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002048 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002049
Paul Jensene0988542015-06-25 15:30:08 -04002050 // Test releasing NetworkRequest disconnects cellular with MMS
2051 cv = mCellNetworkAgent.getDisconnectedCV();
2052 mCm.unregisterNetworkCallback(networkCallback);
2053 waitFor(cv);
2054 verifyActiveNetwork(TRANSPORT_WIFI);
2055 }
2056
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002057 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002058 public void testMMSonCell() throws Exception {
2059 // Test bringing up cellular without MMS
2060 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2061 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2062 mCellNetworkAgent.connect(false);
2063 waitFor(cv);
2064 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002065
Paul Jensene0988542015-06-25 15:30:08 -04002066 // Register MMS NetworkRequest
2067 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2068 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2069 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2070 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002071
Paul Jensene0988542015-06-25 15:30:08 -04002072 // Test bringing up MMS cellular network
Paul Jensene0988542015-06-25 15:30:08 -04002073 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2074 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2075 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002076 networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002077 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002078
Paul Jensene0988542015-06-25 15:30:08 -04002079 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
2080 cv = mmsNetworkAgent.getDisconnectedCV();
2081 mCm.unregisterNetworkCallback(networkCallback);
2082 waitFor(cv);
2083 verifyActiveNetwork(TRANSPORT_CELLULAR);
2084 }
2085
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002086 @Test
Paul Jensencf4c2c62015-07-01 14:16:32 -04002087 public void testCaptivePortal() {
2088 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2089 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2090 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2091 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2092
2093 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2094 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2095 .addCapability(NET_CAPABILITY_VALIDATED).build();
2096 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002097
2098 // Bring up a network with a captive portal.
2099 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002100 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002101 String firstRedirectUrl = "http://example.com/firstPath";
2102 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002103 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002104 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002105
2106 // Take down network.
2107 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002108 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002109 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002110
2111 // Bring up a network with a captive portal.
2112 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002113 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002114 String secondRedirectUrl = "http://example.com/secondPath";
2115 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002116 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002117 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002118
2119 // Make captive portal disappear then revalidate.
2120 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002121 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
2122 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002123 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002124
2125 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002126 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002127
2128 // Break network connectivity.
2129 // Expect NET_CAPABILITY_VALIDATED onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002130 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
2131 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002132 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002133 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002134
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002135 @Test
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002136 public void testCaptivePortalApp() {
2137 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2138 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2139 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2140 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2141
2142 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2143 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2144 .addCapability(NET_CAPABILITY_VALIDATED).build();
2145 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2146
2147 // Bring up wifi.
2148 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2149 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002150 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002151 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2152
2153 // Check that calling startCaptivePortalApp does nothing.
2154 final int fastTimeoutMs = 100;
2155 mCm.startCaptivePortalApp(wifiNetwork);
2156 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
2157
2158 // Turn into a captive portal.
2159 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 302;
2160 mCm.reportNetworkConnectivity(wifiNetwork, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002161 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002162 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2163
2164 // Check that startCaptivePortalApp sends the expected intent.
2165 mCm.startCaptivePortalApp(wifiNetwork);
2166 Intent intent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
2167 assertEquals(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN, intent.getAction());
2168 assertEquals(wifiNetwork, intent.getExtra(ConnectivityManager.EXTRA_NETWORK));
2169
2170 // Have the app report that the captive portal is dismissed, and check that we revalidate.
2171 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
2172 CaptivePortal c = (CaptivePortal) intent.getExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
2173 c.reportCaptivePortalDismissed();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002174 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002175 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2176
2177 mCm.unregisterNetworkCallback(validatedCallback);
2178 mCm.unregisterNetworkCallback(captivePortalCallback);
2179 }
2180
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002181 @Test
Calvin On1f64f3f2016-10-11 15:10:46 -07002182 public void testAvoidOrIgnoreCaptivePortals() {
2183 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2184 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2185 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2186 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2187
2188 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2189 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2190 .addCapability(NET_CAPABILITY_VALIDATED).build();
2191 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2192
2193 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
2194 // Bring up a network with a captive portal.
2195 // Expect it to fail to connect and not result in any callbacks.
2196 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2197 String firstRedirectUrl = "http://example.com/firstPath";
2198
2199 ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
2200 ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
2201 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
2202 waitFor(disconnectCv);
2203 waitFor(avoidCv);
2204
2205 assertNoCallbacks(captivePortalCallback, validatedCallback);
2206
2207 // Now test ignore mode.
2208 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE);
2209
2210 // Bring up a network with a captive portal.
2211 // Since we're ignoring captive portals, the network will validate.
2212 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2213 String secondRedirectUrl = "http://example.com/secondPath";
2214 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
2215
2216 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002217 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Calvin On1f64f3f2016-10-11 15:10:46 -07002218 // But there should be no CaptivePortal callback.
2219 captivePortalCallback.assertNoCallback();
2220 }
2221
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002222 private NetworkRequest.Builder newWifiRequestBuilder() {
2223 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
2224 }
2225
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002226 @Test
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002227 public void testNetworkSpecifier() {
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002228 NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
Etan Cohena7434272017-04-03 12:17:51 -07002229 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002230 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
Etan Cohena7434272017-04-03 12:17:51 -07002231 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
2232 (NetworkSpecifier) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002233 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier("foo").build();
Etan Cohena7434272017-04-03 12:17:51 -07002234 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
2235 new StringNetworkSpecifier("bar")).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002236
2237 TestNetworkCallback cEmpty1 = new TestNetworkCallback();
2238 TestNetworkCallback cEmpty2 = new TestNetworkCallback();
2239 TestNetworkCallback cEmpty3 = new TestNetworkCallback();
Etan Cohena7434272017-04-03 12:17:51 -07002240 TestNetworkCallback cEmpty4 = new TestNetworkCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002241 TestNetworkCallback cFoo = new TestNetworkCallback();
2242 TestNetworkCallback cBar = new TestNetworkCallback();
2243 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
2244 cEmpty1, cEmpty2, cEmpty3 };
2245
2246 mCm.registerNetworkCallback(rEmpty1, cEmpty1);
2247 mCm.registerNetworkCallback(rEmpty2, cEmpty2);
2248 mCm.registerNetworkCallback(rEmpty3, cEmpty3);
Etan Cohena7434272017-04-03 12:17:51 -07002249 mCm.registerNetworkCallback(rEmpty4, cEmpty4);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002250 mCm.registerNetworkCallback(rFoo, cFoo);
2251 mCm.registerNetworkCallback(rBar, cBar);
2252
2253 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2254 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002255 cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2256 cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2257 cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2258 cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002259 assertNoCallbacks(cFoo, cBar);
2260
Etan Cohena7434272017-04-03 12:17:51 -07002261 mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("foo"));
Lorenzo Colitti27334542018-01-12 16:22:21 +09002262 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002263 for (TestNetworkCallback c: emptyCallbacks) {
2264 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
2265 }
2266 cFoo.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
2267 cFoo.assertNoCallback();
2268
Etan Cohena7434272017-04-03 12:17:51 -07002269 mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("bar"));
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002270 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002271 cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002272 for (TestNetworkCallback c: emptyCallbacks) {
2273 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
2274 }
2275 cBar.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
2276 cBar.assertNoCallback();
2277
2278 mWiFiNetworkAgent.setNetworkSpecifier(null);
2279 cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2280 for (TestNetworkCallback c: emptyCallbacks) {
2281 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
2282 }
2283
2284 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cFoo, cBar);
2285 }
2286
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002287 @Test
Etan Cohenddb9ef02015-11-18 10:56:15 -08002288 public void testInvalidNetworkSpecifier() {
Etan Cohenddb9ef02015-11-18 10:56:15 -08002289 try {
2290 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Etan Cohena7434272017-04-03 12:17:51 -07002291 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
2292 fail("NetworkRequest builder with MatchAllNetworkSpecifier");
2293 } catch (IllegalArgumentException expected) {
2294 // expected
Etan Cohenddb9ef02015-11-18 10:56:15 -08002295 }
2296
Etan Cohenddb9ef02015-11-18 10:56:15 -08002297 try {
2298 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
2299 networkCapabilities.addTransportType(TRANSPORT_WIFI)
Etan Cohena7434272017-04-03 12:17:51 -07002300 .setNetworkSpecifier(new MatchAllNetworkSpecifier());
Etan Cohenddb9ef02015-11-18 10:56:15 -08002301 mService.requestNetwork(networkCapabilities, null, 0, null,
2302 ConnectivityManager.TYPE_WIFI);
Etan Cohena7434272017-04-03 12:17:51 -07002303 fail("ConnectivityService requestNetwork with MatchAllNetworkSpecifier");
2304 } catch (IllegalArgumentException expected) {
2305 // expected
Etan Cohenddb9ef02015-11-18 10:56:15 -08002306 }
2307
Etan Cohena7434272017-04-03 12:17:51 -07002308 class NonParcelableSpecifier extends NetworkSpecifier {
2309 public boolean satisfiedBy(NetworkSpecifier other) { return false; }
2310 };
2311 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
2312 @Override public int describeContents() { return 0; }
2313 @Override public void writeToParcel(Parcel p, int flags) {}
2314 }
2315 NetworkRequest.Builder builder;
2316
2317 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
2318 try {
2319 builder.setNetworkSpecifier(new NonParcelableSpecifier());
2320 Parcel parcelW = Parcel.obtain();
2321 builder.build().writeToParcel(parcelW, 0);
2322 fail("Parceling a non-parcelable specifier did not throw an exception");
2323 } catch (Exception e) {
2324 // expected
2325 }
2326
2327 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
2328 builder.setNetworkSpecifier(new ParcelableSpecifier());
2329 NetworkRequest nr = builder.build();
2330 assertNotNull(nr);
2331
2332 try {
2333 Parcel parcelW = Parcel.obtain();
2334 nr.writeToParcel(parcelW, 0);
2335 byte[] bytes = parcelW.marshall();
2336 parcelW.recycle();
2337
2338 Parcel parcelR = Parcel.obtain();
2339 parcelR.unmarshall(bytes, 0, bytes.length);
2340 parcelR.setDataPosition(0);
2341 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
2342 fail("Unparceling a non-framework NetworkSpecifier did not throw an exception");
2343 } catch (Exception e) {
2344 // expected
2345 }
Etan Cohenddb9ef02015-11-18 10:56:15 -08002346 }
2347
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002348 @Test
Etan Cohen859748f2017-04-03 17:42:34 -07002349 public void testNetworkSpecifierUidSpoofSecurityException() {
2350 class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2351 @Override
2352 public boolean satisfiedBy(NetworkSpecifier other) {
2353 return true;
2354 }
2355
2356 @Override
2357 public void assertValidFromUid(int requestorUid) {
2358 throw new SecurityException("failure");
2359 }
2360
2361 @Override
2362 public int describeContents() { return 0; }
2363 @Override
2364 public void writeToParcel(Parcel dest, int flags) {}
2365 }
2366
2367 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2368 mWiFiNetworkAgent.connect(false);
2369
2370 UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
2371 NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier(
2372 networkSpecifier).build();
2373 TestNetworkCallback networkCallback = new TestNetworkCallback();
2374 try {
2375 mCm.requestNetwork(networkRequest, networkCallback);
2376 fail("Network request with spoofed UID did not throw a SecurityException");
2377 } catch (SecurityException e) {
2378 // expected
2379 }
2380 }
2381
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002382 @Test
Erik Klinea2d29402016-03-16 15:31:39 +09002383 public void testRegisterDefaultNetworkCallback() throws Exception {
2384 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
2385 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
2386 defaultNetworkCallback.assertNoCallback();
2387
2388 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
2389 // whenever Wi-Fi is up. Without this, the mobile network agent is
2390 // reaped before any other activity can take place.
2391 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2392 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2393 .addTransportType(TRANSPORT_CELLULAR).build();
2394 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2395 cellNetworkCallback.assertNoCallback();
2396
2397 // Bring up cell and expect CALLBACK_AVAILABLE.
2398 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2399 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002400 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2401 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002402
2403 // Bring up wifi and expect CALLBACK_AVAILABLE.
2404 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2405 mWiFiNetworkAgent.connect(true);
2406 cellNetworkCallback.assertNoCallback();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002407 defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002408
2409 // Bring down cell. Expect no default network callback, since it wasn't the default.
2410 mCellNetworkAgent.disconnect();
2411 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2412 defaultNetworkCallback.assertNoCallback();
2413
2414 // Bring up cell. Expect no default network callback, since it won't be the default.
2415 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2416 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002417 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002418 defaultNetworkCallback.assertNoCallback();
2419
2420 // Bring down wifi. Expect the default network callback to notified of LOST wifi
2421 // followed by AVAILABLE cell.
2422 mWiFiNetworkAgent.disconnect();
2423 cellNetworkCallback.assertNoCallback();
2424 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002425 defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002426 mCellNetworkAgent.disconnect();
2427 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2428 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2429 }
2430
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002431 @Test
Erik Kline1d3db322017-02-28 16:20:20 +09002432 public void testAdditionalStateCallbacks() throws Exception {
Erik Klineacdd6392016-07-07 16:50:58 +09002433 // File a network request for mobile.
Erik Kline1d3db322017-02-28 16:20:20 +09002434 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09002435 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2436 .addTransportType(TRANSPORT_CELLULAR).build();
2437 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2438
2439 // Bring up the mobile network.
2440 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2441 mCellNetworkAgent.connect(true);
2442
Erik Kline1d3db322017-02-28 16:20:20 +09002443 // We should get onAvailable(), onCapabilitiesChanged(), and
2444 // onLinkPropertiesChanged() in rapid succession. Additionally, we
2445 // should get onCapabilitiesChanged() when the mobile network validates.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002446 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09002447 cellNetworkCallback.assertNoCallback();
2448
2449 // Update LinkProperties.
2450 final LinkProperties lp = new LinkProperties();
2451 lp.setInterfaceName("foonet_data0");
2452 mCellNetworkAgent.sendLinkProperties(lp);
2453 // We should get onLinkPropertiesChanged().
2454 cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
2455 cellNetworkCallback.assertNoCallback();
2456
Erik Kline1d3db322017-02-28 16:20:20 +09002457 // Suspend the network.
2458 mCellNetworkAgent.suspend();
2459 cellNetworkCallback.expectCallback(CallbackState.SUSPENDED, mCellNetworkAgent);
2460 cellNetworkCallback.assertNoCallback();
2461
Erik Klineacdd6392016-07-07 16:50:58 +09002462 // Register a garden variety default network request.
Erik Kline1d3db322017-02-28 16:20:20 +09002463 final TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09002464 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09002465 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
2466 // as well as onNetworkSuspended() in rapid succession.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002467 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
Erik Klineacdd6392016-07-07 16:50:58 +09002468 dfltNetworkCallback.assertNoCallback();
2469
Erik Klineacdd6392016-07-07 16:50:58 +09002470 mCm.unregisterNetworkCallback(dfltNetworkCallback);
2471 mCm.unregisterNetworkCallback(cellNetworkCallback);
2472 }
2473
Calvin On1f64f3f2016-10-11 15:10:46 -07002474 private void setCaptivePortalMode(int mode) {
2475 ContentResolver cr = mServiceContext.getContentResolver();
2476 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
2477 }
2478
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002479 private void setMobileDataAlwaysOn(boolean enable) {
2480 ContentResolver cr = mServiceContext.getContentResolver();
2481 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
2482 mService.updateMobileDataAlwaysOn();
Hugo Benichibb91c572017-05-22 10:44:02 +09002483 waitForIdle();
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002484 }
2485
2486 private boolean isForegroundNetwork(MockNetworkAgent network) {
2487 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
2488 assertNotNull(nc);
2489 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
2490 }
2491
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002492 @Test
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002493 public void testBackgroundNetworks() throws Exception {
2494 // Create a background request. We can't do this ourselves because ConnectivityService
2495 // doesn't have an API for it. So just turn on mobile data always on.
2496 setMobileDataAlwaysOn(true);
2497 final NetworkRequest request = new NetworkRequest.Builder().build();
2498 final NetworkRequest fgRequest = new NetworkRequest.Builder()
2499 .addCapability(NET_CAPABILITY_FOREGROUND).build();
2500 final TestNetworkCallback callback = new TestNetworkCallback();
2501 final TestNetworkCallback fgCallback = new TestNetworkCallback();
2502 mCm.registerNetworkCallback(request, callback);
2503 mCm.registerNetworkCallback(fgRequest, fgCallback);
2504
2505 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2506 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002507 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2508 fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002509 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2510
2511 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2512 mWiFiNetworkAgent.connect(true);
2513
2514 // When wifi connects, cell lingers.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002515 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002516 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002517 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002518 fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002519 fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002520 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002521 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2522 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2523
2524 // When lingering is complete, cell is still there but is now in the background.
Hugo Benichibb91c572017-05-22 10:44:02 +09002525 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09002526 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2527 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09002528 // Expect a network capabilities update sans FOREGROUND.
2529 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002530 assertFalse(isForegroundNetwork(mCellNetworkAgent));
2531 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2532
2533 // File a cell request and check that cell comes into the foreground.
2534 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2535 .addTransportType(TRANSPORT_CELLULAR).build();
2536 final TestNetworkCallback cellCallback = new TestNetworkCallback();
2537 mCm.requestNetwork(cellRequest, cellCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09002538 // NOTE: This request causes the network's capabilities to change. This
2539 // is currently delivered before the onAvailable() callbacks.
2540 // TODO: Fix this.
2541 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002542 cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
2543 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002544 // Expect a network capabilities update with FOREGROUND, because the most recent
2545 // request causes its state to change.
2546 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002547 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2548 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2549
2550 // Release the request. The network immediately goes into the background, since it was not
2551 // lingering.
2552 mCm.unregisterNetworkCallback(cellCallback);
2553 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002554 // Expect a network capabilities update sans FOREGROUND.
2555 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002556 assertFalse(isForegroundNetwork(mCellNetworkAgent));
2557 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2558
2559 // Disconnect wifi and check that cell is foreground again.
2560 mWiFiNetworkAgent.disconnect();
2561 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2562 fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002563 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002564 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2565
2566 mCm.unregisterNetworkCallback(callback);
2567 mCm.unregisterNetworkCallback(fgCallback);
2568 }
2569
Hugo Benichi849b81b2017-05-25 13:42:31 +09002570 @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09002571 public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002572 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002573 // Benchmarks connecting and switching performance in the presence of a large number of
2574 // NetworkRequests.
2575 // 1. File NUM_REQUESTS requests.
2576 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
2577 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
2578 // and NUM_REQUESTS onAvailable callbacks to fire.
2579 // See how long it took.
2580 final int NUM_REQUESTS = 90;
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09002581 final int REGISTER_TIME_LIMIT_MS = 200;
2582 final int CONNECT_TIME_LIMIT_MS = 60;
2583 final int SWITCH_TIME_LIMIT_MS = 60;
Hugo Benichibb91c572017-05-22 10:44:02 +09002584 final int UNREGISTER_TIME_LIMIT_MS = 20;
2585
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002586 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
2587 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
2588 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
2589 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
2590
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002591 for (int i = 0; i < NUM_REQUESTS; i++) {
2592 callbacks[i] = new NetworkCallback() {
2593 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
2594 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
2595 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002596 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002597
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002598 assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
2599 for (NetworkCallback cb : callbacks) {
2600 mCm.registerNetworkCallback(request, cb);
2601 }
2602 });
2603
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002604 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2605 // Don't request that the network validate, because otherwise connect() will block until
2606 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
2607 // and we won't actually measure anything.
2608 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002609
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002610 long onAvailableDispatchingDuration = durationOf(() -> {
Hugo Benichibb91c572017-05-22 10:44:02 +09002611 awaitLatch(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002612 });
Hugo Benichibb91c572017-05-22 10:44:02 +09002613 Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
2614 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
2615 onAvailableDispatchingDuration));
2616 assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
2617 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
2618 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002619
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002620 // Give wifi a high enough score that we'll linger cell when wifi comes up.
Hugo Benichibb91c572017-05-22 10:44:02 +09002621 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002622 mWiFiNetworkAgent.adjustScore(40);
2623 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002624
2625 long onLostDispatchingDuration = durationOf(() -> {
Hugo Benichibb91c572017-05-22 10:44:02 +09002626 awaitLatch(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002627 });
Hugo Benichibb91c572017-05-22 10:44:02 +09002628 Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
2629 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
2630 assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
2631 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
2632 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002633
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002634 assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
2635 for (NetworkCallback cb : callbacks) {
2636 mCm.unregisterNetworkCallback(cb);
2637 }
2638 });
2639 }
2640
2641 private long durationOf(Runnable fn) {
2642 long startTime = SystemClock.elapsedRealtime();
2643 fn.run();
2644 return SystemClock.elapsedRealtime() - startTime;
2645 }
2646
2647 private void assertTimeLimit(String descr, long timeLimit, Runnable fn) {
2648 long timeTaken = durationOf(fn);
2649 String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002650 Log.d(TAG, msg);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002651 assertTrue(msg, timeTaken <= timeLimit);
2652 }
2653
2654 private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
2655 try {
Hugo Benichibb91c572017-05-22 10:44:02 +09002656 return l.await(timeoutMs, TimeUnit.MILLISECONDS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002657 } catch (InterruptedException e) {}
2658 return false;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002659 }
2660
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002661 @Test
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002662 public void testMobileDataAlwaysOn() throws Exception {
2663 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2664 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2665 .addTransportType(TRANSPORT_CELLULAR).build();
2666 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
2667
2668 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
2669 handlerThread.start();
2670 NetworkCapabilities filter = new NetworkCapabilities()
2671 .addTransportType(TRANSPORT_CELLULAR)
2672 .addCapability(NET_CAPABILITY_INTERNET);
2673 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
2674 mServiceContext, "testFactory", filter);
2675 testFactory.setScoreFilter(40);
2676
2677 // Register the factory and expect it to start looking for a network.
2678 testFactory.expectAddRequests(1);
2679 testFactory.register();
2680 testFactory.waitForNetworkRequests(1);
2681 assertTrue(testFactory.getMyStartRequested());
2682
2683 // Bring up wifi. The factory stops looking for a network.
2684 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2685 testFactory.expectAddRequests(2); // Because the default request changes score twice.
2686 mWiFiNetworkAgent.connect(true);
2687 testFactory.waitForNetworkRequests(1);
2688 assertFalse(testFactory.getMyStartRequested());
2689
2690 ContentResolver cr = mServiceContext.getContentResolver();
2691
2692 // Turn on mobile data always on. The factory starts looking again.
2693 testFactory.expectAddRequests(1);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002694 setMobileDataAlwaysOn(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002695 testFactory.waitForNetworkRequests(2);
2696 assertTrue(testFactory.getMyStartRequested());
2697
2698 // Bring up cell data and check that the factory stops looking.
Hugo Benichifed512a2017-06-26 10:06:49 +09002699 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002700 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2701 testFactory.expectAddRequests(2); // Because the cell request changes score twice.
2702 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002703 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002704 testFactory.waitForNetworkRequests(2);
2705 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
2706
2707 // Check that cell data stays up.
Hugo Benichibb91c572017-05-22 10:44:02 +09002708 waitForIdle();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002709 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09002710 assertLength(2, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002711
2712 // Turn off mobile data always on and expect the request to disappear...
2713 testFactory.expectRemoveRequests(1);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002714 setMobileDataAlwaysOn(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002715 testFactory.waitForNetworkRequests(1);
2716
2717 // ... and cell data to be torn down.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002718 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Hugo Benichifed512a2017-06-26 10:06:49 +09002719 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002720
2721 testFactory.unregister();
2722 mCm.unregisterNetworkCallback(cellNetworkCallback);
2723 handlerThread.quit();
2724 }
2725
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002726 @Test
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002727 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002728 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09002729 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002730 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
2731
Erik Kline065ab6e2016-10-02 18:02:14 +09002732 tracker.configRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002733 String[] values = new String[] {null, "0", "1"};
2734 for (int i = 0; i < values.length; i++) {
2735 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002736 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09002737 waitForIdle();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002738 String msg = String.format("config=false, setting=%s", values[i]);
Lorenzo Colitti30145d72017-01-27 18:46:03 +09002739 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09002740 assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002741 }
2742
Erik Kline065ab6e2016-10-02 18:02:14 +09002743 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002744
2745 Settings.Global.putInt(cr, settingName, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09002746 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09002747 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09002748 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09002749 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002750
2751 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002752 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09002753 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09002754 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09002755 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002756
2757 Settings.Global.putString(cr, settingName, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09002758 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09002759 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09002760 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09002761 assertTrue(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002762 }
2763
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002764 @Test
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002765 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09002766 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09002767 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002768
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002769 // Pretend we're on a carrier that restricts switching away from bad wifi.
Erik Kline065ab6e2016-10-02 18:02:14 +09002770 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002771
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002772 // File a request for cell to ensure it doesn't go down.
2773 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2774 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2775 .addTransportType(TRANSPORT_CELLULAR).build();
2776 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2777
2778 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2779 mCm.registerDefaultNetworkCallback(defaultCallback);
2780
2781 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
2782 .addTransportType(TRANSPORT_WIFI)
2783 .addCapability(NET_CAPABILITY_VALIDATED)
2784 .build();
2785 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
2786 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
2787
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002788 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09002789 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002790
2791 // Bring up validated cell.
2792 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2793 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002794 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2795 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002796 Network cellNetwork = mCellNetworkAgent.getNetwork();
2797
2798 // Bring up validated wifi.
2799 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2800 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002801 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2802 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002803 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2804
2805 // Fail validation on wifi.
2806 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
2807 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09002808 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002809 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2810
2811 // Because avoid bad wifi is off, we don't switch to cellular.
2812 defaultCallback.assertNoCallback();
2813 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2814 NET_CAPABILITY_VALIDATED));
2815 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2816 NET_CAPABILITY_VALIDATED));
2817 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2818
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002819 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
2820 // that we switch back to cell.
Erik Kline065ab6e2016-10-02 18:02:14 +09002821 tracker.configRestrictsAvoidBadWifi = false;
2822 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002823 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002824 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2825
2826 // Switch back to a restrictive carrier.
Erik Kline065ab6e2016-10-02 18:02:14 +09002827 tracker.configRestrictsAvoidBadWifi = true;
2828 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002829 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002830 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2831
2832 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
2833 mCm.setAvoidUnvalidated(wifiNetwork);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002834 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002835 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2836 NET_CAPABILITY_VALIDATED));
2837 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2838 NET_CAPABILITY_VALIDATED));
2839 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2840
2841 // Disconnect and reconnect wifi to clear the one-time switch above.
2842 mWiFiNetworkAgent.disconnect();
2843 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2844 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002845 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2846 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002847 wifiNetwork = mWiFiNetworkAgent.getNetwork();
2848
2849 // Fail validation on wifi and expect the dialog to appear.
2850 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
2851 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09002852 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002853 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2854
2855 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002856 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002857 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002858
2859 // We now switch to cell.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002860 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002861 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2862 NET_CAPABILITY_VALIDATED));
2863 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2864 NET_CAPABILITY_VALIDATED));
2865 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2866
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002867 // Simulate the user turning the cellular fallback setting off and then on.
2868 // We switch to wifi and then to cell.
2869 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09002870 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002871 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002872 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2873 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09002874 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002875 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09002876 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2877
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002878 // If cell goes down, we switch to wifi.
2879 mCellNetworkAgent.disconnect();
2880 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002881 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09002882 validatedWifiCallback.assertNoCallback();
2883
2884 mCm.unregisterNetworkCallback(cellNetworkCallback);
2885 mCm.unregisterNetworkCallback(validatedWifiCallback);
2886 mCm.unregisterNetworkCallback(defaultCallback);
2887 }
2888
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002889 @Test
Lorenzo Colitti2de49252017-01-24 18:08:41 +09002890 public void testMeteredMultipathPreferenceSetting() throws Exception {
2891 final ContentResolver cr = mServiceContext.getContentResolver();
2892 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
2893 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
2894
2895 for (int config : Arrays.asList(0, 3, 2)) {
2896 for (String setting: Arrays.asList(null, "0", "2", "1")) {
2897 tracker.configMeteredMultipathPreference = config;
2898 Settings.Global.putString(cr, settingName, setting);
2899 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09002900 waitForIdle();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09002901
2902 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
2903 String msg = String.format("config=%d, setting=%s", config, setting);
2904 assertEquals(msg, expected, mCm.getMultipathPreference(null));
2905 }
2906 }
2907 }
2908
Erik Kline3841a482015-11-25 12:49:38 +09002909 /**
2910 * Validate that a satisfied network request does not trigger onUnavailable() once the
2911 * time-out period expires.
2912 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002913 @Test
Erik Kline3841a482015-11-25 12:49:38 +09002914 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
2915 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2916 NetworkCapabilities.TRANSPORT_WIFI).build();
2917 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09002918 final int timeoutMs = 150;
2919 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09002920
2921 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2922 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002923 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09002924
2925 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07002926 networkCallback.assertNoCallback();
2927 }
2928
2929 /**
2930 * Validate that a satisfied network request followed by a disconnected (lost) network does
2931 * not trigger onUnavailable() once the time-out period expires.
2932 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002933 @Test
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07002934 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
2935 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2936 NetworkCapabilities.TRANSPORT_WIFI).build();
2937 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichi91c7ff92017-06-26 10:20:00 +09002938 final int requestTimeoutMs = 50;
Hugo Benichidfb559a2016-12-20 14:57:49 +09002939 mCm.requestNetwork(nr, networkCallback, requestTimeoutMs);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07002940
2941 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2942 mWiFiNetworkAgent.connect(false);
Hugo Benichi91c7ff92017-06-26 10:20:00 +09002943 final int assertTimeoutMs = 100;
Lorenzo Colitti27334542018-01-12 16:22:21 +09002944 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, assertTimeoutMs);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07002945 mWiFiNetworkAgent.disconnect();
2946 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2947
Hugo Benichi91c7ff92017-06-26 10:20:00 +09002948 // Validate that UNAVAILABLE is not called
Erik Kline3841a482015-11-25 12:49:38 +09002949 networkCallback.assertNoCallback();
2950 }
2951
2952 /**
2953 * Validate that when a time-out is specified for a network request the onUnavailable()
2954 * callback is called when time-out expires. Then validate that if network request is
2955 * (somehow) satisfied - the callback isn't called later.
2956 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002957 @Test
Erik Kline3841a482015-11-25 12:49:38 +09002958 public void testTimedoutNetworkRequest() {
2959 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2960 NetworkCapabilities.TRANSPORT_WIFI).build();
2961 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09002962 final int timeoutMs = 10;
2963 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09002964
2965 // pass timeout and validate that UNAVAILABLE is called
2966 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
2967
2968 // create a network satisfying request - validate that request not triggered
2969 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2970 mWiFiNetworkAgent.connect(false);
2971 networkCallback.assertNoCallback();
2972 }
2973
2974 /**
Hugo Benichi91c7ff92017-06-26 10:20:00 +09002975 * Validate that when a network request is unregistered (cancelled), no posterior event can
2976 * trigger the callback.
Erik Kline3841a482015-11-25 12:49:38 +09002977 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002978 @Test
Hugo Benichi91c7ff92017-06-26 10:20:00 +09002979 public void testNoCallbackAfterUnregisteredNetworkRequest() {
Erik Kline3841a482015-11-25 12:49:38 +09002980 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2981 NetworkCapabilities.TRANSPORT_WIFI).build();
2982 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09002983 final int timeoutMs = 10;
Hugo Benichi91c7ff92017-06-26 10:20:00 +09002984
Hugo Benichidfb559a2016-12-20 14:57:49 +09002985 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09002986 mCm.unregisterNetworkCallback(networkCallback);
Hugo Benichi91c7ff92017-06-26 10:20:00 +09002987 // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
2988 // that this callback will not be called.
Erik Kline3841a482015-11-25 12:49:38 +09002989 networkCallback.assertNoCallback();
2990
2991 // create a network satisfying request - validate that request not triggered
2992 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2993 mWiFiNetworkAgent.connect(false);
2994 networkCallback.assertNoCallback();
2995 }
2996
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002997 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
2998
2999 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3000
3001 private class CallbackValue {
3002 public CallbackType callbackType;
3003 public int error;
3004
3005 public CallbackValue(CallbackType type) {
3006 this.callbackType = type;
3007 this.error = PacketKeepalive.SUCCESS;
3008 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3009 }
3010
3011 public CallbackValue(CallbackType type, int error) {
3012 this.callbackType = type;
3013 this.error = error;
3014 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3015 }
3016
3017 @Override
3018 public boolean equals(Object o) {
3019 return o instanceof CallbackValue &&
3020 this.callbackType == ((CallbackValue) o).callbackType &&
3021 this.error == ((CallbackValue) o).error;
3022 }
3023
3024 @Override
3025 public String toString() {
3026 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
3027 }
3028 }
3029
3030 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
3031
3032 @Override
3033 public void onStarted() {
3034 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3035 }
3036
3037 @Override
3038 public void onStopped() {
3039 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3040 }
3041
3042 @Override
3043 public void onError(int error) {
3044 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3045 }
3046
3047 private void expectCallback(CallbackValue callbackValue) {
3048 try {
3049 assertEquals(
3050 callbackValue,
3051 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3052 } catch (InterruptedException e) {
3053 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
3054 }
3055 }
3056
3057 public void expectStarted() {
3058 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3059 }
3060
3061 public void expectStopped() {
3062 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3063 }
3064
3065 public void expectError(int error) {
3066 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3067 }
3068 }
3069
3070 private Network connectKeepaliveNetwork(LinkProperties lp) {
3071 // Ensure the network is disconnected before we do anything.
3072 if (mWiFiNetworkAgent != null) {
3073 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
3074 }
3075
3076 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3077 ConditionVariable cv = waitForConnectivityBroadcasts(1);
3078 mWiFiNetworkAgent.connect(true);
3079 waitFor(cv);
3080 verifyActiveNetwork(TRANSPORT_WIFI);
3081 mWiFiNetworkAgent.sendLinkProperties(lp);
Hugo Benichibb91c572017-05-22 10:44:02 +09003082 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003083 return mWiFiNetworkAgent.getNetwork();
3084 }
3085
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003086 @Test
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003087 public void testPacketKeepalives() throws Exception {
3088 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
3089 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
3090 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
3091 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
3092 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
3093
3094 LinkProperties lp = new LinkProperties();
3095 lp.setInterfaceName("wlan12");
3096 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
3097 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
3098 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
3099 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
3100
3101 Network notMyNet = new Network(61234);
3102 Network myNet = connectKeepaliveNetwork(lp);
3103
3104 TestKeepaliveCallback callback = new TestKeepaliveCallback();
3105 PacketKeepalive ka;
3106
3107 // Attempt to start keepalives with invalid parameters and check for errors.
3108 ka = mCm.startNattKeepalive(notMyNet, 25, callback, myIPv4, 1234, dstIPv4);
3109 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3110
3111 ka = mCm.startNattKeepalive(myNet, 19, callback, notMyIPv4, 1234, dstIPv4);
3112 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
3113
3114 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 1234, dstIPv6);
3115 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3116
3117 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv4);
3118 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3119
3120 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv6);
3121 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); // NAT-T is IPv4-only.
3122
3123 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
3124 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3125
3126 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
3127 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3128
3129 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
3130 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3131
3132 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
3133 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3134
3135 // Check that a started keepalive can be stopped.
3136 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
3137 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
3138 callback.expectStarted();
3139 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
3140 ka.stop();
3141 callback.expectStopped();
3142
3143 // Check that deleting the IP address stops the keepalive.
3144 LinkProperties bogusLp = new LinkProperties(lp);
3145 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
3146 callback.expectStarted();
3147 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
3148 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
3149 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
3150 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3151 mWiFiNetworkAgent.sendLinkProperties(lp);
3152
3153 // Check that a started keepalive is stopped correctly when the network disconnects.
3154 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
3155 callback.expectStarted();
3156 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003157 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003158 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3159
3160 // ... and that stopping it after that has no adverse effects.
Hugo Benichibb91c572017-05-22 10:44:02 +09003161 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003162 final Network myNetAlias = myNet;
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003163 assertNull(mCm.getNetworkCapabilities(myNetAlias));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003164 ka.stop();
3165
3166 // Reconnect.
3167 myNet = connectKeepaliveNetwork(lp);
3168 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
3169
3170 // Check things work as expected when the keepalive is stopped and the network disconnects.
3171 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
3172 callback.expectStarted();
3173 ka.stop();
3174 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003175 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Hugo Benichibb91c572017-05-22 10:44:02 +09003176 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003177 callback.expectStopped();
3178
3179 // Reconnect.
3180 myNet = connectKeepaliveNetwork(lp);
3181 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
3182
3183 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
3184 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
3185 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
3186 callback.expectStarted();
3187
3188 // The second one gets slot 2.
3189 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
3190 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
3191 PacketKeepalive ka2 = mCm.startNattKeepalive(myNet, 25, callback2, myIPv4, 6789, dstIPv4);
3192 callback2.expectStarted();
3193
3194 // Now stop the first one and create a third. This also gets slot 1.
3195 ka.stop();
3196 callback.expectStopped();
3197
3198 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
3199 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
3200 PacketKeepalive ka3 = mCm.startNattKeepalive(myNet, 25, callback3, myIPv4, 9876, dstIPv4);
3201 callback3.expectStarted();
3202
3203 ka2.stop();
3204 callback2.expectStopped();
3205
3206 ka3.stop();
3207 callback3.expectStopped();
3208 }
Udam Sainib7c24872016-01-04 12:16:14 -08003209
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003210 @Test
Udam Sainib7c24872016-01-04 12:16:14 -08003211 public void testGetCaptivePortalServerUrl() throws Exception {
3212 String url = mCm.getCaptivePortalServerUrl();
3213 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
3214 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09003215
3216 private static class TestNetworkPinner extends NetworkPinner {
3217 public static boolean awaitPin(int timeoutMs) {
3218 synchronized(sLock) {
3219 if (sNetwork == null) {
3220 try {
3221 sLock.wait(timeoutMs);
3222 } catch (InterruptedException e) {}
3223 }
3224 return sNetwork != null;
3225 }
3226 }
3227
3228 public static boolean awaitUnpin(int timeoutMs) {
3229 synchronized(sLock) {
3230 if (sNetwork != null) {
3231 try {
3232 sLock.wait(timeoutMs);
3233 } catch (InterruptedException e) {}
3234 }
3235 return sNetwork == null;
3236 }
3237 }
3238 }
3239
3240 private void assertPinnedToWifiWithCellDefault() {
3241 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
3242 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3243 }
3244
3245 private void assertPinnedToWifiWithWifiDefault() {
3246 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
3247 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3248 }
3249
3250 private void assertNotPinnedToWifi() {
3251 assertNull(mCm.getBoundNetworkForProcess());
3252 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3253 }
3254
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003255 @Test
Lorenzo Colitti531a3442016-03-01 12:55:58 +09003256 public void testNetworkPinner() {
3257 NetworkRequest wifiRequest = new NetworkRequest.Builder()
3258 .addTransportType(TRANSPORT_WIFI)
3259 .build();
3260 assertNull(mCm.getBoundNetworkForProcess());
3261
3262 TestNetworkPinner.pin(mServiceContext, wifiRequest);
3263 assertNull(mCm.getBoundNetworkForProcess());
3264
3265 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3266 mCellNetworkAgent.connect(true);
3267 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3268 mWiFiNetworkAgent.connect(false);
3269
3270 // When wi-fi connects, expect to be pinned.
3271 assertTrue(TestNetworkPinner.awaitPin(100));
3272 assertPinnedToWifiWithCellDefault();
3273
3274 // Disconnect and expect the pin to drop.
3275 mWiFiNetworkAgent.disconnect();
3276 assertTrue(TestNetworkPinner.awaitUnpin(100));
3277 assertNotPinnedToWifi();
3278
3279 // Reconnecting does not cause the pin to come back.
3280 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3281 mWiFiNetworkAgent.connect(false);
3282 assertFalse(TestNetworkPinner.awaitPin(100));
3283 assertNotPinnedToWifi();
3284
3285 // Pinning while connected causes the pin to take effect immediately.
3286 TestNetworkPinner.pin(mServiceContext, wifiRequest);
3287 assertTrue(TestNetworkPinner.awaitPin(100));
3288 assertPinnedToWifiWithCellDefault();
3289
3290 // Explicitly unpin and expect to use the default network again.
3291 TestNetworkPinner.unpin();
3292 assertNotPinnedToWifi();
3293
3294 // Disconnect cell and wifi.
3295 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
3296 mCellNetworkAgent.disconnect();
3297 mWiFiNetworkAgent.disconnect();
3298 waitFor(cv);
3299
3300 // Pinning takes effect even if the pinned network is the default when the pin is set...
3301 TestNetworkPinner.pin(mServiceContext, wifiRequest);
3302 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3303 mWiFiNetworkAgent.connect(false);
3304 assertTrue(TestNetworkPinner.awaitPin(100));
3305 assertPinnedToWifiWithWifiDefault();
3306
3307 // ... and is maintained even when that network is no longer the default.
3308 cv = waitForConnectivityBroadcasts(1);
3309 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3310 mCellNetworkAgent.connect(true);
3311 waitFor(cv);
3312 assertPinnedToWifiWithCellDefault();
3313 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003314
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003315 @Test
Hugo Benichi893a7622017-09-29 09:34:08 +09003316 public void testNetworkCallbackMaximum() {
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003317 final int MAX_REQUESTS = 100;
Hugo Benichi893a7622017-09-29 09:34:08 +09003318 final int CALLBACKS = 90;
3319 final int INTENTS = 10;
3320 assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
3321
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003322 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
Hugo Benichi893a7622017-09-29 09:34:08 +09003323 ArrayList<Object> registered = new ArrayList<>();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003324
Hugo Benichi893a7622017-09-29 09:34:08 +09003325 int j = 0;
3326 while (j++ < CALLBACKS / 2) {
3327 NetworkCallback cb = new NetworkCallback();
3328 mCm.requestNetwork(networkRequest, cb);
3329 registered.add(cb);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003330 }
Hugo Benichi893a7622017-09-29 09:34:08 +09003331 while (j++ < CALLBACKS) {
3332 NetworkCallback cb = new NetworkCallback();
3333 mCm.registerNetworkCallback(networkRequest, cb);
3334 registered.add(cb);
3335 }
3336 j = 0;
3337 while (j++ < INTENTS / 2) {
3338 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
3339 mCm.requestNetwork(networkRequest, pi);
3340 registered.add(pi);
3341 }
3342 while (j++ < INTENTS) {
3343 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
3344 mCm.registerNetworkCallback(networkRequest, pi);
3345 registered.add(pi);
3346 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003347
Hugo Benichi893a7622017-09-29 09:34:08 +09003348 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003349 try {
Hugo Benichi893a7622017-09-29 09:34:08 +09003350 mCm.requestNetwork(networkRequest, new NetworkCallback());
3351 fail("Registering " + MAX_REQUESTS + " network requests did not throw exception");
Hugo Benichicb883232017-05-11 13:16:17 +09003352 } catch (TooManyRequestsException expected) {}
Hugo Benichi893a7622017-09-29 09:34:08 +09003353 try {
3354 mCm.registerNetworkCallback(networkRequest, new NetworkCallback());
3355 fail("Registering " + MAX_REQUESTS + " network callbacks did not throw exception");
3356 } catch (TooManyRequestsException expected) {}
3357 try {
3358 mCm.requestNetwork(networkRequest,
3359 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0));
3360 fail("Registering " + MAX_REQUESTS + " PendingIntent requests did not throw exception");
3361 } catch (TooManyRequestsException expected) {}
3362 try {
3363 mCm.registerNetworkCallback(networkRequest,
3364 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0));
3365 fail("Registering " + MAX_REQUESTS
3366 + " PendingIntent callbacks did not throw exception");
3367 } catch (TooManyRequestsException expected) {}
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003368
Hugo Benichi893a7622017-09-29 09:34:08 +09003369 for (Object o : registered) {
3370 if (o instanceof NetworkCallback) {
3371 mCm.unregisterNetworkCallback((NetworkCallback)o);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003372 }
Hugo Benichi893a7622017-09-29 09:34:08 +09003373 if (o instanceof PendingIntent) {
3374 mCm.unregisterNetworkCallback((PendingIntent)o);
3375 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003376 }
Hugo Benichi893a7622017-09-29 09:34:08 +09003377 waitForIdle();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003378
3379 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
3380 for (int i = 0; i < MAX_REQUESTS; i++) {
3381 NetworkCallback networkCallback = new NetworkCallback();
3382 mCm.requestNetwork(networkRequest, networkCallback);
3383 mCm.unregisterNetworkCallback(networkCallback);
3384 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09003385 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09003386
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003387 for (int i = 0; i < MAX_REQUESTS; i++) {
3388 NetworkCallback networkCallback = new NetworkCallback();
3389 mCm.registerNetworkCallback(networkRequest, networkCallback);
3390 mCm.unregisterNetworkCallback(networkCallback);
3391 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09003392 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09003393
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003394 for (int i = 0; i < MAX_REQUESTS; i++) {
3395 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09003396 PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003397 mCm.requestNetwork(networkRequest, pendingIntent);
3398 mCm.unregisterNetworkCallback(pendingIntent);
3399 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09003400 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09003401
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003402 for (int i = 0; i < MAX_REQUESTS; i++) {
3403 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09003404 PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003405 mCm.registerNetworkCallback(networkRequest, pendingIntent);
3406 mCm.unregisterNetworkCallback(pendingIntent);
3407 }
3408 }
Hugo Benichifed512a2017-06-26 10:06:49 +09003409
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003410 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09003411 public void testNetworkInfoOfTypeNone() {
3412 ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1);
3413
3414 verifyNoNetwork();
Hugo Benichic1014502017-07-19 10:10:52 +09003415 MockNetworkAgent wifiAware = new MockNetworkAgent(TRANSPORT_WIFI_AWARE);
Hugo Benichi16f0a942017-06-20 14:07:59 +09003416 assertNull(mCm.getActiveNetworkInfo());
3417
3418 Network[] allNetworks = mCm.getAllNetworks();
3419 assertLength(1, allNetworks);
3420 Network network = allNetworks[0];
3421 NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
3422 assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
3423
3424 final NetworkRequest request =
3425 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
3426 final TestNetworkCallback callback = new TestNetworkCallback();
3427 mCm.registerNetworkCallback(request, callback);
3428
Hugo Benichic1014502017-07-19 10:10:52 +09003429 // Bring up wifi aware network.
3430 wifiAware.connect(false, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003431 callback.expectAvailableCallbacksUnvalidated(wifiAware);
Hugo Benichi16f0a942017-06-20 14:07:59 +09003432
3433 assertNull(mCm.getActiveNetworkInfo());
3434 assertNull(mCm.getActiveNetwork());
Hugo Benichic1014502017-07-19 10:10:52 +09003435 // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
Hugo Benichi16f0a942017-06-20 14:07:59 +09003436 // of this test. Fix it and uncomment the assert below.
3437 //assertEmpty(mCm.getAllNetworkInfo());
3438
Hugo Benichic1014502017-07-19 10:10:52 +09003439 // Disconnect wifi aware network.
3440 wifiAware.disconnect();
3441 callback.expectCallbackLike((info) -> info.state == CallbackState.LOST, TIMEOUT_MS);
Hugo Benichi16f0a942017-06-20 14:07:59 +09003442 mCm.unregisterNetworkCallback(callback);
3443
3444 verifyNoNetwork();
3445 if (broadcastCV.block(10)) {
3446 fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
3447 }
3448 }
3449
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003450 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09003451 public void testDeprecatedAndUnsupportedOperations() throws Exception {
3452 final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
3453 assertNull(mCm.getNetworkInfo(TYPE_NONE));
3454 assertNull(mCm.getNetworkForType(TYPE_NONE));
3455 assertNull(mCm.getLinkProperties(TYPE_NONE));
3456 assertFalse(mCm.isNetworkSupported(TYPE_NONE));
3457
3458 assertException(() -> { mCm.networkCapabilitiesForType(TYPE_NONE); },
3459 IllegalArgumentException.class);
3460
3461 Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
3462 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
3463 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
3464 // TODO: let test context have configuration application target sdk version
3465 // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
3466 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
3467 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
3468 assertException(() -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); }, unsupported);
3469 }
3470
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003471 @Test
Rubin Xu1bb5c082017-09-05 18:40:49 +01003472 public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() {
3473 final NetworkRequest networkRequest = new NetworkRequest.Builder()
3474 .addTransportType(TRANSPORT_WIFI).build();
3475 final TestNetworkCallback networkCallback = new TestNetworkCallback();
3476 mCm.registerNetworkCallback(networkRequest, networkCallback);
3477
3478 LinkProperties lp = new LinkProperties();
3479 lp.setInterfaceName("wlan0");
3480 LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
3481 RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
3482 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
3483 lp.addLinkAddress(myIpv4Address);
3484 lp.addRoute(myIpv4DefaultRoute);
3485
3486 // Verify direct routes are added when network agent is first registered in
3487 // ConnectivityService.
3488 MockNetworkAgent networkAgent = new MockNetworkAgent(TRANSPORT_WIFI, lp);
3489 networkAgent.connect(true);
3490 networkCallback.expectCallback(CallbackState.AVAILABLE, networkAgent);
3491 networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent);
3492 CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
3493 networkAgent);
3494 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
3495 networkCallback.assertNoCallback();
3496 checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address),
3497 Arrays.asList(myIpv4DefaultRoute));
3498 checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
3499 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
3500
3501 // Verify direct routes are added during subsequent link properties updates.
3502 LinkProperties newLp = new LinkProperties(lp);
3503 LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
3504 LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
3505 newLp.addLinkAddress(myIpv6Address1);
3506 newLp.addLinkAddress(myIpv6Address2);
3507 networkAgent.sendLinkProperties(newLp);
3508 cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, networkAgent);
3509 networkCallback.assertNoCallback();
3510 checkDirectlyConnectedRoutes(cbi.arg,
3511 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
3512 Arrays.asList(myIpv4DefaultRoute));
3513 mCm.unregisterNetworkCallback(networkCallback);
3514 }
3515
Jeff Sharkey72f9c422017-10-27 17:22:59 -06003516 @Test
3517 public void testStatsIfacesChanged() throws Exception {
3518 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Lorenzo Colittic78da292018-01-19 00:50:48 +09003519 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3520
3521 Network[] onlyCell = new Network[]{mCellNetworkAgent.getNetwork()};
3522 Network[] onlyWifi = new Network[]{mWiFiNetworkAgent.getNetwork()};
Jeff Sharkey72f9c422017-10-27 17:22:59 -06003523
3524 // Simple connection should have updated ifaces
3525 mCellNetworkAgent.connect(false);
3526 waitForIdle();
Lorenzo Colittic78da292018-01-19 00:50:48 +09003527 verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
3528 reset(mStatsService);
3529
3530 // Default network switch should update ifaces.
3531 mWiFiNetworkAgent.connect(false);
3532 waitForIdle();
3533 verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyWifi);
3534 reset(mStatsService);
3535
3536 // Disconnect should update ifaces.
3537 mWiFiNetworkAgent.disconnect();
3538 waitForIdle();
3539 verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06003540 reset(mStatsService);
3541
3542 // Metered change should update ifaces
3543 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
3544 waitForIdle();
Lorenzo Colittic78da292018-01-19 00:50:48 +09003545 verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06003546 reset(mStatsService);
3547
3548 mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
3549 waitForIdle();
Lorenzo Colittic78da292018-01-19 00:50:48 +09003550 verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06003551 reset(mStatsService);
3552
3553 // Captive portal change shouldn't update ifaces
3554 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
3555 waitForIdle();
Lorenzo Colittic78da292018-01-19 00:50:48 +09003556 verify(mStatsService, never()).forceUpdateIfaces(onlyCell);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06003557 reset(mStatsService);
3558
3559 // Roaming change should update ifaces
3560 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
3561 waitForIdle();
Lorenzo Colittic78da292018-01-19 00:50:48 +09003562 verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06003563 reset(mStatsService);
3564 }
3565
Erik Klinee89953b2018-01-11 16:11:10 +09003566 @Test
3567 public void testBasicDnsConfigurationPushed() throws Exception {
3568 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3569 waitForIdle();
3570 verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
Erik Kline1742fe12017-12-13 19:40:49 +09003571 anyInt(), any(), any(), any(), anyBoolean(), anyString());
Erik Klinee89953b2018-01-11 16:11:10 +09003572
3573 final LinkProperties cellLp = new LinkProperties();
3574 cellLp.setInterfaceName("test_rmnet_data0");
3575 mCellNetworkAgent.sendLinkProperties(cellLp);
3576 mCellNetworkAgent.connect(false);
3577 waitForIdle();
3578 verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
Erik Kline1742fe12017-12-13 19:40:49 +09003579 anyInt(), mStringArrayCaptor.capture(), any(), any(), anyBoolean(), anyString());
Erik Klinee89953b2018-01-11 16:11:10 +09003580 // CS tells netd about the empty DNS config for this network.
3581 assertEmpty(mStringArrayCaptor.getValue());
3582 reset(mNetworkManagementService);
3583
3584 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
3585 mCellNetworkAgent.sendLinkProperties(cellLp);
3586 waitForIdle();
3587 verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
Erik Kline1742fe12017-12-13 19:40:49 +09003588 anyInt(), mStringArrayCaptor.capture(), any(), any(), anyBoolean(), anyString());
Erik Klinee89953b2018-01-11 16:11:10 +09003589 assertEquals(1, mStringArrayCaptor.getValue().length);
3590 assertTrue(ArrayUtils.contains(mStringArrayCaptor.getValue(), "2001:db8::1"));
3591 reset(mNetworkManagementService);
3592
3593 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
3594 mCellNetworkAgent.sendLinkProperties(cellLp);
3595 waitForIdle();
3596 verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
Erik Kline1742fe12017-12-13 19:40:49 +09003597 anyInt(), mStringArrayCaptor.capture(), any(), any(), anyBoolean(), anyString());
Erik Klinee89953b2018-01-11 16:11:10 +09003598 assertEquals(2, mStringArrayCaptor.getValue().length);
3599 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
3600 new String[]{"2001:db8::1", "192.0.2.1"}));
3601 reset(mNetworkManagementService);
3602 }
3603
Rubin Xu1bb5c082017-09-05 18:40:49 +01003604 private void checkDirectlyConnectedRoutes(Object callbackObj,
3605 Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
3606 assertTrue(callbackObj instanceof LinkProperties);
3607 LinkProperties lp = (LinkProperties) callbackObj;
3608
3609 Set<RouteInfo> expectedRoutes = new ArraySet<>();
3610 expectedRoutes.addAll(otherRoutes);
3611 for (LinkAddress address : linkAddresses) {
3612 RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
3613 // Duplicates in linkAddresses are considered failures
3614 assertTrue(expectedRoutes.add(localRoute));
3615 }
3616 List<RouteInfo> observedRoutes = lp.getRoutes();
3617 assertEquals(expectedRoutes.size(), observedRoutes.size());
3618 assertTrue(observedRoutes.containsAll(expectedRoutes));
3619 }
3620
Hugo Benichifed512a2017-06-26 10:06:49 +09003621 private static <T> void assertEmpty(T[] ts) {
3622 int length = ts.length;
3623 assertEquals("expected empty array, but length was " + length, 0, length);
3624 }
3625
3626 private static <T> void assertLength(int expected, T[] got) {
3627 int length = got.length;
3628 assertEquals(String.format("expected array of length %s, but length was %s for %s",
3629 expected, length, Arrays.toString(got)), expected, length);
3630 }
Hugo Benichi16f0a942017-06-20 14:07:59 +09003631
3632 private static <T> void assertException(Runnable block, Class<T> expected) {
3633 try {
3634 block.run();
3635 fail("Expected exception of type " + expected);
3636 } catch (Exception got) {
3637 if (!got.getClass().equals(expected)) {
3638 fail("Expected exception of type " + expected + " but got " + got);
3639 }
3640 return;
3641 }
3642 }
Chalard Jean0b214af2018-01-12 17:22:49 +09003643
3644 @Test
3645 public void testVpnNetworkActive() {
3646 final int uid = Process.myUid();
3647
3648 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
3649 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
3650 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
3651 final NetworkRequest genericRequest = new NetworkRequest.Builder().build();
3652 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
3653 .addTransportType(TRANSPORT_WIFI).build();
3654 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
3655 .addTransportType(TRANSPORT_VPN).build();
3656 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
3657 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
3658 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
3659
3660 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3661 mWiFiNetworkAgent.connect(false);
3662
3663 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3664 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3665 vpnNetworkCallback.assertNoCallback();
3666
3667 // TODO : check callbacks agree with the return value of mCm.getActiveNetwork().
3668 // Right now this is not possible because establish() is not adequately instrumented
3669 // in this test.
3670
3671 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
3672 final ArraySet<UidRange> ranges = new ArraySet<>();
3673 ranges.add(new UidRange(uid, uid));
3674 vpnNetworkAgent.setUids(ranges);
3675 vpnNetworkAgent.connect(false);
3676
3677 genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
3678 wifiNetworkCallback.assertNoCallback();
3679 vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
3680
3681 genericNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
3682 vpnNetworkCallback.expectCapabilitiesLike(
3683 nc -> nc.appliesToUid(uid) && !nc.appliesToUid(uid + 1), vpnNetworkAgent);
3684
3685 ranges.clear();
3686 vpnNetworkAgent.setUids(ranges);
3687
3688 genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
3689 wifiNetworkCallback.assertNoCallback();
3690 vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
3691
3692 ranges.add(new UidRange(uid, uid));
3693 vpnNetworkAgent.setUids(ranges);
3694
3695 genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
3696 wifiNetworkCallback.assertNoCallback();
3697 vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
3698
3699 mWiFiNetworkAgent.disconnect();
3700
3701 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3702 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3703 vpnNetworkCallback.assertNoCallback();
3704
3705 vpnNetworkAgent.disconnect();
3706
3707 genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
3708 wifiNetworkCallback.assertNoCallback();
3709 vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
3710
3711 mCm.unregisterNetworkCallback(genericNetworkCallback);
3712 mCm.unregisterNetworkCallback(wifiNetworkCallback);
3713 mCm.unregisterNetworkCallback(vpnNetworkCallback);
3714 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07003715}