blob: 6fb36513a8ed4b463cce8a2357d080acb172162d [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;
Erik Kline79c6d052018-03-21 07:18:33 -070020import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
21import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
22import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +090023import static android.net.ConnectivityManager.TYPE_ETHERNET;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070024import static android.net.ConnectivityManager.TYPE_MOBILE;
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +090025import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
26import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
Hugo Benichi16f0a942017-06-20 14:07:59 +090027import static android.net.ConnectivityManager.TYPE_NONE;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070028import static android.net.ConnectivityManager.TYPE_WIFI;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060029import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
30import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
31import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
32import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
33import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
34import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
35import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
36import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
37import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
38import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
39import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
40import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
Chalard Jean804b8fb2018-01-30 22:41:41 +090041import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060042import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
43import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
44import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
45import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
46import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
47import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
48import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
49import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
50import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
Chalard Jean0b214af2018-01-12 17:22:49 +090051import static android.net.NetworkCapabilities.TRANSPORT_VPN;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060052import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
53import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
54
55import static com.android.internal.util.TestUtils.waitForIdleHandler;
Chalard Jeanb72b62d2018-02-16 16:08:35 +090056import static com.android.internal.util.TestUtils.waitForIdleLooper;
Lorenzo Colitti83fa2582015-08-07 12:49:01 +090057
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090058import static org.junit.Assert.assertEquals;
59import static org.junit.Assert.assertFalse;
junyulai4a192e22018-06-13 15:00:37 +080060import static org.junit.Assert.assertNotEquals;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090061import static org.junit.Assert.assertNotNull;
62import static org.junit.Assert.assertNull;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060063import static org.junit.Assert.assertTrue;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090064import static org.junit.Assert.fail;
Erik Klinee89953b2018-01-11 16:11:10 +090065import static org.mockito.Matchers.anyBoolean;
66import static org.mockito.Matchers.anyInt;
67import static org.mockito.Matchers.anyString;
68import static org.mockito.Mockito.any;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060069import static org.mockito.Mockito.atLeastOnce;
Erik Kline117e7f32018-03-04 21:01:01 +090070import static org.mockito.Mockito.eq;
Jeff Sharkey3671b1e2013-01-31 17:22:26 -080071import static org.mockito.Mockito.mock;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060072import static org.mockito.Mockito.never;
73import static org.mockito.Mockito.reset;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090074import static org.mockito.Mockito.spy;
Erik Klinee89953b2018-01-11 16:11:10 +090075import static org.mockito.Mockito.times;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060076import static org.mockito.Mockito.verify;
Erik Kline79c6d052018-03-21 07:18:33 -070077import static org.mockito.Mockito.verifyNoMoreInteractions;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090078import static org.mockito.Mockito.when;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070079
Erik Klinee89953b2018-01-11 16:11:10 +090080
Lorenzo Colitti73b209382016-09-15 22:18:09 +090081import android.app.NotificationManager;
Paul Jensenbb2e0e92015-06-16 15:11:58 -040082import android.app.PendingIntent;
Paul Jensend7b6ca92015-05-13 14:05:12 -040083import android.content.BroadcastReceiver;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +090084import android.content.ContentResolver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070085import android.content.Context;
Paul Jensend7b6ca92015-05-13 14:05:12 -040086import android.content.Intent;
87import android.content.IntentFilter;
Chalard Jeanfb0c87e2018-04-18 19:18:58 +090088import android.content.pm.UserInfo;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090089import android.content.res.Resources;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +090090import android.net.CaptivePortal;
Paul Jensend7b6ca92015-05-13 14:05:12 -040091import android.net.ConnectivityManager;
92import android.net.ConnectivityManager.NetworkCallback;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +090093import android.net.ConnectivityManager.PacketKeepalive;
94import android.net.ConnectivityManager.PacketKeepaliveCallback;
Hugo Benichicb883232017-05-11 13:16:17 +090095import android.net.ConnectivityManager.TooManyRequestsException;
Chalard Jeanb72b62d2018-02-16 16:08:35 +090096import android.net.ConnectivityThread;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070097import android.net.INetworkPolicyManager;
98import android.net.INetworkStatsService;
junyulai4a192e22018-06-13 15:00:37 +080099import android.net.InterfaceConfiguration;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900100import android.net.IpPrefix;
101import android.net.LinkAddress;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700102import android.net.LinkProperties;
Etan Cohena7434272017-04-03 12:17:51 -0700103import android.net.MatchAllNetworkSpecifier;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400104import android.net.Network;
105import android.net.NetworkAgent;
106import android.net.NetworkCapabilities;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700107import android.net.NetworkFactory;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700108import android.net.NetworkInfo;
109import android.net.NetworkInfo.DetailedState;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400110import android.net.NetworkMisc;
111import android.net.NetworkRequest;
Etan Cohena7434272017-04-03 12:17:51 -0700112import android.net.NetworkSpecifier;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100113import android.net.NetworkUtils;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700114import android.net.RouteInfo;
Etan Cohena7434272017-04-03 12:17:51 -0700115import android.net.StringNetworkSpecifier;
Chalard Jean0b214af2018-01-12 17:22:49 +0900116import android.net.UidRange;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900117import android.net.VpnService;
Remi NGUYEN VANd63c1192018-05-22 09:58:19 +0900118import android.net.captiveportal.CaptivePortalProbeResult;
Hugo Benichif9fdf872016-07-28 17:53:06 +0900119import android.net.metrics.IpConnectivityLog;
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900120import android.net.util.MultinetworkPolicyTracker;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400121import android.os.ConditionVariable;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700122import android.os.Handler;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700123import android.os.HandlerThread;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700124import android.os.INetworkManagementService;
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900125import android.os.Looper;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900126import android.os.Message;
Etan Cohena7434272017-04-03 12:17:51 -0700127import android.os.Parcel;
128import android.os.Parcelable;
Robin Leed2baf792016-03-24 12:07:00 +0000129import android.os.Process;
junyulai4a192e22018-06-13 15:00:37 +0800130import android.os.RemoteException;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900131import android.os.SystemClock;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900132import android.os.UserHandle;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900133import android.provider.Settings;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900134import android.support.test.InstrumentationRegistry;
135import android.support.test.filters.SmallTest;
136import android.support.test.runner.AndroidJUnit4;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900137import android.test.mock.MockContentResolver;
junyulai4a192e22018-06-13 15:00:37 +0800138import android.text.TextUtils;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100139import android.util.ArraySet;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700140import android.util.Log;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700141
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900142import com.android.internal.net.VpnConfig;
Erik Klinee89953b2018-01-11 16:11:10 +0900143import com.android.internal.util.ArrayUtils;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900144import com.android.internal.util.WakeupMessage;
Lorenzo Colitti3c295b52016-10-28 12:56:03 +0900145import com.android.internal.util.test.BroadcastInterceptingContext;
Lorenzo Colittib8df76e42016-10-28 12:37:38 +0900146import com.android.internal.util.test.FakeSettingsProvider;
Chalard Jeandda156a2018-01-10 21:19:32 +0900147import com.android.server.connectivity.ConnectivityConstants;
Hugo Benichi64901e52017-10-19 14:42:40 +0900148import com.android.server.connectivity.DefaultNetworkMetrics;
Erik Kline117e7f32018-03-04 21:01:01 +0900149import com.android.server.connectivity.DnsManager;
Hugo Benichi64901e52017-10-19 14:42:40 +0900150import com.android.server.connectivity.IpConnectivityMetrics;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900151import com.android.server.connectivity.MockableSystemProperties;
junyulai4a192e22018-06-13 15:00:37 +0800152import com.android.server.connectivity.Nat464Xlat;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400153import com.android.server.connectivity.NetworkAgentInfo;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400154import com.android.server.connectivity.NetworkMonitor;
Chalard Jeandda156a2018-01-10 21:19:32 +0900155import com.android.server.connectivity.Vpn;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900156import com.android.server.net.NetworkPinner;
Hugo Benichi938ab4f2017-02-11 17:04:43 +0900157import com.android.server.net.NetworkPolicyManagerInternal;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400158
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900159import org.junit.After;
160import org.junit.Before;
Hugo Benichi849b81b2017-05-25 13:42:31 +0900161import org.junit.Ignore;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900162import org.junit.Test;
163import org.junit.runner.RunWith;
Erik Klinee89953b2018-01-11 16:11:10 +0900164import org.mockito.ArgumentCaptor;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900165import org.mockito.Mock;
166import org.mockito.MockitoAnnotations;
167import org.mockito.Spy;
168
junyulai4a192e22018-06-13 15:00:37 +0800169import java.net.Inet4Address;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700170import java.net.InetAddress;
junyulai4a192e22018-06-13 15:00:37 +0800171import java.net.UnknownHostException;
Paul Jensen4e1d3fd2016-04-08 13:56:52 -0400172import java.util.ArrayList;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900173import java.util.Arrays;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100174import java.util.Collection;
junyulai4a192e22018-06-13 15:00:37 +0800175import java.util.Collections;
dalyk1fcb7392018-03-05 12:42:22 -0500176import java.util.HashSet;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100177import java.util.List;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +0900178import java.util.Objects;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100179import java.util.Set;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900180import java.util.concurrent.CountDownLatch;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900181import java.util.concurrent.LinkedBlockingQueue;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900182import java.util.concurrent.TimeUnit;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700183import java.util.concurrent.atomic.AtomicBoolean;
Hugo Benichi16f0a942017-06-20 14:07:59 +0900184import java.util.function.Predicate;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700185
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900186
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700187/**
188 * Tests for {@link ConnectivityService}.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400189 *
190 * Build, install and run with:
Hugo Benichibb91c572017-05-22 10:44:02 +0900191 * runtest frameworks-net -c com.android.server.ConnectivityServiceTest
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700192 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900193@RunWith(AndroidJUnit4.class)
194@SmallTest
195public class ConnectivityServiceTest {
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700196 private static final String TAG = "ConnectivityServiceTest";
197
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900198 private static final int TIMEOUT_MS = 500;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900199 private static final int TEST_LINGER_DELAY_MS = 120;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900200
junyulai4a192e22018-06-13 15:00:37 +0800201 private static final String CLAT_PREFIX = "v4-";
Erik Kline79c6d052018-03-21 07:18:33 -0700202 private static final String MOBILE_IFNAME = "test_rmnet_data0";
203 private static final String WIFI_IFNAME = "test_wlan0";
204
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900205 private MockContext mServiceContext;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400206 private WrappedConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900207 private WrappedConnectivityManager mCm;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400208 private MockNetworkAgent mWiFiNetworkAgent;
209 private MockNetworkAgent mCellNetworkAgent;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900210 private MockNetworkAgent mEthernetNetworkAgent;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900211 private MockVpn mMockVpn;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900212 private Context mContext;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700213
Hugo Benichi64901e52017-10-19 14:42:40 +0900214 @Mock IpConnectivityMetrics.Logger mMetricsService;
215 @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
Erik Klinee89953b2018-01-11 16:11:10 +0900216 @Mock INetworkManagementService mNetworkManagementService;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600217 @Mock INetworkStatsService mStatsService;
Hugo Benichi64901e52017-10-19 14:42:40 +0900218
Erik Klinee89953b2018-01-11 16:11:10 +0900219 private ArgumentCaptor<String[]> mStringArrayCaptor = ArgumentCaptor.forClass(String[].class);
220
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900221 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
222 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
223 // reflect the state of our test ConnectivityService.
224 private class WrappedConnectivityManager extends ConnectivityManager {
225 private Network mFakeBoundNetwork;
226
227 public synchronized boolean bindProcessToNetwork(Network network) {
228 mFakeBoundNetwork = network;
229 return true;
230 }
231
232 public synchronized Network getBoundNetworkForProcess() {
233 return mFakeBoundNetwork;
234 }
235
236 public WrappedConnectivityManager(Context context, ConnectivityService service) {
237 super(context, service);
238 }
239 }
240
Paul Jensend7b6ca92015-05-13 14:05:12 -0400241 private class MockContext extends BroadcastInterceptingContext {
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900242 private final MockContentResolver mContentResolver;
243
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900244 @Spy private Resources mResources;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900245 private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900246
Paul Jensend7b6ca92015-05-13 14:05:12 -0400247 MockContext(Context base) {
248 super(base);
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900249
250 mResources = spy(base.getResources());
251 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
252 thenReturn(new String[] {
253 "wifi,1,1,1,-1,true",
254 "mobile,0,0,0,-1,true",
255 "mobile_mms,2,0,2,60000,true",
256 });
257
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900258 mContentResolver = new MockContentResolver();
259 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
Paul Jensend7b6ca92015-05-13 14:05:12 -0400260 }
261
262 @Override
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900263 public void startActivityAsUser(Intent intent, UserHandle handle) {
264 mStartedActivities.offer(intent);
265 }
266
267 public Intent expectStartActivityIntent(int timeoutMs) {
268 Intent intent = null;
269 try {
270 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
271 } catch (InterruptedException e) {}
272 assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
273 return intent;
274 }
275
276 public void expectNoStartActivityIntent(int timeoutMs) {
277 try {
278 assertNull("Received unexpected Intent to start activity",
279 mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
280 } catch (InterruptedException e) {}
281 }
282
283 @Override
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900284 public Object getSystemService(String name) {
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900285 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
286 if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400287 return super.getSystemService(name);
288 }
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900289
290 @Override
291 public ContentResolver getContentResolver() {
292 return mContentResolver;
293 }
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900294
295 @Override
296 public Resources getResources() {
297 return mResources;
298 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400299 }
300
Hugo Benichi669f0232017-06-29 22:58:39 +0900301 public void waitForIdle(int timeoutMsAsInt) {
302 long timeoutMs = timeoutMsAsInt;
Hugo Benichibb91c572017-05-22 10:44:02 +0900303 waitForIdleHandler(mService.mHandlerThread, timeoutMs);
304 waitForIdle(mCellNetworkAgent, timeoutMs);
305 waitForIdle(mWiFiNetworkAgent, timeoutMs);
306 waitForIdle(mEthernetNetworkAgent, timeoutMs);
307 waitForIdleHandler(mService.mHandlerThread, timeoutMs);
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900308 waitForIdleLooper(ConnectivityThread.getInstanceLooper(), timeoutMs);
Hugo Benichibb91c572017-05-22 10:44:02 +0900309 }
310
Hugo Benichi669f0232017-06-29 22:58:39 +0900311 public void waitForIdle(MockNetworkAgent agent, long timeoutMs) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900312 if (agent == null) {
313 return;
314 }
315 waitForIdleHandler(agent.mHandlerThread, timeoutMs);
316 }
317
318 private void waitForIdle() {
319 waitForIdle(TIMEOUT_MS);
320 }
321
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900322 @Test
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900323 public void testWaitForIdle() {
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900324 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
325
326 // Tests that waitForIdle returns immediately if the service is already idle.
327 for (int i = 0; i < attempts; i++) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900328 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900329 }
330
331 // Bring up a network that we can use to send messages to ConnectivityService.
332 ConditionVariable cv = waitForConnectivityBroadcasts(1);
333 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
334 mWiFiNetworkAgent.connect(false);
335 waitFor(cv);
336 Network n = mWiFiNetworkAgent.getNetwork();
337 assertNotNull(n);
338
339 // Tests that calling waitForIdle waits for messages to be processed.
340 for (int i = 0; i < attempts; i++) {
341 mWiFiNetworkAgent.setSignalStrength(i);
Hugo Benichibb91c572017-05-22 10:44:02 +0900342 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900343 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
344 }
Hugo Benichi5d540d12016-10-17 15:54:51 +0900345 }
346
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900347 // This test has an inherent race condition in it, and cannot be enabled for continuous testing
348 // or presubmit tests. It is kept for manual runs and documentation purposes.
Andreas Gampe35dbf352018-01-26 20:41:17 -0800349 @Ignore
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900350 public void verifyThatNotWaitingForIdleCausesRaceConditions() {
Hugo Benichi5d540d12016-10-17 15:54:51 +0900351 // Bring up a network that we can use to send messages to ConnectivityService.
352 ConditionVariable cv = waitForConnectivityBroadcasts(1);
353 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
354 mWiFiNetworkAgent.connect(false);
355 waitFor(cv);
356 Network n = mWiFiNetworkAgent.getNetwork();
357 assertNotNull(n);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900358
359 // Ensure that not calling waitForIdle causes a race condition.
Hugo Benichi5d540d12016-10-17 15:54:51 +0900360 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900361 for (int i = 0; i < attempts; i++) {
362 mWiFiNetworkAgent.setSignalStrength(i);
363 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
364 // We hit a race condition, as expected. Pass the test.
365 return;
366 }
367 }
368
369 // No race? There is a bug in this test.
370 fail("expected race condition at least once in " + attempts + " attempts");
371 }
372
Paul Jensend7b6ca92015-05-13 14:05:12 -0400373 private class MockNetworkAgent {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400374 private final WrappedNetworkMonitor mWrappedNetworkMonitor;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400375 private final NetworkInfo mNetworkInfo;
376 private final NetworkCapabilities mNetworkCapabilities;
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900377 private final HandlerThread mHandlerThread;
Paul Jensene0988542015-06-25 15:30:08 -0400378 private final ConditionVariable mDisconnected = new ConditionVariable();
Paul Jensen232437312016-04-06 09:51:26 -0400379 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
Calvin On1f64f3f2016-10-11 15:10:46 -0700380 private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
Paul Jensen3d911462015-06-12 06:40:24 -0400381 private int mScore;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400382 private NetworkAgent mNetworkAgent;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900383 private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
384 private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE;
385 private Integer mExpectedKeepaliveSlot = null;
Paul Jensen232437312016-04-06 09:51:26 -0400386 // Contains the redirectUrl from networkStatus(). Before reading, wait for
387 // mNetworkStatusReceived.
388 private String mRedirectUrl;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400389
390 MockNetworkAgent(int transport) {
Rubin Xu1bb5c082017-09-05 18:40:49 +0100391 this(transport, new LinkProperties());
392 }
393
394 MockNetworkAgent(int transport, LinkProperties linkProperties) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400395 final int type = transportToLegacyType(transport);
Chalard Jean0b214af2018-01-12 17:22:49 +0900396 final String typeName = ConnectivityManager.getNetworkTypeName(transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400397 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
398 mNetworkCapabilities = new NetworkCapabilities();
399 mNetworkCapabilities.addTransportType(transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400400 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900401 case TRANSPORT_ETHERNET:
402 mScore = 70;
403 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400404 case TRANSPORT_WIFI:
Paul Jensen3d911462015-06-12 06:40:24 -0400405 mScore = 60;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400406 break;
407 case TRANSPORT_CELLULAR:
Paul Jensen3d911462015-06-12 06:40:24 -0400408 mScore = 50;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400409 break;
Hugo Benichi16f0a942017-06-20 14:07:59 +0900410 case TRANSPORT_WIFI_AWARE:
411 mScore = 20;
412 break;
Chalard Jean0b214af2018-01-12 17:22:49 +0900413 case TRANSPORT_VPN:
Chalard Jeanb552c462018-02-21 18:43:54 +0900414 mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN);
Chalard Jeandda156a2018-01-10 21:19:32 +0900415 mScore = ConnectivityConstants.VPN_DEFAULT_SCORE;
Chalard Jean0b214af2018-01-12 17:22:49 +0900416 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400417 default:
418 throw new UnsupportedOperationException("unimplemented network type");
419 }
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900420 mHandlerThread = new HandlerThread("Mock-" + typeName);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900421 mHandlerThread.start();
422 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
423 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
Rubin Xu1bb5c082017-09-05 18:40:49 +0100424 linkProperties, mScore, new NetworkMisc()) {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900425 @Override
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900426 public void unwanted() { mDisconnected.open(); }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900427
428 @Override
429 public void startPacketKeepalive(Message msg) {
430 int slot = msg.arg1;
431 if (mExpectedKeepaliveSlot != null) {
432 assertEquals((int) mExpectedKeepaliveSlot, slot);
433 }
434 onPacketKeepaliveEvent(slot, mStartKeepaliveError);
435 }
436
437 @Override
438 public void stopPacketKeepalive(Message msg) {
439 onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
440 }
Paul Jensen232437312016-04-06 09:51:26 -0400441
442 @Override
443 public void networkStatus(int status, String redirectUrl) {
444 mRedirectUrl = redirectUrl;
445 mNetworkStatusReceived.open();
446 }
Calvin On1f64f3f2016-10-11 15:10:46 -0700447
448 @Override
449 protected void preventAutomaticReconnect() {
450 mPreventReconnectReceived.open();
451 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400452 };
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900453 // Waits for the NetworkAgent to be registered, which includes the creation of the
454 // NetworkMonitor.
Hugo Benichibb91c572017-05-22 10:44:02 +0900455 waitForIdle();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400456 mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor();
Paul Jensen3d911462015-06-12 06:40:24 -0400457 }
458
459 public void adjustScore(int change) {
460 mScore += change;
461 mNetworkAgent.sendNetworkScore(mScore);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400462 }
463
Lorenzo Colitti02cc8392017-05-17 01:28:09 +0900464 public void explicitlySelected(boolean acceptUnvalidated) {
465 mNetworkAgent.explicitlySelected(acceptUnvalidated);
466 }
467
Paul Jensen85cf78e2015-06-25 13:25:07 -0400468 public void addCapability(int capability) {
469 mNetworkCapabilities.addCapability(capability);
470 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
471 }
472
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900473 public void removeCapability(int capability) {
474 mNetworkCapabilities.removeCapability(capability);
475 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
476 }
477
Chalard Jean0b214af2018-01-12 17:22:49 +0900478 public void setUids(Set<UidRange> uids) {
479 mNetworkCapabilities.setUids(uids);
480 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
481 }
482
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900483 public void setSignalStrength(int signalStrength) {
484 mNetworkCapabilities.setSignalStrength(signalStrength);
485 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
486 }
487
Etan Cohena7434272017-04-03 12:17:51 -0700488 public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
489 mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
Lorenzo Colitti6556a222017-04-03 17:46:35 +0900490 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
491 }
492
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900493 public void setNetworkCapabilities(NetworkCapabilities nc,
494 boolean sendToConnectivityService) {
495 mNetworkCapabilities.set(nc);
496 if (sendToConnectivityService) {
497 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
498 }
499 }
500
Paul Jensene0988542015-06-25 15:30:08 -0400501 public void connectWithoutInternet() {
502 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
503 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
504 }
505
Paul Jensend7b6ca92015-05-13 14:05:12 -0400506 /**
Paul Jensene0988542015-06-25 15:30:08 -0400507 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400508 * @param validated Indicate if network should pretend to be validated.
509 */
510 public void connect(boolean validated) {
Hugo Benichi16f0a942017-06-20 14:07:59 +0900511 connect(validated, true);
512 }
513
514 /**
515 * Transition this NetworkAgent to CONNECTED state.
516 * @param validated Indicate if network should pretend to be validated.
517 * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
518 */
519 public void connect(boolean validated, boolean hasInternet) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900520 assertEquals("MockNetworkAgents can only be connected once",
521 mNetworkInfo.getDetailedState(), DetailedState.IDLE);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400522 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
523
Paul Jensend7b6ca92015-05-13 14:05:12 -0400524 NetworkCallback callback = null;
525 final ConditionVariable validatedCv = new ConditionVariable();
526 if (validated) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400527 mWrappedNetworkMonitor.gen204ProbeResult = 204;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400528 NetworkRequest request = new NetworkRequest.Builder()
529 .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
Chalard Jeanfb0c87e2018-04-18 19:18:58 +0900530 .clearCapabilities()
Paul Jensend7b6ca92015-05-13 14:05:12 -0400531 .build();
532 callback = new NetworkCallback() {
533 public void onCapabilitiesChanged(Network network,
534 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400535 if (network.equals(getNetwork()) &&
536 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400537 validatedCv.open();
538 }
539 }
540 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400541 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400542 }
Hugo Benichi16f0a942017-06-20 14:07:59 +0900543 if (hasInternet) {
544 addCapability(NET_CAPABILITY_INTERNET);
545 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400546
Paul Jensene0988542015-06-25 15:30:08 -0400547 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400548
549 if (validated) {
550 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400551 waitFor(validatedCv);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400552 mWrappedNetworkMonitor.gen204ProbeResult = 500;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400553 }
554
555 if (callback != null) mCm.unregisterNetworkCallback(callback);
556 }
557
Paul Jensen232437312016-04-06 09:51:26 -0400558 public void connectWithCaptivePortal(String redirectUrl) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400559 mWrappedNetworkMonitor.gen204ProbeResult = 200;
Paul Jensen232437312016-04-06 09:51:26 -0400560 mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400561 connect(false);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400562 }
563
Erik Kline1d3db322017-02-28 16:20:20 +0900564 public void suspend() {
565 mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null);
566 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
567 }
568
Chalard Jean804b8fb2018-01-30 22:41:41 +0900569 public void resume() {
570 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
571 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
572 }
573
Paul Jensend7b6ca92015-05-13 14:05:12 -0400574 public void disconnect() {
575 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
576 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
577 }
578
579 public Network getNetwork() {
580 return new Network(mNetworkAgent.netId);
581 }
Paul Jensene0988542015-06-25 15:30:08 -0400582
Calvin On1f64f3f2016-10-11 15:10:46 -0700583 public ConditionVariable getPreventReconnectReceived() {
584 return mPreventReconnectReceived;
585 }
586
Paul Jensene0988542015-06-25 15:30:08 -0400587 public ConditionVariable getDisconnectedCV() {
588 return mDisconnected;
589 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400590
591 public WrappedNetworkMonitor getWrappedNetworkMonitor() {
592 return mWrappedNetworkMonitor;
593 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900594
595 public void sendLinkProperties(LinkProperties lp) {
596 mNetworkAgent.sendLinkProperties(lp);
597 }
598
599 public void setStartKeepaliveError(int error) {
600 mStartKeepaliveError = error;
601 }
602
603 public void setStopKeepaliveError(int error) {
604 mStopKeepaliveError = error;
605 }
606
607 public void setExpectedKeepaliveSlot(Integer slot) {
608 mExpectedKeepaliveSlot = slot;
609 }
Paul Jensen232437312016-04-06 09:51:26 -0400610
611 public String waitForRedirectUrl() {
612 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
613 return mRedirectUrl;
614 }
Chalard Jean804b8fb2018-01-30 22:41:41 +0900615
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900616 public NetworkAgent getNetworkAgent() {
617 return mNetworkAgent;
618 }
619
Chalard Jean804b8fb2018-01-30 22:41:41 +0900620 public NetworkCapabilities getNetworkCapabilities() {
621 return mNetworkCapabilities;
622 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400623 }
624
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900625 /**
626 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
627 * operations have been processed. Before ConnectivityService can add or remove any requests,
628 * the factory must be told to expect those operations by calling expectAddRequests or
629 * expectRemoveRequests.
630 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700631 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400632 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
633 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400634 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700635
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900636 // Used to expect that requests be removed or added on a separate thread, without sleeping.
637 // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then
638 // cause some other thread to add or remove requests, then call waitForRequests(). We can
639 // either expect requests to be added or removed, but not both, because CountDownLatch can
640 // only count in one direction.
641 private CountDownLatch mExpectations;
642
643 // Whether we are currently expecting requests to be added or removed. Valid only if
644 // mExpectations is non-null.
645 private boolean mExpectingAdditions;
646
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700647 public MockNetworkFactory(Looper looper, Context context, String logTag,
648 NetworkCapabilities filter) {
649 super(looper, context, logTag, filter);
650 }
651
652 public int getMyRequestCount() {
653 return getRequestCount();
654 }
655
656 protected void startNetwork() {
657 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400658 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700659 }
660
661 protected void stopNetwork() {
662 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400663 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700664 }
665
666 public boolean getMyStartRequested() {
667 return mNetworkStarted.get();
668 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400669
670 public ConditionVariable getNetworkStartedCV() {
671 mNetworkStartedCV.close();
672 return mNetworkStartedCV;
673 }
674
675 public ConditionVariable getNetworkStoppedCV() {
676 mNetworkStoppedCV.close();
677 return mNetworkStoppedCV;
678 }
679
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900680 @Override
681 protected void handleAddRequest(NetworkRequest request, int score) {
682 // If we're expecting anything, we must be expecting additions.
683 if (mExpectations != null && !mExpectingAdditions) {
684 fail("Can't add requests while expecting requests to be removed");
685 }
686
687 // Add the request.
688 super.handleAddRequest(request, score);
689
690 // Reduce the number of request additions we're waiting for.
691 if (mExpectingAdditions) {
692 assertTrue("Added more requests than expected", mExpectations.getCount() > 0);
693 mExpectations.countDown();
694 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400695 }
696
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900697 @Override
698 protected void handleRemoveRequest(NetworkRequest request) {
699 // If we're expecting anything, we must be expecting removals.
700 if (mExpectations != null && mExpectingAdditions) {
701 fail("Can't remove requests while expecting requests to be added");
702 }
703
704 // Remove the request.
705 super.handleRemoveRequest(request);
706
707 // Reduce the number of request removals we're waiting for.
708 if (!mExpectingAdditions) {
709 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0);
710 mExpectations.countDown();
711 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400712 }
713
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900714 private void assertNoExpectations() {
715 if (mExpectations != null) {
716 fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
717 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400718 }
719
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900720 // Expects that count requests will be added.
721 public void expectAddRequests(final int count) {
722 assertNoExpectations();
723 mExpectingAdditions = true;
724 mExpectations = new CountDownLatch(count);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400725 }
726
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900727 // Expects that count requests will be removed.
728 public void expectRemoveRequests(final int count) {
729 assertNoExpectations();
730 mExpectingAdditions = false;
731 mExpectations = new CountDownLatch(count);
732 }
733
734 // Waits for the expected request additions or removals to happen within a timeout.
735 public void waitForRequests() throws InterruptedException {
736 assertNotNull("Nothing to wait for", mExpectations);
737 mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
738 final long count = mExpectations.getCount();
739 final String msg = count + " requests still not " +
740 (mExpectingAdditions ? "added" : "removed") +
741 " after " + TIMEOUT_MS + " ms";
742 assertEquals(msg, 0, count);
743 mExpectations = null;
744 }
745
746 public void waitForNetworkRequests(final int count) throws InterruptedException {
747 waitForRequests();
748 assertEquals(count, getMyRequestCount());
Paul Jensen0a2823e2015-06-12 10:31:09 -0400749 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700750 }
751
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900752 private static Looper startHandlerThreadAndReturnLooper() {
753 final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
754 handlerThread.start();
755 return handlerThread.getLooper();
756 }
757
758 private class MockVpn extends Vpn {
759 // TODO : the interactions between this mock and the mock network agent are too
760 // hard to get right at this moment, because it's unclear in which case which
761 // target needs to get a method call or both, and in what order. It's because
762 // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn
763 // parent class of MockVpn agent wants that responsibility.
764 // That being said inside the test it should be possible to make the interactions
765 // harder to get wrong with precise speccing, judicious comments, helper methods
766 // and a few sprinkled assertions.
767
768 private boolean mConnected = false;
769 // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
770 // not inherit from NetworkAgent.
771 private MockNetworkAgent mMockNetworkAgent;
772
773 public MockVpn(int userId) {
774 super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
775 userId);
776 }
777
778 public void setNetworkAgent(MockNetworkAgent agent) {
779 waitForIdle(agent, TIMEOUT_MS);
780 mMockNetworkAgent = agent;
781 mNetworkAgent = agent.getNetworkAgent();
782 mNetworkCapabilities.set(agent.getNetworkCapabilities());
783 }
784
785 public void setUids(Set<UidRange> uids) {
786 mNetworkCapabilities.setUids(uids);
787 updateCapabilities();
788 }
789
790 @Override
791 public int getNetId() {
792 return mMockNetworkAgent.getNetwork().netId;
793 }
794
795 @Override
796 public boolean appliesToUid(int uid) {
797 return mConnected; // Trickery to simplify testing.
798 }
799
800 @Override
801 protected boolean isCallerEstablishedOwnerLocked() {
802 return mConnected; // Similar trickery
803 }
804
805 public void connect() {
806 mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
807 mConnected = true;
808 mConfig = new VpnConfig();
809 }
810
811 @Override
812 public void updateCapabilities() {
813 if (!mConnected) return;
814 super.updateCapabilities();
815 // Because super.updateCapabilities will update the capabilities of the agent but not
816 // the mock agent, the mock agent needs to know about them.
817 copyCapabilitiesToNetworkAgent();
818 }
819
820 private void copyCapabilitiesToNetworkAgent() {
821 if (null != mMockNetworkAgent) {
822 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
823 false /* sendToConnectivityService */);
824 }
825 }
826
827 public void disconnect() {
828 mConnected = false;
829 mConfig = null;
830 }
831 }
832
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900833 private class FakeWakeupMessage extends WakeupMessage {
834 private static final int UNREASONABLY_LONG_WAIT = 1000;
835
836 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
837 super(context, handler, cmdName, cmd);
838 }
839
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900840 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
841 int arg1, int arg2, Object obj) {
842 super(context, handler, cmdName, cmd, arg1, arg2, obj);
843 }
844
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900845 @Override
846 public void schedule(long when) {
847 long delayMs = when - SystemClock.elapsedRealtime();
848 if (delayMs < 0) delayMs = 0;
849 if (delayMs > UNREASONABLY_LONG_WAIT) {
850 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
851 "ms into the future: " + delayMs);
852 }
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900853 Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
854 mHandler.sendMessageDelayed(msg, delayMs);
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900855 }
856
857 @Override
858 public void cancel() {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900859 mHandler.removeMessages(mCmd, mObj);
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900860 }
861
862 @Override
863 public void onAlarm() {
864 throw new AssertionError("Should never happen. Update this fake.");
865 }
866 }
867
Paul Jensencf4c2c62015-07-01 14:16:32 -0400868 // NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
869 private class WrappedNetworkMonitor extends NetworkMonitor {
Erik Kline79c6d052018-03-21 07:18:33 -0700870 public final Handler connectivityHandler;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400871 // HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
872 public int gen204ProbeResult = 500;
Paul Jensen232437312016-04-06 09:51:26 -0400873 public String gen204ProbeRedirectUrl = null;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400874
875 public WrappedNetworkMonitor(Context context, Handler handler,
Hugo Benichif9fdf872016-07-28 17:53:06 +0900876 NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest,
877 IpConnectivityLog log) {
Hugo Benichic894b122017-07-31 12:58:20 +0900878 super(context, handler, networkAgentInfo, defaultRequest, log,
879 NetworkMonitor.NetworkMonitorSettings.DEFAULT);
Erik Kline117e7f32018-03-04 21:01:01 +0900880 connectivityHandler = handler;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400881 }
882
883 @Override
Paul Jensen232437312016-04-06 09:51:26 -0400884 protected CaptivePortalProbeResult isCaptivePortal() {
Calvin On1f64f3f2016-10-11 15:10:46 -0700885 if (!mIsCaptivePortalCheckEnabled) { return new CaptivePortalProbeResult(204); }
Hugo Benichid953bf82016-09-27 09:22:35 +0900886 return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl, null);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400887 }
888 }
889
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900890 private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
Hugo Benichi53d83d52016-11-15 13:42:34 +0900891 public volatile boolean configRestrictsAvoidBadWifi;
Lorenzo Colitti2de49252017-01-24 18:08:41 +0900892 public volatile int configMeteredMultipathPreference;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400893
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900894 public WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
Erik Kline065ab6e2016-10-02 18:02:14 +0900895 super(c, h, r);
896 }
897
898 @Override
899 public boolean configRestrictsAvoidBadWifi() {
900 return configRestrictsAvoidBadWifi;
901 }
Lorenzo Colitti2de49252017-01-24 18:08:41 +0900902
903 @Override
904 public int configMeteredMultipathPreference() {
905 return configMeteredMultipathPreference;
906 }
Erik Kline065ab6e2016-10-02 18:02:14 +0900907 }
908
909 private class WrappedConnectivityService extends ConnectivityService {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900910 public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
Erik Kline065ab6e2016-10-02 18:02:14 +0900911 private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900912 private MockableSystemProperties mSystemProperties;
Erik Kline065ab6e2016-10-02 18:02:14 +0900913
Paul Jensend7b6ca92015-05-13 14:05:12 -0400914 public WrappedConnectivityService(Context context, INetworkManagementService netManager,
Hugo Benichif9fdf872016-07-28 17:53:06 +0900915 INetworkStatsService statsService, INetworkPolicyManager policyManager,
916 IpConnectivityLog log) {
917 super(context, netManager, statsService, policyManager, log);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900918 mLingerDelayMs = TEST_LINGER_DELAY_MS;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400919 }
920
921 @Override
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900922 protected MockableSystemProperties getSystemProperties() {
923 // Minimal approach to overriding system properties: let most calls fall through to real
924 // device values, and only override ones values that are important to this test.
925 mSystemProperties = spy(new MockableSystemProperties());
926 when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
927 when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
928 return mSystemProperties;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400929 }
Paul Jensen67b0b072015-06-10 11:22:17 -0400930
931 @Override
932 protected int reserveNetId() {
933 while (true) {
934 final int netId = super.reserveNetId();
935
936 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
937 // can have odd side-effects, like network validations succeeding.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900938 Context context = InstrumentationRegistry.getContext();
939 final Network[] networks = ConnectivityManager.from(context).getAllNetworks();
Paul Jensen67b0b072015-06-10 11:22:17 -0400940 boolean overlaps = false;
941 for (Network network : networks) {
942 if (netId == network.netId) {
943 overlaps = true;
944 break;
945 }
946 }
947 if (overlaps) continue;
948
949 return netId;
950 }
951 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400952
953 @Override
954 public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
955 NetworkAgentInfo nai, NetworkRequest defaultRequest) {
Hugo Benichif9fdf872016-07-28 17:53:06 +0900956 final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(
957 context, handler, nai, defaultRequest, mock(IpConnectivityLog.class));
Paul Jensencf4c2c62015-07-01 14:16:32 -0400958 mLastCreatedNetworkMonitor = monitor;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400959 return monitor;
960 }
961
junyulai4a192e22018-06-13 15:00:37 +0800962 public Nat464Xlat getNat464Xlat(MockNetworkAgent mna) {
963 return getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
964 }
965
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900966 @Override
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900967 public MultinetworkPolicyTracker createMultinetworkPolicyTracker(
Erik Kline065ab6e2016-10-02 18:02:14 +0900968 Context c, Handler h, Runnable r) {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900969 final WrappedMultinetworkPolicyTracker tracker = new WrappedMultinetworkPolicyTracker(c, h, r);
Erik Kline065ab6e2016-10-02 18:02:14 +0900970 return tracker;
971 }
972
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900973 public WrappedMultinetworkPolicyTracker getMultinetworkPolicyTracker() {
974 return (WrappedMultinetworkPolicyTracker) mMultinetworkPolicyTracker;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900975 }
976
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900977 @Override
Erik Kline065ab6e2016-10-02 18:02:14 +0900978 public WakeupMessage makeWakeupMessage(
979 Context context, Handler handler, String cmdName, int cmd, Object obj) {
980 return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900981 }
982
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +0900983 @Override
984 public boolean hasService(String name) {
985 // Currenty, the only relevant service that ConnectivityService checks for is
986 // ETHERNET_SERVICE.
987 return Context.ETHERNET_SERVICE.equals(name);
988 }
989
Hugo Benichi64901e52017-10-19 14:42:40 +0900990 @Override
991 protected IpConnectivityMetrics.Logger metricsLogger() {
992 return mMetricsService;
993 }
994
dalyk1fcb7392018-03-05 12:42:22 -0500995 @Override
996 protected void registerNetdEventCallback() {
997 }
998
Paul Jensencf4c2c62015-07-01 14:16:32 -0400999 public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
1000 return mLastCreatedNetworkMonitor;
1001 }
1002
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001003 public void mockVpn(int uid) {
1004 synchronized (mVpns) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001005 int userId = UserHandle.getUserId(uid);
1006 mMockVpn = new MockVpn(userId);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001007 // This has no effect unless the VPN is actually connected, because things like
1008 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
1009 // netId, and check if that network is actually connected.
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001010 mVpns.put(userId, mMockVpn);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001011 }
1012 }
1013
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001014 public void waitForIdle(int timeoutMs) {
Hugo Benichiad4db4e2016-10-17 15:54:51 +09001015 waitForIdleHandler(mHandlerThread, timeoutMs);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001016 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001017
1018 public void waitForIdle() {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001019 waitForIdle(TIMEOUT_MS);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001020 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001021 }
1022
Paul Jensen3d911462015-06-12 06:40:24 -04001023 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001024 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1025 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -04001026 */
1027 static private void waitFor(ConditionVariable conditionVariable) {
Hugo Benichi16f0a942017-06-20 14:07:59 +09001028 if (conditionVariable.block(TIMEOUT_MS)) {
1029 return;
1030 }
1031 fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
Paul Jensen3d911462015-06-12 06:40:24 -04001032 }
1033
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001034 @Before
Paul Jensend7b6ca92015-05-13 14:05:12 -04001035 public void setUp() throws Exception {
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001036 mContext = InstrumentationRegistry.getContext();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001037
Hugo Benichi64901e52017-10-19 14:42:40 +09001038 MockitoAnnotations.initMocks(this);
1039 when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
1040
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001041 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1042 // http://b/25897652 .
1043 if (Looper.myLooper() == null) {
1044 Looper.prepare();
1045 }
1046
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001047 mServiceContext = new MockContext(InstrumentationRegistry.getContext());
Hugo Benichi938ab4f2017-02-11 17:04:43 +09001048 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
1049 LocalServices.addService(
1050 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001051 mService = new WrappedConnectivityService(mServiceContext,
Erik Klinee89953b2018-01-11 16:11:10 +09001052 mNetworkManagementService,
Jeff Sharkey72f9c422017-10-27 17:22:59 -06001053 mStatsService,
Hugo Benichif9fdf872016-07-28 17:53:06 +09001054 mock(INetworkPolicyManager.class),
1055 mock(IpConnectivityLog.class));
Paul Jensend7b6ca92015-05-13 14:05:12 -04001056
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001057 // Create local CM before sending system ready so that we can answer
1058 // getSystemService() correctly.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001059 mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001060 mService.systemReady();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001061 mService.mockVpn(Process.myUid());
Lorenzo Colitti531a3442016-03-01 12:55:58 +09001062 mCm.bindProcessToNetwork(null);
Calvin On1f64f3f2016-10-11 15:10:46 -07001063
1064 // Ensure that the default setting for Captive Portals is used for most tests
1065 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001066 setMobileDataAlwaysOn(false);
Erik Kline79c6d052018-03-21 07:18:33 -07001067 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Paul Jensend7b6ca92015-05-13 14:05:12 -04001068 }
1069
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001070 @After
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001071 public void tearDown() throws Exception {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09001072 setMobileDataAlwaysOn(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001073 if (mCellNetworkAgent != null) {
1074 mCellNetworkAgent.disconnect();
1075 mCellNetworkAgent = null;
1076 }
1077 if (mWiFiNetworkAgent != null) {
1078 mWiFiNetworkAgent.disconnect();
1079 mWiFiNetworkAgent = null;
1080 }
1081 if (mEthernetNetworkAgent != null) {
1082 mEthernetNetworkAgent.disconnect();
1083 mEthernetNetworkAgent = null;
1084 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001085 }
1086
Hugo Benichibb91c572017-05-22 10:44:02 +09001087 private static int transportToLegacyType(int transport) {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001088 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001089 case TRANSPORT_ETHERNET:
1090 return TYPE_ETHERNET;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001091 case TRANSPORT_WIFI:
1092 return TYPE_WIFI;
1093 case TRANSPORT_CELLULAR:
1094 return TYPE_MOBILE;
1095 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001096 return TYPE_NONE;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001097 }
1098 }
1099
1100 private void verifyActiveNetwork(int transport) {
1101 // Test getActiveNetworkInfo()
1102 assertNotNull(mCm.getActiveNetworkInfo());
1103 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
1104 // Test getActiveNetwork()
1105 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001106 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Hugo Benichi16f0a942017-06-20 14:07:59 +09001107 if (!NetworkCapabilities.isValidTransport(transport)) {
1108 throw new IllegalStateException("Unknown transport " + transport);
1109 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001110 switch (transport) {
1111 case TRANSPORT_WIFI:
1112 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
1113 break;
1114 case TRANSPORT_CELLULAR:
1115 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
1116 break;
1117 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001118 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001119 }
1120 // Test getNetworkInfo(Network)
1121 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
Hugo Benichibb91c572017-05-22 10:44:02 +09001122 assertEquals(transportToLegacyType(transport),
1123 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001124 // Test getNetworkCapabilities(Network)
1125 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
1126 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
1127 }
1128
1129 private void verifyNoNetwork() {
Hugo Benichic1014502017-07-19 10:10:52 +09001130 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001131 // Test getActiveNetworkInfo()
1132 assertNull(mCm.getActiveNetworkInfo());
1133 // Test getActiveNetwork()
1134 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001135 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -04001136 // Test getAllNetworks()
Hugo Benichifed512a2017-06-26 10:06:49 +09001137 assertEmpty(mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001138 }
1139
1140 /**
1141 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
1142 * broadcasts are received.
1143 */
1144 private ConditionVariable waitForConnectivityBroadcasts(final int count) {
1145 final ConditionVariable cv = new ConditionVariable();
1146 mServiceContext.registerReceiver(new BroadcastReceiver() {
1147 private int remaining = count;
1148 public void onReceive(Context context, Intent intent) {
1149 if (--remaining == 0) {
1150 cv.open();
1151 mServiceContext.unregisterReceiver(this);
1152 }
1153 }
1154 }, new IntentFilter(CONNECTIVITY_ACTION));
1155 return cv;
1156 }
1157
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001158 @Test
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001159 public void testNetworkTypes() {
1160 // Ensure that our mocks for the networkAttributes config variable work as expected. If they
1161 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
1162 // will fail. Failing here is much easier to debug.
1163 assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
1164 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001165 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
1166 assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
1167
1168 // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
1169 // mocks, this assert exercises the ConnectivityService code path that ensures that
1170 // TYPE_ETHERNET is supported if the ethernet service is running.
1171 assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001172 }
1173
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001174 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001175 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001176 verifyNoNetwork();
1177 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1178 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1179 assertNull(mCm.getActiveNetworkInfo());
1180 assertNull(mCm.getActiveNetwork());
1181 // Test bringing up validated cellular.
1182 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1183 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001184 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001185 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichifed512a2017-06-26 10:06:49 +09001186 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001187 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1188 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1189 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
1190 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
1191 // Test bringing up validated WiFi.
1192 cv = waitForConnectivityBroadcasts(2);
1193 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001194 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001195 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001196 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001197 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1198 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1199 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
1200 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
1201 // Test cellular linger timeout.
Lorenzo Colittid2706122017-01-30 17:45:49 +09001202 waitFor(mCellNetworkAgent.getDisconnectedCV());
Hugo Benichibb91c572017-05-22 10:44:02 +09001203 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09001204 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001205 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001206 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001207 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
1208 // Test WiFi disconnect.
1209 cv = waitForConnectivityBroadcasts(1);
1210 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001211 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001212 verifyNoNetwork();
1213 }
1214
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001215 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001216 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
1217 // Test bringing up unvalidated WiFi
1218 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1219 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1220 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001221 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001222 verifyActiveNetwork(TRANSPORT_WIFI);
1223 // Test bringing up unvalidated cellular
1224 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1225 mCellNetworkAgent.connect(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001226 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001227 verifyActiveNetwork(TRANSPORT_WIFI);
1228 // Test cellular disconnect.
1229 mCellNetworkAgent.disconnect();
Hugo Benichibb91c572017-05-22 10:44:02 +09001230 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001231 verifyActiveNetwork(TRANSPORT_WIFI);
1232 // Test bringing up validated cellular
1233 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1234 cv = waitForConnectivityBroadcasts(2);
1235 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001236 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001237 verifyActiveNetwork(TRANSPORT_CELLULAR);
1238 // Test cellular disconnect.
1239 cv = waitForConnectivityBroadcasts(2);
1240 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001241 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001242 verifyActiveNetwork(TRANSPORT_WIFI);
1243 // Test WiFi disconnect.
1244 cv = waitForConnectivityBroadcasts(1);
1245 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001246 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001247 verifyNoNetwork();
1248 }
1249
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001250 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001251 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
1252 // Test bringing up unvalidated cellular.
1253 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1254 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1255 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001256 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001257 verifyActiveNetwork(TRANSPORT_CELLULAR);
1258 // Test bringing up unvalidated WiFi.
1259 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1260 cv = waitForConnectivityBroadcasts(2);
1261 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001262 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001263 verifyActiveNetwork(TRANSPORT_WIFI);
1264 // Test WiFi disconnect.
1265 cv = waitForConnectivityBroadcasts(2);
1266 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001267 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001268 verifyActiveNetwork(TRANSPORT_CELLULAR);
1269 // Test cellular disconnect.
1270 cv = waitForConnectivityBroadcasts(1);
1271 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001272 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001273 verifyNoNetwork();
1274 }
1275
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001276 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001277 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04001278 // Test bringing up unvalidated WiFi.
Paul Jensene0988542015-06-25 15:30:08 -04001279 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001280 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1281 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -04001282 waitFor(cv);
1283 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001284 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001285 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -04001286 // Test bringing up validated cellular.
1287 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001288 cv = waitForConnectivityBroadcasts(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001289 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -04001290 waitFor(cv);
1291 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001292 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1293 NET_CAPABILITY_VALIDATED));
1294 // Test cellular disconnect.
1295 cv = waitForConnectivityBroadcasts(2);
1296 mCellNetworkAgent.disconnect();
1297 waitFor(cv);
1298 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001299 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001300 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001301 NET_CAPABILITY_VALIDATED));
1302 }
1303
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001304 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001305 public void testCellularOutscoresWeakWifi() throws Exception {
1306 // Test bringing up validated cellular.
1307 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1308 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1309 mCellNetworkAgent.connect(true);
1310 waitFor(cv);
1311 verifyActiveNetwork(TRANSPORT_CELLULAR);
1312 // Test bringing up validated WiFi.
1313 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1314 cv = waitForConnectivityBroadcasts(2);
1315 mWiFiNetworkAgent.connect(true);
1316 waitFor(cv);
1317 verifyActiveNetwork(TRANSPORT_WIFI);
1318 // Test WiFi getting really weak.
1319 cv = waitForConnectivityBroadcasts(2);
1320 mWiFiNetworkAgent.adjustScore(-11);
1321 waitFor(cv);
1322 verifyActiveNetwork(TRANSPORT_CELLULAR);
1323 // Test WiFi restoring signal strength.
1324 cv = waitForConnectivityBroadcasts(2);
1325 mWiFiNetworkAgent.adjustScore(11);
1326 waitFor(cv);
1327 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001328 }
1329
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001330 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001331 public void testReapingNetwork() throws Exception {
1332 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1333 // Expect it to be torn down immediately because it satisfies no requests.
1334 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1335 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
1336 mWiFiNetworkAgent.connectWithoutInternet();
1337 waitFor(cv);
1338 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1339 // Expect it to be torn down immediately because it satisfies no requests.
1340 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1341 cv = mCellNetworkAgent.getDisconnectedCV();
1342 mCellNetworkAgent.connectWithoutInternet();
1343 waitFor(cv);
1344 // Test bringing up validated WiFi.
1345 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1346 cv = waitForConnectivityBroadcasts(1);
1347 mWiFiNetworkAgent.connect(true);
1348 waitFor(cv);
1349 verifyActiveNetwork(TRANSPORT_WIFI);
1350 // Test bringing up unvalidated cellular.
1351 // Expect it to be torn down because it could never be the highest scoring network
1352 // satisfying the default request even if it validated.
1353 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1354 cv = mCellNetworkAgent.getDisconnectedCV();
1355 mCellNetworkAgent.connect(false);
1356 waitFor(cv);
1357 verifyActiveNetwork(TRANSPORT_WIFI);
1358 cv = mWiFiNetworkAgent.getDisconnectedCV();
1359 mWiFiNetworkAgent.disconnect();
1360 waitFor(cv);
1361 }
1362
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001363 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001364 public void testCellularFallback() throws Exception {
1365 // Test bringing up validated cellular.
1366 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1367 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1368 mCellNetworkAgent.connect(true);
1369 waitFor(cv);
1370 verifyActiveNetwork(TRANSPORT_CELLULAR);
1371 // Test bringing up validated WiFi.
1372 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1373 cv = waitForConnectivityBroadcasts(2);
1374 mWiFiNetworkAgent.connect(true);
1375 waitFor(cv);
1376 verifyActiveNetwork(TRANSPORT_WIFI);
1377 // Reevaluate WiFi (it'll instantly fail DNS).
1378 cv = waitForConnectivityBroadcasts(2);
1379 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1380 NET_CAPABILITY_VALIDATED));
1381 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1382 // Should quickly fall back to Cellular.
1383 waitFor(cv);
1384 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1385 NET_CAPABILITY_VALIDATED));
1386 verifyActiveNetwork(TRANSPORT_CELLULAR);
1387 // Reevaluate cellular (it'll instantly fail DNS).
1388 cv = waitForConnectivityBroadcasts(2);
1389 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1390 NET_CAPABILITY_VALIDATED));
1391 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1392 // Should quickly fall back to WiFi.
1393 waitFor(cv);
1394 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1395 NET_CAPABILITY_VALIDATED));
1396 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1397 NET_CAPABILITY_VALIDATED));
1398 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001399 }
1400
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001401 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001402 public void testWiFiFallback() throws Exception {
1403 // Test bringing up unvalidated WiFi.
1404 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1405 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1406 mWiFiNetworkAgent.connect(false);
1407 waitFor(cv);
1408 verifyActiveNetwork(TRANSPORT_WIFI);
1409 // Test bringing up validated cellular.
1410 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1411 cv = waitForConnectivityBroadcasts(2);
1412 mCellNetworkAgent.connect(true);
1413 waitFor(cv);
1414 verifyActiveNetwork(TRANSPORT_CELLULAR);
1415 // Reevaluate cellular (it'll instantly fail DNS).
1416 cv = waitForConnectivityBroadcasts(2);
1417 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1418 NET_CAPABILITY_VALIDATED));
1419 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1420 // Should quickly fall back to WiFi.
1421 waitFor(cv);
1422 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1423 NET_CAPABILITY_VALIDATED));
1424 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001425 }
1426
Paul Jensen3d911462015-06-12 06:40:24 -04001427 enum CallbackState {
1428 NONE,
1429 AVAILABLE,
Erik Klineacdd6392016-07-07 16:50:58 +09001430 NETWORK_CAPABILITIES,
1431 LINK_PROPERTIES,
Erik Kline1d3db322017-02-28 16:20:20 +09001432 SUSPENDED,
Chalard Jean804b8fb2018-01-30 22:41:41 +09001433 RESUMED,
Paul Jensen3d911462015-06-12 06:40:24 -04001434 LOSING,
Erik Kline3841a482015-11-25 12:49:38 +09001435 LOST,
1436 UNAVAILABLE
Paul Jensen3d911462015-06-12 06:40:24 -04001437 }
1438
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001439 private static class CallbackInfo {
1440 public final CallbackState state;
1441 public final Network network;
1442 public final Object arg;
1443 public CallbackInfo(CallbackState s, Network n, Object o) {
1444 state = s; network = n; arg = o;
1445 }
1446 public String toString() {
Erik Kline1d3db322017-02-28 16:20:20 +09001447 return String.format("%s (%s) (%s)", state, network, arg);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001448 }
1449 @Override
1450 public boolean equals(Object o) {
1451 if (!(o instanceof CallbackInfo)) return false;
1452 // Ignore timeMs, since it's unpredictable.
1453 CallbackInfo other = (CallbackInfo) o;
1454 return (state == other.state) && Objects.equals(network, other.network);
1455 }
1456 @Override
1457 public int hashCode() {
1458 return Objects.hash(state, network);
1459 }
1460 }
1461
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001462 /**
1463 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1464 * this class receives, by calling expectCallback() exactly once each time a callback is
1465 * received. assertNoCallback may be called at any time.
1466 */
Paul Jensen3d911462015-06-12 06:40:24 -04001467 private class TestNetworkCallback extends NetworkCallback {
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001468 // Chosen to be less than the linger timeout. This ensures that we can distinguish
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001469 // between a LOST callback that arrives immediately and a LOST callback that arrives after
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001470 // the linger timeout. For this, our assertions should run fast enough to leave less than
1471 // (mService.mLingerDelayMs - TIMEOUT_MS) between the time callbacks are supposedly fired,
1472 // and the time we call expectCallback.
Hugo Benichidfb559a2016-12-20 14:57:49 +09001473 private final static int TIMEOUT_MS = 100;
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001474
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001475 private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001476 private Network mLastAvailableNetwork;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001477
Erik Klineacdd6392016-07-07 16:50:58 +09001478 protected void setLastCallback(CallbackState state, Network network, Object o) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001479 mCallbacks.offer(new CallbackInfo(state, network, o));
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001480 }
Paul Jensen3d911462015-06-12 06:40:24 -04001481
Erik Klineacdd6392016-07-07 16:50:58 +09001482 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001483 public void onAvailable(Network network) {
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001484 mLastAvailableNetwork = network;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001485 setLastCallback(CallbackState.AVAILABLE, network, null);
Paul Jensen3d911462015-06-12 06:40:24 -04001486 }
1487
Erik Klineacdd6392016-07-07 16:50:58 +09001488 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001489 public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
1490 setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
1491 }
1492
1493 @Override
1494 public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
1495 setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
1496 }
1497
1498 @Override
Erik Kline3841a482015-11-25 12:49:38 +09001499 public void onUnavailable() {
1500 setLastCallback(CallbackState.UNAVAILABLE, null, null);
1501 }
1502
1503 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001504 public void onNetworkSuspended(Network network) {
1505 setLastCallback(CallbackState.SUSPENDED, network, null);
1506 }
1507
1508 @Override
Chalard Jean804b8fb2018-01-30 22:41:41 +09001509 public void onNetworkResumed(Network network) {
1510 setLastCallback(CallbackState.RESUMED, network, null);
1511 }
1512
1513 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001514 public void onLosing(Network network, int maxMsToLive) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001515 setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
Paul Jensen3d911462015-06-12 06:40:24 -04001516 }
1517
Erik Klineacdd6392016-07-07 16:50:58 +09001518 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001519 public void onLost(Network network) {
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001520 mLastAvailableNetwork = null;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001521 setLastCallback(CallbackState.LOST, network, null);
1522 }
1523
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001524 public Network getLastAvailableNetwork() {
1525 return mLastAvailableNetwork;
1526 }
1527
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001528 CallbackInfo nextCallback(int timeoutMs) {
1529 CallbackInfo cb = null;
1530 try {
1531 cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
1532 } catch (InterruptedException e) {
1533 }
1534 if (cb == null) {
1535 // LinkedBlockingQueue.poll() returns null if it timeouts.
1536 fail("Did not receive callback after " + timeoutMs + "ms");
1537 }
1538 return cb;
1539 }
1540
Erik Kline1d3db322017-02-28 16:20:20 +09001541 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs) {
1542 final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null;
1543 CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001544 CallbackInfo actual = nextCallback(timeoutMs);
1545 assertEquals("Unexpected callback:", expected, actual);
Erik Kline1d3db322017-02-28 16:20:20 +09001546
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001547 if (state == CallbackState.LOSING) {
1548 String msg = String.format(
1549 "Invalid linger time value %d, must be between %d and %d",
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001550 actual.arg, 0, mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001551 int maxMsToLive = (Integer) actual.arg;
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001552 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001553 }
Erik Kline1d3db322017-02-28 16:20:20 +09001554
1555 return actual;
Erik Klinea2d29402016-03-16 15:31:39 +09001556 }
1557
Erik Kline1d3db322017-02-28 16:20:20 +09001558 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) {
1559 return expectCallback(state, agent, TIMEOUT_MS);
1560 }
1561
Hugo Benichi16f0a942017-06-20 14:07:59 +09001562 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) {
1563 return expectCallbackLike(fn, TIMEOUT_MS);
1564 }
1565
1566 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs) {
1567 int timeLeft = timeoutMs;
1568 while (timeLeft > 0) {
1569 long start = SystemClock.elapsedRealtime();
1570 CallbackInfo info = nextCallback(timeLeft);
1571 if (fn.test(info)) {
1572 return info;
1573 }
1574 timeLeft -= (SystemClock.elapsedRealtime() - start);
1575 }
1576 fail("Did not receive expected callback after " + timeoutMs + "ms");
1577 return null;
1578 }
1579
Lorenzo Colitti27334542018-01-12 16:22:21 +09001580 // Expects onAvailable and the callbacks that follow it. These are:
1581 // - onSuspended, iff the network was suspended when the callbacks fire.
1582 // - onCapabilitiesChanged.
1583 // - onLinkPropertiesChanged.
1584 //
1585 // @param agent the network to expect the callbacks on.
1586 // @param expectSuspended whether to expect a SUSPENDED callback.
1587 // @param expectValidated the expected value of the VALIDATED capability in the
1588 // onCapabilitiesChanged callback.
1589 // @param timeoutMs how long to wait for the callbacks.
1590 void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended,
1591 boolean expectValidated, int timeoutMs) {
Erik Kline1d3db322017-02-28 16:20:20 +09001592 expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
Erik Klinec75d4fa2017-02-15 19:59:17 +09001593 if (expectSuspended) {
1594 expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001595 }
Lorenzo Colitti27334542018-01-12 16:22:21 +09001596 if (expectValidated) {
Chalard Jean1fa777d2018-02-16 16:07:53 +09001597 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001598 } else {
Chalard Jean1fa777d2018-02-16 16:07:53 +09001599 expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001600 }
Erik Klinec75d4fa2017-02-15 19:59:17 +09001601 expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001602 }
1603
Lorenzo Colitti27334542018-01-12 16:22:21 +09001604 // Expects the available callbacks (validated), plus onSuspended.
1605 void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) {
1606 expectAvailableCallbacks(agent, true, expectValidated, TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001607 }
1608
Lorenzo Colitti27334542018-01-12 16:22:21 +09001609 void expectAvailableCallbacksValidated(MockNetworkAgent agent) {
1610 expectAvailableCallbacks(agent, false, true, TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001611 }
1612
Lorenzo Colitti27334542018-01-12 16:22:21 +09001613 void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) {
1614 expectAvailableCallbacks(agent, false, false, TIMEOUT_MS);
1615 }
1616
1617 // Expects the available callbacks (where the onCapabilitiesChanged must contain the
1618 // VALIDATED capability), plus another onCapabilitiesChanged which is identical to the
1619 // one we just sent.
1620 // TODO: this is likely a bug. Fix it and remove this method.
1621 void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) {
1622 expectCallback(CallbackState.AVAILABLE, agent, TIMEOUT_MS);
1623 NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1624 expectCallback(CallbackState.LINK_PROPERTIES, agent, TIMEOUT_MS);
1625 NetworkCapabilities nc2 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1626 assertEquals(nc1, nc2);
1627 }
1628
1629 // Expects the available callbacks where the onCapabilitiesChanged must not have validated,
1630 // then expects another onCapabilitiesChanged that has the validated bit set. This is used
1631 // when a network connects and satisfies a callback, and then immediately validates.
1632 void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) {
1633 expectAvailableCallbacksUnvalidated(agent);
Erik Kline1d3db322017-02-28 16:20:20 +09001634 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1635 }
1636
Lorenzo Colitti27334542018-01-12 16:22:21 +09001637 NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
Chalard Jean1fa777d2018-02-16 16:07:53 +09001638 return expectCapabilitiesWith(capability, agent, TIMEOUT_MS);
1639 }
1640
1641 NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent,
1642 int timeoutMs) {
1643 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001644 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1645 assertTrue(nc.hasCapability(capability));
Lorenzo Colitti27334542018-01-12 16:22:21 +09001646 return nc;
Erik Kline1d3db322017-02-28 16:20:20 +09001647 }
1648
Lorenzo Colitti27334542018-01-12 16:22:21 +09001649 NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
Chalard Jean1fa777d2018-02-16 16:07:53 +09001650 return expectCapabilitiesWithout(capability, agent, TIMEOUT_MS);
1651 }
1652
1653 NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent,
1654 int timeoutMs) {
1655 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001656 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1657 assertFalse(nc.hasCapability(capability));
Lorenzo Colitti27334542018-01-12 16:22:21 +09001658 return nc;
Paul Jensen3d911462015-06-12 06:40:24 -04001659 }
1660
Chalard Jean0b214af2018-01-12 17:22:49 +09001661 void expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent) {
1662 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001663 assertTrue("Received capabilities don't match expectations : " + cbi.arg,
1664 fn.test((NetworkCapabilities) cbi.arg));
Chalard Jean0b214af2018-01-12 17:22:49 +09001665 }
1666
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001667 void assertNoCallback() {
Hugo Benichibb91c572017-05-22 10:44:02 +09001668 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001669 CallbackInfo c = mCallbacks.peek();
1670 assertNull("Unexpected callback: " + c, c);
1671 }
1672 }
1673
1674 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1675 // only be declared in a static or top level type".
1676 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1677 for (TestNetworkCallback c : callbacks) {
1678 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001679 }
1680 }
1681
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001682 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001683 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001684 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001685 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1686 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001687 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1688 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001689 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1690 .addTransportType(TRANSPORT_WIFI).build();
1691 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1692 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001693 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001694 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1695 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1696
1697 // Test unvalidated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001698 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1699 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1700 mCellNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001701 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1702 cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001703 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1704 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001705 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001706
Paul Jensen3d911462015-06-12 06:40:24 -04001707 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1708 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001709 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001710 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001711 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1712
Paul Jensen3d911462015-06-12 06:40:24 -04001713 cv = waitForConnectivityBroadcasts(2);
1714 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1715 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001716 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1717 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001718 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1719 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001720 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001721
Paul Jensen3d911462015-06-12 06:40:24 -04001722 cv = waitForConnectivityBroadcasts(2);
1723 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001724 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1725 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001726 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001727 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001728 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001729
Paul Jensen3d911462015-06-12 06:40:24 -04001730 cv = waitForConnectivityBroadcasts(1);
1731 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001732 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1733 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001734 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001735 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001736
1737 // Test validated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001738 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1739 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001740 genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1741 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001742 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001743 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001744
Paul Jensen3d911462015-06-12 06:40:24 -04001745 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1746 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001747 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001748 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001749 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1750
Paul Jensen3d911462015-06-12 06:40:24 -04001751 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1752 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001753 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001754 genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001755 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001756 wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001757 cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001758 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001759 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001760
Paul Jensen3d911462015-06-12 06:40:24 -04001761 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001762 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1763 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1764 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001765
Paul Jensen3d911462015-06-12 06:40:24 -04001766 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001767 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1768 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1769 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001770 }
1771
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001772 @Test
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001773 public void testMultipleLingering() {
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001774 // This test would be flaky with the default 120ms timer: that is short enough that
1775 // lingered networks are torn down before assertions can be run. We don't want to mock the
1776 // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
1777 // in detecting races.
1778 mService.mLingerDelayMs = 300;
1779
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001780 NetworkRequest request = new NetworkRequest.Builder()
1781 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1782 .build();
1783 TestNetworkCallback callback = new TestNetworkCallback();
1784 mCm.registerNetworkCallback(request, callback);
1785
1786 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1787 mCm.registerDefaultNetworkCallback(defaultCallback);
1788
1789 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1790 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1791 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
1792
1793 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1794 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1795 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1796
1797 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001798 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1799 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001800 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001801 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001802
1803 mWiFiNetworkAgent.connect(true);
1804 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1805 // We then get LOSING when wifi validates and cell is outscored.
Lorenzo Colitti27334542018-01-12 16:22:21 +09001806 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001807 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001808 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001809 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001810 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001811 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001812 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001813
1814 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001815 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001816 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001817 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001818 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001819 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001820 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001821 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001822
1823 mEthernetNetworkAgent.disconnect();
1824 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1825 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001826 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001827 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001828
1829 for (int i = 0; i < 4; i++) {
1830 MockNetworkAgent oldNetwork, newNetwork;
1831 if (i % 2 == 0) {
1832 mWiFiNetworkAgent.adjustScore(-15);
1833 oldNetwork = mWiFiNetworkAgent;
1834 newNetwork = mCellNetworkAgent;
1835 } else {
1836 mWiFiNetworkAgent.adjustScore(15);
1837 oldNetwork = mCellNetworkAgent;
1838 newNetwork = mWiFiNetworkAgent;
1839
1840 }
1841 callback.expectCallback(CallbackState.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001842 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1843 // longer lingering?
Lorenzo Colitti27334542018-01-12 16:22:21 +09001844 defaultCallback.expectAvailableCallbacksValidated(newNetwork);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001845 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
1846 }
1847 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1848
1849 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
1850 // if the network is still up.
1851 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
Erik Kline1d3db322017-02-28 16:20:20 +09001852 // We expect a notification about the capabilities change, and nothing else.
1853 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
1854 defaultCallback.assertNoCallback();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001855 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001856 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001857
1858 // Wifi no longer satisfies our listen, which is for an unmetered network.
1859 // But because its score is 55, it's still up (and the default network).
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001860 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1861
1862 // Disconnect our test networks.
1863 mWiFiNetworkAgent.disconnect();
1864 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001865 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001866 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001867 mCellNetworkAgent.disconnect();
1868 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001869 waitForIdle();
1870 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001871
1872 mCm.unregisterNetworkCallback(callback);
Hugo Benichibb91c572017-05-22 10:44:02 +09001873 waitForIdle();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001874
1875 // Check that a network is only lingered or torn down if it would not satisfy a request even
1876 // if it validated.
1877 request = new NetworkRequest.Builder().clearCapabilities().build();
1878 callback = new TestNetworkCallback();
1879
1880 mCm.registerNetworkCallback(request, callback);
1881
1882 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1883 mCellNetworkAgent.connect(false); // Score: 10
Lorenzo Colitti27334542018-01-12 16:22:21 +09001884 callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1885 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001886 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001887 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001888
1889 // Bring up wifi with a score of 20.
1890 // Cell stays up because it would satisfy the default request if it validated.
1891 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1892 mWiFiNetworkAgent.connect(false); // Score: 20
Lorenzo Colitti27334542018-01-12 16:22:21 +09001893 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1894 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001895 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001896 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001897
1898 mWiFiNetworkAgent.disconnect();
1899 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1900 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001901 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001902 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001903 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001904
1905 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001906 // Cell is lingered because it would not satisfy any request, even if it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001907 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1908 mWiFiNetworkAgent.adjustScore(50);
1909 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti27334542018-01-12 16:22:21 +09001910 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001911 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001912 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001913 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001914 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001915
1916 // Tear down wifi.
1917 mWiFiNetworkAgent.disconnect();
1918 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1919 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001920 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001921 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001922 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001923
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001924 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
1925 // it's arguably correct to linger it, since it was the default network before it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001926 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1927 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001928 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001929 // TODO: Investigate sending validated before losing.
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001930 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001931 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001932 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001933 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001934 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001935
1936 mWiFiNetworkAgent.disconnect();
1937 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001938 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001939 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001940 mCellNetworkAgent.disconnect();
1941 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1942 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001943 waitForIdle();
1944 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001945
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001946 // If a network is lingering, and we add and remove a request from it, resume lingering.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001947 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1948 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001949 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1950 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001951 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001952 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1953 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001954 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
1955 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001956 // TODO: Investigate sending validated before losing.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001957 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001958 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001959 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001960
1961 NetworkRequest cellRequest = new NetworkRequest.Builder()
1962 .addTransportType(TRANSPORT_CELLULAR).build();
1963 NetworkCallback noopCallback = new NetworkCallback();
1964 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001965 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
1966 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001967 mCm.unregisterNetworkCallback(noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001968 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001969
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001970 // Similar to the above: lingering can start even after the lingered request is removed.
1971 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001972 mWiFiNetworkAgent.disconnect();
1973 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001974 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001975 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001976 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001977
1978 // Cell is now the default network. Pin it with a cell-specific request.
1979 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
1980 mCm.requestNetwork(cellRequest, noopCallback);
1981
1982 // Now connect wifi, and expect it to become the default network.
1983 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1984 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001985 callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
1986 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001987 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001988 // The default request is lingering on cell, but nothing happens to cell, and we send no
1989 // callbacks for it, because it's kept up by cellRequest.
1990 callback.assertNoCallback();
1991 // Now unregister cellRequest and expect cell to start lingering.
1992 mCm.unregisterNetworkCallback(noopCallback);
1993 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1994
1995 // Let linger run its course.
1996 callback.assertNoCallback();
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001997 final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
Hugo Benichidfb559a2016-12-20 14:57:49 +09001998 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001999
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002000 // Register a TRACK_DEFAULT request and check that it does not affect lingering.
2001 TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
2002 mCm.registerDefaultNetworkCallback(trackDefaultCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002003 trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002004 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2005 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002006 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002007 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
2008 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002009 trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
2010 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002011 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002012
2013 // Let linger run its course.
2014 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
2015
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002016 // Clean up.
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002017 mEthernetNetworkAgent.disconnect();
2018 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2019 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2020 trackDefaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002021
2022 mCm.unregisterNetworkCallback(callback);
2023 mCm.unregisterNetworkCallback(defaultCallback);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002024 mCm.unregisterNetworkCallback(trackDefaultCallback);
2025 }
2026
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002027 @Test
Chalard Jean1fa777d2018-02-16 16:07:53 +09002028 public void testNetworkGoesIntoBackgroundAfterLinger() {
2029 setMobileDataAlwaysOn(true);
2030 NetworkRequest request = new NetworkRequest.Builder()
2031 .clearCapabilities()
2032 .build();
2033 TestNetworkCallback callback = new TestNetworkCallback();
2034 mCm.registerNetworkCallback(request, callback);
2035
2036 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2037 mCm.registerDefaultNetworkCallback(defaultCallback);
2038
2039 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2040 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2041
2042 mCellNetworkAgent.connect(true);
2043 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2044 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2045
2046 // Wifi comes up and cell lingers.
2047 mWiFiNetworkAgent.connect(true);
2048 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2049 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2050 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2051 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2052
2053 // File a request for cellular, then release it.
2054 NetworkRequest cellRequest = new NetworkRequest.Builder()
2055 .addTransportType(TRANSPORT_CELLULAR).build();
2056 NetworkCallback noopCallback = new NetworkCallback();
2057 mCm.requestNetwork(cellRequest, noopCallback);
2058 mCm.unregisterNetworkCallback(noopCallback);
2059 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2060
2061 // Let linger run its course.
Chalard Jeanb72b62d2018-02-16 16:08:35 +09002062 callback.assertNoCallback();
Chalard Jean1fa777d2018-02-16 16:07:53 +09002063 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2064 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
2065 lingerTimeoutMs);
2066
2067 // Clean up.
2068 mCm.unregisterNetworkCallback(defaultCallback);
2069 mCm.unregisterNetworkCallback(callback);
2070 }
2071
2072 @Test
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002073 public void testExplicitlySelected() {
2074 NetworkRequest request = new NetworkRequest.Builder()
2075 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2076 .build();
2077 TestNetworkCallback callback = new TestNetworkCallback();
2078 mCm.registerNetworkCallback(request, callback);
2079
2080 // Bring up validated cell.
2081 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2082 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002083 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002084
2085 // Bring up unvalidated wifi with explicitlySelected=true.
2086 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2087 mWiFiNetworkAgent.explicitlySelected(false);
2088 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002089 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002090
2091 // Cell Remains the default.
2092 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2093
2094 // Lower wifi's score to below than cell, and check that it doesn't disconnect because
2095 // it's explicitly selected.
2096 mWiFiNetworkAgent.adjustScore(-40);
2097 mWiFiNetworkAgent.adjustScore(40);
2098 callback.assertNoCallback();
2099
2100 // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
2101 // wifi even though it's unvalidated.
2102 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
2103 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2104 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2105
2106 // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
2107 mWiFiNetworkAgent.disconnect();
2108 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2109 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2110 mWiFiNetworkAgent.explicitlySelected(false);
2111 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002112 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002113
2114 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
2115 // network to disconnect.
2116 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
2117 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2118
2119 // Reconnect, again with explicitlySelected=true, but this time validate.
2120 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2121 mWiFiNetworkAgent.explicitlySelected(false);
2122 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002123 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002124 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2125 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2126 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2127
2128 // BUG: the network will no longer linger, even though it's validated and outscored.
2129 // TODO: fix this.
2130 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2131 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002132 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002133 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2134 callback.assertNoCallback();
2135
2136 // Clean up.
2137 mWiFiNetworkAgent.disconnect();
2138 mCellNetworkAgent.disconnect();
2139 mEthernetNetworkAgent.disconnect();
2140
2141 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2142 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2143 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002144 }
2145
Paul Jensen85cf78e2015-06-25 13:25:07 -04002146 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04002147 // Verify NOT_RESTRICTED is set appropriately
2148 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
2149 .build().networkCapabilities;
2150 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
2151 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
2152 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04002153 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04002154 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2155 } else {
2156 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2157 }
2158
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002159 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002160 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002161 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
2162 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04002163 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002164 mServiceContext, "testFactory", filter);
2165 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04002166 ConditionVariable cv = testFactory.getNetworkStartedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002167 testFactory.expectAddRequests(1);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002168 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002169 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002170 int expectedRequestCount = 1;
2171 NetworkCallback networkCallback = null;
2172 // For non-INTERNET capabilities we cannot rely on the default request being present, so
2173 // add one.
2174 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04002175 assertFalse(testFactory.getMyStartRequested());
2176 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
2177 networkCallback = new NetworkCallback();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002178 testFactory.expectAddRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002179 mCm.requestNetwork(request, networkCallback);
2180 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002181 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002182 }
Paul Jensen3d911462015-06-12 06:40:24 -04002183 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002184 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2185 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002186
Paul Jensen85cf78e2015-06-25 13:25:07 -04002187 // Now bring in a higher scored network.
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002188 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002189 // Rather than create a validated network which complicates things by registering it's
2190 // own NetworkRequest during startup, just bump up the score to cancel out the
2191 // unvalidated penalty.
2192 testAgent.adjustScore(40);
2193 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002194
2195 // When testAgent connects, ConnectivityService will re-send us all current requests with
2196 // the new score. There are expectedRequestCount such requests, and we must wait for all of
2197 // them.
2198 testFactory.expectAddRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002199 testAgent.connect(false);
2200 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04002201 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002202 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002203 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002204
Paul Jensen85cf78e2015-06-25 13:25:07 -04002205 // Bring in a bunch of requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002206 testFactory.expectAddRequests(10);
2207 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002208 ConnectivityManager.NetworkCallback[] networkCallbacks =
2209 new ConnectivityManager.NetworkCallback[10];
2210 for (int i = 0; i< networkCallbacks.length; i++) {
2211 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
2212 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002213 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002214 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
2215 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002216 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
2217 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002218
Paul Jensen85cf78e2015-06-25 13:25:07 -04002219 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002220 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002221 for (int i = 0; i < networkCallbacks.length; i++) {
2222 mCm.unregisterNetworkCallback(networkCallbacks[i]);
2223 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002224 testFactory.waitForNetworkRequests(expectedRequestCount);
2225 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002226
Paul Jensen85cf78e2015-06-25 13:25:07 -04002227 // Drop the higher scored network.
2228 cv = testFactory.getNetworkStartedCV();
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002229 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04002230 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002231 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2232 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002233
2234 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002235 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002236 handlerThread.quit();
2237 }
2238
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002239 @Test
Paul Jensen85cf78e2015-06-25 13:25:07 -04002240 public void testNetworkFactoryRequests() throws Exception {
2241 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
2242 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
2243 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
2244 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
2245 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
2246 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
2247 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
2248 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
2249 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
2250 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
2251 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
2252 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
2253 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
2254 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
2255 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
2256 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
2257 }
2258
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002259 @Test
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002260 public void testNoMutableNetworkRequests() throws Exception {
2261 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
Hugo Benichi16f0a942017-06-20 14:07:59 +09002262 NetworkRequest request1 = new NetworkRequest.Builder()
2263 .addCapability(NET_CAPABILITY_VALIDATED)
2264 .build();
2265 NetworkRequest request2 = new NetworkRequest.Builder()
2266 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
2267 .build();
2268
2269 Class<IllegalArgumentException> expected = IllegalArgumentException.class;
2270 assertException(() -> { mCm.requestNetwork(request1, new NetworkCallback()); }, expected);
2271 assertException(() -> { mCm.requestNetwork(request1, pendingIntent); }, expected);
2272 assertException(() -> { mCm.requestNetwork(request2, new NetworkCallback()); }, expected);
2273 assertException(() -> { mCm.requestNetwork(request2, pendingIntent); }, expected);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002274 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002275
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002276 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002277 public void testMMSonWiFi() throws Exception {
2278 // Test bringing up cellular without MMS NetworkRequest gets reaped
2279 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2280 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2281 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
2282 mCellNetworkAgent.connectWithoutInternet();
2283 waitFor(cv);
Hugo Benichibb91c572017-05-22 10:44:02 +09002284 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09002285 assertEmpty(mCm.getAllNetworks());
Paul Jensene0988542015-06-25 15:30:08 -04002286 verifyNoNetwork();
Hugo Benichibb91c572017-05-22 10:44:02 +09002287
Paul Jensene0988542015-06-25 15:30:08 -04002288 // Test bringing up validated WiFi.
2289 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2290 cv = waitForConnectivityBroadcasts(1);
2291 mWiFiNetworkAgent.connect(true);
2292 waitFor(cv);
2293 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002294
Paul Jensene0988542015-06-25 15:30:08 -04002295 // Register MMS NetworkRequest
2296 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2297 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2298 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2299 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002300
Paul Jensene0988542015-06-25 15:30:08 -04002301 // Test bringing up unvalidated cellular with MMS
2302 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2303 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002304 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002305 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002306 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002307
Paul Jensene0988542015-06-25 15:30:08 -04002308 // Test releasing NetworkRequest disconnects cellular with MMS
2309 cv = mCellNetworkAgent.getDisconnectedCV();
2310 mCm.unregisterNetworkCallback(networkCallback);
2311 waitFor(cv);
2312 verifyActiveNetwork(TRANSPORT_WIFI);
2313 }
2314
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002315 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002316 public void testMMSonCell() throws Exception {
2317 // Test bringing up cellular without MMS
2318 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2319 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2320 mCellNetworkAgent.connect(false);
2321 waitFor(cv);
2322 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002323
Paul Jensene0988542015-06-25 15:30:08 -04002324 // Register MMS NetworkRequest
2325 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2326 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2327 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2328 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002329
Paul Jensene0988542015-06-25 15:30:08 -04002330 // Test bringing up MMS cellular network
Paul Jensene0988542015-06-25 15:30:08 -04002331 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2332 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2333 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002334 networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002335 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002336
Paul Jensene0988542015-06-25 15:30:08 -04002337 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
2338 cv = mmsNetworkAgent.getDisconnectedCV();
2339 mCm.unregisterNetworkCallback(networkCallback);
2340 waitFor(cv);
2341 verifyActiveNetwork(TRANSPORT_CELLULAR);
2342 }
2343
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002344 @Test
Paul Jensencf4c2c62015-07-01 14:16:32 -04002345 public void testCaptivePortal() {
2346 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2347 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2348 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2349 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2350
2351 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2352 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2353 .addCapability(NET_CAPABILITY_VALIDATED).build();
2354 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002355
2356 // Bring up a network with a captive portal.
2357 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002358 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002359 String firstRedirectUrl = "http://example.com/firstPath";
2360 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002361 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002362 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002363
2364 // Take down network.
2365 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002366 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002367 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002368
2369 // Bring up a network with a captive portal.
2370 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002371 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002372 String secondRedirectUrl = "http://example.com/secondPath";
2373 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002374 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002375 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002376
2377 // Make captive portal disappear then revalidate.
2378 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002379 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
2380 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002381 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002382
2383 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002384 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002385
2386 // Break network connectivity.
2387 // Expect NET_CAPABILITY_VALIDATED onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002388 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
2389 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002390 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002391 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002392
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002393 @Test
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002394 public void testCaptivePortalApp() {
2395 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2396 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2397 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2398 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2399
2400 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2401 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2402 .addCapability(NET_CAPABILITY_VALIDATED).build();
2403 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2404
2405 // Bring up wifi.
2406 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2407 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002408 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002409 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2410
2411 // Check that calling startCaptivePortalApp does nothing.
2412 final int fastTimeoutMs = 100;
2413 mCm.startCaptivePortalApp(wifiNetwork);
2414 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
2415
2416 // Turn into a captive portal.
2417 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 302;
2418 mCm.reportNetworkConnectivity(wifiNetwork, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002419 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002420 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2421
2422 // Check that startCaptivePortalApp sends the expected intent.
2423 mCm.startCaptivePortalApp(wifiNetwork);
2424 Intent intent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
2425 assertEquals(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN, intent.getAction());
2426 assertEquals(wifiNetwork, intent.getExtra(ConnectivityManager.EXTRA_NETWORK));
2427
2428 // Have the app report that the captive portal is dismissed, and check that we revalidate.
2429 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
2430 CaptivePortal c = (CaptivePortal) intent.getExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
2431 c.reportCaptivePortalDismissed();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002432 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002433 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2434
2435 mCm.unregisterNetworkCallback(validatedCallback);
2436 mCm.unregisterNetworkCallback(captivePortalCallback);
2437 }
2438
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002439 @Test
Calvin On1f64f3f2016-10-11 15:10:46 -07002440 public void testAvoidOrIgnoreCaptivePortals() {
2441 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2442 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2443 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2444 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2445
2446 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2447 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2448 .addCapability(NET_CAPABILITY_VALIDATED).build();
2449 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2450
2451 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
2452 // Bring up a network with a captive portal.
2453 // Expect it to fail to connect and not result in any callbacks.
2454 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2455 String firstRedirectUrl = "http://example.com/firstPath";
2456
2457 ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
2458 ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
2459 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
2460 waitFor(disconnectCv);
2461 waitFor(avoidCv);
2462
2463 assertNoCallbacks(captivePortalCallback, validatedCallback);
2464
2465 // Now test ignore mode.
2466 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE);
2467
2468 // Bring up a network with a captive portal.
2469 // Since we're ignoring captive portals, the network will validate.
2470 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2471 String secondRedirectUrl = "http://example.com/secondPath";
2472 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
2473
2474 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002475 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Calvin On1f64f3f2016-10-11 15:10:46 -07002476 // But there should be no CaptivePortal callback.
2477 captivePortalCallback.assertNoCallback();
2478 }
2479
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002480 private NetworkRequest.Builder newWifiRequestBuilder() {
2481 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
2482 }
2483
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002484 @Test
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002485 public void testNetworkSpecifier() {
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002486 NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
Etan Cohena7434272017-04-03 12:17:51 -07002487 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002488 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
Etan Cohena7434272017-04-03 12:17:51 -07002489 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
2490 (NetworkSpecifier) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002491 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier("foo").build();
Etan Cohena7434272017-04-03 12:17:51 -07002492 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
2493 new StringNetworkSpecifier("bar")).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002494
2495 TestNetworkCallback cEmpty1 = new TestNetworkCallback();
2496 TestNetworkCallback cEmpty2 = new TestNetworkCallback();
2497 TestNetworkCallback cEmpty3 = new TestNetworkCallback();
Etan Cohena7434272017-04-03 12:17:51 -07002498 TestNetworkCallback cEmpty4 = new TestNetworkCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002499 TestNetworkCallback cFoo = new TestNetworkCallback();
2500 TestNetworkCallback cBar = new TestNetworkCallback();
2501 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
2502 cEmpty1, cEmpty2, cEmpty3 };
2503
2504 mCm.registerNetworkCallback(rEmpty1, cEmpty1);
2505 mCm.registerNetworkCallback(rEmpty2, cEmpty2);
2506 mCm.registerNetworkCallback(rEmpty3, cEmpty3);
Etan Cohena7434272017-04-03 12:17:51 -07002507 mCm.registerNetworkCallback(rEmpty4, cEmpty4);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002508 mCm.registerNetworkCallback(rFoo, cFoo);
2509 mCm.registerNetworkCallback(rBar, cBar);
2510
2511 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2512 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002513 cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2514 cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2515 cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2516 cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002517 assertNoCallbacks(cFoo, cBar);
2518
Etan Cohena7434272017-04-03 12:17:51 -07002519 mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("foo"));
Lorenzo Colitti27334542018-01-12 16:22:21 +09002520 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002521 for (TestNetworkCallback c: emptyCallbacks) {
2522 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
2523 }
2524 cFoo.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
2525 cFoo.assertNoCallback();
2526
Etan Cohena7434272017-04-03 12:17:51 -07002527 mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("bar"));
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002528 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002529 cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002530 for (TestNetworkCallback c: emptyCallbacks) {
2531 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
2532 }
2533 cBar.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
2534 cBar.assertNoCallback();
2535
2536 mWiFiNetworkAgent.setNetworkSpecifier(null);
2537 cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2538 for (TestNetworkCallback c: emptyCallbacks) {
2539 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
2540 }
2541
2542 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cFoo, cBar);
2543 }
2544
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002545 @Test
Etan Cohenddb9ef02015-11-18 10:56:15 -08002546 public void testInvalidNetworkSpecifier() {
Etan Cohenddb9ef02015-11-18 10:56:15 -08002547 try {
2548 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Etan Cohena7434272017-04-03 12:17:51 -07002549 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
2550 fail("NetworkRequest builder with MatchAllNetworkSpecifier");
2551 } catch (IllegalArgumentException expected) {
2552 // expected
Etan Cohenddb9ef02015-11-18 10:56:15 -08002553 }
2554
Etan Cohenddb9ef02015-11-18 10:56:15 -08002555 try {
2556 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
2557 networkCapabilities.addTransportType(TRANSPORT_WIFI)
Etan Cohena7434272017-04-03 12:17:51 -07002558 .setNetworkSpecifier(new MatchAllNetworkSpecifier());
Etan Cohenddb9ef02015-11-18 10:56:15 -08002559 mService.requestNetwork(networkCapabilities, null, 0, null,
2560 ConnectivityManager.TYPE_WIFI);
Etan Cohena7434272017-04-03 12:17:51 -07002561 fail("ConnectivityService requestNetwork with MatchAllNetworkSpecifier");
2562 } catch (IllegalArgumentException expected) {
2563 // expected
Etan Cohenddb9ef02015-11-18 10:56:15 -08002564 }
2565
Etan Cohena7434272017-04-03 12:17:51 -07002566 class NonParcelableSpecifier extends NetworkSpecifier {
2567 public boolean satisfiedBy(NetworkSpecifier other) { return false; }
2568 };
2569 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
2570 @Override public int describeContents() { return 0; }
2571 @Override public void writeToParcel(Parcel p, int flags) {}
2572 }
2573 NetworkRequest.Builder builder;
2574
2575 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
2576 try {
2577 builder.setNetworkSpecifier(new NonParcelableSpecifier());
2578 Parcel parcelW = Parcel.obtain();
2579 builder.build().writeToParcel(parcelW, 0);
2580 fail("Parceling a non-parcelable specifier did not throw an exception");
2581 } catch (Exception e) {
2582 // expected
2583 }
2584
2585 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
2586 builder.setNetworkSpecifier(new ParcelableSpecifier());
2587 NetworkRequest nr = builder.build();
2588 assertNotNull(nr);
2589
2590 try {
2591 Parcel parcelW = Parcel.obtain();
2592 nr.writeToParcel(parcelW, 0);
2593 byte[] bytes = parcelW.marshall();
2594 parcelW.recycle();
2595
2596 Parcel parcelR = Parcel.obtain();
2597 parcelR.unmarshall(bytes, 0, bytes.length);
2598 parcelR.setDataPosition(0);
2599 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
2600 fail("Unparceling a non-framework NetworkSpecifier did not throw an exception");
2601 } catch (Exception e) {
2602 // expected
2603 }
Etan Cohenddb9ef02015-11-18 10:56:15 -08002604 }
2605
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002606 @Test
Etan Cohen859748f2017-04-03 17:42:34 -07002607 public void testNetworkSpecifierUidSpoofSecurityException() {
2608 class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2609 @Override
2610 public boolean satisfiedBy(NetworkSpecifier other) {
2611 return true;
2612 }
2613
2614 @Override
2615 public void assertValidFromUid(int requestorUid) {
2616 throw new SecurityException("failure");
2617 }
2618
2619 @Override
2620 public int describeContents() { return 0; }
2621 @Override
2622 public void writeToParcel(Parcel dest, int flags) {}
2623 }
2624
2625 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2626 mWiFiNetworkAgent.connect(false);
2627
2628 UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
2629 NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier(
2630 networkSpecifier).build();
2631 TestNetworkCallback networkCallback = new TestNetworkCallback();
2632 try {
2633 mCm.requestNetwork(networkRequest, networkCallback);
2634 fail("Network request with spoofed UID did not throw a SecurityException");
2635 } catch (SecurityException e) {
2636 // expected
2637 }
2638 }
2639
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002640 @Test
Erik Klinea2d29402016-03-16 15:31:39 +09002641 public void testRegisterDefaultNetworkCallback() throws Exception {
2642 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
2643 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
2644 defaultNetworkCallback.assertNoCallback();
2645
2646 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
2647 // whenever Wi-Fi is up. Without this, the mobile network agent is
2648 // reaped before any other activity can take place.
2649 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2650 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2651 .addTransportType(TRANSPORT_CELLULAR).build();
2652 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2653 cellNetworkCallback.assertNoCallback();
2654
2655 // Bring up cell and expect CALLBACK_AVAILABLE.
2656 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2657 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002658 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2659 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002660 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002661
2662 // Bring up wifi and expect CALLBACK_AVAILABLE.
2663 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2664 mWiFiNetworkAgent.connect(true);
2665 cellNetworkCallback.assertNoCallback();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002666 defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002667 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002668
2669 // Bring down cell. Expect no default network callback, since it wasn't the default.
2670 mCellNetworkAgent.disconnect();
2671 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2672 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002673 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002674
2675 // Bring up cell. Expect no default network callback, since it won't be the default.
2676 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2677 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002678 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002679 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002680 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002681
2682 // Bring down wifi. Expect the default network callback to notified of LOST wifi
2683 // followed by AVAILABLE cell.
2684 mWiFiNetworkAgent.disconnect();
2685 cellNetworkCallback.assertNoCallback();
2686 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002687 defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002688 mCellNetworkAgent.disconnect();
2689 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2690 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002691 waitForIdle();
2692 assertEquals(null, mCm.getActiveNetwork());
2693
2694 final int uid = Process.myUid();
2695 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
2696 final ArraySet<UidRange> ranges = new ArraySet<>();
2697 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09002698 mMockVpn.setNetworkAgent(vpnNetworkAgent);
2699 mMockVpn.setUids(ranges);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002700 vpnNetworkAgent.connect(true);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09002701 mMockVpn.connect();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002702 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
2703 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2704
2705 vpnNetworkAgent.disconnect();
2706 defaultNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
2707 waitForIdle();
2708 assertEquals(null, mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002709 }
2710
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002711 @Test
Erik Kline1d3db322017-02-28 16:20:20 +09002712 public void testAdditionalStateCallbacks() throws Exception {
Erik Klineacdd6392016-07-07 16:50:58 +09002713 // File a network request for mobile.
Erik Kline1d3db322017-02-28 16:20:20 +09002714 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09002715 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2716 .addTransportType(TRANSPORT_CELLULAR).build();
2717 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2718
2719 // Bring up the mobile network.
2720 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2721 mCellNetworkAgent.connect(true);
2722
Erik Kline1d3db322017-02-28 16:20:20 +09002723 // We should get onAvailable(), onCapabilitiesChanged(), and
2724 // onLinkPropertiesChanged() in rapid succession. Additionally, we
2725 // should get onCapabilitiesChanged() when the mobile network validates.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002726 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09002727 cellNetworkCallback.assertNoCallback();
2728
2729 // Update LinkProperties.
2730 final LinkProperties lp = new LinkProperties();
2731 lp.setInterfaceName("foonet_data0");
2732 mCellNetworkAgent.sendLinkProperties(lp);
2733 // We should get onLinkPropertiesChanged().
2734 cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
2735 cellNetworkCallback.assertNoCallback();
2736
Erik Kline1d3db322017-02-28 16:20:20 +09002737 // Suspend the network.
2738 mCellNetworkAgent.suspend();
Chalard Jean804b8fb2018-01-30 22:41:41 +09002739 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
2740 mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002741 cellNetworkCallback.expectCallback(CallbackState.SUSPENDED, mCellNetworkAgent);
2742 cellNetworkCallback.assertNoCallback();
2743
Erik Klineacdd6392016-07-07 16:50:58 +09002744 // Register a garden variety default network request.
Chalard Jean804b8fb2018-01-30 22:41:41 +09002745 TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09002746 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09002747 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
2748 // as well as onNetworkSuspended() in rapid succession.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002749 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
Erik Klineacdd6392016-07-07 16:50:58 +09002750 dfltNetworkCallback.assertNoCallback();
Chalard Jean804b8fb2018-01-30 22:41:41 +09002751 mCm.unregisterNetworkCallback(dfltNetworkCallback);
2752
2753 mCellNetworkAgent.resume();
2754 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
2755 mCellNetworkAgent);
2756 cellNetworkCallback.expectCallback(CallbackState.RESUMED, mCellNetworkAgent);
2757 cellNetworkCallback.assertNoCallback();
2758
2759 dfltNetworkCallback = new TestNetworkCallback();
2760 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
2761 // This time onNetworkSuspended should not be called.
2762 dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
2763 dfltNetworkCallback.assertNoCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09002764
Erik Klineacdd6392016-07-07 16:50:58 +09002765 mCm.unregisterNetworkCallback(dfltNetworkCallback);
2766 mCm.unregisterNetworkCallback(cellNetworkCallback);
2767 }
2768
Calvin On1f64f3f2016-10-11 15:10:46 -07002769 private void setCaptivePortalMode(int mode) {
2770 ContentResolver cr = mServiceContext.getContentResolver();
2771 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
2772 }
2773
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002774 private void setMobileDataAlwaysOn(boolean enable) {
2775 ContentResolver cr = mServiceContext.getContentResolver();
2776 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
2777 mService.updateMobileDataAlwaysOn();
Hugo Benichibb91c572017-05-22 10:44:02 +09002778 waitForIdle();
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002779 }
2780
Erik Kline79c6d052018-03-21 07:18:33 -07002781 private void setPrivateDnsSettings(String mode, String specifier) {
2782 final ContentResolver cr = mServiceContext.getContentResolver();
2783 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
2784 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
2785 mService.updatePrivateDnsSettings();
2786 waitForIdle();
2787 }
2788
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002789 private boolean isForegroundNetwork(MockNetworkAgent network) {
2790 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
2791 assertNotNull(nc);
2792 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
2793 }
2794
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002795 @Test
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002796 public void testBackgroundNetworks() throws Exception {
2797 // Create a background request. We can't do this ourselves because ConnectivityService
2798 // doesn't have an API for it. So just turn on mobile data always on.
2799 setMobileDataAlwaysOn(true);
2800 final NetworkRequest request = new NetworkRequest.Builder().build();
2801 final NetworkRequest fgRequest = new NetworkRequest.Builder()
2802 .addCapability(NET_CAPABILITY_FOREGROUND).build();
2803 final TestNetworkCallback callback = new TestNetworkCallback();
2804 final TestNetworkCallback fgCallback = new TestNetworkCallback();
2805 mCm.registerNetworkCallback(request, callback);
2806 mCm.registerNetworkCallback(fgRequest, fgCallback);
2807
2808 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2809 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002810 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2811 fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002812 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2813
2814 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2815 mWiFiNetworkAgent.connect(true);
2816
2817 // When wifi connects, cell lingers.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002818 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002819 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002820 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002821 fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002822 fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002823 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002824 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2825 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2826
2827 // When lingering is complete, cell is still there but is now in the background.
Hugo Benichibb91c572017-05-22 10:44:02 +09002828 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09002829 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2830 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09002831 // Expect a network capabilities update sans FOREGROUND.
2832 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002833 assertFalse(isForegroundNetwork(mCellNetworkAgent));
2834 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2835
2836 // File a cell request and check that cell comes into the foreground.
2837 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2838 .addTransportType(TRANSPORT_CELLULAR).build();
2839 final TestNetworkCallback cellCallback = new TestNetworkCallback();
2840 mCm.requestNetwork(cellRequest, cellCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09002841 // NOTE: This request causes the network's capabilities to change. This
2842 // is currently delivered before the onAvailable() callbacks.
2843 // TODO: Fix this.
2844 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002845 cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
2846 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002847 // Expect a network capabilities update with FOREGROUND, because the most recent
2848 // request causes its state to change.
2849 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002850 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2851 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2852
2853 // Release the request. The network immediately goes into the background, since it was not
2854 // lingering.
2855 mCm.unregisterNetworkCallback(cellCallback);
2856 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002857 // Expect a network capabilities update sans FOREGROUND.
2858 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002859 assertFalse(isForegroundNetwork(mCellNetworkAgent));
2860 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2861
2862 // Disconnect wifi and check that cell is foreground again.
2863 mWiFiNetworkAgent.disconnect();
2864 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2865 fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002866 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002867 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2868
2869 mCm.unregisterNetworkCallback(callback);
2870 mCm.unregisterNetworkCallback(fgCallback);
2871 }
2872
Hugo Benichi849b81b2017-05-25 13:42:31 +09002873 @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09002874 public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002875 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002876 // Benchmarks connecting and switching performance in the presence of a large number of
2877 // NetworkRequests.
2878 // 1. File NUM_REQUESTS requests.
2879 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
2880 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
2881 // and NUM_REQUESTS onAvailable callbacks to fire.
2882 // See how long it took.
2883 final int NUM_REQUESTS = 90;
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09002884 final int REGISTER_TIME_LIMIT_MS = 200;
2885 final int CONNECT_TIME_LIMIT_MS = 60;
2886 final int SWITCH_TIME_LIMIT_MS = 60;
Hugo Benichibb91c572017-05-22 10:44:02 +09002887 final int UNREGISTER_TIME_LIMIT_MS = 20;
2888
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002889 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
2890 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
2891 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
2892 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
2893
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002894 for (int i = 0; i < NUM_REQUESTS; i++) {
2895 callbacks[i] = new NetworkCallback() {
2896 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
2897 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
2898 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002899 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002900
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002901 assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
2902 for (NetworkCallback cb : callbacks) {
2903 mCm.registerNetworkCallback(request, cb);
2904 }
2905 });
2906
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002907 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2908 // Don't request that the network validate, because otherwise connect() will block until
2909 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
2910 // and we won't actually measure anything.
2911 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002912
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002913 long onAvailableDispatchingDuration = durationOf(() -> {
Hugo Benichibb91c572017-05-22 10:44:02 +09002914 awaitLatch(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002915 });
Hugo Benichibb91c572017-05-22 10:44:02 +09002916 Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
2917 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
2918 onAvailableDispatchingDuration));
2919 assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
2920 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
2921 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002922
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002923 // Give wifi a high enough score that we'll linger cell when wifi comes up.
Hugo Benichibb91c572017-05-22 10:44:02 +09002924 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002925 mWiFiNetworkAgent.adjustScore(40);
2926 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002927
2928 long onLostDispatchingDuration = durationOf(() -> {
Hugo Benichibb91c572017-05-22 10:44:02 +09002929 awaitLatch(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002930 });
Hugo Benichibb91c572017-05-22 10:44:02 +09002931 Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
2932 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
2933 assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
2934 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
2935 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002936
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002937 assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
2938 for (NetworkCallback cb : callbacks) {
2939 mCm.unregisterNetworkCallback(cb);
2940 }
2941 });
2942 }
2943
2944 private long durationOf(Runnable fn) {
2945 long startTime = SystemClock.elapsedRealtime();
2946 fn.run();
2947 return SystemClock.elapsedRealtime() - startTime;
2948 }
2949
2950 private void assertTimeLimit(String descr, long timeLimit, Runnable fn) {
2951 long timeTaken = durationOf(fn);
2952 String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002953 Log.d(TAG, msg);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002954 assertTrue(msg, timeTaken <= timeLimit);
2955 }
2956
2957 private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
2958 try {
Hugo Benichibb91c572017-05-22 10:44:02 +09002959 return l.await(timeoutMs, TimeUnit.MILLISECONDS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09002960 } catch (InterruptedException e) {}
2961 return false;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002962 }
2963
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002964 @Test
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002965 public void testMobileDataAlwaysOn() throws Exception {
2966 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2967 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2968 .addTransportType(TRANSPORT_CELLULAR).build();
2969 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
2970
2971 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
2972 handlerThread.start();
2973 NetworkCapabilities filter = new NetworkCapabilities()
2974 .addTransportType(TRANSPORT_CELLULAR)
2975 .addCapability(NET_CAPABILITY_INTERNET);
2976 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
2977 mServiceContext, "testFactory", filter);
2978 testFactory.setScoreFilter(40);
2979
2980 // Register the factory and expect it to start looking for a network.
2981 testFactory.expectAddRequests(1);
2982 testFactory.register();
2983 testFactory.waitForNetworkRequests(1);
2984 assertTrue(testFactory.getMyStartRequested());
2985
2986 // Bring up wifi. The factory stops looking for a network.
2987 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2988 testFactory.expectAddRequests(2); // Because the default request changes score twice.
2989 mWiFiNetworkAgent.connect(true);
2990 testFactory.waitForNetworkRequests(1);
2991 assertFalse(testFactory.getMyStartRequested());
2992
2993 ContentResolver cr = mServiceContext.getContentResolver();
2994
2995 // Turn on mobile data always on. The factory starts looking again.
2996 testFactory.expectAddRequests(1);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002997 setMobileDataAlwaysOn(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09002998 testFactory.waitForNetworkRequests(2);
2999 assertTrue(testFactory.getMyStartRequested());
3000
3001 // Bring up cell data and check that the factory stops looking.
Hugo Benichifed512a2017-06-26 10:06:49 +09003002 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003003 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3004 testFactory.expectAddRequests(2); // Because the cell request changes score twice.
3005 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003006 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003007 testFactory.waitForNetworkRequests(2);
3008 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
3009
3010 // Check that cell data stays up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003011 waitForIdle();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003012 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09003013 assertLength(2, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003014
3015 // Turn off mobile data always on and expect the request to disappear...
3016 testFactory.expectRemoveRequests(1);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003017 setMobileDataAlwaysOn(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003018 testFactory.waitForNetworkRequests(1);
3019
3020 // ... and cell data to be torn down.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003021 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Hugo Benichifed512a2017-06-26 10:06:49 +09003022 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003023
3024 testFactory.unregister();
3025 mCm.unregisterNetworkCallback(cellNetworkCallback);
3026 handlerThread.quit();
3027 }
3028
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003029 @Test
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003030 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003031 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09003032 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003033 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
3034
Erik Kline065ab6e2016-10-02 18:02:14 +09003035 tracker.configRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003036 String[] values = new String[] {null, "0", "1"};
3037 for (int i = 0; i < values.length; i++) {
3038 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003039 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003040 waitForIdle();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003041 String msg = String.format("config=false, setting=%s", values[i]);
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003042 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003043 assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003044 }
3045
Erik Kline065ab6e2016-10-02 18:02:14 +09003046 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003047
3048 Settings.Global.putInt(cr, settingName, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09003049 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003050 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003051 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003052 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003053
3054 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003055 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003056 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003057 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003058 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003059
3060 Settings.Global.putString(cr, settingName, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09003061 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003062 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003063 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003064 assertTrue(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003065 }
3066
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003067 @Test
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003068 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09003069 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09003070 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003071
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003072 // Pretend we're on a carrier that restricts switching away from bad wifi.
Erik Kline065ab6e2016-10-02 18:02:14 +09003073 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003074
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003075 // File a request for cell to ensure it doesn't go down.
3076 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3077 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3078 .addTransportType(TRANSPORT_CELLULAR).build();
3079 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3080
3081 TestNetworkCallback defaultCallback = new TestNetworkCallback();
3082 mCm.registerDefaultNetworkCallback(defaultCallback);
3083
3084 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
3085 .addTransportType(TRANSPORT_WIFI)
3086 .addCapability(NET_CAPABILITY_VALIDATED)
3087 .build();
3088 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
3089 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
3090
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003091 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09003092 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003093
3094 // Bring up validated cell.
3095 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3096 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003097 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3098 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003099 Network cellNetwork = mCellNetworkAgent.getNetwork();
3100
3101 // Bring up validated wifi.
3102 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3103 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003104 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3105 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003106 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
3107
3108 // Fail validation on wifi.
3109 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
3110 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003111 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003112 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3113
3114 // Because avoid bad wifi is off, we don't switch to cellular.
3115 defaultCallback.assertNoCallback();
3116 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3117 NET_CAPABILITY_VALIDATED));
3118 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3119 NET_CAPABILITY_VALIDATED));
3120 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3121
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003122 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
3123 // that we switch back to cell.
Erik Kline065ab6e2016-10-02 18:02:14 +09003124 tracker.configRestrictsAvoidBadWifi = false;
3125 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003126 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003127 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3128
3129 // Switch back to a restrictive carrier.
Erik Kline065ab6e2016-10-02 18:02:14 +09003130 tracker.configRestrictsAvoidBadWifi = true;
3131 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003132 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003133 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3134
3135 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
3136 mCm.setAvoidUnvalidated(wifiNetwork);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003137 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003138 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3139 NET_CAPABILITY_VALIDATED));
3140 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3141 NET_CAPABILITY_VALIDATED));
3142 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3143
3144 // Disconnect and reconnect wifi to clear the one-time switch above.
3145 mWiFiNetworkAgent.disconnect();
3146 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3147 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003148 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3149 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003150 wifiNetwork = mWiFiNetworkAgent.getNetwork();
3151
3152 // Fail validation on wifi and expect the dialog to appear.
3153 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
3154 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003155 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003156 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3157
3158 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003159 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003160 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003161
3162 // We now switch to cell.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003163 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003164 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3165 NET_CAPABILITY_VALIDATED));
3166 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3167 NET_CAPABILITY_VALIDATED));
3168 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3169
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003170 // Simulate the user turning the cellular fallback setting off and then on.
3171 // We switch to wifi and then to cell.
3172 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09003173 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003174 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003175 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3176 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003177 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003178 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003179 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3180
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003181 // If cell goes down, we switch to wifi.
3182 mCellNetworkAgent.disconnect();
3183 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003184 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003185 validatedWifiCallback.assertNoCallback();
3186
3187 mCm.unregisterNetworkCallback(cellNetworkCallback);
3188 mCm.unregisterNetworkCallback(validatedWifiCallback);
3189 mCm.unregisterNetworkCallback(defaultCallback);
3190 }
3191
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003192 @Test
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003193 public void testMeteredMultipathPreferenceSetting() throws Exception {
3194 final ContentResolver cr = mServiceContext.getContentResolver();
3195 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
3196 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
3197
3198 for (int config : Arrays.asList(0, 3, 2)) {
3199 for (String setting: Arrays.asList(null, "0", "2", "1")) {
3200 tracker.configMeteredMultipathPreference = config;
3201 Settings.Global.putString(cr, settingName, setting);
3202 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003203 waitForIdle();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003204
3205 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
3206 String msg = String.format("config=%d, setting=%s", config, setting);
3207 assertEquals(msg, expected, mCm.getMultipathPreference(null));
3208 }
3209 }
3210 }
3211
Erik Kline3841a482015-11-25 12:49:38 +09003212 /**
3213 * Validate that a satisfied network request does not trigger onUnavailable() once the
3214 * time-out period expires.
3215 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003216 @Test
Erik Kline3841a482015-11-25 12:49:38 +09003217 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
3218 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3219 NetworkCapabilities.TRANSPORT_WIFI).build();
3220 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003221 final int timeoutMs = 150;
3222 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003223
3224 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3225 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003226 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003227
3228 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003229 networkCallback.assertNoCallback();
3230 }
3231
3232 /**
3233 * Validate that a satisfied network request followed by a disconnected (lost) network does
3234 * not trigger onUnavailable() once the time-out period expires.
3235 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003236 @Test
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003237 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
3238 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3239 NetworkCapabilities.TRANSPORT_WIFI).build();
3240 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003241 final int requestTimeoutMs = 50;
Hugo Benichidfb559a2016-12-20 14:57:49 +09003242 mCm.requestNetwork(nr, networkCallback, requestTimeoutMs);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003243
3244 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3245 mWiFiNetworkAgent.connect(false);
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003246 final int assertTimeoutMs = 100;
Lorenzo Colitti27334542018-01-12 16:22:21 +09003247 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, assertTimeoutMs);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003248 mWiFiNetworkAgent.disconnect();
3249 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3250
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003251 // Validate that UNAVAILABLE is not called
Erik Kline3841a482015-11-25 12:49:38 +09003252 networkCallback.assertNoCallback();
3253 }
3254
3255 /**
3256 * Validate that when a time-out is specified for a network request the onUnavailable()
3257 * callback is called when time-out expires. Then validate that if network request is
3258 * (somehow) satisfied - the callback isn't called later.
3259 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003260 @Test
Erik Kline3841a482015-11-25 12:49:38 +09003261 public void testTimedoutNetworkRequest() {
3262 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3263 NetworkCapabilities.TRANSPORT_WIFI).build();
3264 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003265 final int timeoutMs = 10;
3266 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003267
3268 // pass timeout and validate that UNAVAILABLE is called
3269 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
3270
3271 // create a network satisfying request - validate that request not triggered
3272 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3273 mWiFiNetworkAgent.connect(false);
3274 networkCallback.assertNoCallback();
3275 }
3276
3277 /**
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003278 * Validate that when a network request is unregistered (cancelled), no posterior event can
3279 * trigger the callback.
Erik Kline3841a482015-11-25 12:49:38 +09003280 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003281 @Test
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003282 public void testNoCallbackAfterUnregisteredNetworkRequest() {
Erik Kline3841a482015-11-25 12:49:38 +09003283 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3284 NetworkCapabilities.TRANSPORT_WIFI).build();
3285 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003286 final int timeoutMs = 10;
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003287
Hugo Benichidfb559a2016-12-20 14:57:49 +09003288 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003289 mCm.unregisterNetworkCallback(networkCallback);
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003290 // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
3291 // that this callback will not be called.
Erik Kline3841a482015-11-25 12:49:38 +09003292 networkCallback.assertNoCallback();
3293
3294 // create a network satisfying request - validate that request not triggered
3295 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3296 mWiFiNetworkAgent.connect(false);
3297 networkCallback.assertNoCallback();
3298 }
3299
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003300 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
3301
3302 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3303
3304 private class CallbackValue {
3305 public CallbackType callbackType;
3306 public int error;
3307
3308 public CallbackValue(CallbackType type) {
3309 this.callbackType = type;
3310 this.error = PacketKeepalive.SUCCESS;
3311 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3312 }
3313
3314 public CallbackValue(CallbackType type, int error) {
3315 this.callbackType = type;
3316 this.error = error;
3317 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3318 }
3319
3320 @Override
3321 public boolean equals(Object o) {
3322 return o instanceof CallbackValue &&
3323 this.callbackType == ((CallbackValue) o).callbackType &&
3324 this.error == ((CallbackValue) o).error;
3325 }
3326
3327 @Override
3328 public String toString() {
3329 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
3330 }
3331 }
3332
3333 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
3334
3335 @Override
3336 public void onStarted() {
3337 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3338 }
3339
3340 @Override
3341 public void onStopped() {
3342 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3343 }
3344
3345 @Override
3346 public void onError(int error) {
3347 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3348 }
3349
3350 private void expectCallback(CallbackValue callbackValue) {
3351 try {
3352 assertEquals(
3353 callbackValue,
3354 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3355 } catch (InterruptedException e) {
3356 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
3357 }
3358 }
3359
3360 public void expectStarted() {
3361 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3362 }
3363
3364 public void expectStopped() {
3365 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3366 }
3367
3368 public void expectError(int error) {
3369 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3370 }
3371 }
3372
3373 private Network connectKeepaliveNetwork(LinkProperties lp) {
3374 // Ensure the network is disconnected before we do anything.
3375 if (mWiFiNetworkAgent != null) {
3376 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
3377 }
3378
3379 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3380 ConditionVariable cv = waitForConnectivityBroadcasts(1);
3381 mWiFiNetworkAgent.connect(true);
3382 waitFor(cv);
3383 verifyActiveNetwork(TRANSPORT_WIFI);
3384 mWiFiNetworkAgent.sendLinkProperties(lp);
Hugo Benichibb91c572017-05-22 10:44:02 +09003385 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003386 return mWiFiNetworkAgent.getNetwork();
3387 }
3388
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003389 @Test
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003390 public void testPacketKeepalives() throws Exception {
3391 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
3392 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
3393 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
3394 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
3395 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
3396
Nathan Harold63dd8132018-02-14 13:09:45 -08003397 final int validKaInterval = 15;
3398 final int invalidKaInterval = 9;
3399
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003400 LinkProperties lp = new LinkProperties();
3401 lp.setInterfaceName("wlan12");
3402 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
3403 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
3404 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
3405 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
3406
3407 Network notMyNet = new Network(61234);
3408 Network myNet = connectKeepaliveNetwork(lp);
3409
3410 TestKeepaliveCallback callback = new TestKeepaliveCallback();
3411 PacketKeepalive ka;
3412
3413 // Attempt to start keepalives with invalid parameters and check for errors.
Nathan Harold63dd8132018-02-14 13:09:45 -08003414 ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003415 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3416
Nathan Harold63dd8132018-02-14 13:09:45 -08003417 ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003418 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
3419
Nathan Harold63dd8132018-02-14 13:09:45 -08003420 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003421 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3422
Nathan Harold63dd8132018-02-14 13:09:45 -08003423 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003424 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3425
Nathan Harold63dd8132018-02-14 13:09:45 -08003426 // NAT-T is only supported for IPv4.
3427 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
3428 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003429
Nathan Harold63dd8132018-02-14 13:09:45 -08003430 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003431 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3432
Nathan Harold63dd8132018-02-14 13:09:45 -08003433 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003434 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3435
Nathan Harold63dd8132018-02-14 13:09:45 -08003436 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003437 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3438
Nathan Harold63dd8132018-02-14 13:09:45 -08003439 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003440 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3441
3442 // Check that a started keepalive can be stopped.
3443 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
Nathan Harold63dd8132018-02-14 13:09:45 -08003444 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003445 callback.expectStarted();
3446 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
3447 ka.stop();
3448 callback.expectStopped();
3449
3450 // Check that deleting the IP address stops the keepalive.
3451 LinkProperties bogusLp = new LinkProperties(lp);
Nathan Harold63dd8132018-02-14 13:09:45 -08003452 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003453 callback.expectStarted();
3454 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
3455 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
3456 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
3457 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3458 mWiFiNetworkAgent.sendLinkProperties(lp);
3459
3460 // Check that a started keepalive is stopped correctly when the network disconnects.
Nathan Harold63dd8132018-02-14 13:09:45 -08003461 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003462 callback.expectStarted();
3463 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003464 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003465 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3466
3467 // ... and that stopping it after that has no adverse effects.
Hugo Benichibb91c572017-05-22 10:44:02 +09003468 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003469 final Network myNetAlias = myNet;
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003470 assertNull(mCm.getNetworkCapabilities(myNetAlias));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003471 ka.stop();
3472
3473 // Reconnect.
3474 myNet = connectKeepaliveNetwork(lp);
3475 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
3476
3477 // Check things work as expected when the keepalive is stopped and the network disconnects.
Nathan Harold63dd8132018-02-14 13:09:45 -08003478 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003479 callback.expectStarted();
3480 ka.stop();
3481 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003482 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Hugo Benichibb91c572017-05-22 10:44:02 +09003483 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003484 callback.expectStopped();
3485
3486 // Reconnect.
3487 myNet = connectKeepaliveNetwork(lp);
3488 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
3489
3490 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
3491 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
Nathan Harold63dd8132018-02-14 13:09:45 -08003492 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003493 callback.expectStarted();
3494
3495 // The second one gets slot 2.
3496 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
3497 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08003498 PacketKeepalive ka2 = mCm.startNattKeepalive(
3499 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003500 callback2.expectStarted();
3501
3502 // Now stop the first one and create a third. This also gets slot 1.
3503 ka.stop();
3504 callback.expectStopped();
3505
3506 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
3507 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08003508 PacketKeepalive ka3 = mCm.startNattKeepalive(
3509 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003510 callback3.expectStarted();
3511
3512 ka2.stop();
3513 callback2.expectStopped();
3514
3515 ka3.stop();
3516 callback3.expectStopped();
3517 }
Udam Sainib7c24872016-01-04 12:16:14 -08003518
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003519 @Test
Udam Sainib7c24872016-01-04 12:16:14 -08003520 public void testGetCaptivePortalServerUrl() throws Exception {
3521 String url = mCm.getCaptivePortalServerUrl();
3522 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
3523 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09003524
3525 private static class TestNetworkPinner extends NetworkPinner {
3526 public static boolean awaitPin(int timeoutMs) {
3527 synchronized(sLock) {
3528 if (sNetwork == null) {
3529 try {
3530 sLock.wait(timeoutMs);
3531 } catch (InterruptedException e) {}
3532 }
3533 return sNetwork != null;
3534 }
3535 }
3536
3537 public static boolean awaitUnpin(int timeoutMs) {
3538 synchronized(sLock) {
3539 if (sNetwork != null) {
3540 try {
3541 sLock.wait(timeoutMs);
3542 } catch (InterruptedException e) {}
3543 }
3544 return sNetwork == null;
3545 }
3546 }
3547 }
3548
3549 private void assertPinnedToWifiWithCellDefault() {
3550 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
3551 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3552 }
3553
3554 private void assertPinnedToWifiWithWifiDefault() {
3555 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
3556 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3557 }
3558
3559 private void assertNotPinnedToWifi() {
3560 assertNull(mCm.getBoundNetworkForProcess());
3561 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3562 }
3563
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003564 @Test
Lorenzo Colitti531a3442016-03-01 12:55:58 +09003565 public void testNetworkPinner() {
3566 NetworkRequest wifiRequest = new NetworkRequest.Builder()
3567 .addTransportType(TRANSPORT_WIFI)
3568 .build();
3569 assertNull(mCm.getBoundNetworkForProcess());
3570
3571 TestNetworkPinner.pin(mServiceContext, wifiRequest);
3572 assertNull(mCm.getBoundNetworkForProcess());
3573
3574 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3575 mCellNetworkAgent.connect(true);
3576 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3577 mWiFiNetworkAgent.connect(false);
3578
3579 // When wi-fi connects, expect to be pinned.
3580 assertTrue(TestNetworkPinner.awaitPin(100));
3581 assertPinnedToWifiWithCellDefault();
3582
3583 // Disconnect and expect the pin to drop.
3584 mWiFiNetworkAgent.disconnect();
3585 assertTrue(TestNetworkPinner.awaitUnpin(100));
3586 assertNotPinnedToWifi();
3587
3588 // Reconnecting does not cause the pin to come back.
3589 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3590 mWiFiNetworkAgent.connect(false);
3591 assertFalse(TestNetworkPinner.awaitPin(100));
3592 assertNotPinnedToWifi();
3593
3594 // Pinning while connected causes the pin to take effect immediately.
3595 TestNetworkPinner.pin(mServiceContext, wifiRequest);
3596 assertTrue(TestNetworkPinner.awaitPin(100));
3597 assertPinnedToWifiWithCellDefault();
3598
3599 // Explicitly unpin and expect to use the default network again.
3600 TestNetworkPinner.unpin();
3601 assertNotPinnedToWifi();
3602
3603 // Disconnect cell and wifi.
3604 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
3605 mCellNetworkAgent.disconnect();
3606 mWiFiNetworkAgent.disconnect();
3607 waitFor(cv);
3608
3609 // Pinning takes effect even if the pinned network is the default when the pin is set...
3610 TestNetworkPinner.pin(mServiceContext, wifiRequest);
3611 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3612 mWiFiNetworkAgent.connect(false);
3613 assertTrue(TestNetworkPinner.awaitPin(100));
3614 assertPinnedToWifiWithWifiDefault();
3615
3616 // ... and is maintained even when that network is no longer the default.
3617 cv = waitForConnectivityBroadcasts(1);
3618 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3619 mCellNetworkAgent.connect(true);
3620 waitFor(cv);
3621 assertPinnedToWifiWithCellDefault();
3622 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003623
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003624 @Test
Hugo Benichi893a7622017-09-29 09:34:08 +09003625 public void testNetworkCallbackMaximum() {
Jeff Sharkeye0c29952018-02-20 17:24:55 -07003626 // We can only have 99 callbacks, because MultipathPolicyTracker is
3627 // already one of them.
3628 final int MAX_REQUESTS = 99;
3629 final int CALLBACKS = 89;
Hugo Benichi893a7622017-09-29 09:34:08 +09003630 final int INTENTS = 10;
3631 assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
3632
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003633 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
Hugo Benichi893a7622017-09-29 09:34:08 +09003634 ArrayList<Object> registered = new ArrayList<>();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003635
Hugo Benichi893a7622017-09-29 09:34:08 +09003636 int j = 0;
3637 while (j++ < CALLBACKS / 2) {
3638 NetworkCallback cb = new NetworkCallback();
3639 mCm.requestNetwork(networkRequest, cb);
3640 registered.add(cb);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003641 }
Hugo Benichi893a7622017-09-29 09:34:08 +09003642 while (j++ < CALLBACKS) {
3643 NetworkCallback cb = new NetworkCallback();
3644 mCm.registerNetworkCallback(networkRequest, cb);
3645 registered.add(cb);
3646 }
3647 j = 0;
3648 while (j++ < INTENTS / 2) {
3649 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
3650 mCm.requestNetwork(networkRequest, pi);
3651 registered.add(pi);
3652 }
3653 while (j++ < INTENTS) {
3654 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
3655 mCm.registerNetworkCallback(networkRequest, pi);
3656 registered.add(pi);
3657 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003658
Hugo Benichi893a7622017-09-29 09:34:08 +09003659 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003660 try {
Hugo Benichi893a7622017-09-29 09:34:08 +09003661 mCm.requestNetwork(networkRequest, new NetworkCallback());
3662 fail("Registering " + MAX_REQUESTS + " network requests did not throw exception");
Hugo Benichicb883232017-05-11 13:16:17 +09003663 } catch (TooManyRequestsException expected) {}
Hugo Benichi893a7622017-09-29 09:34:08 +09003664 try {
3665 mCm.registerNetworkCallback(networkRequest, new NetworkCallback());
3666 fail("Registering " + MAX_REQUESTS + " network callbacks did not throw exception");
3667 } catch (TooManyRequestsException expected) {}
3668 try {
3669 mCm.requestNetwork(networkRequest,
3670 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0));
3671 fail("Registering " + MAX_REQUESTS + " PendingIntent requests did not throw exception");
3672 } catch (TooManyRequestsException expected) {}
3673 try {
3674 mCm.registerNetworkCallback(networkRequest,
3675 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0));
3676 fail("Registering " + MAX_REQUESTS
3677 + " PendingIntent callbacks did not throw exception");
3678 } catch (TooManyRequestsException expected) {}
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003679
Hugo Benichi893a7622017-09-29 09:34:08 +09003680 for (Object o : registered) {
3681 if (o instanceof NetworkCallback) {
3682 mCm.unregisterNetworkCallback((NetworkCallback)o);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003683 }
Hugo Benichi893a7622017-09-29 09:34:08 +09003684 if (o instanceof PendingIntent) {
3685 mCm.unregisterNetworkCallback((PendingIntent)o);
3686 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003687 }
Hugo Benichi893a7622017-09-29 09:34:08 +09003688 waitForIdle();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003689
3690 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
3691 for (int i = 0; i < MAX_REQUESTS; i++) {
3692 NetworkCallback networkCallback = new NetworkCallback();
3693 mCm.requestNetwork(networkRequest, networkCallback);
3694 mCm.unregisterNetworkCallback(networkCallback);
3695 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09003696 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09003697
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003698 for (int i = 0; i < MAX_REQUESTS; i++) {
3699 NetworkCallback networkCallback = new NetworkCallback();
3700 mCm.registerNetworkCallback(networkRequest, networkCallback);
3701 mCm.unregisterNetworkCallback(networkCallback);
3702 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09003703 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09003704
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003705 for (int i = 0; i < MAX_REQUESTS; i++) {
3706 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09003707 PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003708 mCm.requestNetwork(networkRequest, pendingIntent);
3709 mCm.unregisterNetworkCallback(pendingIntent);
3710 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09003711 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09003712
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003713 for (int i = 0; i < MAX_REQUESTS; i++) {
3714 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09003715 PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04003716 mCm.registerNetworkCallback(networkRequest, pendingIntent);
3717 mCm.unregisterNetworkCallback(pendingIntent);
3718 }
3719 }
Hugo Benichifed512a2017-06-26 10:06:49 +09003720
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003721 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09003722 public void testNetworkInfoOfTypeNone() {
3723 ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1);
3724
3725 verifyNoNetwork();
Hugo Benichic1014502017-07-19 10:10:52 +09003726 MockNetworkAgent wifiAware = new MockNetworkAgent(TRANSPORT_WIFI_AWARE);
Hugo Benichi16f0a942017-06-20 14:07:59 +09003727 assertNull(mCm.getActiveNetworkInfo());
3728
3729 Network[] allNetworks = mCm.getAllNetworks();
3730 assertLength(1, allNetworks);
3731 Network network = allNetworks[0];
3732 NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
3733 assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
3734
3735 final NetworkRequest request =
3736 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
3737 final TestNetworkCallback callback = new TestNetworkCallback();
3738 mCm.registerNetworkCallback(request, callback);
3739
Hugo Benichic1014502017-07-19 10:10:52 +09003740 // Bring up wifi aware network.
3741 wifiAware.connect(false, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003742 callback.expectAvailableCallbacksUnvalidated(wifiAware);
Hugo Benichi16f0a942017-06-20 14:07:59 +09003743
3744 assertNull(mCm.getActiveNetworkInfo());
3745 assertNull(mCm.getActiveNetwork());
Hugo Benichic1014502017-07-19 10:10:52 +09003746 // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
Hugo Benichi16f0a942017-06-20 14:07:59 +09003747 // of this test. Fix it and uncomment the assert below.
3748 //assertEmpty(mCm.getAllNetworkInfo());
3749
Hugo Benichic1014502017-07-19 10:10:52 +09003750 // Disconnect wifi aware network.
3751 wifiAware.disconnect();
3752 callback.expectCallbackLike((info) -> info.state == CallbackState.LOST, TIMEOUT_MS);
Hugo Benichi16f0a942017-06-20 14:07:59 +09003753 mCm.unregisterNetworkCallback(callback);
3754
3755 verifyNoNetwork();
3756 if (broadcastCV.block(10)) {
3757 fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
3758 }
3759 }
3760
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003761 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09003762 public void testDeprecatedAndUnsupportedOperations() throws Exception {
3763 final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
3764 assertNull(mCm.getNetworkInfo(TYPE_NONE));
3765 assertNull(mCm.getNetworkForType(TYPE_NONE));
3766 assertNull(mCm.getLinkProperties(TYPE_NONE));
3767 assertFalse(mCm.isNetworkSupported(TYPE_NONE));
3768
3769 assertException(() -> { mCm.networkCapabilitiesForType(TYPE_NONE); },
3770 IllegalArgumentException.class);
3771
3772 Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
3773 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
3774 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
3775 // TODO: let test context have configuration application target sdk version
3776 // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
3777 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
3778 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
3779 assertException(() -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); }, unsupported);
3780 }
3781
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003782 @Test
Rubin Xu1bb5c082017-09-05 18:40:49 +01003783 public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() {
3784 final NetworkRequest networkRequest = new NetworkRequest.Builder()
3785 .addTransportType(TRANSPORT_WIFI).build();
3786 final TestNetworkCallback networkCallback = new TestNetworkCallback();
3787 mCm.registerNetworkCallback(networkRequest, networkCallback);
3788
3789 LinkProperties lp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07003790 lp.setInterfaceName(WIFI_IFNAME);
Rubin Xu1bb5c082017-09-05 18:40:49 +01003791 LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
3792 RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
3793 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
3794 lp.addLinkAddress(myIpv4Address);
3795 lp.addRoute(myIpv4DefaultRoute);
3796
3797 // Verify direct routes are added when network agent is first registered in
3798 // ConnectivityService.
3799 MockNetworkAgent networkAgent = new MockNetworkAgent(TRANSPORT_WIFI, lp);
3800 networkAgent.connect(true);
3801 networkCallback.expectCallback(CallbackState.AVAILABLE, networkAgent);
3802 networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent);
3803 CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
3804 networkAgent);
3805 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
3806 networkCallback.assertNoCallback();
3807 checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address),
3808 Arrays.asList(myIpv4DefaultRoute));
3809 checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
3810 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
3811
3812 // Verify direct routes are added during subsequent link properties updates.
3813 LinkProperties newLp = new LinkProperties(lp);
3814 LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
3815 LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
3816 newLp.addLinkAddress(myIpv6Address1);
3817 newLp.addLinkAddress(myIpv6Address2);
3818 networkAgent.sendLinkProperties(newLp);
3819 cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, networkAgent);
3820 networkCallback.assertNoCallback();
3821 checkDirectlyConnectedRoutes(cbi.arg,
3822 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
3823 Arrays.asList(myIpv4DefaultRoute));
3824 mCm.unregisterNetworkCallback(networkCallback);
3825 }
3826
Jeff Sharkey72f9c422017-10-27 17:22:59 -06003827 @Test
3828 public void testStatsIfacesChanged() throws Exception {
3829 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Lorenzo Colittic78da292018-01-19 00:50:48 +09003830 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3831
3832 Network[] onlyCell = new Network[]{mCellNetworkAgent.getNetwork()};
3833 Network[] onlyWifi = new Network[]{mWiFiNetworkAgent.getNetwork()};
Jeff Sharkey72f9c422017-10-27 17:22:59 -06003834
3835 // Simple connection should have updated ifaces
3836 mCellNetworkAgent.connect(false);
3837 waitForIdle();
Lorenzo Colittic78da292018-01-19 00:50:48 +09003838 verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
3839 reset(mStatsService);
3840
3841 // Default network switch should update ifaces.
3842 mWiFiNetworkAgent.connect(false);
3843 waitForIdle();
3844 verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyWifi);
3845 reset(mStatsService);
3846
3847 // Disconnect should update ifaces.
3848 mWiFiNetworkAgent.disconnect();
3849 waitForIdle();
3850 verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06003851 reset(mStatsService);
3852
3853 // Metered change should update ifaces
3854 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
3855 waitForIdle();
Lorenzo Colittic78da292018-01-19 00:50:48 +09003856 verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06003857 reset(mStatsService);
3858
3859 mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
3860 waitForIdle();
Lorenzo Colittic78da292018-01-19 00:50:48 +09003861 verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06003862 reset(mStatsService);
3863
3864 // Captive portal change shouldn't update ifaces
3865 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
3866 waitForIdle();
Lorenzo Colittic78da292018-01-19 00:50:48 +09003867 verify(mStatsService, never()).forceUpdateIfaces(onlyCell);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06003868 reset(mStatsService);
3869
3870 // Roaming change should update ifaces
3871 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
3872 waitForIdle();
Lorenzo Colittic78da292018-01-19 00:50:48 +09003873 verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06003874 reset(mStatsService);
3875 }
3876
Erik Klinee89953b2018-01-11 16:11:10 +09003877 @Test
3878 public void testBasicDnsConfigurationPushed() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07003879 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
3880 ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class);
3881
3882 // Clear any interactions that occur as a result of CS starting up.
3883 reset(mNetworkManagementService);
3884
3885 final String[] EMPTY_STRING_ARRAY = new String[0];
Erik Klinee89953b2018-01-11 16:11:10 +09003886 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3887 waitForIdle();
3888 verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
Erik Kline79c6d052018-03-21 07:18:33 -07003889 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
3890 verifyNoMoreInteractions(mNetworkManagementService);
Erik Klinee89953b2018-01-11 16:11:10 +09003891
3892 final LinkProperties cellLp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07003893 cellLp.setInterfaceName(MOBILE_IFNAME);
Erik Kline117e7f32018-03-04 21:01:01 +09003894 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
3895 // "is-reachable" testing in order to not program netd with unreachable
3896 // nameservers that it might try repeated to validate.
3897 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
Erik Kline79c6d052018-03-21 07:18:33 -07003898 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
3899 MOBILE_IFNAME));
Erik Kline117e7f32018-03-04 21:01:01 +09003900 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
Erik Kline79c6d052018-03-21 07:18:33 -07003901 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
3902 MOBILE_IFNAME));
Erik Klinee89953b2018-01-11 16:11:10 +09003903 mCellNetworkAgent.sendLinkProperties(cellLp);
3904 mCellNetworkAgent.connect(false);
3905 waitForIdle();
Erik Klinee89953b2018-01-11 16:11:10 +09003906 // CS tells netd about the empty DNS config for this network.
Erik Kline79c6d052018-03-21 07:18:33 -07003907 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
3908 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
Erik Klinee89953b2018-01-11 16:11:10 +09003909 reset(mNetworkManagementService);
3910
3911 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
3912 mCellNetworkAgent.sendLinkProperties(cellLp);
3913 waitForIdle();
Erik Kline79c6d052018-03-21 07:18:33 -07003914 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
Erik Kline117e7f32018-03-04 21:01:01 +09003915 anyInt(), mStringArrayCaptor.capture(), any(), any(),
Erik Kline79c6d052018-03-21 07:18:33 -07003916 eq(""), tlsServers.capture());
Erik Klinee89953b2018-01-11 16:11:10 +09003917 assertEquals(1, mStringArrayCaptor.getValue().length);
3918 assertTrue(ArrayUtils.contains(mStringArrayCaptor.getValue(), "2001:db8::1"));
Erik Kline79c6d052018-03-21 07:18:33 -07003919 // Opportunistic mode.
3920 assertTrue(ArrayUtils.contains(tlsServers.getValue(), "2001:db8::1"));
Erik Klinee89953b2018-01-11 16:11:10 +09003921 reset(mNetworkManagementService);
3922
3923 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
3924 mCellNetworkAgent.sendLinkProperties(cellLp);
3925 waitForIdle();
Erik Kline79c6d052018-03-21 07:18:33 -07003926 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
Erik Kline117e7f32018-03-04 21:01:01 +09003927 anyInt(), mStringArrayCaptor.capture(), any(), any(),
Erik Kline79c6d052018-03-21 07:18:33 -07003928 eq(""), tlsServers.capture());
Erik Kline117e7f32018-03-04 21:01:01 +09003929 assertEquals(2, mStringArrayCaptor.getValue().length);
3930 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
3931 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline79c6d052018-03-21 07:18:33 -07003932 // Opportunistic mode.
3933 assertEquals(2, tlsServers.getValue().length);
3934 assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
3935 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline117e7f32018-03-04 21:01:01 +09003936 reset(mNetworkManagementService);
3937
3938 final String TLS_SPECIFIER = "tls.example.com";
3939 final String TLS_SERVER6 = "2001:db8:53::53";
3940 final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
3941 final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
3942 final Handler h = mCellNetworkAgent.getWrappedNetworkMonitor().connectivityHandler;
3943 h.sendMessage(h.obtainMessage(
3944 NetworkMonitor.EVENT_PRIVATE_DNS_CONFIG_RESOLVED, 0,
3945 mCellNetworkAgent.getNetwork().netId,
3946 new DnsManager.PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS)));
3947 waitForIdle();
Erik Kline79c6d052018-03-21 07:18:33 -07003948 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
Erik Kline117e7f32018-03-04 21:01:01 +09003949 anyInt(), mStringArrayCaptor.capture(), any(), any(),
3950 eq(TLS_SPECIFIER), eq(TLS_SERVERS));
Erik Klinee89953b2018-01-11 16:11:10 +09003951 assertEquals(2, mStringArrayCaptor.getValue().length);
3952 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
3953 new String[]{"2001:db8::1", "192.0.2.1"}));
3954 reset(mNetworkManagementService);
3955 }
3956
Erik Kline79c6d052018-03-21 07:18:33 -07003957 @Test
3958 public void testPrivateDnsSettingsChange() throws Exception {
3959 final String[] EMPTY_STRING_ARRAY = new String[0];
3960 ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class);
3961
3962 // Clear any interactions that occur as a result of CS starting up.
3963 reset(mNetworkManagementService);
3964
3965 // The default on Android is opportunistic mode ("Automatic").
3966 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
3967
dalyk1fcb7392018-03-05 12:42:22 -05003968 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3969 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3970 .addTransportType(TRANSPORT_CELLULAR).build();
3971 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3972
Erik Kline79c6d052018-03-21 07:18:33 -07003973 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3974 waitForIdle();
3975 // CS tells netd about the empty DNS config for this network.
3976 verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
3977 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
3978 verifyNoMoreInteractions(mNetworkManagementService);
3979
3980 final LinkProperties cellLp = new LinkProperties();
3981 cellLp.setInterfaceName(MOBILE_IFNAME);
3982 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
3983 // "is-reachable" testing in order to not program netd with unreachable
3984 // nameservers that it might try repeated to validate.
3985 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
3986 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
3987 MOBILE_IFNAME));
3988 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
3989 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
3990 MOBILE_IFNAME));
3991 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
3992 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
3993
3994 mCellNetworkAgent.sendLinkProperties(cellLp);
3995 mCellNetworkAgent.connect(false);
3996 waitForIdle();
3997 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
3998 anyInt(), mStringArrayCaptor.capture(), any(), any(),
3999 eq(""), tlsServers.capture());
4000 assertEquals(2, mStringArrayCaptor.getValue().length);
4001 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4002 new String[]{"2001:db8::1", "192.0.2.1"}));
4003 // Opportunistic mode.
4004 assertEquals(2, tlsServers.getValue().length);
4005 assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
4006 new String[]{"2001:db8::1", "192.0.2.1"}));
4007 reset(mNetworkManagementService);
dalyk1fcb7392018-03-05 12:42:22 -05004008 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
4009 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
4010 mCellNetworkAgent);
4011 CallbackInfo cbi = cellNetworkCallback.expectCallback(
4012 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
4013 cellNetworkCallback.assertNoCallback();
4014 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4015 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
Erik Kline79c6d052018-03-21 07:18:33 -07004016
4017 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
4018 verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
4019 anyInt(), mStringArrayCaptor.capture(), any(), any(),
4020 eq(""), eq(EMPTY_STRING_ARRAY));
4021 assertEquals(2, mStringArrayCaptor.getValue().length);
4022 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4023 new String[]{"2001:db8::1", "192.0.2.1"}));
4024 reset(mNetworkManagementService);
dalyk1fcb7392018-03-05 12:42:22 -05004025 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07004026
4027 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4028 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
4029 anyInt(), mStringArrayCaptor.capture(), any(), any(),
4030 eq(""), tlsServers.capture());
4031 assertEquals(2, mStringArrayCaptor.getValue().length);
4032 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4033 new String[]{"2001:db8::1", "192.0.2.1"}));
4034 assertEquals(2, tlsServers.getValue().length);
4035 assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
4036 new String[]{"2001:db8::1", "192.0.2.1"}));
4037 reset(mNetworkManagementService);
dalyk1fcb7392018-03-05 12:42:22 -05004038 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07004039
dalyk1fcb7392018-03-05 12:42:22 -05004040 setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
4041 // Can't test dns configuration for strict mode without properly mocking
4042 // out the DNS lookups, but can test that LinkProperties is updated.
4043 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4044 mCellNetworkAgent);
4045 cellNetworkCallback.assertNoCallback();
4046 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
4047 assertEquals("strict.example.com", ((LinkProperties)cbi.arg).getPrivateDnsServerName());
4048 }
4049
4050 @Test
4051 public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
4052 // The default on Android is opportunistic mode ("Automatic").
4053 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4054
4055 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4056 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4057 .addTransportType(TRANSPORT_CELLULAR).build();
4058 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4059
4060 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4061 waitForIdle();
4062 LinkProperties lp = new LinkProperties();
4063 mCellNetworkAgent.sendLinkProperties(lp);
4064 mCellNetworkAgent.connect(false);
4065 waitForIdle();
4066 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
4067 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
4068 mCellNetworkAgent);
4069 CallbackInfo cbi = cellNetworkCallback.expectCallback(
4070 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
4071 cellNetworkCallback.assertNoCallback();
4072 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4073 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4074 Set<InetAddress> dnsServers = new HashSet<>();
4075 checkDnsServers(cbi.arg, dnsServers);
4076
4077 // Send a validation event for a server that is not part of the current
4078 // resolver config. The validation event should be ignored.
4079 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4080 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
4081 cellNetworkCallback.assertNoCallback();
4082
4083 // Add a dns server to the LinkProperties.
4084 LinkProperties lp2 = new LinkProperties(lp);
4085 lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
4086 mCellNetworkAgent.sendLinkProperties(lp2);
4087 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4088 mCellNetworkAgent);
4089 cellNetworkCallback.assertNoCallback();
4090 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4091 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4092 dnsServers.add(InetAddress.getByName("145.100.185.16"));
4093 checkDnsServers(cbi.arg, dnsServers);
4094
4095 // Send a validation event containing a hostname that is not part of
4096 // the current resolver config. The validation event should be ignored.
4097 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4098 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
4099 cellNetworkCallback.assertNoCallback();
4100
4101 // Send a validation event where validation failed.
4102 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4103 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
4104 cellNetworkCallback.assertNoCallback();
4105
4106 // Send a validation event where validation succeeded for a server in
4107 // the current resolver config. A LinkProperties callback with updated
4108 // private dns fields should be sent.
4109 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4110 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
4111 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4112 mCellNetworkAgent);
4113 cellNetworkCallback.assertNoCallback();
4114 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
4115 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4116 checkDnsServers(cbi.arg, dnsServers);
4117
4118 // The private dns fields in LinkProperties should be preserved when
4119 // the network agent sends unrelated changes.
4120 LinkProperties lp3 = new LinkProperties(lp2);
4121 lp3.setMtu(1300);
4122 mCellNetworkAgent.sendLinkProperties(lp3);
4123 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4124 mCellNetworkAgent);
4125 cellNetworkCallback.assertNoCallback();
4126 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
4127 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4128 checkDnsServers(cbi.arg, dnsServers);
4129 assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
4130
4131 // Removing the only validated server should affect the private dns
4132 // fields in LinkProperties.
4133 LinkProperties lp4 = new LinkProperties(lp3);
4134 lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
4135 mCellNetworkAgent.sendLinkProperties(lp4);
4136 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4137 mCellNetworkAgent);
4138 cellNetworkCallback.assertNoCallback();
4139 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4140 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4141 dnsServers.remove(InetAddress.getByName("145.100.185.16"));
4142 checkDnsServers(cbi.arg, dnsServers);
4143 assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
Erik Kline79c6d052018-03-21 07:18:33 -07004144 }
4145
Rubin Xu1bb5c082017-09-05 18:40:49 +01004146 private void checkDirectlyConnectedRoutes(Object callbackObj,
4147 Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
4148 assertTrue(callbackObj instanceof LinkProperties);
4149 LinkProperties lp = (LinkProperties) callbackObj;
4150
4151 Set<RouteInfo> expectedRoutes = new ArraySet<>();
4152 expectedRoutes.addAll(otherRoutes);
4153 for (LinkAddress address : linkAddresses) {
4154 RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
4155 // Duplicates in linkAddresses are considered failures
4156 assertTrue(expectedRoutes.add(localRoute));
4157 }
4158 List<RouteInfo> observedRoutes = lp.getRoutes();
4159 assertEquals(expectedRoutes.size(), observedRoutes.size());
4160 assertTrue(observedRoutes.containsAll(expectedRoutes));
4161 }
4162
dalyk1fcb7392018-03-05 12:42:22 -05004163 private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
4164 assertTrue(callbackObj instanceof LinkProperties);
4165 LinkProperties lp = (LinkProperties) callbackObj;
4166 assertEquals(dnsServers.size(), lp.getDnsServers().size());
4167 assertTrue(lp.getDnsServers().containsAll(dnsServers));
4168 }
4169
Hugo Benichifed512a2017-06-26 10:06:49 +09004170 private static <T> void assertEmpty(T[] ts) {
4171 int length = ts.length;
4172 assertEquals("expected empty array, but length was " + length, 0, length);
4173 }
4174
4175 private static <T> void assertLength(int expected, T[] got) {
4176 int length = got.length;
4177 assertEquals(String.format("expected array of length %s, but length was %s for %s",
4178 expected, length, Arrays.toString(got)), expected, length);
4179 }
Hugo Benichi16f0a942017-06-20 14:07:59 +09004180
4181 private static <T> void assertException(Runnable block, Class<T> expected) {
4182 try {
4183 block.run();
4184 fail("Expected exception of type " + expected);
4185 } catch (Exception got) {
4186 if (!got.getClass().equals(expected)) {
4187 fail("Expected exception of type " + expected + " but got " + got);
4188 }
4189 return;
4190 }
4191 }
Chalard Jean0b214af2018-01-12 17:22:49 +09004192
4193 @Test
4194 public void testVpnNetworkActive() {
4195 final int uid = Process.myUid();
4196
4197 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09004198 final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004199 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
4200 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004201 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09004202 final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
4203 final NetworkRequest genericRequest = new NetworkRequest.Builder()
4204 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
Chalard Jean0b214af2018-01-12 17:22:49 +09004205 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
4206 .addTransportType(TRANSPORT_WIFI).build();
4207 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
Chalard Jeanb552c462018-02-21 18:43:54 +09004208 .removeCapability(NET_CAPABILITY_NOT_VPN)
Chalard Jean0b214af2018-01-12 17:22:49 +09004209 .addTransportType(TRANSPORT_VPN).build();
4210 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Chalard Jeanb552c462018-02-21 18:43:54 +09004211 mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09004212 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
4213 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004214 mCm.registerDefaultNetworkCallback(defaultCallback);
4215 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004216
4217 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4218 mWiFiNetworkAgent.connect(false);
4219
4220 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004221 genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004222 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004223 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004224 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004225 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004226
4227 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4228 final ArraySet<UidRange> ranges = new ArraySet<>();
4229 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004230 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4231 mMockVpn.setUids(ranges);
Chalard Jean0b214af2018-01-12 17:22:49 +09004232 vpnNetworkAgent.connect(false);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004233 mMockVpn.connect();
Chalard Jean0b214af2018-01-12 17:22:49 +09004234
4235 genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004236 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004237 wifiNetworkCallback.assertNoCallback();
4238 vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004239 defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
4240 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004241
4242 genericNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004243 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jeanf19db372018-01-26 19:24:40 +09004244 vpnNetworkCallback.expectCapabilitiesLike(nc -> null == nc.getUids(), vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004245 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
4246 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004247
4248 ranges.clear();
4249 vpnNetworkAgent.setUids(ranges);
4250
4251 genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004252 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004253 wifiNetworkCallback.assertNoCallback();
4254 vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
4255
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004256 // TODO : The default network callback should actually get a LOST call here (also see the
4257 // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
4258 // ranges at all when determining whether a network should be rematched. In practice, VPNs
4259 // can't currently update their UIDs without disconnecting, so this does not matter too
4260 // much, but that is the reason the test here has to check for an update to the
4261 // capabilities instead of the expected LOST then AVAILABLE.
4262 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
4263
Chalard Jean0b214af2018-01-12 17:22:49 +09004264 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004265 mMockVpn.setUids(ranges);
Chalard Jean0b214af2018-01-12 17:22:49 +09004266
4267 genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004268 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004269 wifiNetworkCallback.assertNoCallback();
4270 vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004271 // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
4272 // happen outside of the test, ConnectivityService does not rematch callbacks.
4273 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004274
4275 mWiFiNetworkAgent.disconnect();
4276
4277 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004278 genericNotVpnNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004279 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
4280 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004281 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004282
4283 vpnNetworkAgent.disconnect();
4284
4285 genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004286 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004287 wifiNetworkCallback.assertNoCallback();
4288 vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004289 defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
4290 assertEquals(null, mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004291
4292 mCm.unregisterNetworkCallback(genericNetworkCallback);
4293 mCm.unregisterNetworkCallback(wifiNetworkCallback);
4294 mCm.unregisterNetworkCallback(vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004295 mCm.unregisterNetworkCallback(defaultCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09004296 }
Chalard Jean26400492018-04-18 20:18:38 +09004297
4298 @Test
4299 public void testVpnWithAndWithoutInternet() {
4300 final int uid = Process.myUid();
4301
4302 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
4303 mCm.registerDefaultNetworkCallback(defaultCallback);
4304 defaultCallback.assertNoCallback();
4305
4306 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4307 mWiFiNetworkAgent.connect(true);
4308
4309 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
4310 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4311
4312 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4313 final ArraySet<UidRange> ranges = new ArraySet<>();
4314 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004315 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4316 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09004317 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004318 mMockVpn.connect();
Chalard Jean26400492018-04-18 20:18:38 +09004319
4320 defaultCallback.assertNoCallback();
4321 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4322
4323 vpnNetworkAgent.disconnect();
4324 defaultCallback.assertNoCallback();
4325
4326 vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004327 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4328 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09004329 vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004330 mMockVpn.connect();
Chalard Jean26400492018-04-18 20:18:38 +09004331 defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
4332 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4333
4334 vpnNetworkAgent.disconnect();
4335 defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
4336 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
4337
4338 vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
Chalard Jean26400492018-04-18 20:18:38 +09004339 ranges.clear();
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004340 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4341 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09004342 vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004343 mMockVpn.connect();
Chalard Jean26400492018-04-18 20:18:38 +09004344 defaultCallback.assertNoCallback();
4345
4346 mCm.unregisterNetworkCallback(defaultCallback);
4347 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004348
4349 @Test
4350 public void testVpnSetUnderlyingNetworks() {
4351 final int uid = Process.myUid();
4352
4353 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
4354 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
4355 .removeCapability(NET_CAPABILITY_NOT_VPN)
4356 .addTransportType(TRANSPORT_VPN)
4357 .build();
4358 NetworkCapabilities nc;
4359 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
4360 vpnNetworkCallback.assertNoCallback();
4361
4362 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4363 final ArraySet<UidRange> ranges = new ArraySet<>();
4364 ranges.add(new UidRange(uid, uid));
4365 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4366 mMockVpn.connect();
4367 mMockVpn.setUids(ranges);
4368 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
4369
4370 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
4371 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
4372 assertTrue(nc.hasTransport(TRANSPORT_VPN));
4373 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
4374 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
4375 // For safety reasons a VPN without underlying networks is considered metered.
4376 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
4377
4378 // Connect cell and use it as an underlying network.
4379 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4380 mCellNetworkAgent.connect(true);
4381
4382 mService.setUnderlyingNetworksForVpn(
4383 new Network[] { mCellNetworkAgent.getNetwork() });
4384
4385 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4386 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
4387 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4388 vpnNetworkAgent);
4389
4390 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4391 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
4392 mWiFiNetworkAgent.connect(true);
4393
4394 mService.setUnderlyingNetworksForVpn(
4395 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
4396
4397 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4398 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
4399 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4400 vpnNetworkAgent);
4401
4402 // Don't disconnect, but note the VPN is not using wifi any more.
4403 mService.setUnderlyingNetworksForVpn(
4404 new Network[] { mCellNetworkAgent.getNetwork() });
4405
4406 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4407 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
4408 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4409 vpnNetworkAgent);
4410
4411 // Use Wifi but not cell. Note the VPN is now unmetered.
4412 mService.setUnderlyingNetworksForVpn(
4413 new Network[] { mWiFiNetworkAgent.getNetwork() });
4414
4415 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4416 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
4417 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4418 vpnNetworkAgent);
4419
4420 // Use both again.
4421 mService.setUnderlyingNetworksForVpn(
4422 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
4423
4424 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4425 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
4426 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4427 vpnNetworkAgent);
4428
Chalard Jean6b65ec72018-05-18 22:02:56 +09004429 // Disconnect cell. Receive update without even removing the dead network from the
4430 // underlying networks – it's dead anyway. Not metered any more.
4431 mCellNetworkAgent.disconnect();
4432 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4433 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
4434 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4435 vpnNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004436
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09004437 // Disconnect wifi too. No underlying networks means this is now metered.
Chalard Jean6b65ec72018-05-18 22:02:56 +09004438 mWiFiNetworkAgent.disconnect();
4439 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4440 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09004441 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
Chalard Jean6b65ec72018-05-18 22:02:56 +09004442 vpnNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004443
4444 mMockVpn.disconnect();
4445 }
junyulai4a192e22018-06-13 15:00:37 +08004446
4447 /**
4448 * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
4449 */
4450 private InterfaceConfiguration getClatInterfaceConfig(LinkAddress la) {
4451 InterfaceConfiguration cfg = new InterfaceConfiguration();
4452 cfg.setHardwareAddress("11:22:33:44:55:66");
4453 cfg.setLinkAddress(la);
4454 return cfg;
4455 }
4456
4457 /**
4458 * Make expected stack link properties, copied from Nat464Xlat.
4459 */
4460 private LinkProperties makeClatLinkProperties(LinkAddress la) {
4461 LinkAddress clatAddress = la;
4462 LinkProperties stacked = new LinkProperties();
4463 stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME);
4464 RouteInfo ipv4Default = new RouteInfo(
4465 new LinkAddress(Inet4Address.ANY, 0),
4466 clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME);
4467 stacked.addRoute(ipv4Default);
4468 stacked.addLinkAddress(clatAddress);
4469 return stacked;
4470 }
4471
4472 @Test
4473 public void testStackedLinkProperties() throws UnknownHostException, RemoteException {
4474 final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
4475 final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
4476 final NetworkRequest networkRequest = new NetworkRequest.Builder()
4477 .addTransportType(TRANSPORT_CELLULAR)
4478 .addCapability(NET_CAPABILITY_INTERNET)
4479 .build();
4480 final TestNetworkCallback networkCallback = new TestNetworkCallback();
4481 mCm.registerNetworkCallback(networkRequest, networkCallback);
4482
4483 // Prepare ipv6 only link properties and connect.
4484 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4485 final LinkProperties cellLp = new LinkProperties();
4486 cellLp.setInterfaceName(MOBILE_IFNAME);
4487 cellLp.addLinkAddress(myIpv6);
4488 cellLp.addRoute(new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME));
4489 cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME));
4490 reset(mNetworkManagementService);
4491 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
4492 .thenReturn(getClatInterfaceConfig(myIpv4));
4493
4494 // Connect with ipv6 link properties, then expect clat setup ipv4 and update link
4495 // properties properly.
4496 mCellNetworkAgent.sendLinkProperties(cellLp);
4497 mCellNetworkAgent.connect(true);
4498 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
4499 verify(mNetworkManagementService, times(1)).startClatd(MOBILE_IFNAME);
4500 Nat464Xlat clat = mService.getNat464Xlat(mCellNetworkAgent);
4501
4502 // Clat iface up, expect stack link updated.
4503 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
4504 waitForIdle();
4505 List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
4506 .getStackedLinks();
4507 assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
4508
4509 // Change trivial linkproperties and see if stacked link is preserved.
4510 cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
4511 mCellNetworkAgent.sendLinkProperties(cellLp);
4512 waitForIdle();
4513 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
4514
4515 List<LinkProperties> stackedLpsAfterChange =
4516 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
4517 assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
4518 assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
4519
4520 // Add ipv4 address, expect stacked linkproperties be cleaned up
4521 cellLp.addLinkAddress(myIpv4);
4522 cellLp.addRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
4523 mCellNetworkAgent.sendLinkProperties(cellLp);
4524 waitForIdle();
4525 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
4526 verify(mNetworkManagementService, times(1)).stopClatd(MOBILE_IFNAME);
4527
4528 // Clat iface removed, expect linkproperties revert to original one
4529 clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
4530 waitForIdle();
4531 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
4532 LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
4533 assertEquals(cellLp, actualLpAfterIpv4);
4534
4535 // Clean up
4536 mCellNetworkAgent.disconnect();
4537 mCm.unregisterNetworkCallback(networkCallback);
4538 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07004539}