blob: b460c904cf991def5439a5d02f18c1b596d2a43a [file] [log] [blame]
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
Erik Klinef851d6d2015-04-20 16:03:48 +090019import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
Lorenzo Colittif56ff042019-02-25 10:56:06 +090020import static android.net.ConnectivityManager.NETID_UNSET;
Erik Kline79c6d052018-03-21 07:18:33 -070021import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
22import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
23import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +090024import static android.net.ConnectivityManager.TYPE_ETHERNET;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070025import static android.net.ConnectivityManager.TYPE_MOBILE;
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +090026import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
27import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
Hugo Benichi16f0a942017-06-20 14:07:59 +090028import static android.net.ConnectivityManager.TYPE_NONE;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070029import static android.net.ConnectivityManager.TYPE_WIFI;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090030import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_INVALID;
31import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_VALID;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060032import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
33import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
34import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
35import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
36import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
37import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
38import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
39import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
40import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
41import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
42import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
43import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
Chalard Jean804b8fb2018-01-30 22:41:41 +090044import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060045import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
46import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
47import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
48import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
49import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
50import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
51import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
52import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
53import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
Chalard Jean0b214af2018-01-12 17:22:49 +090054import static android.net.NetworkCapabilities.TRANSPORT_VPN;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060055import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
56import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
Mike Yuf9729752018-08-17 15:22:05 +080057import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
58import static android.net.NetworkPolicyManager.RULE_NONE;
59import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
60import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +090061import static android.net.shared.NetworkParcelableUtil.fromStableParcelable;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060062
63import static com.android.internal.util.TestUtils.waitForIdleHandler;
Chalard Jeanb72b62d2018-02-16 16:08:35 +090064import static com.android.internal.util.TestUtils.waitForIdleLooper;
Lorenzo Colitti83fa2582015-08-07 12:49:01 +090065
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090066import static org.junit.Assert.assertEquals;
67import static org.junit.Assert.assertFalse;
junyulai4a192e22018-06-13 15:00:37 +080068import static org.junit.Assert.assertNotEquals;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090069import static org.junit.Assert.assertNotNull;
70import static org.junit.Assert.assertNull;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060071import static org.junit.Assert.assertTrue;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090072import static org.junit.Assert.fail;
Erik Klinee89953b2018-01-11 16:11:10 +090073import static org.mockito.Matchers.anyInt;
Erik Klinee89953b2018-01-11 16:11:10 +090074import static org.mockito.Mockito.any;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060075import static org.mockito.Mockito.atLeastOnce;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090076import static org.mockito.Mockito.doAnswer;
77import static org.mockito.Mockito.doNothing;
Erik Kline117e7f32018-03-04 21:01:01 +090078import static org.mockito.Mockito.eq;
Jeff Sharkey3671b1e2013-01-31 17:22:26 -080079import static org.mockito.Mockito.mock;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060080import static org.mockito.Mockito.never;
81import static org.mockito.Mockito.reset;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090082import static org.mockito.Mockito.spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090083import static org.mockito.Mockito.timeout;
Erik Klinee89953b2018-01-11 16:11:10 +090084import static org.mockito.Mockito.times;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060085import static org.mockito.Mockito.verify;
Erik Kline79c6d052018-03-21 07:18:33 -070086import static org.mockito.Mockito.verifyNoMoreInteractions;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090087import static org.mockito.Mockito.when;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070088
Lorenzo Colitti73b209382016-09-15 22:18:09 +090089import android.app.NotificationManager;
Paul Jensenbb2e0e92015-06-16 15:11:58 -040090import android.app.PendingIntent;
Paul Jensend7b6ca92015-05-13 14:05:12 -040091import android.content.BroadcastReceiver;
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +090092import android.content.ContentProvider;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +090093import android.content.ContentResolver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070094import android.content.Context;
Paul Jensend7b6ca92015-05-13 14:05:12 -040095import android.content.Intent;
96import android.content.IntentFilter;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090097import android.content.res.Resources;
Paul Jensend7b6ca92015-05-13 14:05:12 -040098import android.net.ConnectivityManager;
99import android.net.ConnectivityManager.NetworkCallback;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900100import android.net.ConnectivityManager.PacketKeepalive;
101import android.net.ConnectivityManager.PacketKeepaliveCallback;
Hugo Benichicb883232017-05-11 13:16:17 +0900102import android.net.ConnectivityManager.TooManyRequestsException;
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900103import android.net.ConnectivityThread;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800104import android.net.INetd;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900105import android.net.INetworkMonitor;
106import android.net.INetworkMonitorCallbacks;
Mike Yuf9729752018-08-17 15:22:05 +0800107import android.net.INetworkPolicyListener;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700108import android.net.INetworkPolicyManager;
109import android.net.INetworkStatsService;
junyulai4a192e22018-06-13 15:00:37 +0800110import android.net.InterfaceConfiguration;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900111import android.net.IpPrefix;
junyulai48eac1d42018-12-27 17:25:29 +0800112import android.net.IpSecManager;
113import android.net.IpSecManager.UdpEncapsulationSocket;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900114import android.net.LinkAddress;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700115import android.net.LinkProperties;
Etan Cohena7434272017-04-03 12:17:51 -0700116import android.net.MatchAllNetworkSpecifier;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400117import android.net.Network;
118import android.net.NetworkAgent;
119import android.net.NetworkCapabilities;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700120import android.net.NetworkFactory;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700121import android.net.NetworkInfo;
122import android.net.NetworkInfo.DetailedState;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400123import android.net.NetworkMisc;
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +0900124import android.net.NetworkParcelable;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400125import android.net.NetworkRequest;
Etan Cohena7434272017-04-03 12:17:51 -0700126import android.net.NetworkSpecifier;
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900127import android.net.NetworkStackClient;
Varun Anandd33cbc62019-02-07 14:13:13 -0800128import android.net.NetworkState;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100129import android.net.NetworkUtils;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000130import android.net.ProxyInfo;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700131import android.net.RouteInfo;
junyulai48eac1d42018-12-27 17:25:29 +0800132import android.net.SocketKeepalive;
Chalard Jean0b214af2018-01-12 17:22:49 +0900133import android.net.UidRange;
Hugo Benichif9fdf872016-07-28 17:53:06 +0900134import android.net.metrics.IpConnectivityLog;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900135import android.net.shared.NetworkMonitorUtils;
136import android.net.shared.PrivateDnsConfig;
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900137import android.net.util.MultinetworkPolicyTracker;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400138import android.os.ConditionVariable;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700139import android.os.Handler;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700140import android.os.HandlerThread;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700141import android.os.INetworkManagementService;
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900142import android.os.Looper;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900143import android.os.Message;
Etan Cohena7434272017-04-03 12:17:51 -0700144import android.os.Parcel;
145import android.os.Parcelable;
Robin Leed2baf792016-03-24 12:07:00 +0000146import android.os.Process;
junyulai4a192e22018-06-13 15:00:37 +0800147import android.os.RemoteException;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900148import android.os.SystemClock;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900149import android.os.UserHandle;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900150import android.provider.Settings;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900151import android.support.test.InstrumentationRegistry;
152import android.support.test.filters.SmallTest;
153import android.support.test.runner.AndroidJUnit4;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900154import android.test.mock.MockContentResolver;
Etan Cohen836ad572018-12-30 17:59:59 -0800155import android.text.TextUtils;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100156import android.util.ArraySet;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700157import android.util.Log;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700158
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900159import com.android.internal.net.VpnConfig;
Varun Anandd33cbc62019-02-07 14:13:13 -0800160import com.android.internal.net.VpnInfo;
Erik Klinee89953b2018-01-11 16:11:10 +0900161import com.android.internal.util.ArrayUtils;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900162import com.android.internal.util.WakeupMessage;
Lorenzo Colitti3c295b52016-10-28 12:56:03 +0900163import com.android.internal.util.test.BroadcastInterceptingContext;
Lorenzo Colittib8df76e42016-10-28 12:37:38 +0900164import com.android.internal.util.test.FakeSettingsProvider;
Chalard Jeandda156a2018-01-10 21:19:32 +0900165import com.android.server.connectivity.ConnectivityConstants;
Hugo Benichi64901e52017-10-19 14:42:40 +0900166import com.android.server.connectivity.DefaultNetworkMetrics;
167import com.android.server.connectivity.IpConnectivityMetrics;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900168import com.android.server.connectivity.MockableSystemProperties;
junyulai4a192e22018-06-13 15:00:37 +0800169import com.android.server.connectivity.Nat464Xlat;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000170import com.android.server.connectivity.ProxyTracker;
Mike Yuf9729752018-08-17 15:22:05 +0800171import com.android.server.connectivity.Tethering;
Chalard Jeandda156a2018-01-10 21:19:32 +0900172import com.android.server.connectivity.Vpn;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900173import com.android.server.net.NetworkPinner;
Hugo Benichi938ab4f2017-02-11 17:04:43 +0900174import com.android.server.net.NetworkPolicyManagerInternal;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400175
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900176import org.junit.After;
177import org.junit.Before;
Hugo Benichi849b81b2017-05-25 13:42:31 +0900178import org.junit.Ignore;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900179import org.junit.Test;
180import org.junit.runner.RunWith;
Erik Klinee89953b2018-01-11 16:11:10 +0900181import org.mockito.ArgumentCaptor;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900182import org.mockito.Mock;
183import org.mockito.MockitoAnnotations;
184import org.mockito.Spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900185import org.mockito.stubbing.Answer;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900186
junyulai4a192e22018-06-13 15:00:37 +0800187import java.net.Inet4Address;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700188import java.net.InetAddress;
junyulai4a192e22018-06-13 15:00:37 +0800189import java.net.UnknownHostException;
Paul Jensen4e1d3fd2016-04-08 13:56:52 -0400190import java.util.ArrayList;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900191import java.util.Arrays;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100192import java.util.Collection;
junyulai4a192e22018-06-13 15:00:37 +0800193import java.util.Collections;
dalyk1fcb7392018-03-05 12:42:22 -0500194import java.util.HashSet;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100195import java.util.List;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +0900196import java.util.Objects;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100197import java.util.Set;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900198import java.util.concurrent.CountDownLatch;
junyulai48eac1d42018-12-27 17:25:29 +0800199import java.util.concurrent.Executor;
junyulai06835112019-01-03 18:50:15 +0800200import java.util.concurrent.ExecutorService;
junyulai48eac1d42018-12-27 17:25:29 +0800201import java.util.concurrent.Executors;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900202import java.util.concurrent.LinkedBlockingQueue;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900203import java.util.concurrent.TimeUnit;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700204import java.util.concurrent.atomic.AtomicBoolean;
Hugo Benichi16f0a942017-06-20 14:07:59 +0900205import java.util.function.Predicate;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700206
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900207
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700208/**
209 * Tests for {@link ConnectivityService}.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400210 *
211 * Build, install and run with:
Hugo Benichibb91c572017-05-22 10:44:02 +0900212 * runtest frameworks-net -c com.android.server.ConnectivityServiceTest
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700213 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900214@RunWith(AndroidJUnit4.class)
215@SmallTest
216public class ConnectivityServiceTest {
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700217 private static final String TAG = "ConnectivityServiceTest";
218
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900219 private static final int TIMEOUT_MS = 500;
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +0900220 private static final int TEST_LINGER_DELAY_MS = 250;
221 // Chosen to be less than the linger timeout. This ensures that we can distinguish between a
222 // LOST callback that arrives immediately and a LOST callback that arrives after the linger
223 // timeout. For this, our assertions should run fast enough to leave less than
224 // (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
225 // supposedly fired, and the time we call expectCallback.
226 private final static int TEST_CALLBACK_TIMEOUT_MS = 200;
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +0900227 // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
228 // complete before callbacks are verified.
229 private final static int TEST_REQUEST_TIMEOUT_MS = 150;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900230
junyulai4a192e22018-06-13 15:00:37 +0800231 private static final String CLAT_PREFIX = "v4-";
Erik Kline79c6d052018-03-21 07:18:33 -0700232 private static final String MOBILE_IFNAME = "test_rmnet_data0";
233 private static final String WIFI_IFNAME = "test_wlan0";
234
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900235 private MockContext mServiceContext;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400236 private WrappedConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900237 private WrappedConnectivityManager mCm;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400238 private MockNetworkAgent mWiFiNetworkAgent;
239 private MockNetworkAgent mCellNetworkAgent;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900240 private MockNetworkAgent mEthernetNetworkAgent;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900241 private MockVpn mMockVpn;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900242 private Context mContext;
Mike Yuf9729752018-08-17 15:22:05 +0800243 private INetworkPolicyListener mPolicyListener;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700244
Hugo Benichi64901e52017-10-19 14:42:40 +0900245 @Mock IpConnectivityMetrics.Logger mMetricsService;
246 @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
Erik Klinee89953b2018-01-11 16:11:10 +0900247 @Mock INetworkManagementService mNetworkManagementService;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600248 @Mock INetworkStatsService mStatsService;
Mike Yuf9729752018-08-17 15:22:05 +0800249 @Mock INetworkPolicyManager mNpm;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800250 @Mock INetd mMockNetd;
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900251 @Mock NetworkStackClient mNetworkStack;
Hugo Benichi64901e52017-10-19 14:42:40 +0900252
Erik Klinee89953b2018-01-11 16:11:10 +0900253 private ArgumentCaptor<String[]> mStringArrayCaptor = ArgumentCaptor.forClass(String[].class);
254
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900255 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
256 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
257 // reflect the state of our test ConnectivityService.
258 private class WrappedConnectivityManager extends ConnectivityManager {
259 private Network mFakeBoundNetwork;
260
261 public synchronized boolean bindProcessToNetwork(Network network) {
262 mFakeBoundNetwork = network;
263 return true;
264 }
265
266 public synchronized Network getBoundNetworkForProcess() {
267 return mFakeBoundNetwork;
268 }
269
270 public WrappedConnectivityManager(Context context, ConnectivityService service) {
271 super(context, service);
272 }
273 }
274
Paul Jensend7b6ca92015-05-13 14:05:12 -0400275 private class MockContext extends BroadcastInterceptingContext {
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900276 private final MockContentResolver mContentResolver;
277
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900278 @Spy private Resources mResources;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900279 private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900280
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900281 MockContext(Context base, ContentProvider settingsProvider) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400282 super(base);
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900283
284 mResources = spy(base.getResources());
285 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
286 thenReturn(new String[] {
287 "wifi,1,1,1,-1,true",
288 "mobile,0,0,0,-1,true",
289 "mobile_mms,2,0,2,60000,true",
290 });
291
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900292 mContentResolver = new MockContentResolver();
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900293 mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400294 }
295
296 @Override
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900297 public void startActivityAsUser(Intent intent, UserHandle handle) {
298 mStartedActivities.offer(intent);
299 }
300
301 public Intent expectStartActivityIntent(int timeoutMs) {
302 Intent intent = null;
303 try {
304 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
305 } catch (InterruptedException e) {}
306 assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
307 return intent;
308 }
309
310 public void expectNoStartActivityIntent(int timeoutMs) {
311 try {
312 assertNull("Received unexpected Intent to start activity",
313 mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
314 } catch (InterruptedException e) {}
315 }
316
317 @Override
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900318 public Object getSystemService(String name) {
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900319 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
320 if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900321 if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400322 return super.getSystemService(name);
323 }
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900324
325 @Override
326 public ContentResolver getContentResolver() {
327 return mContentResolver;
328 }
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900329
330 @Override
331 public Resources getResources() {
332 return mResources;
333 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400334 }
335
Hugo Benichi669f0232017-06-29 22:58:39 +0900336 public void waitForIdle(int timeoutMsAsInt) {
337 long timeoutMs = timeoutMsAsInt;
Hugo Benichibb91c572017-05-22 10:44:02 +0900338 waitForIdleHandler(mService.mHandlerThread, timeoutMs);
339 waitForIdle(mCellNetworkAgent, timeoutMs);
340 waitForIdle(mWiFiNetworkAgent, timeoutMs);
341 waitForIdle(mEthernetNetworkAgent, timeoutMs);
342 waitForIdleHandler(mService.mHandlerThread, timeoutMs);
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900343 waitForIdleLooper(ConnectivityThread.getInstanceLooper(), timeoutMs);
Hugo Benichibb91c572017-05-22 10:44:02 +0900344 }
345
Hugo Benichi669f0232017-06-29 22:58:39 +0900346 public void waitForIdle(MockNetworkAgent agent, long timeoutMs) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900347 if (agent == null) {
348 return;
349 }
350 waitForIdleHandler(agent.mHandlerThread, timeoutMs);
351 }
352
353 private void waitForIdle() {
354 waitForIdle(TIMEOUT_MS);
355 }
356
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900357 @Test
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900358 public void testWaitForIdle() {
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900359 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
360
361 // Tests that waitForIdle returns immediately if the service is already idle.
362 for (int i = 0; i < attempts; i++) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900363 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900364 }
365
366 // Bring up a network that we can use to send messages to ConnectivityService.
367 ConditionVariable cv = waitForConnectivityBroadcasts(1);
368 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
369 mWiFiNetworkAgent.connect(false);
370 waitFor(cv);
371 Network n = mWiFiNetworkAgent.getNetwork();
372 assertNotNull(n);
373
374 // Tests that calling waitForIdle waits for messages to be processed.
375 for (int i = 0; i < attempts; i++) {
376 mWiFiNetworkAgent.setSignalStrength(i);
Hugo Benichibb91c572017-05-22 10:44:02 +0900377 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900378 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
379 }
Hugo Benichi5d540d12016-10-17 15:54:51 +0900380 }
381
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900382 // This test has an inherent race condition in it, and cannot be enabled for continuous testing
383 // or presubmit tests. It is kept for manual runs and documentation purposes.
Andreas Gampe35dbf352018-01-26 20:41:17 -0800384 @Ignore
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900385 public void verifyThatNotWaitingForIdleCausesRaceConditions() {
Hugo Benichi5d540d12016-10-17 15:54:51 +0900386 // Bring up a network that we can use to send messages to ConnectivityService.
387 ConditionVariable cv = waitForConnectivityBroadcasts(1);
388 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
389 mWiFiNetworkAgent.connect(false);
390 waitFor(cv);
391 Network n = mWiFiNetworkAgent.getNetwork();
392 assertNotNull(n);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900393
394 // Ensure that not calling waitForIdle causes a race condition.
Hugo Benichi5d540d12016-10-17 15:54:51 +0900395 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900396 for (int i = 0; i < attempts; i++) {
397 mWiFiNetworkAgent.setSignalStrength(i);
398 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
399 // We hit a race condition, as expected. Pass the test.
400 return;
401 }
402 }
403
404 // No race? There is a bug in this test.
405 fail("expected race condition at least once in " + attempts + " attempts");
406 }
407
Paul Jensend7b6ca92015-05-13 14:05:12 -0400408 private class MockNetworkAgent {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900409 private final INetworkMonitor mNetworkMonitor;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400410 private final NetworkInfo mNetworkInfo;
411 private final NetworkCapabilities mNetworkCapabilities;
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900412 private final HandlerThread mHandlerThread;
Paul Jensene0988542015-06-25 15:30:08 -0400413 private final ConditionVariable mDisconnected = new ConditionVariable();
Paul Jensen232437312016-04-06 09:51:26 -0400414 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
Calvin On1f64f3f2016-10-11 15:10:46 -0700415 private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
Paul Jensen3d911462015-06-12 06:40:24 -0400416 private int mScore;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400417 private NetworkAgent mNetworkAgent;
junyulai48eac1d42018-12-27 17:25:29 +0800418 private int mStartKeepaliveError = SocketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
419 private int mStopKeepaliveError = SocketKeepalive.NO_KEEPALIVE;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900420 private Integer mExpectedKeepaliveSlot = null;
Paul Jensen232437312016-04-06 09:51:26 -0400421 // Contains the redirectUrl from networkStatus(). Before reading, wait for
422 // mNetworkStatusReceived.
423 private String mRedirectUrl;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400424
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900425 private INetworkMonitorCallbacks mNmCallbacks;
426 private int mNmValidationResult = NETWORK_TEST_RESULT_INVALID;
427 private String mNmValidationRedirectUrl = null;
428 private boolean mNmProvNotificationRequested = false;
429
430 void setNetworkValid() {
431 mNmValidationResult = NETWORK_TEST_RESULT_VALID;
432 mNmValidationRedirectUrl = null;
433 }
434
435 void setNetworkInvalid() {
436 mNmValidationResult = NETWORK_TEST_RESULT_INVALID;
437 mNmValidationRedirectUrl = null;
438 }
439
440 void setNetworkPortal(String redirectUrl) {
441 setNetworkInvalid();
442 mNmValidationRedirectUrl = redirectUrl;
443 }
444
Paul Jensend7b6ca92015-05-13 14:05:12 -0400445 MockNetworkAgent(int transport) {
Rubin Xu1bb5c082017-09-05 18:40:49 +0100446 this(transport, new LinkProperties());
447 }
448
449 MockNetworkAgent(int transport, LinkProperties linkProperties) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400450 final int type = transportToLegacyType(transport);
Chalard Jean0b214af2018-01-12 17:22:49 +0900451 final String typeName = ConnectivityManager.getNetworkTypeName(transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400452 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
453 mNetworkCapabilities = new NetworkCapabilities();
454 mNetworkCapabilities.addTransportType(transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400455 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900456 case TRANSPORT_ETHERNET:
457 mScore = 70;
458 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400459 case TRANSPORT_WIFI:
Paul Jensen3d911462015-06-12 06:40:24 -0400460 mScore = 60;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400461 break;
462 case TRANSPORT_CELLULAR:
Paul Jensen3d911462015-06-12 06:40:24 -0400463 mScore = 50;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400464 break;
Hugo Benichi16f0a942017-06-20 14:07:59 +0900465 case TRANSPORT_WIFI_AWARE:
466 mScore = 20;
467 break;
Chalard Jean0b214af2018-01-12 17:22:49 +0900468 case TRANSPORT_VPN:
Chalard Jeanb552c462018-02-21 18:43:54 +0900469 mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN);
Chalard Jeandda156a2018-01-10 21:19:32 +0900470 mScore = ConnectivityConstants.VPN_DEFAULT_SCORE;
Chalard Jean0b214af2018-01-12 17:22:49 +0900471 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400472 default:
473 throw new UnsupportedOperationException("unimplemented network type");
474 }
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900475 mHandlerThread = new HandlerThread("Mock-" + typeName);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900476 mHandlerThread.start();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900477
478 mNetworkMonitor = mock(INetworkMonitor.class);
479 final Answer validateAnswer = inv -> {
480 new Thread(this::onValidationRequested).start();
481 return null;
482 };
483
484 try {
485 doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected();
486 doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
487 } catch (RemoteException e) {
488 fail(e.getMessage());
489 }
490
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +0900491 final ArgumentCaptor<NetworkParcelable> nmNetworkCaptor =
492 ArgumentCaptor.forClass(NetworkParcelable.class);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900493 final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
494 ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
495 doNothing().when(mNetworkStack).makeNetworkMonitor(
496 nmNetworkCaptor.capture(),
497 any() /* name */,
498 nmCbCaptor.capture());
499
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900500 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
501 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
Rubin Xu1bb5c082017-09-05 18:40:49 +0100502 linkProperties, mScore, new NetworkMisc()) {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900503 @Override
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900504 public void unwanted() { mDisconnected.open(); }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900505
506 @Override
junyulai06835112019-01-03 18:50:15 +0800507 public void startSocketKeepalive(Message msg) {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900508 int slot = msg.arg1;
509 if (mExpectedKeepaliveSlot != null) {
510 assertEquals((int) mExpectedKeepaliveSlot, slot);
511 }
junyulai06835112019-01-03 18:50:15 +0800512 onSocketKeepaliveEvent(slot, mStartKeepaliveError);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900513 }
514
515 @Override
junyulai06835112019-01-03 18:50:15 +0800516 public void stopSocketKeepalive(Message msg) {
517 onSocketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900518 }
Paul Jensen232437312016-04-06 09:51:26 -0400519
520 @Override
521 public void networkStatus(int status, String redirectUrl) {
522 mRedirectUrl = redirectUrl;
523 mNetworkStatusReceived.open();
524 }
Calvin On1f64f3f2016-10-11 15:10:46 -0700525
526 @Override
527 protected void preventAutomaticReconnect() {
528 mPreventReconnectReceived.open();
529 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400530 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900531
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +0900532 assertEquals(
533 mNetworkAgent.netId, fromStableParcelable(nmNetworkCaptor.getValue()).netId);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900534 mNmCallbacks = nmCbCaptor.getValue();
535
536 try {
537 mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
538 } catch (RemoteException e) {
539 fail(e.getMessage());
540 }
541
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900542 // Waits for the NetworkAgent to be registered, which includes the creation of the
543 // NetworkMonitor.
Hugo Benichibb91c572017-05-22 10:44:02 +0900544 waitForIdle();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900545 }
546
547 private void onValidationRequested() {
548 try {
549 if (mNmProvNotificationRequested
550 && mNmValidationResult == NETWORK_TEST_RESULT_VALID) {
551 mNmCallbacks.hideProvisioningNotification();
552 mNmProvNotificationRequested = false;
553 }
554
555 mNmCallbacks.notifyNetworkTested(
556 mNmValidationResult, mNmValidationRedirectUrl);
557
558 if (mNmValidationRedirectUrl != null) {
559 mNmCallbacks.showProvisioningNotification(
Remi NGUYEN VAN9c5d9642019-02-07 21:29:57 +0900560 "test_provisioning_notif_action", "com.android.test.package");
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900561 mNmProvNotificationRequested = true;
562 }
563 } catch (RemoteException e) {
564 fail(e.getMessage());
565 }
Paul Jensen3d911462015-06-12 06:40:24 -0400566 }
567
568 public void adjustScore(int change) {
569 mScore += change;
570 mNetworkAgent.sendNetworkScore(mScore);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400571 }
572
Lorenzo Colitti02cc8392017-05-17 01:28:09 +0900573 public void explicitlySelected(boolean acceptUnvalidated) {
574 mNetworkAgent.explicitlySelected(acceptUnvalidated);
575 }
576
Paul Jensen85cf78e2015-06-25 13:25:07 -0400577 public void addCapability(int capability) {
578 mNetworkCapabilities.addCapability(capability);
579 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
580 }
581
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900582 public void removeCapability(int capability) {
583 mNetworkCapabilities.removeCapability(capability);
584 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
585 }
586
Chalard Jean0b214af2018-01-12 17:22:49 +0900587 public void setUids(Set<UidRange> uids) {
588 mNetworkCapabilities.setUids(uids);
589 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
590 }
591
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900592 public void setSignalStrength(int signalStrength) {
593 mNetworkCapabilities.setSignalStrength(signalStrength);
594 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
595 }
596
Etan Cohena7434272017-04-03 12:17:51 -0700597 public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
598 mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
Lorenzo Colitti6556a222017-04-03 17:46:35 +0900599 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
600 }
601
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900602 public void setNetworkCapabilities(NetworkCapabilities nc,
603 boolean sendToConnectivityService) {
604 mNetworkCapabilities.set(nc);
605 if (sendToConnectivityService) {
606 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
607 }
608 }
609
Paul Jensene0988542015-06-25 15:30:08 -0400610 public void connectWithoutInternet() {
611 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
612 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
613 }
614
Paul Jensend7b6ca92015-05-13 14:05:12 -0400615 /**
Paul Jensene0988542015-06-25 15:30:08 -0400616 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400617 * @param validated Indicate if network should pretend to be validated.
618 */
619 public void connect(boolean validated) {
Hugo Benichi16f0a942017-06-20 14:07:59 +0900620 connect(validated, true);
621 }
622
623 /**
624 * Transition this NetworkAgent to CONNECTED state.
625 * @param validated Indicate if network should pretend to be validated.
626 * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
627 */
628 public void connect(boolean validated, boolean hasInternet) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900629 assertEquals("MockNetworkAgents can only be connected once",
630 mNetworkInfo.getDetailedState(), DetailedState.IDLE);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400631 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
632
Paul Jensend7b6ca92015-05-13 14:05:12 -0400633 NetworkCallback callback = null;
634 final ConditionVariable validatedCv = new ConditionVariable();
635 if (validated) {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900636 setNetworkValid();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400637 NetworkRequest request = new NetworkRequest.Builder()
638 .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
Chalard Jeanfb0c87e2018-04-18 19:18:58 +0900639 .clearCapabilities()
Paul Jensend7b6ca92015-05-13 14:05:12 -0400640 .build();
641 callback = new NetworkCallback() {
642 public void onCapabilitiesChanged(Network network,
643 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400644 if (network.equals(getNetwork()) &&
645 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400646 validatedCv.open();
647 }
648 }
649 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400650 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400651 }
Hugo Benichi16f0a942017-06-20 14:07:59 +0900652 if (hasInternet) {
653 addCapability(NET_CAPABILITY_INTERNET);
654 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400655
Paul Jensene0988542015-06-25 15:30:08 -0400656 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400657
658 if (validated) {
659 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400660 waitFor(validatedCv);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900661 setNetworkInvalid();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400662 }
663
664 if (callback != null) mCm.unregisterNetworkCallback(callback);
665 }
666
Paul Jensen232437312016-04-06 09:51:26 -0400667 public void connectWithCaptivePortal(String redirectUrl) {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900668 setNetworkPortal(redirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400669 connect(false);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400670 }
671
Erik Kline1d3db322017-02-28 16:20:20 +0900672 public void suspend() {
673 mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null);
674 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
675 }
676
Chalard Jean804b8fb2018-01-30 22:41:41 +0900677 public void resume() {
678 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
679 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
680 }
681
Paul Jensend7b6ca92015-05-13 14:05:12 -0400682 public void disconnect() {
683 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
684 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
685 }
686
687 public Network getNetwork() {
688 return new Network(mNetworkAgent.netId);
689 }
Paul Jensene0988542015-06-25 15:30:08 -0400690
Calvin On1f64f3f2016-10-11 15:10:46 -0700691 public ConditionVariable getPreventReconnectReceived() {
692 return mPreventReconnectReceived;
693 }
694
Paul Jensene0988542015-06-25 15:30:08 -0400695 public ConditionVariable getDisconnectedCV() {
696 return mDisconnected;
697 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400698
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900699 public void sendLinkProperties(LinkProperties lp) {
700 mNetworkAgent.sendLinkProperties(lp);
701 }
702
703 public void setStartKeepaliveError(int error) {
704 mStartKeepaliveError = error;
705 }
706
707 public void setStopKeepaliveError(int error) {
708 mStopKeepaliveError = error;
709 }
710
711 public void setExpectedKeepaliveSlot(Integer slot) {
712 mExpectedKeepaliveSlot = slot;
713 }
Paul Jensen232437312016-04-06 09:51:26 -0400714
715 public String waitForRedirectUrl() {
716 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
717 return mRedirectUrl;
718 }
Chalard Jean804b8fb2018-01-30 22:41:41 +0900719
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900720 public NetworkAgent getNetworkAgent() {
721 return mNetworkAgent;
722 }
723
Chalard Jean804b8fb2018-01-30 22:41:41 +0900724 public NetworkCapabilities getNetworkCapabilities() {
725 return mNetworkCapabilities;
726 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400727 }
728
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900729 /**
730 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
731 * operations have been processed. Before ConnectivityService can add or remove any requests,
732 * the factory must be told to expect those operations by calling expectAddRequests or
733 * expectRemoveRequests.
734 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700735 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400736 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
737 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400738 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700739
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900740 // Used to expect that requests be removed or added on a separate thread, without sleeping.
741 // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then
742 // cause some other thread to add or remove requests, then call waitForRequests(). We can
743 // either expect requests to be added or removed, but not both, because CountDownLatch can
744 // only count in one direction.
745 private CountDownLatch mExpectations;
746
747 // Whether we are currently expecting requests to be added or removed. Valid only if
748 // mExpectations is non-null.
749 private boolean mExpectingAdditions;
750
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700751 public MockNetworkFactory(Looper looper, Context context, String logTag,
752 NetworkCapabilities filter) {
753 super(looper, context, logTag, filter);
754 }
755
756 public int getMyRequestCount() {
757 return getRequestCount();
758 }
759
760 protected void startNetwork() {
761 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400762 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700763 }
764
765 protected void stopNetwork() {
766 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400767 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700768 }
769
770 public boolean getMyStartRequested() {
771 return mNetworkStarted.get();
772 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400773
774 public ConditionVariable getNetworkStartedCV() {
775 mNetworkStartedCV.close();
776 return mNetworkStartedCV;
777 }
778
779 public ConditionVariable getNetworkStoppedCV() {
780 mNetworkStoppedCV.close();
781 return mNetworkStoppedCV;
782 }
783
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900784 @Override
785 protected void handleAddRequest(NetworkRequest request, int score) {
786 // If we're expecting anything, we must be expecting additions.
787 if (mExpectations != null && !mExpectingAdditions) {
788 fail("Can't add requests while expecting requests to be removed");
789 }
790
791 // Add the request.
792 super.handleAddRequest(request, score);
793
794 // Reduce the number of request additions we're waiting for.
795 if (mExpectingAdditions) {
796 assertTrue("Added more requests than expected", mExpectations.getCount() > 0);
797 mExpectations.countDown();
798 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400799 }
800
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900801 @Override
802 protected void handleRemoveRequest(NetworkRequest request) {
803 // If we're expecting anything, we must be expecting removals.
804 if (mExpectations != null && mExpectingAdditions) {
805 fail("Can't remove requests while expecting requests to be added");
806 }
807
808 // Remove the request.
809 super.handleRemoveRequest(request);
810
811 // Reduce the number of request removals we're waiting for.
812 if (!mExpectingAdditions) {
813 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0);
814 mExpectations.countDown();
815 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400816 }
817
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900818 private void assertNoExpectations() {
819 if (mExpectations != null) {
820 fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
821 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400822 }
823
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900824 // Expects that count requests will be added.
825 public void expectAddRequests(final int count) {
826 assertNoExpectations();
827 mExpectingAdditions = true;
828 mExpectations = new CountDownLatch(count);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400829 }
830
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900831 // Expects that count requests will be removed.
832 public void expectRemoveRequests(final int count) {
833 assertNoExpectations();
834 mExpectingAdditions = false;
835 mExpectations = new CountDownLatch(count);
836 }
837
838 // Waits for the expected request additions or removals to happen within a timeout.
839 public void waitForRequests() throws InterruptedException {
840 assertNotNull("Nothing to wait for", mExpectations);
841 mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
842 final long count = mExpectations.getCount();
843 final String msg = count + " requests still not " +
844 (mExpectingAdditions ? "added" : "removed") +
845 " after " + TIMEOUT_MS + " ms";
846 assertEquals(msg, 0, count);
847 mExpectations = null;
848 }
849
850 public void waitForNetworkRequests(final int count) throws InterruptedException {
851 waitForRequests();
852 assertEquals(count, getMyRequestCount());
Paul Jensen0a2823e2015-06-12 10:31:09 -0400853 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700854 }
855
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900856 private static Looper startHandlerThreadAndReturnLooper() {
857 final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
858 handlerThread.start();
859 return handlerThread.getLooper();
860 }
861
862 private class MockVpn extends Vpn {
863 // TODO : the interactions between this mock and the mock network agent are too
864 // hard to get right at this moment, because it's unclear in which case which
865 // target needs to get a method call or both, and in what order. It's because
866 // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn
867 // parent class of MockVpn agent wants that responsibility.
868 // That being said inside the test it should be possible to make the interactions
869 // harder to get wrong with precise speccing, judicious comments, helper methods
870 // and a few sprinkled assertions.
871
872 private boolean mConnected = false;
873 // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
874 // not inherit from NetworkAgent.
875 private MockNetworkAgent mMockNetworkAgent;
876
877 public MockVpn(int userId) {
878 super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
879 userId);
880 }
881
882 public void setNetworkAgent(MockNetworkAgent agent) {
883 waitForIdle(agent, TIMEOUT_MS);
884 mMockNetworkAgent = agent;
885 mNetworkAgent = agent.getNetworkAgent();
886 mNetworkCapabilities.set(agent.getNetworkCapabilities());
887 }
888
889 public void setUids(Set<UidRange> uids) {
890 mNetworkCapabilities.setUids(uids);
Varun Anand4fa80e82019-02-06 10:13:38 -0800891 updateCapabilities(null /* defaultNetwork */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900892 }
893
894 @Override
895 public int getNetId() {
Varun Anand4fa80e82019-02-06 10:13:38 -0800896 if (mMockNetworkAgent == null) {
897 return NETID_UNSET;
898 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900899 return mMockNetworkAgent.getNetwork().netId;
900 }
901
902 @Override
903 public boolean appliesToUid(int uid) {
904 return mConnected; // Trickery to simplify testing.
905 }
906
907 @Override
908 protected boolean isCallerEstablishedOwnerLocked() {
909 return mConnected; // Similar trickery
910 }
911
912 public void connect() {
913 mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
914 mConnected = true;
915 mConfig = new VpnConfig();
Varun Anand1215f092019-01-14 11:45:33 -0800916 mConfig.isMetered = false;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900917 }
918
919 @Override
Varun Anand4fa80e82019-02-06 10:13:38 -0800920 public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
921 if (!mConnected) return null;
922 super.updateCapabilities(defaultNetwork);
923 // Because super.updateCapabilities will update the capabilities of the agent but
924 // not the mock agent, the mock agent needs to know about them.
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900925 copyCapabilitiesToNetworkAgent();
Varun Anand4fa80e82019-02-06 10:13:38 -0800926 return new NetworkCapabilities(mNetworkCapabilities);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900927 }
928
929 private void copyCapabilitiesToNetworkAgent() {
930 if (null != mMockNetworkAgent) {
931 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
932 false /* sendToConnectivityService */);
933 }
934 }
935
936 public void disconnect() {
937 mConnected = false;
938 mConfig = null;
939 }
940 }
941
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900942 private class FakeWakeupMessage extends WakeupMessage {
943 private static final int UNREASONABLY_LONG_WAIT = 1000;
944
945 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
946 super(context, handler, cmdName, cmd);
947 }
948
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900949 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
950 int arg1, int arg2, Object obj) {
951 super(context, handler, cmdName, cmd, arg1, arg2, obj);
952 }
953
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900954 @Override
955 public void schedule(long when) {
956 long delayMs = when - SystemClock.elapsedRealtime();
957 if (delayMs < 0) delayMs = 0;
958 if (delayMs > UNREASONABLY_LONG_WAIT) {
959 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
960 "ms into the future: " + delayMs);
961 }
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900962 Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
963 mHandler.sendMessageDelayed(msg, delayMs);
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900964 }
965
966 @Override
967 public void cancel() {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900968 mHandler.removeMessages(mCmd, mObj);
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900969 }
970
971 @Override
972 public void onAlarm() {
973 throw new AssertionError("Should never happen. Update this fake.");
974 }
975 }
976
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900977 private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
Hugo Benichi53d83d52016-11-15 13:42:34 +0900978 public volatile boolean configRestrictsAvoidBadWifi;
Lorenzo Colitti2de49252017-01-24 18:08:41 +0900979 public volatile int configMeteredMultipathPreference;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400980
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900981 public WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
Erik Kline065ab6e2016-10-02 18:02:14 +0900982 super(c, h, r);
983 }
984
985 @Override
986 public boolean configRestrictsAvoidBadWifi() {
987 return configRestrictsAvoidBadWifi;
988 }
Lorenzo Colitti2de49252017-01-24 18:08:41 +0900989
990 @Override
991 public int configMeteredMultipathPreference() {
992 return configMeteredMultipathPreference;
993 }
Erik Kline065ab6e2016-10-02 18:02:14 +0900994 }
995
996 private class WrappedConnectivityService extends ConnectivityService {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900997 public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900998 private MockableSystemProperties mSystemProperties;
Erik Kline065ab6e2016-10-02 18:02:14 +0900999
Paul Jensend7b6ca92015-05-13 14:05:12 -04001000 public WrappedConnectivityService(Context context, INetworkManagementService netManager,
Hugo Benichif9fdf872016-07-28 17:53:06 +09001001 INetworkStatsService statsService, INetworkPolicyManager policyManager,
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001002 IpConnectivityLog log, INetd netd) {
Hugo Benichif9fdf872016-07-28 17:53:06 +09001003 super(context, netManager, statsService, policyManager, log);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001004 mNetd = netd;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001005 mLingerDelayMs = TEST_LINGER_DELAY_MS;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001006 }
1007
1008 @Override
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001009 protected MockableSystemProperties getSystemProperties() {
1010 // Minimal approach to overriding system properties: let most calls fall through to real
1011 // device values, and only override ones values that are important to this test.
1012 mSystemProperties = spy(new MockableSystemProperties());
1013 when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
1014 when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
1015 return mSystemProperties;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001016 }
Paul Jensen67b0b072015-06-10 11:22:17 -04001017
1018 @Override
Mike Yuf9729752018-08-17 15:22:05 +08001019 protected Tethering makeTethering() {
1020 return mock(Tethering.class);
1021 }
1022
1023 @Override
Irina Dumitrescu044a4362018-12-05 16:19:47 +00001024 protected ProxyTracker makeProxyTracker() {
1025 return mock(ProxyTracker.class);
1026 }
1027
1028 @Override
Paul Jensen67b0b072015-06-10 11:22:17 -04001029 protected int reserveNetId() {
1030 while (true) {
1031 final int netId = super.reserveNetId();
1032
1033 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
1034 // can have odd side-effects, like network validations succeeding.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001035 Context context = InstrumentationRegistry.getContext();
1036 final Network[] networks = ConnectivityManager.from(context).getAllNetworks();
Paul Jensen67b0b072015-06-10 11:22:17 -04001037 boolean overlaps = false;
1038 for (Network network : networks) {
1039 if (netId == network.netId) {
1040 overlaps = true;
1041 break;
1042 }
1043 }
1044 if (overlaps) continue;
1045
1046 return netId;
1047 }
1048 }
Paul Jensencf4c2c62015-07-01 14:16:32 -04001049
Irina Dumitrescu044a4362018-12-05 16:19:47 +00001050 @Override
1051 protected boolean queryUserAccess(int uid, int netId) {
1052 return true;
1053 }
1054
junyulai4a192e22018-06-13 15:00:37 +08001055 public Nat464Xlat getNat464Xlat(MockNetworkAgent mna) {
1056 return getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
1057 }
1058
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001059 @Override
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001060 public MultinetworkPolicyTracker createMultinetworkPolicyTracker(
Erik Kline065ab6e2016-10-02 18:02:14 +09001061 Context c, Handler h, Runnable r) {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001062 final WrappedMultinetworkPolicyTracker tracker = new WrappedMultinetworkPolicyTracker(c, h, r);
Erik Kline065ab6e2016-10-02 18:02:14 +09001063 return tracker;
1064 }
1065
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001066 public WrappedMultinetworkPolicyTracker getMultinetworkPolicyTracker() {
1067 return (WrappedMultinetworkPolicyTracker) mMultinetworkPolicyTracker;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001068 }
1069
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09001070 @Override
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +09001071 protected NetworkStackClient getNetworkStack() {
1072 return mNetworkStack;
1073 }
1074
1075 @Override
Erik Kline065ab6e2016-10-02 18:02:14 +09001076 public WakeupMessage makeWakeupMessage(
1077 Context context, Handler handler, String cmdName, int cmd, Object obj) {
1078 return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09001079 }
1080
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001081 @Override
1082 public boolean hasService(String name) {
1083 // Currenty, the only relevant service that ConnectivityService checks for is
1084 // ETHERNET_SERVICE.
1085 return Context.ETHERNET_SERVICE.equals(name);
1086 }
1087
Hugo Benichi64901e52017-10-19 14:42:40 +09001088 @Override
1089 protected IpConnectivityMetrics.Logger metricsLogger() {
1090 return mMetricsService;
1091 }
1092
dalyk1fcb7392018-03-05 12:42:22 -05001093 @Override
1094 protected void registerNetdEventCallback() {
1095 }
1096
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001097 public void mockVpn(int uid) {
1098 synchronized (mVpns) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001099 int userId = UserHandle.getUserId(uid);
1100 mMockVpn = new MockVpn(userId);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001101 // This has no effect unless the VPN is actually connected, because things like
1102 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
1103 // netId, and check if that network is actually connected.
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001104 mVpns.put(userId, mMockVpn);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001105 }
1106 }
1107
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001108 public void waitForIdle(int timeoutMs) {
Hugo Benichiad4db4e2016-10-17 15:54:51 +09001109 waitForIdleHandler(mHandlerThread, timeoutMs);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001110 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001111
1112 public void waitForIdle() {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001113 waitForIdle(TIMEOUT_MS);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001114 }
Mike Yuf9729752018-08-17 15:22:05 +08001115
1116 public void setUidRulesChanged(int uidRules) {
1117 try {
1118 mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
1119 } catch (RemoteException ignored) {
1120 }
1121 }
1122
1123 public void setRestrictBackgroundChanged(boolean restrictBackground) {
1124 try {
1125 mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
1126 } catch (RemoteException ignored) {
1127 }
1128 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001129 }
1130
Paul Jensen3d911462015-06-12 06:40:24 -04001131 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001132 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1133 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -04001134 */
1135 static private void waitFor(ConditionVariable conditionVariable) {
Hugo Benichi16f0a942017-06-20 14:07:59 +09001136 if (conditionVariable.block(TIMEOUT_MS)) {
1137 return;
1138 }
1139 fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
Paul Jensen3d911462015-06-12 06:40:24 -04001140 }
1141
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001142 @Before
Paul Jensend7b6ca92015-05-13 14:05:12 -04001143 public void setUp() throws Exception {
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001144 mContext = InstrumentationRegistry.getContext();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001145
Hugo Benichi64901e52017-10-19 14:42:40 +09001146 MockitoAnnotations.initMocks(this);
1147 when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
1148
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001149 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1150 // http://b/25897652 .
1151 if (Looper.myLooper() == null) {
1152 Looper.prepare();
1153 }
1154
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001155 FakeSettingsProvider.clearSettingsProvider();
1156 mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1157 new FakeSettingsProvider());
Hugo Benichi938ab4f2017-02-11 17:04:43 +09001158 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
1159 LocalServices.addService(
1160 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
Mike Yuf9729752018-08-17 15:22:05 +08001161
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001162 mService = new WrappedConnectivityService(mServiceContext,
Erik Klinee89953b2018-01-11 16:11:10 +09001163 mNetworkManagementService,
Jeff Sharkey72f9c422017-10-27 17:22:59 -06001164 mStatsService,
Mike Yuf9729752018-08-17 15:22:05 +08001165 mNpm,
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001166 mock(IpConnectivityLog.class),
1167 mMockNetd);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001168
Mike Yuf9729752018-08-17 15:22:05 +08001169 final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
1170 ArgumentCaptor.forClass(INetworkPolicyListener.class);
1171 verify(mNpm).registerListener(policyListenerCaptor.capture());
1172 mPolicyListener = policyListenerCaptor.getValue();
1173
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001174 // Create local CM before sending system ready so that we can answer
1175 // getSystemService() correctly.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001176 mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001177 mService.systemReady();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001178 mService.mockVpn(Process.myUid());
Lorenzo Colitti531a3442016-03-01 12:55:58 +09001179 mCm.bindProcessToNetwork(null);
Calvin On1f64f3f2016-10-11 15:10:46 -07001180
1181 // Ensure that the default setting for Captive Portals is used for most tests
1182 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001183 setAlwaysOnNetworks(false);
Erik Kline79c6d052018-03-21 07:18:33 -07001184 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Paul Jensend7b6ca92015-05-13 14:05:12 -04001185 }
1186
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001187 @After
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001188 public void tearDown() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001189 setAlwaysOnNetworks(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001190 if (mCellNetworkAgent != null) {
1191 mCellNetworkAgent.disconnect();
1192 mCellNetworkAgent = null;
1193 }
1194 if (mWiFiNetworkAgent != null) {
1195 mWiFiNetworkAgent.disconnect();
1196 mWiFiNetworkAgent = null;
1197 }
1198 if (mEthernetNetworkAgent != null) {
1199 mEthernetNetworkAgent.disconnect();
1200 mEthernetNetworkAgent = null;
1201 }
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001202 FakeSettingsProvider.clearSettingsProvider();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001203 }
1204
Hugo Benichibb91c572017-05-22 10:44:02 +09001205 private static int transportToLegacyType(int transport) {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001206 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001207 case TRANSPORT_ETHERNET:
1208 return TYPE_ETHERNET;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001209 case TRANSPORT_WIFI:
1210 return TYPE_WIFI;
1211 case TRANSPORT_CELLULAR:
1212 return TYPE_MOBILE;
1213 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001214 return TYPE_NONE;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001215 }
1216 }
1217
1218 private void verifyActiveNetwork(int transport) {
1219 // Test getActiveNetworkInfo()
1220 assertNotNull(mCm.getActiveNetworkInfo());
1221 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
1222 // Test getActiveNetwork()
1223 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001224 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Hugo Benichi16f0a942017-06-20 14:07:59 +09001225 if (!NetworkCapabilities.isValidTransport(transport)) {
1226 throw new IllegalStateException("Unknown transport " + transport);
1227 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001228 switch (transport) {
1229 case TRANSPORT_WIFI:
1230 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
1231 break;
1232 case TRANSPORT_CELLULAR:
1233 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
1234 break;
1235 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001236 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001237 }
1238 // Test getNetworkInfo(Network)
1239 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
Hugo Benichibb91c572017-05-22 10:44:02 +09001240 assertEquals(transportToLegacyType(transport),
1241 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001242 // Test getNetworkCapabilities(Network)
1243 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
1244 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
1245 }
1246
1247 private void verifyNoNetwork() {
Hugo Benichic1014502017-07-19 10:10:52 +09001248 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001249 // Test getActiveNetworkInfo()
1250 assertNull(mCm.getActiveNetworkInfo());
1251 // Test getActiveNetwork()
1252 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001253 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -04001254 // Test getAllNetworks()
Hugo Benichifed512a2017-06-26 10:06:49 +09001255 assertEmpty(mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001256 }
1257
1258 /**
1259 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
1260 * broadcasts are received.
1261 */
1262 private ConditionVariable waitForConnectivityBroadcasts(final int count) {
1263 final ConditionVariable cv = new ConditionVariable();
1264 mServiceContext.registerReceiver(new BroadcastReceiver() {
1265 private int remaining = count;
1266 public void onReceive(Context context, Intent intent) {
1267 if (--remaining == 0) {
1268 cv.open();
1269 mServiceContext.unregisterReceiver(this);
1270 }
1271 }
1272 }, new IntentFilter(CONNECTIVITY_ACTION));
1273 return cv;
1274 }
1275
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001276 @Test
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001277 public void testNetworkTypes() {
1278 // Ensure that our mocks for the networkAttributes config variable work as expected. If they
1279 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
1280 // will fail. Failing here is much easier to debug.
1281 assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
1282 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001283 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
1284 assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
1285
1286 // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
1287 // mocks, this assert exercises the ConnectivityService code path that ensures that
1288 // TYPE_ETHERNET is supported if the ethernet service is running.
1289 assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001290 }
1291
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001292 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001293 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001294 verifyNoNetwork();
1295 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1296 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1297 assertNull(mCm.getActiveNetworkInfo());
1298 assertNull(mCm.getActiveNetwork());
1299 // Test bringing up validated cellular.
1300 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1301 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001302 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001303 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichifed512a2017-06-26 10:06:49 +09001304 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001305 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1306 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1307 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
1308 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
1309 // Test bringing up validated WiFi.
1310 cv = waitForConnectivityBroadcasts(2);
1311 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001312 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001313 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001314 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001315 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1316 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1317 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
1318 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
1319 // Test cellular linger timeout.
Lorenzo Colittid2706122017-01-30 17:45:49 +09001320 waitFor(mCellNetworkAgent.getDisconnectedCV());
Hugo Benichibb91c572017-05-22 10:44:02 +09001321 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09001322 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001323 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001324 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001325 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
1326 // Test WiFi disconnect.
1327 cv = waitForConnectivityBroadcasts(1);
1328 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001329 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001330 verifyNoNetwork();
1331 }
1332
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001333 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001334 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
1335 // Test bringing up unvalidated WiFi
1336 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1337 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1338 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001339 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001340 verifyActiveNetwork(TRANSPORT_WIFI);
1341 // Test bringing up unvalidated cellular
1342 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1343 mCellNetworkAgent.connect(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001344 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001345 verifyActiveNetwork(TRANSPORT_WIFI);
1346 // Test cellular disconnect.
1347 mCellNetworkAgent.disconnect();
Hugo Benichibb91c572017-05-22 10:44:02 +09001348 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001349 verifyActiveNetwork(TRANSPORT_WIFI);
1350 // Test bringing up validated cellular
1351 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1352 cv = waitForConnectivityBroadcasts(2);
1353 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001354 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001355 verifyActiveNetwork(TRANSPORT_CELLULAR);
1356 // Test cellular disconnect.
1357 cv = waitForConnectivityBroadcasts(2);
1358 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001359 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001360 verifyActiveNetwork(TRANSPORT_WIFI);
1361 // Test WiFi disconnect.
1362 cv = waitForConnectivityBroadcasts(1);
1363 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001364 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001365 verifyNoNetwork();
1366 }
1367
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001368 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001369 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
1370 // Test bringing up unvalidated cellular.
1371 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1372 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1373 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001374 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001375 verifyActiveNetwork(TRANSPORT_CELLULAR);
1376 // Test bringing up unvalidated WiFi.
1377 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1378 cv = waitForConnectivityBroadcasts(2);
1379 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001380 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001381 verifyActiveNetwork(TRANSPORT_WIFI);
1382 // Test WiFi disconnect.
1383 cv = waitForConnectivityBroadcasts(2);
1384 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001385 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001386 verifyActiveNetwork(TRANSPORT_CELLULAR);
1387 // Test cellular disconnect.
1388 cv = waitForConnectivityBroadcasts(1);
1389 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001390 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001391 verifyNoNetwork();
1392 }
1393
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001394 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001395 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04001396 // Test bringing up unvalidated WiFi.
Paul Jensene0988542015-06-25 15:30:08 -04001397 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001398 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1399 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -04001400 waitFor(cv);
1401 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001402 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001403 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -04001404 // Test bringing up validated cellular.
1405 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001406 cv = waitForConnectivityBroadcasts(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001407 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -04001408 waitFor(cv);
1409 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001410 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1411 NET_CAPABILITY_VALIDATED));
1412 // Test cellular disconnect.
1413 cv = waitForConnectivityBroadcasts(2);
1414 mCellNetworkAgent.disconnect();
1415 waitFor(cv);
1416 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001417 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001418 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001419 NET_CAPABILITY_VALIDATED));
1420 }
1421
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001422 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001423 public void testCellularOutscoresWeakWifi() throws Exception {
1424 // Test bringing up validated cellular.
1425 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1426 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1427 mCellNetworkAgent.connect(true);
1428 waitFor(cv);
1429 verifyActiveNetwork(TRANSPORT_CELLULAR);
1430 // Test bringing up validated WiFi.
1431 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1432 cv = waitForConnectivityBroadcasts(2);
1433 mWiFiNetworkAgent.connect(true);
1434 waitFor(cv);
1435 verifyActiveNetwork(TRANSPORT_WIFI);
1436 // Test WiFi getting really weak.
1437 cv = waitForConnectivityBroadcasts(2);
1438 mWiFiNetworkAgent.adjustScore(-11);
1439 waitFor(cv);
1440 verifyActiveNetwork(TRANSPORT_CELLULAR);
1441 // Test WiFi restoring signal strength.
1442 cv = waitForConnectivityBroadcasts(2);
1443 mWiFiNetworkAgent.adjustScore(11);
1444 waitFor(cv);
1445 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001446 }
1447
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001448 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001449 public void testReapingNetwork() throws Exception {
1450 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1451 // Expect it to be torn down immediately because it satisfies no requests.
1452 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1453 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
1454 mWiFiNetworkAgent.connectWithoutInternet();
1455 waitFor(cv);
1456 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1457 // Expect it to be torn down immediately because it satisfies no requests.
1458 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1459 cv = mCellNetworkAgent.getDisconnectedCV();
1460 mCellNetworkAgent.connectWithoutInternet();
1461 waitFor(cv);
1462 // Test bringing up validated WiFi.
1463 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1464 cv = waitForConnectivityBroadcasts(1);
1465 mWiFiNetworkAgent.connect(true);
1466 waitFor(cv);
1467 verifyActiveNetwork(TRANSPORT_WIFI);
1468 // Test bringing up unvalidated cellular.
1469 // Expect it to be torn down because it could never be the highest scoring network
1470 // satisfying the default request even if it validated.
1471 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1472 cv = mCellNetworkAgent.getDisconnectedCV();
1473 mCellNetworkAgent.connect(false);
1474 waitFor(cv);
1475 verifyActiveNetwork(TRANSPORT_WIFI);
1476 cv = mWiFiNetworkAgent.getDisconnectedCV();
1477 mWiFiNetworkAgent.disconnect();
1478 waitFor(cv);
1479 }
1480
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001481 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001482 public void testCellularFallback() throws Exception {
1483 // Test bringing up validated cellular.
1484 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1485 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1486 mCellNetworkAgent.connect(true);
1487 waitFor(cv);
1488 verifyActiveNetwork(TRANSPORT_CELLULAR);
1489 // Test bringing up validated WiFi.
1490 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1491 cv = waitForConnectivityBroadcasts(2);
1492 mWiFiNetworkAgent.connect(true);
1493 waitFor(cv);
1494 verifyActiveNetwork(TRANSPORT_WIFI);
1495 // Reevaluate WiFi (it'll instantly fail DNS).
1496 cv = waitForConnectivityBroadcasts(2);
1497 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1498 NET_CAPABILITY_VALIDATED));
1499 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1500 // Should quickly fall back to Cellular.
1501 waitFor(cv);
1502 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1503 NET_CAPABILITY_VALIDATED));
1504 verifyActiveNetwork(TRANSPORT_CELLULAR);
1505 // Reevaluate cellular (it'll instantly fail DNS).
1506 cv = waitForConnectivityBroadcasts(2);
1507 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1508 NET_CAPABILITY_VALIDATED));
1509 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1510 // Should quickly fall back to WiFi.
1511 waitFor(cv);
1512 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1513 NET_CAPABILITY_VALIDATED));
1514 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1515 NET_CAPABILITY_VALIDATED));
1516 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001517 }
1518
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001519 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001520 public void testWiFiFallback() throws Exception {
1521 // Test bringing up unvalidated WiFi.
1522 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1523 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1524 mWiFiNetworkAgent.connect(false);
1525 waitFor(cv);
1526 verifyActiveNetwork(TRANSPORT_WIFI);
1527 // Test bringing up validated cellular.
1528 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1529 cv = waitForConnectivityBroadcasts(2);
1530 mCellNetworkAgent.connect(true);
1531 waitFor(cv);
1532 verifyActiveNetwork(TRANSPORT_CELLULAR);
1533 // Reevaluate cellular (it'll instantly fail DNS).
1534 cv = waitForConnectivityBroadcasts(2);
1535 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1536 NET_CAPABILITY_VALIDATED));
1537 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1538 // Should quickly fall back to WiFi.
1539 waitFor(cv);
1540 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1541 NET_CAPABILITY_VALIDATED));
1542 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001543 }
1544
Lorenzo Colittied3168e2019-01-23 17:54:08 +09001545 @Test
1546 public void testRequiresValidation() {
1547 assertTrue(NetworkMonitorUtils.isValidationRequired(
1548 mCm.getDefaultRequest().networkCapabilities));
1549 }
1550
Paul Jensen3d911462015-06-12 06:40:24 -04001551 enum CallbackState {
1552 NONE,
1553 AVAILABLE,
Erik Klineacdd6392016-07-07 16:50:58 +09001554 NETWORK_CAPABILITIES,
1555 LINK_PROPERTIES,
Erik Kline1d3db322017-02-28 16:20:20 +09001556 SUSPENDED,
Chalard Jean804b8fb2018-01-30 22:41:41 +09001557 RESUMED,
Paul Jensen3d911462015-06-12 06:40:24 -04001558 LOSING,
Erik Kline3841a482015-11-25 12:49:38 +09001559 LOST,
Mike Yuf9729752018-08-17 15:22:05 +08001560 UNAVAILABLE,
1561 BLOCKED_STATUS
Paul Jensen3d911462015-06-12 06:40:24 -04001562 }
1563
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001564 private static class CallbackInfo {
1565 public final CallbackState state;
1566 public final Network network;
1567 public final Object arg;
1568 public CallbackInfo(CallbackState s, Network n, Object o) {
1569 state = s; network = n; arg = o;
1570 }
1571 public String toString() {
Erik Kline1d3db322017-02-28 16:20:20 +09001572 return String.format("%s (%s) (%s)", state, network, arg);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001573 }
1574 @Override
1575 public boolean equals(Object o) {
1576 if (!(o instanceof CallbackInfo)) return false;
1577 // Ignore timeMs, since it's unpredictable.
1578 CallbackInfo other = (CallbackInfo) o;
1579 return (state == other.state) && Objects.equals(network, other.network);
1580 }
1581 @Override
1582 public int hashCode() {
1583 return Objects.hash(state, network);
1584 }
1585 }
1586
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001587 /**
1588 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1589 * this class receives, by calling expectCallback() exactly once each time a callback is
1590 * received. assertNoCallback may be called at any time.
1591 */
Paul Jensen3d911462015-06-12 06:40:24 -04001592 private class TestNetworkCallback extends NetworkCallback {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001593 private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001594 private Network mLastAvailableNetwork;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001595
Erik Klineacdd6392016-07-07 16:50:58 +09001596 protected void setLastCallback(CallbackState state, Network network, Object o) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001597 mCallbacks.offer(new CallbackInfo(state, network, o));
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001598 }
Paul Jensen3d911462015-06-12 06:40:24 -04001599
Erik Klineacdd6392016-07-07 16:50:58 +09001600 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001601 public void onAvailable(Network network) {
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001602 mLastAvailableNetwork = network;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001603 setLastCallback(CallbackState.AVAILABLE, network, null);
Paul Jensen3d911462015-06-12 06:40:24 -04001604 }
1605
Erik Klineacdd6392016-07-07 16:50:58 +09001606 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001607 public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
1608 setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
1609 }
1610
1611 @Override
1612 public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
1613 setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
1614 }
1615
1616 @Override
Erik Kline3841a482015-11-25 12:49:38 +09001617 public void onUnavailable() {
1618 setLastCallback(CallbackState.UNAVAILABLE, null, null);
1619 }
1620
1621 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001622 public void onNetworkSuspended(Network network) {
1623 setLastCallback(CallbackState.SUSPENDED, network, null);
1624 }
1625
1626 @Override
Chalard Jean804b8fb2018-01-30 22:41:41 +09001627 public void onNetworkResumed(Network network) {
1628 setLastCallback(CallbackState.RESUMED, network, null);
1629 }
1630
1631 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001632 public void onLosing(Network network, int maxMsToLive) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001633 setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
Paul Jensen3d911462015-06-12 06:40:24 -04001634 }
1635
Erik Klineacdd6392016-07-07 16:50:58 +09001636 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001637 public void onLost(Network network) {
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001638 mLastAvailableNetwork = null;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001639 setLastCallback(CallbackState.LOST, network, null);
1640 }
1641
Mike Yuf9729752018-08-17 15:22:05 +08001642 @Override
1643 public void onBlockedStatusChanged(Network network, boolean blocked) {
1644 setLastCallback(CallbackState.BLOCKED_STATUS, network, blocked);
1645 }
1646
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001647 public Network getLastAvailableNetwork() {
1648 return mLastAvailableNetwork;
1649 }
1650
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001651 CallbackInfo nextCallback(int timeoutMs) {
1652 CallbackInfo cb = null;
1653 try {
1654 cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
1655 } catch (InterruptedException e) {
1656 }
1657 if (cb == null) {
1658 // LinkedBlockingQueue.poll() returns null if it timeouts.
1659 fail("Did not receive callback after " + timeoutMs + "ms");
1660 }
1661 return cb;
1662 }
1663
Erik Kline1d3db322017-02-28 16:20:20 +09001664 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs) {
1665 final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null;
1666 CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001667 CallbackInfo actual = nextCallback(timeoutMs);
1668 assertEquals("Unexpected callback:", expected, actual);
Erik Kline1d3db322017-02-28 16:20:20 +09001669
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001670 if (state == CallbackState.LOSING) {
1671 String msg = String.format(
1672 "Invalid linger time value %d, must be between %d and %d",
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001673 actual.arg, 0, mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001674 int maxMsToLive = (Integer) actual.arg;
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001675 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001676 }
Erik Kline1d3db322017-02-28 16:20:20 +09001677
1678 return actual;
Erik Klinea2d29402016-03-16 15:31:39 +09001679 }
1680
Erik Kline1d3db322017-02-28 16:20:20 +09001681 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001682 return expectCallback(state, agent, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001683 }
1684
Hugo Benichi16f0a942017-06-20 14:07:59 +09001685 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001686 return expectCallbackLike(fn, TEST_CALLBACK_TIMEOUT_MS);
Hugo Benichi16f0a942017-06-20 14:07:59 +09001687 }
1688
1689 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs) {
1690 int timeLeft = timeoutMs;
1691 while (timeLeft > 0) {
1692 long start = SystemClock.elapsedRealtime();
1693 CallbackInfo info = nextCallback(timeLeft);
1694 if (fn.test(info)) {
1695 return info;
1696 }
1697 timeLeft -= (SystemClock.elapsedRealtime() - start);
1698 }
1699 fail("Did not receive expected callback after " + timeoutMs + "ms");
1700 return null;
1701 }
1702
Lorenzo Colitti27334542018-01-12 16:22:21 +09001703 // Expects onAvailable and the callbacks that follow it. These are:
1704 // - onSuspended, iff the network was suspended when the callbacks fire.
1705 // - onCapabilitiesChanged.
1706 // - onLinkPropertiesChanged.
Mike Yuf9729752018-08-17 15:22:05 +08001707 // - onBlockedStatusChanged.
Lorenzo Colitti27334542018-01-12 16:22:21 +09001708 //
1709 // @param agent the network to expect the callbacks on.
1710 // @param expectSuspended whether to expect a SUSPENDED callback.
1711 // @param expectValidated the expected value of the VALIDATED capability in the
1712 // onCapabilitiesChanged callback.
1713 // @param timeoutMs how long to wait for the callbacks.
1714 void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended,
Mike Yuf9729752018-08-17 15:22:05 +08001715 boolean expectValidated, boolean expectBlocked, int timeoutMs) {
Erik Kline1d3db322017-02-28 16:20:20 +09001716 expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
Erik Klinec75d4fa2017-02-15 19:59:17 +09001717 if (expectSuspended) {
1718 expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001719 }
Lorenzo Colitti27334542018-01-12 16:22:21 +09001720 if (expectValidated) {
Chalard Jean1fa777d2018-02-16 16:07:53 +09001721 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001722 } else {
Chalard Jean1fa777d2018-02-16 16:07:53 +09001723 expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001724 }
Erik Klinec75d4fa2017-02-15 19:59:17 +09001725 expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs);
Mike Yuf9729752018-08-17 15:22:05 +08001726 expectBlockedStatusCallback(expectBlocked, agent);
Erik Kline1d3db322017-02-28 16:20:20 +09001727 }
1728
Lorenzo Colitti27334542018-01-12 16:22:21 +09001729 // Expects the available callbacks (validated), plus onSuspended.
1730 void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) {
Mike Yuf9729752018-08-17 15:22:05 +08001731 expectAvailableCallbacks(agent, true, expectValidated, false, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001732 }
1733
Lorenzo Colitti27334542018-01-12 16:22:21 +09001734 void expectAvailableCallbacksValidated(MockNetworkAgent agent) {
Mike Yuf9729752018-08-17 15:22:05 +08001735 expectAvailableCallbacks(agent, false, true, false, TEST_CALLBACK_TIMEOUT_MS);
1736 }
1737
1738 void expectAvailableCallbacksValidatedAndBlocked(MockNetworkAgent agent) {
1739 expectAvailableCallbacks(agent, false, true, true, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001740 }
1741
Lorenzo Colitti27334542018-01-12 16:22:21 +09001742 void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) {
Mike Yuf9729752018-08-17 15:22:05 +08001743 expectAvailableCallbacks(agent, false, false, false, TEST_CALLBACK_TIMEOUT_MS);
1744 }
1745
1746 void expectAvailableCallbacksUnvalidatedAndBlocked(MockNetworkAgent agent) {
1747 expectAvailableCallbacks(agent, false, false, true, TEST_CALLBACK_TIMEOUT_MS);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001748 }
1749
1750 // Expects the available callbacks (where the onCapabilitiesChanged must contain the
1751 // VALIDATED capability), plus another onCapabilitiesChanged which is identical to the
1752 // one we just sent.
1753 // TODO: this is likely a bug. Fix it and remove this method.
1754 void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001755 expectCallback(CallbackState.AVAILABLE, agent, TEST_CALLBACK_TIMEOUT_MS);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001756 NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001757 expectCallback(CallbackState.LINK_PROPERTIES, agent, TEST_CALLBACK_TIMEOUT_MS);
Mike Yuf9729752018-08-17 15:22:05 +08001758 // Implicitly check the network is allowed to use.
1759 // TODO: should we need to consider if network is in blocked status in this case?
1760 expectBlockedStatusCallback(false, agent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001761 NetworkCapabilities nc2 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1762 assertEquals(nc1, nc2);
1763 }
1764
1765 // Expects the available callbacks where the onCapabilitiesChanged must not have validated,
1766 // then expects another onCapabilitiesChanged that has the validated bit set. This is used
1767 // when a network connects and satisfies a callback, and then immediately validates.
1768 void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) {
1769 expectAvailableCallbacksUnvalidated(agent);
Erik Kline1d3db322017-02-28 16:20:20 +09001770 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1771 }
1772
Lorenzo Colitti27334542018-01-12 16:22:21 +09001773 NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001774 return expectCapabilitiesWith(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001775 }
1776
1777 NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent,
1778 int timeoutMs) {
1779 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001780 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1781 assertTrue(nc.hasCapability(capability));
Lorenzo Colitti27334542018-01-12 16:22:21 +09001782 return nc;
Erik Kline1d3db322017-02-28 16:20:20 +09001783 }
1784
Lorenzo Colitti27334542018-01-12 16:22:21 +09001785 NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001786 return expectCapabilitiesWithout(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001787 }
1788
1789 NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent,
1790 int timeoutMs) {
1791 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001792 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1793 assertFalse(nc.hasCapability(capability));
Lorenzo Colitti27334542018-01-12 16:22:21 +09001794 return nc;
Paul Jensen3d911462015-06-12 06:40:24 -04001795 }
1796
Chalard Jean0b214af2018-01-12 17:22:49 +09001797 void expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent) {
1798 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001799 assertTrue("Received capabilities don't match expectations : " + cbi.arg,
1800 fn.test((NetworkCapabilities) cbi.arg));
Chalard Jean0b214af2018-01-12 17:22:49 +09001801 }
1802
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09001803 void expectLinkPropertiesLike(Predicate<LinkProperties> fn, MockNetworkAgent agent) {
1804 CallbackInfo cbi = expectCallback(CallbackState.LINK_PROPERTIES, agent);
1805 assertTrue("Received LinkProperties don't match expectations : " + cbi.arg,
1806 fn.test((LinkProperties) cbi.arg));
1807 }
1808
Mike Yuf9729752018-08-17 15:22:05 +08001809 void expectBlockedStatusCallback(boolean expectBlocked, MockNetworkAgent agent) {
1810 CallbackInfo cbi = expectCallback(CallbackState.BLOCKED_STATUS, agent);
1811 boolean actualBlocked = (boolean) cbi.arg;
1812 assertEquals(expectBlocked, actualBlocked);
1813 }
1814
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001815 void assertNoCallback() {
Hugo Benichibb91c572017-05-22 10:44:02 +09001816 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001817 CallbackInfo c = mCallbacks.peek();
1818 assertNull("Unexpected callback: " + c, c);
1819 }
1820 }
1821
1822 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1823 // only be declared in a static or top level type".
1824 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1825 for (TestNetworkCallback c : callbacks) {
1826 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001827 }
1828 }
1829
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001830 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001831 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001832 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001833 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1834 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001835 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1836 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001837 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1838 .addTransportType(TRANSPORT_WIFI).build();
1839 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1840 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001841 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001842 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1843 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1844
1845 // Test unvalidated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001846 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1847 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1848 mCellNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001849 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1850 cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001851 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1852 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001853 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001854
Paul Jensen3d911462015-06-12 06:40:24 -04001855 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1856 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001857 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001858 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001859 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1860
Paul Jensen3d911462015-06-12 06:40:24 -04001861 cv = waitForConnectivityBroadcasts(2);
1862 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1863 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001864 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1865 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001866 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1867 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001868 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001869
Paul Jensen3d911462015-06-12 06:40:24 -04001870 cv = waitForConnectivityBroadcasts(2);
1871 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001872 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1873 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001874 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001875 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001876 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001877
Paul Jensen3d911462015-06-12 06:40:24 -04001878 cv = waitForConnectivityBroadcasts(1);
1879 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001880 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1881 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001882 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001883 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001884
1885 // Test validated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001886 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1887 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001888 genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1889 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001890 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001891 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001892
Paul Jensen3d911462015-06-12 06:40:24 -04001893 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1894 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001895 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001896 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001897 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1898
Paul Jensen3d911462015-06-12 06:40:24 -04001899 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1900 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001901 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001902 genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001903 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001904 wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001905 cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001906 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001907 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001908
Paul Jensen3d911462015-06-12 06:40:24 -04001909 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001910 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1911 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1912 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001913
Paul Jensen3d911462015-06-12 06:40:24 -04001914 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001915 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1916 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1917 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001918 }
1919
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001920 @Test
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001921 public void testMultipleLingering() {
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001922 // This test would be flaky with the default 120ms timer: that is short enough that
1923 // lingered networks are torn down before assertions can be run. We don't want to mock the
1924 // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
1925 // in detecting races.
1926 mService.mLingerDelayMs = 300;
1927
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001928 NetworkRequest request = new NetworkRequest.Builder()
1929 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1930 .build();
1931 TestNetworkCallback callback = new TestNetworkCallback();
1932 mCm.registerNetworkCallback(request, callback);
1933
1934 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1935 mCm.registerDefaultNetworkCallback(defaultCallback);
1936
1937 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1938 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1939 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
1940
1941 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1942 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1943 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1944
1945 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001946 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1947 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001948 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001949 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001950
1951 mWiFiNetworkAgent.connect(true);
1952 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1953 // We then get LOSING when wifi validates and cell is outscored.
Lorenzo Colitti27334542018-01-12 16:22:21 +09001954 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001955 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001956 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001957 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001958 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001959 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001960 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001961
1962 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001963 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001964 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001965 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001966 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001967 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001968 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001969 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001970
1971 mEthernetNetworkAgent.disconnect();
1972 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1973 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001974 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001975 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001976
1977 for (int i = 0; i < 4; i++) {
1978 MockNetworkAgent oldNetwork, newNetwork;
1979 if (i % 2 == 0) {
1980 mWiFiNetworkAgent.adjustScore(-15);
1981 oldNetwork = mWiFiNetworkAgent;
1982 newNetwork = mCellNetworkAgent;
1983 } else {
1984 mWiFiNetworkAgent.adjustScore(15);
1985 oldNetwork = mCellNetworkAgent;
1986 newNetwork = mWiFiNetworkAgent;
1987
1988 }
1989 callback.expectCallback(CallbackState.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001990 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1991 // longer lingering?
Lorenzo Colitti27334542018-01-12 16:22:21 +09001992 defaultCallback.expectAvailableCallbacksValidated(newNetwork);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001993 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
1994 }
1995 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1996
1997 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
1998 // if the network is still up.
1999 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
Erik Kline1d3db322017-02-28 16:20:20 +09002000 // We expect a notification about the capabilities change, and nothing else.
2001 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
2002 defaultCallback.assertNoCallback();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002003 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002004 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002005
2006 // Wifi no longer satisfies our listen, which is for an unmetered network.
2007 // But because its score is 55, it's still up (and the default network).
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002008 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2009
2010 // Disconnect our test networks.
2011 mWiFiNetworkAgent.disconnect();
2012 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002013 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002014 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002015 mCellNetworkAgent.disconnect();
2016 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002017 waitForIdle();
2018 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002019
2020 mCm.unregisterNetworkCallback(callback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002021 waitForIdle();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002022
2023 // Check that a network is only lingered or torn down if it would not satisfy a request even
2024 // if it validated.
2025 request = new NetworkRequest.Builder().clearCapabilities().build();
2026 callback = new TestNetworkCallback();
2027
2028 mCm.registerNetworkCallback(request, callback);
2029
2030 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2031 mCellNetworkAgent.connect(false); // Score: 10
Lorenzo Colitti27334542018-01-12 16:22:21 +09002032 callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2033 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002034 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002035 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002036
2037 // Bring up wifi with a score of 20.
2038 // Cell stays up because it would satisfy the default request if it validated.
2039 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2040 mWiFiNetworkAgent.connect(false); // Score: 20
Lorenzo Colitti27334542018-01-12 16:22:21 +09002041 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2042 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002043 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002044 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002045
2046 mWiFiNetworkAgent.disconnect();
2047 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2048 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002049 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002050 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002051 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002052
2053 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002054 // Cell is lingered because it would not satisfy any request, even if it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002055 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2056 mWiFiNetworkAgent.adjustScore(50);
2057 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti27334542018-01-12 16:22:21 +09002058 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002059 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002060 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002061 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002062 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002063
2064 // Tear down wifi.
2065 mWiFiNetworkAgent.disconnect();
2066 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2067 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002068 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002069 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002070 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002071
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002072 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
2073 // it's arguably correct to linger it, since it was the default network before it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002074 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2075 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002076 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002077 // TODO: Investigate sending validated before losing.
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002078 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002079 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002080 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002081 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002082 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002083
2084 mWiFiNetworkAgent.disconnect();
2085 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002086 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002087 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002088 mCellNetworkAgent.disconnect();
2089 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2090 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002091 waitForIdle();
2092 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002093
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002094 // If a network is lingering, and we add and remove a request from it, resume lingering.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002095 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2096 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002097 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2098 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002099 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002100 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2101 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002102 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2103 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002104 // TODO: Investigate sending validated before losing.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002105 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002106 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002107 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002108
2109 NetworkRequest cellRequest = new NetworkRequest.Builder()
2110 .addTransportType(TRANSPORT_CELLULAR).build();
2111 NetworkCallback noopCallback = new NetworkCallback();
2112 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002113 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
2114 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002115 mCm.unregisterNetworkCallback(noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002116 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002117
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002118 // Similar to the above: lingering can start even after the lingered request is removed.
2119 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002120 mWiFiNetworkAgent.disconnect();
2121 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002122 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002123 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002124 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002125
2126 // Cell is now the default network. Pin it with a cell-specific request.
2127 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
2128 mCm.requestNetwork(cellRequest, noopCallback);
2129
2130 // Now connect wifi, and expect it to become the default network.
2131 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2132 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002133 callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
2134 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002135 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002136 // The default request is lingering on cell, but nothing happens to cell, and we send no
2137 // callbacks for it, because it's kept up by cellRequest.
2138 callback.assertNoCallback();
2139 // Now unregister cellRequest and expect cell to start lingering.
2140 mCm.unregisterNetworkCallback(noopCallback);
2141 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2142
2143 // Let linger run its course.
2144 callback.assertNoCallback();
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09002145 final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
Hugo Benichidfb559a2016-12-20 14:57:49 +09002146 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002147
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002148 // Register a TRACK_DEFAULT request and check that it does not affect lingering.
2149 TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
2150 mCm.registerDefaultNetworkCallback(trackDefaultCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002151 trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002152 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2153 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002154 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002155 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
2156 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002157 trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
2158 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002159 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002160
2161 // Let linger run its course.
2162 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
2163
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002164 // Clean up.
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002165 mEthernetNetworkAgent.disconnect();
2166 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2167 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2168 trackDefaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002169
2170 mCm.unregisterNetworkCallback(callback);
2171 mCm.unregisterNetworkCallback(defaultCallback);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002172 mCm.unregisterNetworkCallback(trackDefaultCallback);
2173 }
2174
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002175 @Test
Chalard Jean1fa777d2018-02-16 16:07:53 +09002176 public void testNetworkGoesIntoBackgroundAfterLinger() {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002177 setAlwaysOnNetworks(true);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002178 NetworkRequest request = new NetworkRequest.Builder()
2179 .clearCapabilities()
2180 .build();
2181 TestNetworkCallback callback = new TestNetworkCallback();
2182 mCm.registerNetworkCallback(request, callback);
2183
2184 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2185 mCm.registerDefaultNetworkCallback(defaultCallback);
2186
2187 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2188 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2189
2190 mCellNetworkAgent.connect(true);
2191 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2192 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2193
2194 // Wifi comes up and cell lingers.
2195 mWiFiNetworkAgent.connect(true);
2196 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2197 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2198 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2199 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2200
2201 // File a request for cellular, then release it.
2202 NetworkRequest cellRequest = new NetworkRequest.Builder()
2203 .addTransportType(TRANSPORT_CELLULAR).build();
2204 NetworkCallback noopCallback = new NetworkCallback();
2205 mCm.requestNetwork(cellRequest, noopCallback);
2206 mCm.unregisterNetworkCallback(noopCallback);
2207 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2208
2209 // Let linger run its course.
Chalard Jeanb72b62d2018-02-16 16:08:35 +09002210 callback.assertNoCallback();
Chalard Jean1fa777d2018-02-16 16:07:53 +09002211 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2212 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
2213 lingerTimeoutMs);
2214
2215 // Clean up.
2216 mCm.unregisterNetworkCallback(defaultCallback);
2217 mCm.unregisterNetworkCallback(callback);
2218 }
2219
2220 @Test
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002221 public void testExplicitlySelected() {
2222 NetworkRequest request = new NetworkRequest.Builder()
2223 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2224 .build();
2225 TestNetworkCallback callback = new TestNetworkCallback();
2226 mCm.registerNetworkCallback(request, callback);
2227
2228 // Bring up validated cell.
2229 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2230 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002231 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002232
2233 // Bring up unvalidated wifi with explicitlySelected=true.
2234 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2235 mWiFiNetworkAgent.explicitlySelected(false);
2236 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002237 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002238
2239 // Cell Remains the default.
2240 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2241
2242 // Lower wifi's score to below than cell, and check that it doesn't disconnect because
2243 // it's explicitly selected.
2244 mWiFiNetworkAgent.adjustScore(-40);
2245 mWiFiNetworkAgent.adjustScore(40);
2246 callback.assertNoCallback();
2247
2248 // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
2249 // wifi even though it's unvalidated.
2250 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
2251 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2252 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2253
2254 // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
2255 mWiFiNetworkAgent.disconnect();
2256 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2257 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2258 mWiFiNetworkAgent.explicitlySelected(false);
2259 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002260 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002261
2262 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
2263 // network to disconnect.
2264 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
2265 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2266
2267 // Reconnect, again with explicitlySelected=true, but this time validate.
2268 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2269 mWiFiNetworkAgent.explicitlySelected(false);
2270 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002271 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002272 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2273 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2274 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2275
2276 // BUG: the network will no longer linger, even though it's validated and outscored.
2277 // TODO: fix this.
2278 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2279 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002280 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002281 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2282 callback.assertNoCallback();
2283
2284 // Clean up.
2285 mWiFiNetworkAgent.disconnect();
2286 mCellNetworkAgent.disconnect();
2287 mEthernetNetworkAgent.disconnect();
2288
2289 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2290 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2291 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002292 }
2293
Paul Jensen85cf78e2015-06-25 13:25:07 -04002294 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04002295 // Verify NOT_RESTRICTED is set appropriately
2296 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
2297 .build().networkCapabilities;
2298 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
2299 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
2300 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04002301 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04002302 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2303 } else {
2304 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2305 }
2306
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002307 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002308 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002309 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
2310 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04002311 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002312 mServiceContext, "testFactory", filter);
2313 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04002314 ConditionVariable cv = testFactory.getNetworkStartedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002315 testFactory.expectAddRequests(1);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002316 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002317 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002318 int expectedRequestCount = 1;
2319 NetworkCallback networkCallback = null;
2320 // For non-INTERNET capabilities we cannot rely on the default request being present, so
2321 // add one.
2322 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04002323 assertFalse(testFactory.getMyStartRequested());
2324 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
2325 networkCallback = new NetworkCallback();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002326 testFactory.expectAddRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002327 mCm.requestNetwork(request, networkCallback);
2328 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002329 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002330 }
Paul Jensen3d911462015-06-12 06:40:24 -04002331 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002332 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2333 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002334
Paul Jensen85cf78e2015-06-25 13:25:07 -04002335 // Now bring in a higher scored network.
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002336 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002337 // Rather than create a validated network which complicates things by registering it's
2338 // own NetworkRequest during startup, just bump up the score to cancel out the
2339 // unvalidated penalty.
2340 testAgent.adjustScore(40);
2341 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002342
2343 // When testAgent connects, ConnectivityService will re-send us all current requests with
2344 // the new score. There are expectedRequestCount such requests, and we must wait for all of
2345 // them.
2346 testFactory.expectAddRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002347 testAgent.connect(false);
2348 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04002349 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002350 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002351 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002352
Paul Jensen85cf78e2015-06-25 13:25:07 -04002353 // Bring in a bunch of requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002354 testFactory.expectAddRequests(10);
2355 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002356 ConnectivityManager.NetworkCallback[] networkCallbacks =
2357 new ConnectivityManager.NetworkCallback[10];
2358 for (int i = 0; i< networkCallbacks.length; i++) {
2359 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
2360 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002361 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002362 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
2363 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002364 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
2365 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002366
Paul Jensen85cf78e2015-06-25 13:25:07 -04002367 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002368 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002369 for (int i = 0; i < networkCallbacks.length; i++) {
2370 mCm.unregisterNetworkCallback(networkCallbacks[i]);
2371 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002372 testFactory.waitForNetworkRequests(expectedRequestCount);
2373 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002374
Paul Jensen85cf78e2015-06-25 13:25:07 -04002375 // Drop the higher scored network.
2376 cv = testFactory.getNetworkStartedCV();
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002377 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04002378 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002379 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2380 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002381
2382 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002383 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002384 handlerThread.quit();
2385 }
2386
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002387 @Test
Paul Jensen85cf78e2015-06-25 13:25:07 -04002388 public void testNetworkFactoryRequests() throws Exception {
2389 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
2390 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
2391 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
2392 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
2393 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
2394 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
2395 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
2396 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
2397 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
2398 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
2399 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
2400 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
2401 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
2402 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
2403 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
2404 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
2405 }
2406
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002407 @Test
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002408 public void testNoMutableNetworkRequests() throws Exception {
2409 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
Hugo Benichi16f0a942017-06-20 14:07:59 +09002410 NetworkRequest request1 = new NetworkRequest.Builder()
2411 .addCapability(NET_CAPABILITY_VALIDATED)
2412 .build();
2413 NetworkRequest request2 = new NetworkRequest.Builder()
2414 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
2415 .build();
2416
2417 Class<IllegalArgumentException> expected = IllegalArgumentException.class;
2418 assertException(() -> { mCm.requestNetwork(request1, new NetworkCallback()); }, expected);
2419 assertException(() -> { mCm.requestNetwork(request1, pendingIntent); }, expected);
2420 assertException(() -> { mCm.requestNetwork(request2, new NetworkCallback()); }, expected);
2421 assertException(() -> { mCm.requestNetwork(request2, pendingIntent); }, expected);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002422 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002423
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002424 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002425 public void testMMSonWiFi() throws Exception {
2426 // Test bringing up cellular without MMS NetworkRequest gets reaped
2427 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2428 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2429 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
2430 mCellNetworkAgent.connectWithoutInternet();
2431 waitFor(cv);
Hugo Benichibb91c572017-05-22 10:44:02 +09002432 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09002433 assertEmpty(mCm.getAllNetworks());
Paul Jensene0988542015-06-25 15:30:08 -04002434 verifyNoNetwork();
Hugo Benichibb91c572017-05-22 10:44:02 +09002435
Paul Jensene0988542015-06-25 15:30:08 -04002436 // Test bringing up validated WiFi.
2437 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2438 cv = waitForConnectivityBroadcasts(1);
2439 mWiFiNetworkAgent.connect(true);
2440 waitFor(cv);
2441 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002442
Paul Jensene0988542015-06-25 15:30:08 -04002443 // Register MMS NetworkRequest
2444 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2445 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2446 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2447 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002448
Paul Jensene0988542015-06-25 15:30:08 -04002449 // Test bringing up unvalidated cellular with MMS
2450 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2451 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002452 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002453 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002454 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002455
Paul Jensene0988542015-06-25 15:30:08 -04002456 // Test releasing NetworkRequest disconnects cellular with MMS
2457 cv = mCellNetworkAgent.getDisconnectedCV();
2458 mCm.unregisterNetworkCallback(networkCallback);
2459 waitFor(cv);
2460 verifyActiveNetwork(TRANSPORT_WIFI);
2461 }
2462
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002463 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002464 public void testMMSonCell() throws Exception {
2465 // Test bringing up cellular without MMS
2466 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2467 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2468 mCellNetworkAgent.connect(false);
2469 waitFor(cv);
2470 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002471
Paul Jensene0988542015-06-25 15:30:08 -04002472 // Register MMS NetworkRequest
2473 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2474 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2475 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2476 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002477
Paul Jensene0988542015-06-25 15:30:08 -04002478 // Test bringing up MMS cellular network
Paul Jensene0988542015-06-25 15:30:08 -04002479 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2480 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2481 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002482 networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002483 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002484
Paul Jensene0988542015-06-25 15:30:08 -04002485 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
2486 cv = mmsNetworkAgent.getDisconnectedCV();
2487 mCm.unregisterNetworkCallback(networkCallback);
2488 waitFor(cv);
2489 verifyActiveNetwork(TRANSPORT_CELLULAR);
2490 }
2491
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002492 @Test
Paul Jensencf4c2c62015-07-01 14:16:32 -04002493 public void testCaptivePortal() {
2494 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2495 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2496 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2497 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2498
2499 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2500 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2501 .addCapability(NET_CAPABILITY_VALIDATED).build();
2502 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002503
2504 // Bring up a network with a captive portal.
2505 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002506 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002507 String firstRedirectUrl = "http://example.com/firstPath";
2508 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002509 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002510 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002511
2512 // Take down network.
2513 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002514 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002515 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002516
2517 // Bring up a network with a captive portal.
2518 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002519 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002520 String secondRedirectUrl = "http://example.com/secondPath";
2521 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002522 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002523 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002524
2525 // Make captive portal disappear then revalidate.
2526 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002527 mWiFiNetworkAgent.setNetworkValid();
Paul Jensencf4c2c62015-07-01 14:16:32 -04002528 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002529 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002530
2531 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002532 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002533
2534 // Break network connectivity.
2535 // Expect NET_CAPABILITY_VALIDATED onLost callback.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002536 mWiFiNetworkAgent.setNetworkInvalid();
Paul Jensencf4c2c62015-07-01 14:16:32 -04002537 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002538 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002539 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002540
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002541 @Test
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002542 public void testCaptivePortalApp() throws RemoteException {
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002543 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2544 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2545 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2546 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2547
2548 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2549 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2550 .addCapability(NET_CAPABILITY_VALIDATED).build();
2551 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2552
2553 // Bring up wifi.
2554 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2555 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002556 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002557 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2558
2559 // Check that calling startCaptivePortalApp does nothing.
2560 final int fastTimeoutMs = 100;
2561 mCm.startCaptivePortalApp(wifiNetwork);
2562 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
2563
2564 // Turn into a captive portal.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002565 mWiFiNetworkAgent.setNetworkPortal("http://example.com");
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002566 mCm.reportNetworkConnectivity(wifiNetwork, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002567 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002568 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2569
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002570 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002571 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002572 verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
2573 .launchCaptivePortalApp();
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002574
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002575 // Report that the captive portal is dismissed, and check that callbacks are fired
2576 mWiFiNetworkAgent.setNetworkValid();
2577 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
Lorenzo Colitti27334542018-01-12 16:22:21 +09002578 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002579 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2580
2581 mCm.unregisterNetworkCallback(validatedCallback);
2582 mCm.unregisterNetworkCallback(captivePortalCallback);
2583 }
2584
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002585 @Test
Calvin On1f64f3f2016-10-11 15:10:46 -07002586 public void testAvoidOrIgnoreCaptivePortals() {
2587 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2588 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2589 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2590 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2591
2592 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2593 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2594 .addCapability(NET_CAPABILITY_VALIDATED).build();
2595 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2596
2597 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
2598 // Bring up a network with a captive portal.
2599 // Expect it to fail to connect and not result in any callbacks.
2600 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2601 String firstRedirectUrl = "http://example.com/firstPath";
2602
2603 ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
2604 ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
2605 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
2606 waitFor(disconnectCv);
2607 waitFor(avoidCv);
2608
2609 assertNoCallbacks(captivePortalCallback, validatedCallback);
Calvin On1f64f3f2016-10-11 15:10:46 -07002610 }
2611
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002612 private NetworkRequest.Builder newWifiRequestBuilder() {
2613 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
2614 }
2615
Etan Cohen836ad572018-12-30 17:59:59 -08002616 /**
2617 * Verify request matching behavior with network specifiers.
2618 *
2619 * Note: this test is somewhat problematic since it involves removing capabilities from
2620 * agents - i.e. agents rejecting requests which they previously accepted. This is flagged
2621 * as a WTF bug in
2622 * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but
2623 * does work.
2624 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002625 @Test
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002626 public void testNetworkSpecifier() {
Etan Cohen836ad572018-12-30 17:59:59 -08002627 // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
2628 class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
2629 Parcelable {
2630 @Override
2631 public boolean satisfiedBy(NetworkSpecifier other) {
2632 return true;
2633 }
2634
2635 @Override
2636 public int describeContents() {
2637 return 0;
2638 }
2639
2640 @Override
2641 public void writeToParcel(Parcel dest, int flags) {}
2642
2643 @Override
2644 public NetworkSpecifier redact() {
2645 return null;
2646 }
2647 }
2648
2649 // A network specifier that matches either another LocalNetworkSpecifier with the same
2650 // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
2651 class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2652 private String mString;
2653
2654 LocalStringNetworkSpecifier(String string) {
2655 mString = string;
2656 }
2657
2658 @Override
2659 public boolean satisfiedBy(NetworkSpecifier other) {
2660 if (other instanceof LocalStringNetworkSpecifier) {
2661 return TextUtils.equals(mString,
2662 ((LocalStringNetworkSpecifier) other).mString);
2663 }
2664 if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
2665 return false;
2666 }
2667
2668 @Override
2669 public int describeContents() {
2670 return 0;
2671 }
2672 @Override
2673 public void writeToParcel(Parcel dest, int flags) {}
2674 }
2675
2676
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002677 NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
Etan Cohena7434272017-04-03 12:17:51 -07002678 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002679 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
Etan Cohena7434272017-04-03 12:17:51 -07002680 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
2681 (NetworkSpecifier) null).build();
Etan Cohen836ad572018-12-30 17:59:59 -08002682 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
2683 new LocalStringNetworkSpecifier("foo")).build();
Etan Cohena7434272017-04-03 12:17:51 -07002684 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
Etan Cohen836ad572018-12-30 17:59:59 -08002685 new LocalStringNetworkSpecifier("bar")).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002686
2687 TestNetworkCallback cEmpty1 = new TestNetworkCallback();
2688 TestNetworkCallback cEmpty2 = new TestNetworkCallback();
2689 TestNetworkCallback cEmpty3 = new TestNetworkCallback();
Etan Cohena7434272017-04-03 12:17:51 -07002690 TestNetworkCallback cEmpty4 = new TestNetworkCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002691 TestNetworkCallback cFoo = new TestNetworkCallback();
2692 TestNetworkCallback cBar = new TestNetworkCallback();
2693 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
Etan Cohen836ad572018-12-30 17:59:59 -08002694 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002695
2696 mCm.registerNetworkCallback(rEmpty1, cEmpty1);
2697 mCm.registerNetworkCallback(rEmpty2, cEmpty2);
2698 mCm.registerNetworkCallback(rEmpty3, cEmpty3);
Etan Cohena7434272017-04-03 12:17:51 -07002699 mCm.registerNetworkCallback(rEmpty4, cEmpty4);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002700 mCm.registerNetworkCallback(rFoo, cFoo);
2701 mCm.registerNetworkCallback(rBar, cBar);
2702
Etan Cohen836ad572018-12-30 17:59:59 -08002703 LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
2704 LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
2705
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002706 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2707 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002708 cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2709 cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2710 cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2711 cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002712 assertNoCallbacks(cFoo, cBar);
2713
Etan Cohen836ad572018-12-30 17:59:59 -08002714 mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002715 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002716 for (TestNetworkCallback c: emptyCallbacks) {
Etan Cohen836ad572018-12-30 17:59:59 -08002717 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
2718 mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002719 }
Etan Cohen836ad572018-12-30 17:59:59 -08002720 cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
2721 mWiFiNetworkAgent);
2722 assertEquals(nsFoo,
2723 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002724 cFoo.assertNoCallback();
2725
Etan Cohen836ad572018-12-30 17:59:59 -08002726 mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002727 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002728 cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002729 for (TestNetworkCallback c: emptyCallbacks) {
Etan Cohen836ad572018-12-30 17:59:59 -08002730 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
2731 mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002732 }
Etan Cohen836ad572018-12-30 17:59:59 -08002733 cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
2734 mWiFiNetworkAgent);
2735 assertEquals(nsBar,
2736 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
2737 cBar.assertNoCallback();
2738
2739 mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
2740 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2741 for (TestNetworkCallback c : emptyCallbacks) {
2742 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
2743 mWiFiNetworkAgent);
2744 }
2745 cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
2746 mWiFiNetworkAgent);
2747 cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
2748 mWiFiNetworkAgent);
2749 assertNull(
2750 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
2751 cFoo.assertNoCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002752 cBar.assertNoCallback();
2753
2754 mWiFiNetworkAgent.setNetworkSpecifier(null);
Etan Cohen836ad572018-12-30 17:59:59 -08002755 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002756 cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2757 for (TestNetworkCallback c: emptyCallbacks) {
2758 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
2759 }
2760
Etan Cohen836ad572018-12-30 17:59:59 -08002761 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002762 }
2763
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002764 @Test
Etan Cohenddb9ef02015-11-18 10:56:15 -08002765 public void testInvalidNetworkSpecifier() {
Etan Cohenddb9ef02015-11-18 10:56:15 -08002766 try {
2767 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Etan Cohena7434272017-04-03 12:17:51 -07002768 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
2769 fail("NetworkRequest builder with MatchAllNetworkSpecifier");
2770 } catch (IllegalArgumentException expected) {
2771 // expected
Etan Cohenddb9ef02015-11-18 10:56:15 -08002772 }
2773
Etan Cohenddb9ef02015-11-18 10:56:15 -08002774 try {
2775 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
2776 networkCapabilities.addTransportType(TRANSPORT_WIFI)
Etan Cohena7434272017-04-03 12:17:51 -07002777 .setNetworkSpecifier(new MatchAllNetworkSpecifier());
Etan Cohenddb9ef02015-11-18 10:56:15 -08002778 mService.requestNetwork(networkCapabilities, null, 0, null,
2779 ConnectivityManager.TYPE_WIFI);
Etan Cohena7434272017-04-03 12:17:51 -07002780 fail("ConnectivityService requestNetwork with MatchAllNetworkSpecifier");
2781 } catch (IllegalArgumentException expected) {
2782 // expected
Etan Cohenddb9ef02015-11-18 10:56:15 -08002783 }
2784
Etan Cohena7434272017-04-03 12:17:51 -07002785 class NonParcelableSpecifier extends NetworkSpecifier {
2786 public boolean satisfiedBy(NetworkSpecifier other) { return false; }
2787 };
2788 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
2789 @Override public int describeContents() { return 0; }
2790 @Override public void writeToParcel(Parcel p, int flags) {}
2791 }
2792 NetworkRequest.Builder builder;
2793
2794 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
2795 try {
2796 builder.setNetworkSpecifier(new NonParcelableSpecifier());
2797 Parcel parcelW = Parcel.obtain();
2798 builder.build().writeToParcel(parcelW, 0);
2799 fail("Parceling a non-parcelable specifier did not throw an exception");
2800 } catch (Exception e) {
2801 // expected
2802 }
2803
2804 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
2805 builder.setNetworkSpecifier(new ParcelableSpecifier());
2806 NetworkRequest nr = builder.build();
2807 assertNotNull(nr);
2808
2809 try {
2810 Parcel parcelW = Parcel.obtain();
2811 nr.writeToParcel(parcelW, 0);
2812 byte[] bytes = parcelW.marshall();
2813 parcelW.recycle();
2814
2815 Parcel parcelR = Parcel.obtain();
2816 parcelR.unmarshall(bytes, 0, bytes.length);
2817 parcelR.setDataPosition(0);
2818 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
2819 fail("Unparceling a non-framework NetworkSpecifier did not throw an exception");
2820 } catch (Exception e) {
2821 // expected
2822 }
Etan Cohenddb9ef02015-11-18 10:56:15 -08002823 }
2824
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002825 @Test
Etan Cohen859748f2017-04-03 17:42:34 -07002826 public void testNetworkSpecifierUidSpoofSecurityException() {
2827 class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2828 @Override
2829 public boolean satisfiedBy(NetworkSpecifier other) {
2830 return true;
2831 }
2832
2833 @Override
2834 public void assertValidFromUid(int requestorUid) {
2835 throw new SecurityException("failure");
2836 }
2837
2838 @Override
2839 public int describeContents() { return 0; }
2840 @Override
2841 public void writeToParcel(Parcel dest, int flags) {}
2842 }
2843
2844 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2845 mWiFiNetworkAgent.connect(false);
2846
2847 UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
2848 NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier(
2849 networkSpecifier).build();
2850 TestNetworkCallback networkCallback = new TestNetworkCallback();
2851 try {
2852 mCm.requestNetwork(networkRequest, networkCallback);
2853 fail("Network request with spoofed UID did not throw a SecurityException");
2854 } catch (SecurityException e) {
2855 // expected
2856 }
2857 }
2858
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002859 @Test
Erik Klinea2d29402016-03-16 15:31:39 +09002860 public void testRegisterDefaultNetworkCallback() throws Exception {
2861 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
2862 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
2863 defaultNetworkCallback.assertNoCallback();
2864
2865 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
2866 // whenever Wi-Fi is up. Without this, the mobile network agent is
2867 // reaped before any other activity can take place.
2868 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2869 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2870 .addTransportType(TRANSPORT_CELLULAR).build();
2871 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2872 cellNetworkCallback.assertNoCallback();
2873
2874 // Bring up cell and expect CALLBACK_AVAILABLE.
2875 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2876 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002877 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2878 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002879 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002880
2881 // Bring up wifi and expect CALLBACK_AVAILABLE.
2882 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2883 mWiFiNetworkAgent.connect(true);
2884 cellNetworkCallback.assertNoCallback();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002885 defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002886 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002887
2888 // Bring down cell. Expect no default network callback, since it wasn't the default.
2889 mCellNetworkAgent.disconnect();
2890 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2891 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002892 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002893
2894 // Bring up cell. Expect no default network callback, since it won't be the default.
2895 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2896 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002897 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002898 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002899 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002900
2901 // Bring down wifi. Expect the default network callback to notified of LOST wifi
2902 // followed by AVAILABLE cell.
2903 mWiFiNetworkAgent.disconnect();
2904 cellNetworkCallback.assertNoCallback();
2905 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002906 defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002907 mCellNetworkAgent.disconnect();
2908 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2909 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002910 waitForIdle();
2911 assertEquals(null, mCm.getActiveNetwork());
2912
2913 final int uid = Process.myUid();
2914 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
2915 final ArraySet<UidRange> ranges = new ArraySet<>();
2916 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09002917 mMockVpn.setNetworkAgent(vpnNetworkAgent);
2918 mMockVpn.setUids(ranges);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002919 vpnNetworkAgent.connect(true);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09002920 mMockVpn.connect();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002921 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
2922 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2923
2924 vpnNetworkAgent.disconnect();
2925 defaultNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
2926 waitForIdle();
2927 assertEquals(null, mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002928 }
2929
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002930 @Test
Erik Kline1d3db322017-02-28 16:20:20 +09002931 public void testAdditionalStateCallbacks() throws Exception {
Erik Klineacdd6392016-07-07 16:50:58 +09002932 // File a network request for mobile.
Erik Kline1d3db322017-02-28 16:20:20 +09002933 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09002934 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2935 .addTransportType(TRANSPORT_CELLULAR).build();
2936 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2937
2938 // Bring up the mobile network.
2939 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2940 mCellNetworkAgent.connect(true);
2941
Erik Kline1d3db322017-02-28 16:20:20 +09002942 // We should get onAvailable(), onCapabilitiesChanged(), and
2943 // onLinkPropertiesChanged() in rapid succession. Additionally, we
2944 // should get onCapabilitiesChanged() when the mobile network validates.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002945 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09002946 cellNetworkCallback.assertNoCallback();
2947
2948 // Update LinkProperties.
2949 final LinkProperties lp = new LinkProperties();
2950 lp.setInterfaceName("foonet_data0");
2951 mCellNetworkAgent.sendLinkProperties(lp);
2952 // We should get onLinkPropertiesChanged().
2953 cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
2954 cellNetworkCallback.assertNoCallback();
2955
Erik Kline1d3db322017-02-28 16:20:20 +09002956 // Suspend the network.
2957 mCellNetworkAgent.suspend();
Chalard Jean804b8fb2018-01-30 22:41:41 +09002958 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
2959 mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002960 cellNetworkCallback.expectCallback(CallbackState.SUSPENDED, mCellNetworkAgent);
2961 cellNetworkCallback.assertNoCallback();
2962
Erik Klineacdd6392016-07-07 16:50:58 +09002963 // Register a garden variety default network request.
Chalard Jean804b8fb2018-01-30 22:41:41 +09002964 TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09002965 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09002966 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
2967 // as well as onNetworkSuspended() in rapid succession.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002968 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
Erik Klineacdd6392016-07-07 16:50:58 +09002969 dfltNetworkCallback.assertNoCallback();
Chalard Jean804b8fb2018-01-30 22:41:41 +09002970 mCm.unregisterNetworkCallback(dfltNetworkCallback);
2971
2972 mCellNetworkAgent.resume();
2973 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
2974 mCellNetworkAgent);
2975 cellNetworkCallback.expectCallback(CallbackState.RESUMED, mCellNetworkAgent);
2976 cellNetworkCallback.assertNoCallback();
2977
2978 dfltNetworkCallback = new TestNetworkCallback();
2979 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
2980 // This time onNetworkSuspended should not be called.
2981 dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
2982 dfltNetworkCallback.assertNoCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09002983
Erik Klineacdd6392016-07-07 16:50:58 +09002984 mCm.unregisterNetworkCallback(dfltNetworkCallback);
2985 mCm.unregisterNetworkCallback(cellNetworkCallback);
2986 }
2987
Calvin On1f64f3f2016-10-11 15:10:46 -07002988 private void setCaptivePortalMode(int mode) {
2989 ContentResolver cr = mServiceContext.getContentResolver();
2990 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
2991 }
2992
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002993 private void setAlwaysOnNetworks(boolean enable) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002994 ContentResolver cr = mServiceContext.getContentResolver();
2995 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002996 mService.updateAlwaysOnNetworks();
Hugo Benichibb91c572017-05-22 10:44:02 +09002997 waitForIdle();
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09002998 }
2999
Erik Kline79c6d052018-03-21 07:18:33 -07003000 private void setPrivateDnsSettings(String mode, String specifier) {
3001 final ContentResolver cr = mServiceContext.getContentResolver();
3002 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
3003 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
3004 mService.updatePrivateDnsSettings();
3005 waitForIdle();
3006 }
3007
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003008 private boolean isForegroundNetwork(MockNetworkAgent network) {
3009 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
3010 assertNotNull(nc);
3011 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
3012 }
3013
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003014 @Test
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003015 public void testBackgroundNetworks() throws Exception {
3016 // Create a background request. We can't do this ourselves because ConnectivityService
3017 // doesn't have an API for it. So just turn on mobile data always on.
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003018 setAlwaysOnNetworks(true);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003019 final NetworkRequest request = new NetworkRequest.Builder().build();
3020 final NetworkRequest fgRequest = new NetworkRequest.Builder()
3021 .addCapability(NET_CAPABILITY_FOREGROUND).build();
3022 final TestNetworkCallback callback = new TestNetworkCallback();
3023 final TestNetworkCallback fgCallback = new TestNetworkCallback();
3024 mCm.registerNetworkCallback(request, callback);
3025 mCm.registerNetworkCallback(fgRequest, fgCallback);
3026
3027 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3028 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003029 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3030 fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003031 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3032
3033 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3034 mWiFiNetworkAgent.connect(true);
3035
3036 // When wifi connects, cell lingers.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003037 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003038 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003039 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003040 fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003041 fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003042 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003043 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3044 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3045
3046 // When lingering is complete, cell is still there but is now in the background.
Hugo Benichibb91c572017-05-22 10:44:02 +09003047 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003048 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
3049 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09003050 // Expect a network capabilities update sans FOREGROUND.
3051 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003052 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3053 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3054
3055 // File a cell request and check that cell comes into the foreground.
3056 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3057 .addTransportType(TRANSPORT_CELLULAR).build();
3058 final TestNetworkCallback cellCallback = new TestNetworkCallback();
3059 mCm.requestNetwork(cellRequest, cellCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09003060 // NOTE: This request causes the network's capabilities to change. This
3061 // is currently delivered before the onAvailable() callbacks.
3062 // TODO: Fix this.
3063 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003064 cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3065 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003066 // Expect a network capabilities update with FOREGROUND, because the most recent
3067 // request causes its state to change.
3068 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003069 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3070 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3071
3072 // Release the request. The network immediately goes into the background, since it was not
3073 // lingering.
3074 mCm.unregisterNetworkCallback(cellCallback);
3075 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003076 // Expect a network capabilities update sans FOREGROUND.
3077 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003078 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3079 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3080
3081 // Disconnect wifi and check that cell is foreground again.
3082 mWiFiNetworkAgent.disconnect();
3083 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3084 fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003085 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003086 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3087
3088 mCm.unregisterNetworkCallback(callback);
3089 mCm.unregisterNetworkCallback(fgCallback);
3090 }
3091
Hugo Benichi849b81b2017-05-25 13:42:31 +09003092 @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003093 public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003094 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003095 // Benchmarks connecting and switching performance in the presence of a large number of
3096 // NetworkRequests.
3097 // 1. File NUM_REQUESTS requests.
3098 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
3099 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
3100 // and NUM_REQUESTS onAvailable callbacks to fire.
3101 // See how long it took.
3102 final int NUM_REQUESTS = 90;
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003103 final int REGISTER_TIME_LIMIT_MS = 200;
3104 final int CONNECT_TIME_LIMIT_MS = 60;
3105 final int SWITCH_TIME_LIMIT_MS = 60;
Hugo Benichibb91c572017-05-22 10:44:02 +09003106 final int UNREGISTER_TIME_LIMIT_MS = 20;
3107
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003108 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
3109 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
3110 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
3111 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
3112
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003113 for (int i = 0; i < NUM_REQUESTS; i++) {
3114 callbacks[i] = new NetworkCallback() {
3115 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
3116 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
3117 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003118 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003119
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003120 assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
3121 for (NetworkCallback cb : callbacks) {
3122 mCm.registerNetworkCallback(request, cb);
3123 }
3124 });
3125
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003126 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3127 // Don't request that the network validate, because otherwise connect() will block until
3128 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
3129 // and we won't actually measure anything.
3130 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003131
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003132 long onAvailableDispatchingDuration = durationOf(() -> {
Hugo Benichibb91c572017-05-22 10:44:02 +09003133 awaitLatch(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003134 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003135 Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
3136 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
3137 onAvailableDispatchingDuration));
3138 assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
3139 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
3140 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003141
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003142 // Give wifi a high enough score that we'll linger cell when wifi comes up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003143 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003144 mWiFiNetworkAgent.adjustScore(40);
3145 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003146
3147 long onLostDispatchingDuration = durationOf(() -> {
Hugo Benichibb91c572017-05-22 10:44:02 +09003148 awaitLatch(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003149 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003150 Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
3151 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
3152 assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
3153 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
3154 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003155
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003156 assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
3157 for (NetworkCallback cb : callbacks) {
3158 mCm.unregisterNetworkCallback(cb);
3159 }
3160 });
3161 }
3162
3163 private long durationOf(Runnable fn) {
3164 long startTime = SystemClock.elapsedRealtime();
3165 fn.run();
3166 return SystemClock.elapsedRealtime() - startTime;
3167 }
3168
3169 private void assertTimeLimit(String descr, long timeLimit, Runnable fn) {
3170 long timeTaken = durationOf(fn);
3171 String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003172 Log.d(TAG, msg);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003173 assertTrue(msg, timeTaken <= timeLimit);
3174 }
3175
3176 private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
3177 try {
Hugo Benichibb91c572017-05-22 10:44:02 +09003178 return l.await(timeoutMs, TimeUnit.MILLISECONDS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003179 } catch (InterruptedException e) {}
3180 return false;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003181 }
3182
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003183 @Test
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003184 public void testMobileDataAlwaysOn() throws Exception {
3185 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3186 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3187 .addTransportType(TRANSPORT_CELLULAR).build();
3188 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3189
3190 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
3191 handlerThread.start();
3192 NetworkCapabilities filter = new NetworkCapabilities()
3193 .addTransportType(TRANSPORT_CELLULAR)
3194 .addCapability(NET_CAPABILITY_INTERNET);
3195 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3196 mServiceContext, "testFactory", filter);
3197 testFactory.setScoreFilter(40);
3198
3199 // Register the factory and expect it to start looking for a network.
3200 testFactory.expectAddRequests(1);
3201 testFactory.register();
3202 testFactory.waitForNetworkRequests(1);
3203 assertTrue(testFactory.getMyStartRequested());
3204
3205 // Bring up wifi. The factory stops looking for a network.
3206 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3207 testFactory.expectAddRequests(2); // Because the default request changes score twice.
3208 mWiFiNetworkAgent.connect(true);
3209 testFactory.waitForNetworkRequests(1);
3210 assertFalse(testFactory.getMyStartRequested());
3211
3212 ContentResolver cr = mServiceContext.getContentResolver();
3213
3214 // Turn on mobile data always on. The factory starts looking again.
3215 testFactory.expectAddRequests(1);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003216 setAlwaysOnNetworks(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003217 testFactory.waitForNetworkRequests(2);
3218 assertTrue(testFactory.getMyStartRequested());
3219
3220 // Bring up cell data and check that the factory stops looking.
Hugo Benichifed512a2017-06-26 10:06:49 +09003221 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003222 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3223 testFactory.expectAddRequests(2); // Because the cell request changes score twice.
3224 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003225 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003226 testFactory.waitForNetworkRequests(2);
3227 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
3228
3229 // Check that cell data stays up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003230 waitForIdle();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003231 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09003232 assertLength(2, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003233
3234 // Turn off mobile data always on and expect the request to disappear...
3235 testFactory.expectRemoveRequests(1);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003236 setAlwaysOnNetworks(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003237 testFactory.waitForNetworkRequests(1);
3238
3239 // ... and cell data to be torn down.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003240 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Hugo Benichifed512a2017-06-26 10:06:49 +09003241 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003242
3243 testFactory.unregister();
3244 mCm.unregisterNetworkCallback(cellNetworkCallback);
3245 handlerThread.quit();
3246 }
3247
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003248 @Test
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003249 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003250 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09003251 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003252 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
3253
Erik Kline065ab6e2016-10-02 18:02:14 +09003254 tracker.configRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003255 String[] values = new String[] {null, "0", "1"};
3256 for (int i = 0; i < values.length; i++) {
3257 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003258 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003259 waitForIdle();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003260 String msg = String.format("config=false, setting=%s", values[i]);
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003261 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003262 assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003263 }
3264
Erik Kline065ab6e2016-10-02 18:02:14 +09003265 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003266
3267 Settings.Global.putInt(cr, settingName, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09003268 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003269 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003270 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003271 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003272
3273 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003274 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003275 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003276 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003277 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003278
3279 Settings.Global.putString(cr, settingName, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09003280 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003281 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003282 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003283 assertTrue(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003284 }
3285
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003286 @Test
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003287 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09003288 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09003289 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003290
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003291 // Pretend we're on a carrier that restricts switching away from bad wifi.
Erik Kline065ab6e2016-10-02 18:02:14 +09003292 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003293
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003294 // File a request for cell to ensure it doesn't go down.
3295 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3296 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3297 .addTransportType(TRANSPORT_CELLULAR).build();
3298 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3299
3300 TestNetworkCallback defaultCallback = new TestNetworkCallback();
3301 mCm.registerDefaultNetworkCallback(defaultCallback);
3302
3303 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
3304 .addTransportType(TRANSPORT_WIFI)
3305 .addCapability(NET_CAPABILITY_VALIDATED)
3306 .build();
3307 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
3308 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
3309
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003310 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09003311 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003312
3313 // Bring up validated cell.
3314 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3315 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003316 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3317 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003318 Network cellNetwork = mCellNetworkAgent.getNetwork();
3319
3320 // Bring up validated wifi.
3321 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3322 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003323 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3324 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003325 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
3326
3327 // Fail validation on wifi.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09003328 mWiFiNetworkAgent.setNetworkInvalid();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003329 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003330 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003331 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3332
3333 // Because avoid bad wifi is off, we don't switch to cellular.
3334 defaultCallback.assertNoCallback();
3335 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3336 NET_CAPABILITY_VALIDATED));
3337 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3338 NET_CAPABILITY_VALIDATED));
3339 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3340
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003341 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
3342 // that we switch back to cell.
Erik Kline065ab6e2016-10-02 18:02:14 +09003343 tracker.configRestrictsAvoidBadWifi = false;
3344 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003345 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003346 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3347
3348 // Switch back to a restrictive carrier.
Erik Kline065ab6e2016-10-02 18:02:14 +09003349 tracker.configRestrictsAvoidBadWifi = true;
3350 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003351 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003352 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3353
3354 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
3355 mCm.setAvoidUnvalidated(wifiNetwork);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003356 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003357 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3358 NET_CAPABILITY_VALIDATED));
3359 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3360 NET_CAPABILITY_VALIDATED));
3361 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3362
3363 // Disconnect and reconnect wifi to clear the one-time switch above.
3364 mWiFiNetworkAgent.disconnect();
3365 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3366 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003367 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3368 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003369 wifiNetwork = mWiFiNetworkAgent.getNetwork();
3370
3371 // Fail validation on wifi and expect the dialog to appear.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09003372 mWiFiNetworkAgent.setNetworkInvalid();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003373 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003374 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003375 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3376
3377 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003378 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003379 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003380
3381 // We now switch to cell.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003382 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003383 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3384 NET_CAPABILITY_VALIDATED));
3385 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3386 NET_CAPABILITY_VALIDATED));
3387 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3388
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003389 // Simulate the user turning the cellular fallback setting off and then on.
3390 // We switch to wifi and then to cell.
3391 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09003392 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003393 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003394 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3395 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003396 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003397 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003398 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3399
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003400 // If cell goes down, we switch to wifi.
3401 mCellNetworkAgent.disconnect();
3402 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003403 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003404 validatedWifiCallback.assertNoCallback();
3405
3406 mCm.unregisterNetworkCallback(cellNetworkCallback);
3407 mCm.unregisterNetworkCallback(validatedWifiCallback);
3408 mCm.unregisterNetworkCallback(defaultCallback);
3409 }
3410
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003411 @Test
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003412 public void testMeteredMultipathPreferenceSetting() throws Exception {
3413 final ContentResolver cr = mServiceContext.getContentResolver();
3414 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
3415 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
3416
3417 for (int config : Arrays.asList(0, 3, 2)) {
3418 for (String setting: Arrays.asList(null, "0", "2", "1")) {
3419 tracker.configMeteredMultipathPreference = config;
3420 Settings.Global.putString(cr, settingName, setting);
3421 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003422 waitForIdle();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003423
3424 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
3425 String msg = String.format("config=%d, setting=%s", config, setting);
3426 assertEquals(msg, expected, mCm.getMultipathPreference(null));
3427 }
3428 }
3429 }
3430
Erik Kline3841a482015-11-25 12:49:38 +09003431 /**
3432 * Validate that a satisfied network request does not trigger onUnavailable() once the
3433 * time-out period expires.
3434 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003435 @Test
Erik Kline3841a482015-11-25 12:49:38 +09003436 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
3437 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3438 NetworkCapabilities.TRANSPORT_WIFI).build();
3439 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003440 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003441
3442 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3443 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003444 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003445 TEST_CALLBACK_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003446
3447 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003448 networkCallback.assertNoCallback();
3449 }
3450
3451 /**
3452 * Validate that a satisfied network request followed by a disconnected (lost) network does
3453 * not trigger onUnavailable() once the time-out period expires.
3454 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003455 @Test
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003456 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
3457 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3458 NetworkCapabilities.TRANSPORT_WIFI).build();
3459 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003460 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003461
3462 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3463 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003464 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003465 TEST_CALLBACK_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003466 mWiFiNetworkAgent.disconnect();
3467 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3468
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003469 // Validate that UNAVAILABLE is not called
Erik Kline3841a482015-11-25 12:49:38 +09003470 networkCallback.assertNoCallback();
3471 }
3472
3473 /**
3474 * Validate that when a time-out is specified for a network request the onUnavailable()
3475 * callback is called when time-out expires. Then validate that if network request is
3476 * (somehow) satisfied - the callback isn't called later.
3477 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003478 @Test
Erik Kline3841a482015-11-25 12:49:38 +09003479 public void testTimedoutNetworkRequest() {
3480 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3481 NetworkCapabilities.TRANSPORT_WIFI).build();
3482 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003483 final int timeoutMs = 10;
3484 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003485
3486 // pass timeout and validate that UNAVAILABLE is called
3487 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
3488
3489 // create a network satisfying request - validate that request not triggered
3490 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3491 mWiFiNetworkAgent.connect(false);
3492 networkCallback.assertNoCallback();
3493 }
3494
3495 /**
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003496 * Validate that when a network request is unregistered (cancelled), no posterior event can
3497 * trigger the callback.
Erik Kline3841a482015-11-25 12:49:38 +09003498 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003499 @Test
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003500 public void testNoCallbackAfterUnregisteredNetworkRequest() {
Erik Kline3841a482015-11-25 12:49:38 +09003501 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3502 NetworkCapabilities.TRANSPORT_WIFI).build();
3503 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003504 final int timeoutMs = 10;
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003505
Hugo Benichidfb559a2016-12-20 14:57:49 +09003506 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003507 mCm.unregisterNetworkCallback(networkCallback);
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003508 // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
3509 // that this callback will not be called.
Erik Kline3841a482015-11-25 12:49:38 +09003510 networkCallback.assertNoCallback();
3511
3512 // create a network satisfying request - validate that request not triggered
3513 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3514 mWiFiNetworkAgent.connect(false);
3515 networkCallback.assertNoCallback();
3516 }
3517
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003518 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
3519
3520 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3521
3522 private class CallbackValue {
3523 public CallbackType callbackType;
3524 public int error;
3525
3526 public CallbackValue(CallbackType type) {
3527 this.callbackType = type;
3528 this.error = PacketKeepalive.SUCCESS;
3529 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3530 }
3531
3532 public CallbackValue(CallbackType type, int error) {
3533 this.callbackType = type;
3534 this.error = error;
3535 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3536 }
3537
3538 @Override
3539 public boolean equals(Object o) {
3540 return o instanceof CallbackValue &&
3541 this.callbackType == ((CallbackValue) o).callbackType &&
3542 this.error == ((CallbackValue) o).error;
3543 }
3544
3545 @Override
3546 public String toString() {
3547 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
3548 }
3549 }
3550
3551 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
3552
3553 @Override
3554 public void onStarted() {
3555 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3556 }
3557
3558 @Override
3559 public void onStopped() {
3560 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3561 }
3562
3563 @Override
3564 public void onError(int error) {
3565 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3566 }
3567
3568 private void expectCallback(CallbackValue callbackValue) {
3569 try {
3570 assertEquals(
3571 callbackValue,
3572 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3573 } catch (InterruptedException e) {
3574 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
3575 }
3576 }
3577
3578 public void expectStarted() {
3579 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3580 }
3581
3582 public void expectStopped() {
3583 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3584 }
3585
3586 public void expectError(int error) {
3587 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3588 }
3589 }
3590
junyulai48eac1d42018-12-27 17:25:29 +08003591 private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
3592
3593 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3594
3595 private class CallbackValue {
3596 public CallbackType callbackType;
3597 public int error;
3598
3599 CallbackValue(CallbackType type) {
3600 this.callbackType = type;
3601 this.error = SocketKeepalive.SUCCESS;
3602 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3603 }
3604
3605 CallbackValue(CallbackType type, int error) {
3606 this.callbackType = type;
3607 this.error = error;
3608 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3609 }
3610
3611 @Override
3612 public boolean equals(Object o) {
3613 return o instanceof CallbackValue
3614 && this.callbackType == ((CallbackValue) o).callbackType
3615 && this.error == ((CallbackValue) o).error;
3616 }
3617
3618 @Override
3619 public String toString() {
3620 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
3621 error);
3622 }
3623 }
3624
3625 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
3626
3627 @Override
3628 public void onStarted() {
3629 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3630 }
3631
3632 @Override
3633 public void onStopped() {
3634 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3635 }
3636
3637 @Override
3638 public void onError(int error) {
3639 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3640 }
3641
3642 private void expectCallback(CallbackValue callbackValue) {
3643 try {
3644 assertEquals(
3645 callbackValue,
3646 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3647 } catch (InterruptedException e) {
3648 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
3649 }
3650 }
3651
3652 public void expectStarted() {
3653 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3654 }
3655
3656 public void expectStopped() {
3657 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3658 }
3659
3660 public void expectError(int error) {
3661 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3662 }
3663 }
3664
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003665 private Network connectKeepaliveNetwork(LinkProperties lp) {
3666 // Ensure the network is disconnected before we do anything.
3667 if (mWiFiNetworkAgent != null) {
3668 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
3669 }
3670
3671 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3672 ConditionVariable cv = waitForConnectivityBroadcasts(1);
3673 mWiFiNetworkAgent.connect(true);
3674 waitFor(cv);
3675 verifyActiveNetwork(TRANSPORT_WIFI);
3676 mWiFiNetworkAgent.sendLinkProperties(lp);
Hugo Benichibb91c572017-05-22 10:44:02 +09003677 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003678 return mWiFiNetworkAgent.getNetwork();
3679 }
3680
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003681 @Test
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003682 public void testPacketKeepalives() throws Exception {
3683 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
3684 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
3685 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
3686 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
3687 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
3688
Nathan Harold63dd8132018-02-14 13:09:45 -08003689 final int validKaInterval = 15;
3690 final int invalidKaInterval = 9;
3691
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003692 LinkProperties lp = new LinkProperties();
3693 lp.setInterfaceName("wlan12");
3694 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
3695 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
3696 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
3697 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
3698
3699 Network notMyNet = new Network(61234);
3700 Network myNet = connectKeepaliveNetwork(lp);
3701
3702 TestKeepaliveCallback callback = new TestKeepaliveCallback();
3703 PacketKeepalive ka;
3704
3705 // Attempt to start keepalives with invalid parameters and check for errors.
Nathan Harold63dd8132018-02-14 13:09:45 -08003706 ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003707 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3708
Nathan Harold63dd8132018-02-14 13:09:45 -08003709 ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003710 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
3711
Nathan Harold63dd8132018-02-14 13:09:45 -08003712 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003713 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3714
Nathan Harold63dd8132018-02-14 13:09:45 -08003715 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003716 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3717
Nathan Harold63dd8132018-02-14 13:09:45 -08003718 // NAT-T is only supported for IPv4.
3719 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
3720 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003721
Nathan Harold63dd8132018-02-14 13:09:45 -08003722 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003723 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3724
Nathan Harold63dd8132018-02-14 13:09:45 -08003725 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003726 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3727
Nathan Harold63dd8132018-02-14 13:09:45 -08003728 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003729 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3730
Nathan Harold63dd8132018-02-14 13:09:45 -08003731 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003732 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3733
3734 // Check that a started keepalive can be stopped.
3735 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
Nathan Harold63dd8132018-02-14 13:09:45 -08003736 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003737 callback.expectStarted();
3738 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
3739 ka.stop();
3740 callback.expectStopped();
3741
3742 // Check that deleting the IP address stops the keepalive.
3743 LinkProperties bogusLp = new LinkProperties(lp);
Nathan Harold63dd8132018-02-14 13:09:45 -08003744 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003745 callback.expectStarted();
3746 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
3747 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
3748 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
3749 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3750 mWiFiNetworkAgent.sendLinkProperties(lp);
3751
3752 // Check that a started keepalive is stopped correctly when the network disconnects.
Nathan Harold63dd8132018-02-14 13:09:45 -08003753 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003754 callback.expectStarted();
3755 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003756 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003757 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3758
3759 // ... and that stopping it after that has no adverse effects.
Hugo Benichibb91c572017-05-22 10:44:02 +09003760 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003761 final Network myNetAlias = myNet;
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003762 assertNull(mCm.getNetworkCapabilities(myNetAlias));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003763 ka.stop();
3764
3765 // Reconnect.
3766 myNet = connectKeepaliveNetwork(lp);
3767 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
3768
3769 // Check things work as expected when the keepalive is stopped and the network disconnects.
Nathan Harold63dd8132018-02-14 13:09:45 -08003770 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003771 callback.expectStarted();
3772 ka.stop();
3773 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003774 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Hugo Benichibb91c572017-05-22 10:44:02 +09003775 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003776 callback.expectStopped();
3777
3778 // Reconnect.
3779 myNet = connectKeepaliveNetwork(lp);
3780 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
3781
3782 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
3783 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
Nathan Harold63dd8132018-02-14 13:09:45 -08003784 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003785 callback.expectStarted();
3786
3787 // The second one gets slot 2.
3788 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
3789 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08003790 PacketKeepalive ka2 = mCm.startNattKeepalive(
3791 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003792 callback2.expectStarted();
3793
3794 // Now stop the first one and create a third. This also gets slot 1.
3795 ka.stop();
3796 callback.expectStopped();
3797
3798 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
3799 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08003800 PacketKeepalive ka3 = mCm.startNattKeepalive(
3801 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003802 callback3.expectStarted();
3803
3804 ka2.stop();
3805 callback2.expectStopped();
3806
3807 ka3.stop();
3808 callback3.expectStopped();
3809 }
Udam Sainib7c24872016-01-04 12:16:14 -08003810
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003811 @Test
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09003812 public void testNattSocketKeepalives_SingleThreadExecutor() throws Exception {
junyulai06835112019-01-03 18:50:15 +08003813 final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
3814 doTestNattSocketKeepalivesWithExecutor(executorSingleThread);
3815 executorSingleThread.shutdown();
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09003816 }
junyulai06835112019-01-03 18:50:15 +08003817
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09003818 @Test
3819 public void testNattSocketKeepalives_InlineExecutor() throws Exception {
junyulai06835112019-01-03 18:50:15 +08003820 final Executor executorInline = (Runnable r) -> r.run();
3821 doTestNattSocketKeepalivesWithExecutor(executorInline);
3822 }
3823
3824 private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
junyulai48eac1d42018-12-27 17:25:29 +08003825 // TODO: 1. Move this outside of ConnectivityServiceTest.
junyulai06835112019-01-03 18:50:15 +08003826 // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
junyulai48eac1d42018-12-27 17:25:29 +08003827 final int srcPort = 12345;
3828 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
3829 final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
3830 final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
3831 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
3832 final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
3833
3834 final int validKaInterval = 15;
3835 final int invalidKaInterval = 9;
3836
3837 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
3838 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket(srcPort);
3839
junyulai48eac1d42018-12-27 17:25:29 +08003840 LinkProperties lp = new LinkProperties();
3841 lp.setInterfaceName("wlan12");
3842 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
3843 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
3844 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
3845 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
3846
3847 Network notMyNet = new Network(61234);
3848 Network myNet = connectKeepaliveNetwork(lp);
3849
3850 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback();
3851 SocketKeepalive ka;
3852
3853 // Attempt to start keepalives with invalid parameters and check for errors.
3854 // Invalid network.
3855 ka = mCm.createSocketKeepalive(notMyNet, testSocket, myIPv4, dstIPv4, executor, callback);
3856 ka.start(validKaInterval);
3857 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
3858
3859 // Invalid interval.
3860 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
3861 ka.start(invalidKaInterval);
3862 callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
3863
3864 // Invalid destination.
3865 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv6, executor, callback);
3866 ka.start(validKaInterval);
3867 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3868
3869 // Invalid source;
3870 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv6, dstIPv4, executor, callback);
3871 ka.start(validKaInterval);
3872 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3873
3874 // NAT-T is only supported for IPv4.
3875 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv6, dstIPv6, executor, callback);
3876 ka.start(validKaInterval);
3877 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3878
3879 // Sanity check before testing started keepalive.
3880 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
3881 ka.start(validKaInterval);
3882 callback.expectError(SocketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3883
3884 // Check that a started keepalive can be stopped.
3885 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
3886 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
3887 ka.start(validKaInterval);
3888 callback.expectStarted();
3889 mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS);
3890 ka.stop();
3891 callback.expectStopped();
3892
3893 // Check that deleting the IP address stops the keepalive.
3894 LinkProperties bogusLp = new LinkProperties(lp);
3895 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
3896 ka.start(validKaInterval);
3897 callback.expectStarted();
3898 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
3899 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
3900 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
3901 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3902 mWiFiNetworkAgent.sendLinkProperties(lp);
3903
3904 // Check that a started keepalive is stopped correctly when the network disconnects.
3905 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
3906 ka.start(validKaInterval);
3907 callback.expectStarted();
3908 mWiFiNetworkAgent.disconnect();
3909 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
3910 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
3911
3912 // ... and that stopping it after that has no adverse effects.
3913 waitForIdle();
3914 final Network myNetAlias = myNet;
3915 assertNull(mCm.getNetworkCapabilities(myNetAlias));
3916 ka.stop();
3917
3918 // Reconnect.
3919 myNet = connectKeepaliveNetwork(lp);
3920 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
3921
3922 // Check things work as expected when the keepalive is stopped and the network disconnects.
3923 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
3924 ka.start(validKaInterval);
3925 callback.expectStarted();
3926 ka.stop();
3927 mWiFiNetworkAgent.disconnect();
3928 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
3929 waitForIdle();
3930 callback.expectStopped();
3931
3932 // Reconnect.
3933 myNet = connectKeepaliveNetwork(lp);
3934 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
3935
3936 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
3937 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
3938 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
3939 ka.start(validKaInterval);
3940 callback.expectStarted();
3941
3942 // The second one gets slot 2.
3943 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
3944 final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket(6789);
3945 TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback();
3946 SocketKeepalive ka2 =
3947 mCm.createSocketKeepalive(myNet, testSocket2, myIPv4, dstIPv4, executor, callback2);
3948 ka2.start(validKaInterval);
3949 callback2.expectStarted();
3950
3951 ka.stop();
3952 callback.expectStopped();
3953
3954 ka2.stop();
3955 callback2.expectStopped();
junyulai06835112019-01-03 18:50:15 +08003956
3957 testSocket.close();
3958 testSocket2.close();
3959
3960 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09003961 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
junyulai48eac1d42018-12-27 17:25:29 +08003962 }
3963
3964 @Test
Udam Sainib7c24872016-01-04 12:16:14 -08003965 public void testGetCaptivePortalServerUrl() throws Exception {
3966 String url = mCm.getCaptivePortalServerUrl();
3967 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
3968 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09003969
3970 private static class TestNetworkPinner extends NetworkPinner {
3971 public static boolean awaitPin(int timeoutMs) {
3972 synchronized(sLock) {
3973 if (sNetwork == null) {
3974 try {
3975 sLock.wait(timeoutMs);
3976 } catch (InterruptedException e) {}
3977 }
3978 return sNetwork != null;
3979 }
3980 }
3981
3982 public static boolean awaitUnpin(int timeoutMs) {
3983 synchronized(sLock) {
3984 if (sNetwork != null) {
3985 try {
3986 sLock.wait(timeoutMs);
3987 } catch (InterruptedException e) {}
3988 }
3989 return sNetwork == null;
3990 }
3991 }
3992 }
3993
3994 private void assertPinnedToWifiWithCellDefault() {
3995 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
3996 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3997 }
3998
3999 private void assertPinnedToWifiWithWifiDefault() {
4000 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4001 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4002 }
4003
4004 private void assertNotPinnedToWifi() {
4005 assertNull(mCm.getBoundNetworkForProcess());
4006 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4007 }
4008
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004009 @Test
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004010 public void testNetworkPinner() {
4011 NetworkRequest wifiRequest = new NetworkRequest.Builder()
4012 .addTransportType(TRANSPORT_WIFI)
4013 .build();
4014 assertNull(mCm.getBoundNetworkForProcess());
4015
4016 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4017 assertNull(mCm.getBoundNetworkForProcess());
4018
4019 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4020 mCellNetworkAgent.connect(true);
4021 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4022 mWiFiNetworkAgent.connect(false);
4023
4024 // When wi-fi connects, expect to be pinned.
4025 assertTrue(TestNetworkPinner.awaitPin(100));
4026 assertPinnedToWifiWithCellDefault();
4027
4028 // Disconnect and expect the pin to drop.
4029 mWiFiNetworkAgent.disconnect();
4030 assertTrue(TestNetworkPinner.awaitUnpin(100));
4031 assertNotPinnedToWifi();
4032
4033 // Reconnecting does not cause the pin to come back.
4034 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4035 mWiFiNetworkAgent.connect(false);
4036 assertFalse(TestNetworkPinner.awaitPin(100));
4037 assertNotPinnedToWifi();
4038
4039 // Pinning while connected causes the pin to take effect immediately.
4040 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4041 assertTrue(TestNetworkPinner.awaitPin(100));
4042 assertPinnedToWifiWithCellDefault();
4043
4044 // Explicitly unpin and expect to use the default network again.
4045 TestNetworkPinner.unpin();
4046 assertNotPinnedToWifi();
4047
4048 // Disconnect cell and wifi.
4049 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
4050 mCellNetworkAgent.disconnect();
4051 mWiFiNetworkAgent.disconnect();
4052 waitFor(cv);
4053
4054 // Pinning takes effect even if the pinned network is the default when the pin is set...
4055 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4056 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4057 mWiFiNetworkAgent.connect(false);
4058 assertTrue(TestNetworkPinner.awaitPin(100));
4059 assertPinnedToWifiWithWifiDefault();
4060
4061 // ... and is maintained even when that network is no longer the default.
4062 cv = waitForConnectivityBroadcasts(1);
4063 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4064 mCellNetworkAgent.connect(true);
4065 waitFor(cv);
4066 assertPinnedToWifiWithCellDefault();
4067 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004068
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004069 @Test
Hugo Benichi893a7622017-09-29 09:34:08 +09004070 public void testNetworkCallbackMaximum() {
Jeff Sharkeye0c29952018-02-20 17:24:55 -07004071 // We can only have 99 callbacks, because MultipathPolicyTracker is
4072 // already one of them.
4073 final int MAX_REQUESTS = 99;
4074 final int CALLBACKS = 89;
Hugo Benichi893a7622017-09-29 09:34:08 +09004075 final int INTENTS = 10;
4076 assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
4077
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004078 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
Hugo Benichi893a7622017-09-29 09:34:08 +09004079 ArrayList<Object> registered = new ArrayList<>();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004080
Hugo Benichi893a7622017-09-29 09:34:08 +09004081 int j = 0;
4082 while (j++ < CALLBACKS / 2) {
4083 NetworkCallback cb = new NetworkCallback();
4084 mCm.requestNetwork(networkRequest, cb);
4085 registered.add(cb);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004086 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004087 while (j++ < CALLBACKS) {
4088 NetworkCallback cb = new NetworkCallback();
4089 mCm.registerNetworkCallback(networkRequest, cb);
4090 registered.add(cb);
4091 }
4092 j = 0;
4093 while (j++ < INTENTS / 2) {
4094 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
4095 mCm.requestNetwork(networkRequest, pi);
4096 registered.add(pi);
4097 }
4098 while (j++ < INTENTS) {
4099 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
4100 mCm.registerNetworkCallback(networkRequest, pi);
4101 registered.add(pi);
4102 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004103
Hugo Benichi893a7622017-09-29 09:34:08 +09004104 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004105 try {
Hugo Benichi893a7622017-09-29 09:34:08 +09004106 mCm.requestNetwork(networkRequest, new NetworkCallback());
4107 fail("Registering " + MAX_REQUESTS + " network requests did not throw exception");
Hugo Benichicb883232017-05-11 13:16:17 +09004108 } catch (TooManyRequestsException expected) {}
Hugo Benichi893a7622017-09-29 09:34:08 +09004109 try {
4110 mCm.registerNetworkCallback(networkRequest, new NetworkCallback());
4111 fail("Registering " + MAX_REQUESTS + " network callbacks did not throw exception");
4112 } catch (TooManyRequestsException expected) {}
4113 try {
4114 mCm.requestNetwork(networkRequest,
4115 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0));
4116 fail("Registering " + MAX_REQUESTS + " PendingIntent requests did not throw exception");
4117 } catch (TooManyRequestsException expected) {}
4118 try {
4119 mCm.registerNetworkCallback(networkRequest,
4120 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0));
4121 fail("Registering " + MAX_REQUESTS
4122 + " PendingIntent callbacks did not throw exception");
4123 } catch (TooManyRequestsException expected) {}
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004124
Hugo Benichi893a7622017-09-29 09:34:08 +09004125 for (Object o : registered) {
4126 if (o instanceof NetworkCallback) {
4127 mCm.unregisterNetworkCallback((NetworkCallback)o);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004128 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004129 if (o instanceof PendingIntent) {
4130 mCm.unregisterNetworkCallback((PendingIntent)o);
4131 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004132 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004133 waitForIdle();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004134
4135 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
4136 for (int i = 0; i < MAX_REQUESTS; i++) {
4137 NetworkCallback networkCallback = new NetworkCallback();
4138 mCm.requestNetwork(networkRequest, networkCallback);
4139 mCm.unregisterNetworkCallback(networkCallback);
4140 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004141 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004142
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004143 for (int i = 0; i < MAX_REQUESTS; i++) {
4144 NetworkCallback networkCallback = new NetworkCallback();
4145 mCm.registerNetworkCallback(networkRequest, networkCallback);
4146 mCm.unregisterNetworkCallback(networkCallback);
4147 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004148 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004149
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004150 for (int i = 0; i < MAX_REQUESTS; i++) {
4151 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004152 PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004153 mCm.requestNetwork(networkRequest, pendingIntent);
4154 mCm.unregisterNetworkCallback(pendingIntent);
4155 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004156 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004157
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004158 for (int i = 0; i < MAX_REQUESTS; i++) {
4159 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004160 PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004161 mCm.registerNetworkCallback(networkRequest, pendingIntent);
4162 mCm.unregisterNetworkCallback(pendingIntent);
4163 }
4164 }
Hugo Benichifed512a2017-06-26 10:06:49 +09004165
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004166 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004167 public void testNetworkInfoOfTypeNone() {
4168 ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1);
4169
4170 verifyNoNetwork();
Hugo Benichic1014502017-07-19 10:10:52 +09004171 MockNetworkAgent wifiAware = new MockNetworkAgent(TRANSPORT_WIFI_AWARE);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004172 assertNull(mCm.getActiveNetworkInfo());
4173
4174 Network[] allNetworks = mCm.getAllNetworks();
4175 assertLength(1, allNetworks);
4176 Network network = allNetworks[0];
4177 NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
4178 assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
4179
4180 final NetworkRequest request =
4181 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
4182 final TestNetworkCallback callback = new TestNetworkCallback();
4183 mCm.registerNetworkCallback(request, callback);
4184
Hugo Benichic1014502017-07-19 10:10:52 +09004185 // Bring up wifi aware network.
4186 wifiAware.connect(false, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09004187 callback.expectAvailableCallbacksUnvalidated(wifiAware);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004188
4189 assertNull(mCm.getActiveNetworkInfo());
4190 assertNull(mCm.getActiveNetwork());
Hugo Benichic1014502017-07-19 10:10:52 +09004191 // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
Hugo Benichi16f0a942017-06-20 14:07:59 +09004192 // of this test. Fix it and uncomment the assert below.
4193 //assertEmpty(mCm.getAllNetworkInfo());
4194
Hugo Benichic1014502017-07-19 10:10:52 +09004195 // Disconnect wifi aware network.
4196 wifiAware.disconnect();
4197 callback.expectCallbackLike((info) -> info.state == CallbackState.LOST, TIMEOUT_MS);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004198 mCm.unregisterNetworkCallback(callback);
4199
4200 verifyNoNetwork();
4201 if (broadcastCV.block(10)) {
4202 fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
4203 }
4204 }
4205
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004206 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004207 public void testDeprecatedAndUnsupportedOperations() throws Exception {
4208 final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
4209 assertNull(mCm.getNetworkInfo(TYPE_NONE));
4210 assertNull(mCm.getNetworkForType(TYPE_NONE));
4211 assertNull(mCm.getLinkProperties(TYPE_NONE));
4212 assertFalse(mCm.isNetworkSupported(TYPE_NONE));
4213
4214 assertException(() -> { mCm.networkCapabilitiesForType(TYPE_NONE); },
4215 IllegalArgumentException.class);
4216
4217 Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
4218 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
4219 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
4220 // TODO: let test context have configuration application target sdk version
4221 // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
4222 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
4223 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
4224 assertException(() -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); }, unsupported);
4225 }
4226
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004227 @Test
Rubin Xu1bb5c082017-09-05 18:40:49 +01004228 public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() {
4229 final NetworkRequest networkRequest = new NetworkRequest.Builder()
4230 .addTransportType(TRANSPORT_WIFI).build();
4231 final TestNetworkCallback networkCallback = new TestNetworkCallback();
4232 mCm.registerNetworkCallback(networkRequest, networkCallback);
4233
4234 LinkProperties lp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004235 lp.setInterfaceName(WIFI_IFNAME);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004236 LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
4237 RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
4238 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
4239 lp.addLinkAddress(myIpv4Address);
4240 lp.addRoute(myIpv4DefaultRoute);
4241
4242 // Verify direct routes are added when network agent is first registered in
4243 // ConnectivityService.
4244 MockNetworkAgent networkAgent = new MockNetworkAgent(TRANSPORT_WIFI, lp);
4245 networkAgent.connect(true);
4246 networkCallback.expectCallback(CallbackState.AVAILABLE, networkAgent);
4247 networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent);
4248 CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4249 networkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08004250 networkCallback.expectCallback(CallbackState.BLOCKED_STATUS, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004251 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
4252 networkCallback.assertNoCallback();
4253 checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address),
4254 Arrays.asList(myIpv4DefaultRoute));
4255 checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
4256 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
4257
4258 // Verify direct routes are added during subsequent link properties updates.
4259 LinkProperties newLp = new LinkProperties(lp);
4260 LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
4261 LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
4262 newLp.addLinkAddress(myIpv6Address1);
4263 newLp.addLinkAddress(myIpv6Address2);
4264 networkAgent.sendLinkProperties(newLp);
4265 cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, networkAgent);
4266 networkCallback.assertNoCallback();
4267 checkDirectlyConnectedRoutes(cbi.arg,
4268 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
4269 Arrays.asList(myIpv4DefaultRoute));
4270 mCm.unregisterNetworkCallback(networkCallback);
4271 }
4272
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004273 @Test
4274 public void testStatsIfacesChanged() throws Exception {
4275 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004276 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4277
Varun Anandd33cbc62019-02-07 14:13:13 -08004278 Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
4279 Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
4280
4281 LinkProperties cellLp = new LinkProperties();
4282 cellLp.setInterfaceName(MOBILE_IFNAME);
4283 LinkProperties wifiLp = new LinkProperties();
4284 wifiLp.setInterfaceName(WIFI_IFNAME);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004285
4286 // Simple connection should have updated ifaces
4287 mCellNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004288 mCellNetworkAgent.sendLinkProperties(cellLp);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004289 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004290 verify(mStatsService, atLeastOnce())
4291 .forceUpdateIfaces(
4292 eq(onlyCell),
4293 eq(new VpnInfo[0]),
4294 any(NetworkState[].class),
4295 eq(MOBILE_IFNAME));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004296 reset(mStatsService);
4297
4298 // Default network switch should update ifaces.
4299 mWiFiNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004300 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004301 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004302 assertEquals(wifiLp, mService.getActiveLinkProperties());
4303 verify(mStatsService, atLeastOnce())
4304 .forceUpdateIfaces(
4305 eq(onlyWifi),
4306 eq(new VpnInfo[0]),
4307 any(NetworkState[].class),
4308 eq(WIFI_IFNAME));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004309 reset(mStatsService);
4310
4311 // Disconnect should update ifaces.
4312 mWiFiNetworkAgent.disconnect();
4313 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004314 verify(mStatsService, atLeastOnce())
4315 .forceUpdateIfaces(
4316 eq(onlyCell),
4317 eq(new VpnInfo[0]),
4318 any(NetworkState[].class),
4319 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004320 reset(mStatsService);
4321
4322 // Metered change should update ifaces
4323 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4324 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004325 verify(mStatsService, atLeastOnce())
4326 .forceUpdateIfaces(
4327 eq(onlyCell),
4328 eq(new VpnInfo[0]),
4329 any(NetworkState[].class),
4330 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004331 reset(mStatsService);
4332
4333 mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4334 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004335 verify(mStatsService, atLeastOnce())
4336 .forceUpdateIfaces(
4337 eq(onlyCell),
4338 eq(new VpnInfo[0]),
4339 any(NetworkState[].class),
4340 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004341 reset(mStatsService);
4342
4343 // Captive portal change shouldn't update ifaces
4344 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
4345 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004346 verify(mStatsService, never())
4347 .forceUpdateIfaces(
4348 eq(onlyCell),
4349 eq(new VpnInfo[0]),
4350 any(NetworkState[].class),
4351 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004352 reset(mStatsService);
4353
4354 // Roaming change should update ifaces
4355 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
4356 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004357 verify(mStatsService, atLeastOnce())
4358 .forceUpdateIfaces(
4359 eq(onlyCell),
4360 eq(new VpnInfo[0]),
4361 any(NetworkState[].class),
4362 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004363 reset(mStatsService);
4364 }
4365
Erik Klinee89953b2018-01-11 16:11:10 +09004366 @Test
4367 public void testBasicDnsConfigurationPushed() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004368 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4369 ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class);
4370
4371 // Clear any interactions that occur as a result of CS starting up.
4372 reset(mNetworkManagementService);
4373
4374 final String[] EMPTY_STRING_ARRAY = new String[0];
Erik Klinee89953b2018-01-11 16:11:10 +09004375 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4376 waitForIdle();
4377 verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
Erik Kline79c6d052018-03-21 07:18:33 -07004378 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
4379 verifyNoMoreInteractions(mNetworkManagementService);
Erik Klinee89953b2018-01-11 16:11:10 +09004380
4381 final LinkProperties cellLp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004382 cellLp.setInterfaceName(MOBILE_IFNAME);
Erik Kline117e7f32018-03-04 21:01:01 +09004383 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4384 // "is-reachable" testing in order to not program netd with unreachable
4385 // nameservers that it might try repeated to validate.
4386 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
Erik Kline79c6d052018-03-21 07:18:33 -07004387 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4388 MOBILE_IFNAME));
Erik Kline117e7f32018-03-04 21:01:01 +09004389 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
Erik Kline79c6d052018-03-21 07:18:33 -07004390 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4391 MOBILE_IFNAME));
Erik Klinee89953b2018-01-11 16:11:10 +09004392 mCellNetworkAgent.sendLinkProperties(cellLp);
4393 mCellNetworkAgent.connect(false);
4394 waitForIdle();
Erik Klinee89953b2018-01-11 16:11:10 +09004395 // CS tells netd about the empty DNS config for this network.
Erik Kline79c6d052018-03-21 07:18:33 -07004396 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
4397 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
Erik Klinee89953b2018-01-11 16:11:10 +09004398 reset(mNetworkManagementService);
4399
4400 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4401 mCellNetworkAgent.sendLinkProperties(cellLp);
4402 waitForIdle();
Erik Kline79c6d052018-03-21 07:18:33 -07004403 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
Erik Kline117e7f32018-03-04 21:01:01 +09004404 anyInt(), mStringArrayCaptor.capture(), any(), any(),
Erik Kline79c6d052018-03-21 07:18:33 -07004405 eq(""), tlsServers.capture());
Erik Klinee89953b2018-01-11 16:11:10 +09004406 assertEquals(1, mStringArrayCaptor.getValue().length);
4407 assertTrue(ArrayUtils.contains(mStringArrayCaptor.getValue(), "2001:db8::1"));
Erik Kline79c6d052018-03-21 07:18:33 -07004408 // Opportunistic mode.
4409 assertTrue(ArrayUtils.contains(tlsServers.getValue(), "2001:db8::1"));
Erik Klinee89953b2018-01-11 16:11:10 +09004410 reset(mNetworkManagementService);
4411
4412 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4413 mCellNetworkAgent.sendLinkProperties(cellLp);
4414 waitForIdle();
Erik Kline79c6d052018-03-21 07:18:33 -07004415 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
Erik Kline117e7f32018-03-04 21:01:01 +09004416 anyInt(), mStringArrayCaptor.capture(), any(), any(),
Erik Kline79c6d052018-03-21 07:18:33 -07004417 eq(""), tlsServers.capture());
Erik Kline117e7f32018-03-04 21:01:01 +09004418 assertEquals(2, mStringArrayCaptor.getValue().length);
4419 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4420 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline79c6d052018-03-21 07:18:33 -07004421 // Opportunistic mode.
4422 assertEquals(2, tlsServers.getValue().length);
4423 assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
4424 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline117e7f32018-03-04 21:01:01 +09004425 reset(mNetworkManagementService);
4426
4427 final String TLS_SPECIFIER = "tls.example.com";
4428 final String TLS_SERVER6 = "2001:db8:53::53";
4429 final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
4430 final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004431 mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
4432 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
4433
Erik Kline117e7f32018-03-04 21:01:01 +09004434 waitForIdle();
Erik Kline79c6d052018-03-21 07:18:33 -07004435 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
Erik Kline117e7f32018-03-04 21:01:01 +09004436 anyInt(), mStringArrayCaptor.capture(), any(), any(),
4437 eq(TLS_SPECIFIER), eq(TLS_SERVERS));
Erik Klinee89953b2018-01-11 16:11:10 +09004438 assertEquals(2, mStringArrayCaptor.getValue().length);
4439 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4440 new String[]{"2001:db8::1", "192.0.2.1"}));
4441 reset(mNetworkManagementService);
4442 }
4443
Erik Kline79c6d052018-03-21 07:18:33 -07004444 @Test
4445 public void testPrivateDnsSettingsChange() throws Exception {
4446 final String[] EMPTY_STRING_ARRAY = new String[0];
4447 ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class);
4448
4449 // Clear any interactions that occur as a result of CS starting up.
4450 reset(mNetworkManagementService);
4451
4452 // The default on Android is opportunistic mode ("Automatic").
4453 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4454
dalyk1fcb7392018-03-05 12:42:22 -05004455 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4456 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4457 .addTransportType(TRANSPORT_CELLULAR).build();
4458 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4459
Erik Kline79c6d052018-03-21 07:18:33 -07004460 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4461 waitForIdle();
4462 // CS tells netd about the empty DNS config for this network.
4463 verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
4464 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
4465 verifyNoMoreInteractions(mNetworkManagementService);
4466
4467 final LinkProperties cellLp = new LinkProperties();
4468 cellLp.setInterfaceName(MOBILE_IFNAME);
4469 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4470 // "is-reachable" testing in order to not program netd with unreachable
4471 // nameservers that it might try repeated to validate.
4472 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
4473 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4474 MOBILE_IFNAME));
4475 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
4476 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4477 MOBILE_IFNAME));
4478 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4479 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4480
4481 mCellNetworkAgent.sendLinkProperties(cellLp);
4482 mCellNetworkAgent.connect(false);
4483 waitForIdle();
4484 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
4485 anyInt(), mStringArrayCaptor.capture(), any(), any(),
4486 eq(""), tlsServers.capture());
4487 assertEquals(2, mStringArrayCaptor.getValue().length);
4488 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4489 new String[]{"2001:db8::1", "192.0.2.1"}));
4490 // Opportunistic mode.
4491 assertEquals(2, tlsServers.getValue().length);
4492 assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
4493 new String[]{"2001:db8::1", "192.0.2.1"}));
4494 reset(mNetworkManagementService);
dalyk1fcb7392018-03-05 12:42:22 -05004495 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
4496 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
4497 mCellNetworkAgent);
4498 CallbackInfo cbi = cellNetworkCallback.expectCallback(
4499 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08004500 cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05004501 cellNetworkCallback.assertNoCallback();
4502 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4503 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
Erik Kline79c6d052018-03-21 07:18:33 -07004504
4505 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
4506 verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
4507 anyInt(), mStringArrayCaptor.capture(), any(), any(),
4508 eq(""), eq(EMPTY_STRING_ARRAY));
4509 assertEquals(2, mStringArrayCaptor.getValue().length);
4510 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4511 new String[]{"2001:db8::1", "192.0.2.1"}));
4512 reset(mNetworkManagementService);
dalyk1fcb7392018-03-05 12:42:22 -05004513 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07004514
4515 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4516 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
4517 anyInt(), mStringArrayCaptor.capture(), any(), any(),
4518 eq(""), tlsServers.capture());
4519 assertEquals(2, mStringArrayCaptor.getValue().length);
4520 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4521 new String[]{"2001:db8::1", "192.0.2.1"}));
4522 assertEquals(2, tlsServers.getValue().length);
4523 assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
4524 new String[]{"2001:db8::1", "192.0.2.1"}));
4525 reset(mNetworkManagementService);
dalyk1fcb7392018-03-05 12:42:22 -05004526 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07004527
dalyk1fcb7392018-03-05 12:42:22 -05004528 setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
4529 // Can't test dns configuration for strict mode without properly mocking
4530 // out the DNS lookups, but can test that LinkProperties is updated.
4531 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4532 mCellNetworkAgent);
4533 cellNetworkCallback.assertNoCallback();
4534 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
4535 assertEquals("strict.example.com", ((LinkProperties)cbi.arg).getPrivateDnsServerName());
4536 }
4537
4538 @Test
4539 public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
4540 // The default on Android is opportunistic mode ("Automatic").
4541 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4542
4543 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4544 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4545 .addTransportType(TRANSPORT_CELLULAR).build();
4546 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4547
4548 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4549 waitForIdle();
4550 LinkProperties lp = new LinkProperties();
4551 mCellNetworkAgent.sendLinkProperties(lp);
4552 mCellNetworkAgent.connect(false);
4553 waitForIdle();
4554 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
4555 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
4556 mCellNetworkAgent);
4557 CallbackInfo cbi = cellNetworkCallback.expectCallback(
4558 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08004559 cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05004560 cellNetworkCallback.assertNoCallback();
4561 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4562 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4563 Set<InetAddress> dnsServers = new HashSet<>();
4564 checkDnsServers(cbi.arg, dnsServers);
4565
4566 // Send a validation event for a server that is not part of the current
4567 // resolver config. The validation event should be ignored.
4568 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4569 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
4570 cellNetworkCallback.assertNoCallback();
4571
4572 // Add a dns server to the LinkProperties.
4573 LinkProperties lp2 = new LinkProperties(lp);
4574 lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
4575 mCellNetworkAgent.sendLinkProperties(lp2);
4576 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4577 mCellNetworkAgent);
4578 cellNetworkCallback.assertNoCallback();
4579 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4580 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4581 dnsServers.add(InetAddress.getByName("145.100.185.16"));
4582 checkDnsServers(cbi.arg, dnsServers);
4583
4584 // Send a validation event containing a hostname that is not part of
4585 // the current resolver config. The validation event should be ignored.
4586 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4587 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
4588 cellNetworkCallback.assertNoCallback();
4589
4590 // Send a validation event where validation failed.
4591 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4592 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
4593 cellNetworkCallback.assertNoCallback();
4594
4595 // Send a validation event where validation succeeded for a server in
4596 // the current resolver config. A LinkProperties callback with updated
4597 // private dns fields should be sent.
4598 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4599 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
4600 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4601 mCellNetworkAgent);
4602 cellNetworkCallback.assertNoCallback();
4603 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
4604 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4605 checkDnsServers(cbi.arg, dnsServers);
4606
4607 // The private dns fields in LinkProperties should be preserved when
4608 // the network agent sends unrelated changes.
4609 LinkProperties lp3 = new LinkProperties(lp2);
4610 lp3.setMtu(1300);
4611 mCellNetworkAgent.sendLinkProperties(lp3);
4612 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4613 mCellNetworkAgent);
4614 cellNetworkCallback.assertNoCallback();
4615 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
4616 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4617 checkDnsServers(cbi.arg, dnsServers);
4618 assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
4619
4620 // Removing the only validated server should affect the private dns
4621 // fields in LinkProperties.
4622 LinkProperties lp4 = new LinkProperties(lp3);
4623 lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
4624 mCellNetworkAgent.sendLinkProperties(lp4);
4625 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4626 mCellNetworkAgent);
4627 cellNetworkCallback.assertNoCallback();
4628 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4629 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4630 dnsServers.remove(InetAddress.getByName("145.100.185.16"));
4631 checkDnsServers(cbi.arg, dnsServers);
4632 assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
Erik Kline79c6d052018-03-21 07:18:33 -07004633 }
4634
Rubin Xu1bb5c082017-09-05 18:40:49 +01004635 private void checkDirectlyConnectedRoutes(Object callbackObj,
4636 Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
4637 assertTrue(callbackObj instanceof LinkProperties);
4638 LinkProperties lp = (LinkProperties) callbackObj;
4639
4640 Set<RouteInfo> expectedRoutes = new ArraySet<>();
4641 expectedRoutes.addAll(otherRoutes);
4642 for (LinkAddress address : linkAddresses) {
4643 RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
4644 // Duplicates in linkAddresses are considered failures
4645 assertTrue(expectedRoutes.add(localRoute));
4646 }
4647 List<RouteInfo> observedRoutes = lp.getRoutes();
4648 assertEquals(expectedRoutes.size(), observedRoutes.size());
4649 assertTrue(observedRoutes.containsAll(expectedRoutes));
4650 }
4651
dalyk1fcb7392018-03-05 12:42:22 -05004652 private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
4653 assertTrue(callbackObj instanceof LinkProperties);
4654 LinkProperties lp = (LinkProperties) callbackObj;
4655 assertEquals(dnsServers.size(), lp.getDnsServers().size());
4656 assertTrue(lp.getDnsServers().containsAll(dnsServers));
4657 }
4658
Hugo Benichifed512a2017-06-26 10:06:49 +09004659 private static <T> void assertEmpty(T[] ts) {
4660 int length = ts.length;
4661 assertEquals("expected empty array, but length was " + length, 0, length);
4662 }
4663
4664 private static <T> void assertLength(int expected, T[] got) {
4665 int length = got.length;
4666 assertEquals(String.format("expected array of length %s, but length was %s for %s",
4667 expected, length, Arrays.toString(got)), expected, length);
4668 }
Hugo Benichi16f0a942017-06-20 14:07:59 +09004669
4670 private static <T> void assertException(Runnable block, Class<T> expected) {
4671 try {
4672 block.run();
4673 fail("Expected exception of type " + expected);
4674 } catch (Exception got) {
4675 if (!got.getClass().equals(expected)) {
4676 fail("Expected exception of type " + expected + " but got " + got);
4677 }
4678 return;
4679 }
4680 }
Chalard Jean0b214af2018-01-12 17:22:49 +09004681
4682 @Test
4683 public void testVpnNetworkActive() {
4684 final int uid = Process.myUid();
4685
4686 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09004687 final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004688 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
4689 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004690 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09004691 final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
4692 final NetworkRequest genericRequest = new NetworkRequest.Builder()
4693 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
Chalard Jean0b214af2018-01-12 17:22:49 +09004694 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
4695 .addTransportType(TRANSPORT_WIFI).build();
4696 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
Chalard Jeanb552c462018-02-21 18:43:54 +09004697 .removeCapability(NET_CAPABILITY_NOT_VPN)
Chalard Jean0b214af2018-01-12 17:22:49 +09004698 .addTransportType(TRANSPORT_VPN).build();
4699 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Chalard Jeanb552c462018-02-21 18:43:54 +09004700 mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09004701 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
4702 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004703 mCm.registerDefaultNetworkCallback(defaultCallback);
4704 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004705
4706 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4707 mWiFiNetworkAgent.connect(false);
4708
4709 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004710 genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004711 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004712 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004713 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004714 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004715
4716 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4717 final ArraySet<UidRange> ranges = new ArraySet<>();
4718 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004719 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4720 mMockVpn.setUids(ranges);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004721 // VPN networks do not satisfy the default request and are automatically validated
4722 // by NetworkMonitor
Lorenzo Colittied3168e2019-01-23 17:54:08 +09004723 assertFalse(NetworkMonitorUtils.isValidationRequired(vpnNetworkAgent.mNetworkCapabilities));
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004724 vpnNetworkAgent.setNetworkValid();
4725
Chalard Jean0b214af2018-01-12 17:22:49 +09004726 vpnNetworkAgent.connect(false);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004727 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08004728 mMockVpn.setUnderlyingNetworks(new Network[0]);
Chalard Jean0b214af2018-01-12 17:22:49 +09004729
4730 genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004731 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004732 wifiNetworkCallback.assertNoCallback();
4733 vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004734 defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
4735 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004736
4737 genericNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004738 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jeanf19db372018-01-26 19:24:40 +09004739 vpnNetworkCallback.expectCapabilitiesLike(nc -> null == nc.getUids(), vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004740 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
4741 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004742
4743 ranges.clear();
4744 vpnNetworkAgent.setUids(ranges);
4745
4746 genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004747 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004748 wifiNetworkCallback.assertNoCallback();
4749 vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
4750
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004751 // TODO : The default network callback should actually get a LOST call here (also see the
4752 // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
4753 // ranges at all when determining whether a network should be rematched. In practice, VPNs
4754 // can't currently update their UIDs without disconnecting, so this does not matter too
4755 // much, but that is the reason the test here has to check for an update to the
4756 // capabilities instead of the expected LOST then AVAILABLE.
4757 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
4758
Chalard Jean0b214af2018-01-12 17:22:49 +09004759 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004760 mMockVpn.setUids(ranges);
Varun Anand4fa80e82019-02-06 10:13:38 -08004761 vpnNetworkAgent.setUids(ranges);
Chalard Jean0b214af2018-01-12 17:22:49 +09004762
4763 genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004764 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004765 wifiNetworkCallback.assertNoCallback();
4766 vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004767 // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
4768 // happen outside of the test, ConnectivityService does not rematch callbacks.
4769 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004770
4771 mWiFiNetworkAgent.disconnect();
4772
4773 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004774 genericNotVpnNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004775 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
4776 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004777 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004778
4779 vpnNetworkAgent.disconnect();
4780
4781 genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004782 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004783 wifiNetworkCallback.assertNoCallback();
4784 vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004785 defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
4786 assertEquals(null, mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004787
4788 mCm.unregisterNetworkCallback(genericNetworkCallback);
4789 mCm.unregisterNetworkCallback(wifiNetworkCallback);
4790 mCm.unregisterNetworkCallback(vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004791 mCm.unregisterNetworkCallback(defaultCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09004792 }
Chalard Jean26400492018-04-18 20:18:38 +09004793
4794 @Test
Varun Anand4fa80e82019-02-06 10:13:38 -08004795 public void testVpnWithoutInternet() {
Chalard Jean26400492018-04-18 20:18:38 +09004796 final int uid = Process.myUid();
4797
4798 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
4799 mCm.registerDefaultNetworkCallback(defaultCallback);
Chalard Jean26400492018-04-18 20:18:38 +09004800
4801 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4802 mWiFiNetworkAgent.connect(true);
4803
4804 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
4805 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4806
4807 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4808 final ArraySet<UidRange> ranges = new ArraySet<>();
4809 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004810 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4811 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09004812 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004813 mMockVpn.connect();
Chalard Jean26400492018-04-18 20:18:38 +09004814
4815 defaultCallback.assertNoCallback();
4816 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4817
4818 vpnNetworkAgent.disconnect();
4819 defaultCallback.assertNoCallback();
4820
Varun Anand4fa80e82019-02-06 10:13:38 -08004821 mCm.unregisterNetworkCallback(defaultCallback);
4822 }
4823
4824 @Test
4825 public void testVpnWithInternet() {
4826 final int uid = Process.myUid();
4827
4828 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
4829 mCm.registerDefaultNetworkCallback(defaultCallback);
4830
4831 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4832 mWiFiNetworkAgent.connect(true);
4833
4834 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
4835 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4836
4837 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4838 final ArraySet<UidRange> ranges = new ArraySet<>();
4839 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004840 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4841 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09004842 vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004843 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08004844
Chalard Jean26400492018-04-18 20:18:38 +09004845 defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
4846 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4847
4848 vpnNetworkAgent.disconnect();
4849 defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
4850 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
4851
Chalard Jean26400492018-04-18 20:18:38 +09004852 mCm.unregisterNetworkCallback(defaultCallback);
4853 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004854
4855 @Test
4856 public void testVpnSetUnderlyingNetworks() {
4857 final int uid = Process.myUid();
4858
4859 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
4860 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
4861 .removeCapability(NET_CAPABILITY_NOT_VPN)
4862 .addTransportType(TRANSPORT_VPN)
4863 .build();
4864 NetworkCapabilities nc;
4865 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
4866 vpnNetworkCallback.assertNoCallback();
4867
4868 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4869 final ArraySet<UidRange> ranges = new ArraySet<>();
4870 ranges.add(new UidRange(uid, uid));
4871 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4872 mMockVpn.connect();
4873 mMockVpn.setUids(ranges);
4874 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
4875
4876 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
4877 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
4878 assertTrue(nc.hasTransport(TRANSPORT_VPN));
4879 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
4880 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
4881 // For safety reasons a VPN without underlying networks is considered metered.
4882 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
4883
4884 // Connect cell and use it as an underlying network.
4885 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4886 mCellNetworkAgent.connect(true);
4887
4888 mService.setUnderlyingNetworksForVpn(
4889 new Network[] { mCellNetworkAgent.getNetwork() });
4890
4891 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4892 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
4893 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4894 vpnNetworkAgent);
4895
4896 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4897 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
4898 mWiFiNetworkAgent.connect(true);
4899
4900 mService.setUnderlyingNetworksForVpn(
4901 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
4902
4903 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4904 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
4905 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4906 vpnNetworkAgent);
4907
4908 // Don't disconnect, but note the VPN is not using wifi any more.
4909 mService.setUnderlyingNetworksForVpn(
4910 new Network[] { mCellNetworkAgent.getNetwork() });
4911
4912 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4913 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
4914 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4915 vpnNetworkAgent);
4916
4917 // Use Wifi but not cell. Note the VPN is now unmetered.
4918 mService.setUnderlyingNetworksForVpn(
4919 new Network[] { mWiFiNetworkAgent.getNetwork() });
4920
4921 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4922 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
4923 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4924 vpnNetworkAgent);
4925
4926 // Use both again.
4927 mService.setUnderlyingNetworksForVpn(
4928 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
4929
4930 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4931 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
4932 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4933 vpnNetworkAgent);
4934
Chalard Jean6b65ec72018-05-18 22:02:56 +09004935 // Disconnect cell. Receive update without even removing the dead network from the
4936 // underlying networks – it's dead anyway. Not metered any more.
4937 mCellNetworkAgent.disconnect();
4938 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4939 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
4940 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4941 vpnNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004942
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09004943 // Disconnect wifi too. No underlying networks means this is now metered.
Chalard Jean6b65ec72018-05-18 22:02:56 +09004944 mWiFiNetworkAgent.disconnect();
4945 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4946 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09004947 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
Chalard Jean6b65ec72018-05-18 22:02:56 +09004948 vpnNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004949
4950 mMockVpn.disconnect();
4951 }
junyulai4a192e22018-06-13 15:00:37 +08004952
Mike Yuf9729752018-08-17 15:22:05 +08004953 @Test
Varun Anand4fa80e82019-02-06 10:13:38 -08004954 public void testNullUnderlyingNetworks() {
4955 final int uid = Process.myUid();
4956
4957 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
4958 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
4959 .removeCapability(NET_CAPABILITY_NOT_VPN)
4960 .addTransportType(TRANSPORT_VPN)
4961 .build();
4962 NetworkCapabilities nc;
4963 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
4964 vpnNetworkCallback.assertNoCallback();
4965
4966 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4967 final ArraySet<UidRange> ranges = new ArraySet<>();
4968 ranges.add(new UidRange(uid, uid));
4969 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4970 mMockVpn.connect();
4971 mMockVpn.setUids(ranges);
4972 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
4973
4974 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
4975 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
4976 assertTrue(nc.hasTransport(TRANSPORT_VPN));
4977 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
4978 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
4979 // By default, VPN is set to track default network (i.e. its underlying networks is null).
4980 // In case of no default network, VPN is considered metered.
4981 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
4982
4983 // Connect to Cell; Cell is the default network.
4984 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4985 mCellNetworkAgent.connect(true);
4986
4987 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4988 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
4989 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4990 vpnNetworkAgent);
4991
4992 // Connect to WiFi; WiFi is the new default.
4993 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4994 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
4995 mWiFiNetworkAgent.connect(true);
4996
4997 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4998 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
4999 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5000 vpnNetworkAgent);
5001
5002 // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
5003 // the capabilities.
5004 mCellNetworkAgent.disconnect();
5005
5006 // Disconnect wifi too. Now we have no default network.
5007 mWiFiNetworkAgent.disconnect();
5008
5009 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5010 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5011 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5012 vpnNetworkAgent);
5013
5014 mMockVpn.disconnect();
5015 }
5016
5017 @Test
Mike Yuf9729752018-08-17 15:22:05 +08005018 public void testNetworkBlockedStatus() {
5019 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5020 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5021 .addTransportType(TRANSPORT_CELLULAR)
5022 .build();
5023 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
5024
5025 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5026 mCellNetworkAgent.connect(true);
5027 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5028
5029 mService.setUidRulesChanged(RULE_REJECT_ALL);
5030 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5031
5032 // ConnectivityService should cache it not to invoke the callback again.
5033 mService.setUidRulesChanged(RULE_REJECT_METERED);
5034 cellNetworkCallback.assertNoCallback();
5035
5036 mService.setUidRulesChanged(RULE_NONE);
5037 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5038
5039 mService.setUidRulesChanged(RULE_REJECT_METERED);
5040 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5041
5042 // Restrict the network based on UID rule and NOT_METERED capability change.
5043 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5044 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5045 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5046 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5047 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
5048 mCellNetworkAgent);
5049 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5050 mService.setUidRulesChanged(RULE_ALLOW_METERED);
5051 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5052
5053 mService.setUidRulesChanged(RULE_NONE);
5054 cellNetworkCallback.assertNoCallback();
5055
5056 // Restrict the network based on BackgroundRestricted.
5057 mService.setRestrictBackgroundChanged(true);
5058 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5059 mService.setRestrictBackgroundChanged(true);
5060 cellNetworkCallback.assertNoCallback();
5061 mService.setRestrictBackgroundChanged(false);
5062 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5063 cellNetworkCallback.assertNoCallback();
5064
5065 mCm.unregisterNetworkCallback(cellNetworkCallback);
5066 }
5067
5068 @Test
5069 public void testNetworkBlockedStatusBeforeAndAfterConnect() {
5070 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5071 mCm.registerDefaultNetworkCallback(defaultCallback);
5072
5073 // No Networkcallbacks invoked before any network is active.
5074 mService.setUidRulesChanged(RULE_REJECT_ALL);
5075 mService.setUidRulesChanged(RULE_NONE);
5076 mService.setUidRulesChanged(RULE_REJECT_METERED);
5077 defaultCallback.assertNoCallback();
5078
5079 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5080 mCellNetworkAgent.connect(true);
5081 defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
5082 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
5083
5084 // Allow to use the network after switching to NOT_METERED network.
5085 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5086 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5087 mWiFiNetworkAgent.connect(true);
5088 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
5089
5090 // Switch to METERED network. Restrict the use of the network.
5091 mWiFiNetworkAgent.disconnect();
5092 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
5093 defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
5094
5095 // Network becomes NOT_METERED.
5096 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5097 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5098 defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5099
5100 // Verify there's no Networkcallbacks invoked after data saver on/off.
5101 mService.setRestrictBackgroundChanged(true);
5102 mService.setRestrictBackgroundChanged(false);
5103 defaultCallback.assertNoCallback();
5104
5105 mCellNetworkAgent.disconnect();
5106 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
5107 defaultCallback.assertNoCallback();
5108
5109 mCm.unregisterNetworkCallback(defaultCallback);
5110 }
5111
junyulai4a192e22018-06-13 15:00:37 +08005112 /**
5113 * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
5114 */
5115 private InterfaceConfiguration getClatInterfaceConfig(LinkAddress la) {
5116 InterfaceConfiguration cfg = new InterfaceConfiguration();
5117 cfg.setHardwareAddress("11:22:33:44:55:66");
5118 cfg.setLinkAddress(la);
5119 return cfg;
5120 }
5121
5122 /**
5123 * Make expected stack link properties, copied from Nat464Xlat.
5124 */
5125 private LinkProperties makeClatLinkProperties(LinkAddress la) {
5126 LinkAddress clatAddress = la;
5127 LinkProperties stacked = new LinkProperties();
5128 stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME);
5129 RouteInfo ipv4Default = new RouteInfo(
5130 new LinkAddress(Inet4Address.ANY, 0),
5131 clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME);
5132 stacked.addRoute(ipv4Default);
5133 stacked.addLinkAddress(clatAddress);
5134 return stacked;
5135 }
5136
5137 @Test
5138 public void testStackedLinkProperties() throws UnknownHostException, RemoteException {
5139 final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
5140 final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005141 final String kNat64PrefixString = "2001:db8:64:64:64:64::";
5142 final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
5143
junyulai4a192e22018-06-13 15:00:37 +08005144 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5145 .addTransportType(TRANSPORT_CELLULAR)
5146 .addCapability(NET_CAPABILITY_INTERNET)
5147 .build();
5148 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5149 mCm.registerNetworkCallback(networkRequest, networkCallback);
5150
Lorenzo Colittid593e292019-02-19 13:21:56 +09005151 // Prepare ipv6 only link properties.
junyulai4a192e22018-06-13 15:00:37 +08005152 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005153 final int cellNetId = mCellNetworkAgent.getNetwork().netId;
junyulai4a192e22018-06-13 15:00:37 +08005154 final LinkProperties cellLp = new LinkProperties();
5155 cellLp.setInterfaceName(MOBILE_IFNAME);
5156 cellLp.addLinkAddress(myIpv6);
5157 cellLp.addRoute(new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME));
5158 cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME));
5159 reset(mNetworkManagementService);
5160 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
5161 .thenReturn(getClatInterfaceConfig(myIpv4));
5162
Lorenzo Colittid593e292019-02-19 13:21:56 +09005163 // Connect with ipv6 link properties. Expect prefix discovery to be started.
junyulai4a192e22018-06-13 15:00:37 +08005164 mCellNetworkAgent.sendLinkProperties(cellLp);
5165 mCellNetworkAgent.connect(true);
5166 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005167 verify(mMockNetd, times(1)).resolverStartPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005168
Lorenzo Colittid593e292019-02-19 13:21:56 +09005169 // Switching default network updates TCP buffer sizes.
5170 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
5171
5172 // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
5173 // the NAT64 prefix was removed because one was never discovered.
5174 cellLp.addLinkAddress(myIpv4);
5175 mCellNetworkAgent.sendLinkProperties(cellLp);
5176 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
5177 verify(mMockNetd, times(1)).resolverStopPrefix64Discovery(cellNetId);
5178
5179 verifyNoMoreInteractions(mMockNetd);
5180 reset(mMockNetd);
5181
5182 // Remove IPv4 address. Expect prefix discovery to be started again.
5183 cellLp.removeLinkAddress(myIpv4);
5184 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5185 mCellNetworkAgent.sendLinkProperties(cellLp);
5186 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
5187 verify(mMockNetd, times(1)).resolverStartPrefix64Discovery(cellNetId);
5188
5189 // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005190 Nat464Xlat clat = mService.getNat464Xlat(mCellNetworkAgent);
5191 assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
Lorenzo Colittid593e292019-02-19 13:21:56 +09005192 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
5193 kNat64PrefixString, 96);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005194 LinkProperties lpBeforeClat = (LinkProperties) networkCallback.expectCallback(
5195 CallbackState.LINK_PROPERTIES, mCellNetworkAgent).arg;
5196 assertEquals(0, lpBeforeClat.getStackedLinks().size());
5197 assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
5198 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
5199
5200 // Clat iface comes up. Expect stacked link to be added.
junyulai4a192e22018-06-13 15:00:37 +08005201 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Lorenzo Colitti2412c132019-01-22 09:47:54 +09005202 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08005203 List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
5204 .getStackedLinks();
5205 assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
5206
5207 // Change trivial linkproperties and see if stacked link is preserved.
5208 cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
5209 mCellNetworkAgent.sendLinkProperties(cellLp);
junyulai4a192e22018-06-13 15:00:37 +08005210 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
5211
5212 List<LinkProperties> stackedLpsAfterChange =
5213 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
5214 assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
5215 assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
5216
Lorenzo Colittid593e292019-02-19 13:21:56 +09005217 // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
5218 // linkproperties are cleaned up.
junyulai4a192e22018-06-13 15:00:37 +08005219 cellLp.addLinkAddress(myIpv4);
5220 cellLp.addRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5221 mCellNetworkAgent.sendLinkProperties(cellLp);
junyulai4a192e22018-06-13 15:00:37 +08005222 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colitti9307ca22019-01-12 01:54:23 +09005223 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005224 verify(mMockNetd, times(1)).resolverStopPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005225
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005226 // As soon as stop is called, the linkproperties lose the stacked interface.
Lorenzo Colittid593e292019-02-19 13:21:56 +09005227 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005228 LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
5229 LinkProperties expected = new LinkProperties(cellLp);
5230 expected.setNat64Prefix(kNat64Prefix);
5231 assertEquals(expected, actualLpAfterIpv4);
5232 assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
5233
5234 // The interface removed callback happens but has no effect after stop is called.
5235 clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
5236 networkCallback.assertNoCallback();
5237
Lorenzo Colittid593e292019-02-19 13:21:56 +09005238 verifyNoMoreInteractions(mMockNetd);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005239 reset(mMockNetd);
5240
Lorenzo Colittid593e292019-02-19 13:21:56 +09005241 // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
5242 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
5243 kNat64PrefixString, 96);
5244 networkCallback.expectLinkPropertiesLike((lp) -> lp.getNat64Prefix() == null,
5245 mCellNetworkAgent);
5246
5247 // Remove IPv4 address and expect prefix discovery and clatd to be started again.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005248 cellLp.removeLinkAddress(myIpv4);
5249 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5250 cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
5251 mCellNetworkAgent.sendLinkProperties(cellLp);
5252 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005253 verify(mMockNetd, times(1)).resolverStartPrefix64Discovery(cellNetId);
5254 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
5255 kNat64PrefixString, 96);
5256 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005257 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
5258
Lorenzo Colittid593e292019-02-19 13:21:56 +09005259
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005260 // Clat iface comes up. Expect stacked link to be added.
5261 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005262 networkCallback.expectLinkPropertiesLike(
5263 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null,
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005264 mCellNetworkAgent);
5265
5266 // NAT64 prefix is removed. Expect that clat is stopped.
Lorenzo Colittid593e292019-02-19 13:21:56 +09005267 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
5268 kNat64PrefixString, 96);
5269 networkCallback.expectLinkPropertiesLike(
5270 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null,
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005271 mCellNetworkAgent);
5272 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
5273 networkCallback.expectLinkPropertiesLike((lp) -> lp.getStackedLinks().size() == 0,
5274 mCellNetworkAgent);
5275
5276 // Clean up.
junyulai4a192e22018-06-13 15:00:37 +08005277 mCellNetworkAgent.disconnect();
Lorenzo Colitti2412c132019-01-22 09:47:54 +09005278 networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
5279 networkCallback.assertNoCallback();
junyulai4a192e22018-06-13 15:00:37 +08005280 mCm.unregisterNetworkCallback(networkCallback);
5281 }
Chiachang Wanga6093042018-09-28 22:42:48 +08005282
5283 @Test
5284 public void testDataActivityTracking() throws RemoteException {
5285 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5286 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5287 .addCapability(NET_CAPABILITY_INTERNET)
5288 .build();
5289 mCm.registerNetworkCallback(networkRequest, networkCallback);
5290
5291 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5292 final LinkProperties cellLp = new LinkProperties();
5293 cellLp.setInterfaceName(MOBILE_IFNAME);
5294 mCellNetworkAgent.sendLinkProperties(cellLp);
5295 reset(mNetworkManagementService);
5296 mCellNetworkAgent.connect(true);
5297 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5298 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
5299 eq(ConnectivityManager.TYPE_MOBILE));
5300
5301 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5302 final LinkProperties wifiLp = new LinkProperties();
5303 wifiLp.setInterfaceName(WIFI_IFNAME);
5304 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
5305
5306 // Network switch
5307 reset(mNetworkManagementService);
5308 mWiFiNetworkAgent.connect(true);
5309 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5310 networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
5311 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5312 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
5313 eq(ConnectivityManager.TYPE_WIFI));
5314 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
5315
5316 // Disconnect wifi and switch back to cell
5317 reset(mNetworkManagementService);
5318 mWiFiNetworkAgent.disconnect();
5319 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
5320 assertNoCallbacks(networkCallback);
5321 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
5322 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
5323 eq(ConnectivityManager.TYPE_MOBILE));
5324
5325 // reconnect wifi
5326 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5327 wifiLp.setInterfaceName(WIFI_IFNAME);
5328 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
5329 mWiFiNetworkAgent.connect(true);
5330 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5331 networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
5332 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5333
5334 // Disconnect cell
5335 reset(mNetworkManagementService);
5336 mCellNetworkAgent.disconnect();
5337 networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
5338 // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
5339 // sent as network being switched. Ensure rule removal for cell will not be triggered
5340 // unexpectedly before network being removed.
5341 waitForIdle();
5342 verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
5343 verify(mNetworkManagementService, times(1)).removeNetwork(
5344 eq(mCellNetworkAgent.getNetwork().netId));
5345
5346 // Disconnect wifi
5347 ConditionVariable cv = waitForConnectivityBroadcasts(1);
5348 reset(mNetworkManagementService);
5349 mWiFiNetworkAgent.disconnect();
5350 waitFor(cv);
5351 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
5352
5353 // Clean up
5354 mCm.unregisterNetworkCallback(networkCallback);
5355 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005356
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005357 private void verifyTcpBufferSizeChange(String tcpBufferSizes) {
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005358 String[] values = tcpBufferSizes.split(",");
5359 String rmemValues = String.join(" ", values[0], values[1], values[2]);
5360 String wmemValues = String.join(" ", values[3], values[4], values[5]);
5361 waitForIdle();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005362 try {
5363 verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
5364 } catch (RemoteException e) {
5365 fail("mMockNetd should never throw RemoteException");
5366 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005367 reset(mMockNetd);
5368 }
5369
5370 @Test
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005371 public void testTcpBufferReset() {
5372 final String testTcpBufferSizes = "1,2,3,4,5,6";
5373
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005374 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5375 reset(mMockNetd);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005376 // Switching default network updates TCP buffer sizes.
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005377 mCellNetworkAgent.connect(false);
5378 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
5379
5380 // Change link Properties should have updated tcp buffer size.
5381 LinkProperties lp = new LinkProperties();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005382 lp.setTcpBufferSizes(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005383 mCellNetworkAgent.sendLinkProperties(lp);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005384 verifyTcpBufferSizeChange(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005385 }
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005386
5387 @Test
5388 public void testGetGlobalProxyForNetwork() {
5389 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
5390 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5391 final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
5392 when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
5393 assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
5394 }
5395
5396 @Test
5397 public void testGetProxyForActiveNetwork() {
5398 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
5399 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5400 mWiFiNetworkAgent.connect(true);
5401 waitForIdle();
5402 assertNull(mService.getProxyForNetwork(null));
5403
5404 final LinkProperties testLinkProperties = new LinkProperties();
5405 testLinkProperties.setHttpProxy(testProxyInfo);
5406
5407 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
5408 waitForIdle();
5409
5410 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
5411 }
5412
5413 @Test
5414 public void testGetProxyForVPN() {
5415 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
5416
5417 // Set up a WiFi network with no proxy
5418 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5419 mWiFiNetworkAgent.connect(true);
5420 waitForIdle();
5421 assertNull(mService.getProxyForNetwork(null));
5422
5423 // Set up a VPN network with a proxy
5424 final int uid = Process.myUid();
5425 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5426 final ArraySet<UidRange> ranges = new ArraySet<>();
5427 ranges.add(new UidRange(uid, uid));
5428 mMockVpn.setUids(ranges);
5429 LinkProperties testLinkProperties = new LinkProperties();
5430 testLinkProperties.setHttpProxy(testProxyInfo);
5431 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
5432 waitForIdle();
5433
5434 // Connect to VPN with proxy
5435 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5436 vpnNetworkAgent.connect(true);
5437 mMockVpn.connect();
5438 waitForIdle();
5439
5440 // Test that the VPN network returns a proxy, and the WiFi does not.
5441 assertEquals(testProxyInfo, mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
5442 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
5443 assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
5444
5445 // Test that the VPN network returns no proxy when it is set to null.
5446 testLinkProperties.setHttpProxy(null);
5447 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
5448 waitForIdle();
5449 assertNull(mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
5450 assertNull(mService.getProxyForNetwork(null));
5451
5452 // Set WiFi proxy and check that the vpn proxy is still null.
5453 testLinkProperties.setHttpProxy(testProxyInfo);
5454 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
5455 waitForIdle();
5456 assertNull(mService.getProxyForNetwork(null));
5457
5458 // Disconnect from VPN and check that the active network, which is now the WiFi, has the
5459 // correct proxy setting.
5460 vpnNetworkAgent.disconnect();
5461 waitForIdle();
5462 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5463 assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
5464 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
5465 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07005466}