blob: c25ad5f7bbd53783339c8b26acd81e024975e7bf [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
Varun Anandc51b06d2019-02-25 17:22:02 -0800912 private void connect(boolean isAlwaysMetered) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900913 mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
914 mConnected = true;
915 mConfig = new VpnConfig();
Varun Anandc51b06d2019-02-25 17:22:02 -0800916 mConfig.isMetered = isAlwaysMetered;
917 }
918
919 public void connectAsAlwaysMetered() {
920 connect(true /* isAlwaysMetered */);
921 }
922
923 public void connect() {
924 connect(false /* isAlwaysMetered */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900925 }
926
927 @Override
Varun Anand4fa80e82019-02-06 10:13:38 -0800928 public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
929 if (!mConnected) return null;
930 super.updateCapabilities(defaultNetwork);
931 // Because super.updateCapabilities will update the capabilities of the agent but
932 // not the mock agent, the mock agent needs to know about them.
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900933 copyCapabilitiesToNetworkAgent();
Varun Anand4fa80e82019-02-06 10:13:38 -0800934 return new NetworkCapabilities(mNetworkCapabilities);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900935 }
936
937 private void copyCapabilitiesToNetworkAgent() {
938 if (null != mMockNetworkAgent) {
939 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
940 false /* sendToConnectivityService */);
941 }
942 }
943
944 public void disconnect() {
945 mConnected = false;
946 mConfig = null;
947 }
948 }
949
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900950 private class FakeWakeupMessage extends WakeupMessage {
951 private static final int UNREASONABLY_LONG_WAIT = 1000;
952
953 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
954 super(context, handler, cmdName, cmd);
955 }
956
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900957 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
958 int arg1, int arg2, Object obj) {
959 super(context, handler, cmdName, cmd, arg1, arg2, obj);
960 }
961
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900962 @Override
963 public void schedule(long when) {
964 long delayMs = when - SystemClock.elapsedRealtime();
965 if (delayMs < 0) delayMs = 0;
966 if (delayMs > UNREASONABLY_LONG_WAIT) {
967 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
968 "ms into the future: " + delayMs);
969 }
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900970 Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
971 mHandler.sendMessageDelayed(msg, delayMs);
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900972 }
973
974 @Override
975 public void cancel() {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900976 mHandler.removeMessages(mCmd, mObj);
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900977 }
978
979 @Override
980 public void onAlarm() {
981 throw new AssertionError("Should never happen. Update this fake.");
982 }
983 }
984
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900985 private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
Hugo Benichi53d83d52016-11-15 13:42:34 +0900986 public volatile boolean configRestrictsAvoidBadWifi;
Lorenzo Colitti2de49252017-01-24 18:08:41 +0900987 public volatile int configMeteredMultipathPreference;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400988
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900989 public WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
Erik Kline065ab6e2016-10-02 18:02:14 +0900990 super(c, h, r);
991 }
992
993 @Override
994 public boolean configRestrictsAvoidBadWifi() {
995 return configRestrictsAvoidBadWifi;
996 }
Lorenzo Colitti2de49252017-01-24 18:08:41 +0900997
998 @Override
999 public int configMeteredMultipathPreference() {
1000 return configMeteredMultipathPreference;
1001 }
Erik Kline065ab6e2016-10-02 18:02:14 +09001002 }
1003
1004 private class WrappedConnectivityService extends ConnectivityService {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001005 public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001006 private MockableSystemProperties mSystemProperties;
Erik Kline065ab6e2016-10-02 18:02:14 +09001007
Paul Jensend7b6ca92015-05-13 14:05:12 -04001008 public WrappedConnectivityService(Context context, INetworkManagementService netManager,
Hugo Benichif9fdf872016-07-28 17:53:06 +09001009 INetworkStatsService statsService, INetworkPolicyManager policyManager,
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001010 IpConnectivityLog log, INetd netd) {
Hugo Benichif9fdf872016-07-28 17:53:06 +09001011 super(context, netManager, statsService, policyManager, log);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001012 mNetd = netd;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001013 mLingerDelayMs = TEST_LINGER_DELAY_MS;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001014 }
1015
1016 @Override
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001017 protected MockableSystemProperties getSystemProperties() {
1018 // Minimal approach to overriding system properties: let most calls fall through to real
1019 // device values, and only override ones values that are important to this test.
1020 mSystemProperties = spy(new MockableSystemProperties());
1021 when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
1022 when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
1023 return mSystemProperties;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001024 }
Paul Jensen67b0b072015-06-10 11:22:17 -04001025
1026 @Override
Mike Yuf9729752018-08-17 15:22:05 +08001027 protected Tethering makeTethering() {
1028 return mock(Tethering.class);
1029 }
1030
1031 @Override
Irina Dumitrescu044a4362018-12-05 16:19:47 +00001032 protected ProxyTracker makeProxyTracker() {
1033 return mock(ProxyTracker.class);
1034 }
1035
1036 @Override
Paul Jensen67b0b072015-06-10 11:22:17 -04001037 protected int reserveNetId() {
1038 while (true) {
1039 final int netId = super.reserveNetId();
1040
1041 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
1042 // can have odd side-effects, like network validations succeeding.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001043 Context context = InstrumentationRegistry.getContext();
1044 final Network[] networks = ConnectivityManager.from(context).getAllNetworks();
Paul Jensen67b0b072015-06-10 11:22:17 -04001045 boolean overlaps = false;
1046 for (Network network : networks) {
1047 if (netId == network.netId) {
1048 overlaps = true;
1049 break;
1050 }
1051 }
1052 if (overlaps) continue;
1053
1054 return netId;
1055 }
1056 }
Paul Jensencf4c2c62015-07-01 14:16:32 -04001057
Irina Dumitrescu044a4362018-12-05 16:19:47 +00001058 @Override
1059 protected boolean queryUserAccess(int uid, int netId) {
1060 return true;
1061 }
1062
junyulai4a192e22018-06-13 15:00:37 +08001063 public Nat464Xlat getNat464Xlat(MockNetworkAgent mna) {
1064 return getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
1065 }
1066
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001067 @Override
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001068 public MultinetworkPolicyTracker createMultinetworkPolicyTracker(
Erik Kline065ab6e2016-10-02 18:02:14 +09001069 Context c, Handler h, Runnable r) {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001070 final WrappedMultinetworkPolicyTracker tracker = new WrappedMultinetworkPolicyTracker(c, h, r);
Erik Kline065ab6e2016-10-02 18:02:14 +09001071 return tracker;
1072 }
1073
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001074 public WrappedMultinetworkPolicyTracker getMultinetworkPolicyTracker() {
1075 return (WrappedMultinetworkPolicyTracker) mMultinetworkPolicyTracker;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001076 }
1077
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09001078 @Override
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +09001079 protected NetworkStackClient getNetworkStack() {
1080 return mNetworkStack;
1081 }
1082
1083 @Override
Erik Kline065ab6e2016-10-02 18:02:14 +09001084 public WakeupMessage makeWakeupMessage(
1085 Context context, Handler handler, String cmdName, int cmd, Object obj) {
1086 return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09001087 }
1088
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001089 @Override
1090 public boolean hasService(String name) {
1091 // Currenty, the only relevant service that ConnectivityService checks for is
1092 // ETHERNET_SERVICE.
1093 return Context.ETHERNET_SERVICE.equals(name);
1094 }
1095
Hugo Benichi64901e52017-10-19 14:42:40 +09001096 @Override
1097 protected IpConnectivityMetrics.Logger metricsLogger() {
1098 return mMetricsService;
1099 }
1100
dalyk1fcb7392018-03-05 12:42:22 -05001101 @Override
1102 protected void registerNetdEventCallback() {
1103 }
1104
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001105 public void mockVpn(int uid) {
1106 synchronized (mVpns) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001107 int userId = UserHandle.getUserId(uid);
1108 mMockVpn = new MockVpn(userId);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001109 // This has no effect unless the VPN is actually connected, because things like
1110 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
1111 // netId, and check if that network is actually connected.
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001112 mVpns.put(userId, mMockVpn);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001113 }
1114 }
1115
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001116 public void waitForIdle(int timeoutMs) {
Hugo Benichiad4db4e2016-10-17 15:54:51 +09001117 waitForIdleHandler(mHandlerThread, timeoutMs);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001118 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001119
1120 public void waitForIdle() {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001121 waitForIdle(TIMEOUT_MS);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001122 }
Mike Yuf9729752018-08-17 15:22:05 +08001123
1124 public void setUidRulesChanged(int uidRules) {
1125 try {
1126 mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
1127 } catch (RemoteException ignored) {
1128 }
1129 }
1130
1131 public void setRestrictBackgroundChanged(boolean restrictBackground) {
1132 try {
1133 mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
1134 } catch (RemoteException ignored) {
1135 }
1136 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001137 }
1138
Paul Jensen3d911462015-06-12 06:40:24 -04001139 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001140 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1141 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -04001142 */
1143 static private void waitFor(ConditionVariable conditionVariable) {
Hugo Benichi16f0a942017-06-20 14:07:59 +09001144 if (conditionVariable.block(TIMEOUT_MS)) {
1145 return;
1146 }
1147 fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
Paul Jensen3d911462015-06-12 06:40:24 -04001148 }
1149
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001150 @Before
Paul Jensend7b6ca92015-05-13 14:05:12 -04001151 public void setUp() throws Exception {
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001152 mContext = InstrumentationRegistry.getContext();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001153
Hugo Benichi64901e52017-10-19 14:42:40 +09001154 MockitoAnnotations.initMocks(this);
1155 when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
1156
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001157 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1158 // http://b/25897652 .
1159 if (Looper.myLooper() == null) {
1160 Looper.prepare();
1161 }
1162
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001163 FakeSettingsProvider.clearSettingsProvider();
1164 mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1165 new FakeSettingsProvider());
Hugo Benichi938ab4f2017-02-11 17:04:43 +09001166 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
1167 LocalServices.addService(
1168 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
Mike Yuf9729752018-08-17 15:22:05 +08001169
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001170 mService = new WrappedConnectivityService(mServiceContext,
Erik Klinee89953b2018-01-11 16:11:10 +09001171 mNetworkManagementService,
Jeff Sharkey72f9c422017-10-27 17:22:59 -06001172 mStatsService,
Mike Yuf9729752018-08-17 15:22:05 +08001173 mNpm,
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001174 mock(IpConnectivityLog.class),
1175 mMockNetd);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001176
Mike Yuf9729752018-08-17 15:22:05 +08001177 final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
1178 ArgumentCaptor.forClass(INetworkPolicyListener.class);
1179 verify(mNpm).registerListener(policyListenerCaptor.capture());
1180 mPolicyListener = policyListenerCaptor.getValue();
1181
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001182 // Create local CM before sending system ready so that we can answer
1183 // getSystemService() correctly.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001184 mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001185 mService.systemReady();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001186 mService.mockVpn(Process.myUid());
Lorenzo Colitti531a3442016-03-01 12:55:58 +09001187 mCm.bindProcessToNetwork(null);
Calvin On1f64f3f2016-10-11 15:10:46 -07001188
1189 // Ensure that the default setting for Captive Portals is used for most tests
1190 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001191 setAlwaysOnNetworks(false);
Erik Kline79c6d052018-03-21 07:18:33 -07001192 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Paul Jensend7b6ca92015-05-13 14:05:12 -04001193 }
1194
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001195 @After
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001196 public void tearDown() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001197 setAlwaysOnNetworks(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001198 if (mCellNetworkAgent != null) {
1199 mCellNetworkAgent.disconnect();
1200 mCellNetworkAgent = null;
1201 }
1202 if (mWiFiNetworkAgent != null) {
1203 mWiFiNetworkAgent.disconnect();
1204 mWiFiNetworkAgent = null;
1205 }
1206 if (mEthernetNetworkAgent != null) {
1207 mEthernetNetworkAgent.disconnect();
1208 mEthernetNetworkAgent = null;
1209 }
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001210 FakeSettingsProvider.clearSettingsProvider();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001211 }
1212
Hugo Benichibb91c572017-05-22 10:44:02 +09001213 private static int transportToLegacyType(int transport) {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001214 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001215 case TRANSPORT_ETHERNET:
1216 return TYPE_ETHERNET;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001217 case TRANSPORT_WIFI:
1218 return TYPE_WIFI;
1219 case TRANSPORT_CELLULAR:
1220 return TYPE_MOBILE;
1221 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001222 return TYPE_NONE;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001223 }
1224 }
1225
1226 private void verifyActiveNetwork(int transport) {
1227 // Test getActiveNetworkInfo()
1228 assertNotNull(mCm.getActiveNetworkInfo());
1229 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
1230 // Test getActiveNetwork()
1231 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001232 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Hugo Benichi16f0a942017-06-20 14:07:59 +09001233 if (!NetworkCapabilities.isValidTransport(transport)) {
1234 throw new IllegalStateException("Unknown transport " + transport);
1235 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001236 switch (transport) {
1237 case TRANSPORT_WIFI:
1238 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
1239 break;
1240 case TRANSPORT_CELLULAR:
1241 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
1242 break;
1243 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001244 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001245 }
1246 // Test getNetworkInfo(Network)
1247 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
Hugo Benichibb91c572017-05-22 10:44:02 +09001248 assertEquals(transportToLegacyType(transport),
1249 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001250 // Test getNetworkCapabilities(Network)
1251 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
1252 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
1253 }
1254
1255 private void verifyNoNetwork() {
Hugo Benichic1014502017-07-19 10:10:52 +09001256 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001257 // Test getActiveNetworkInfo()
1258 assertNull(mCm.getActiveNetworkInfo());
1259 // Test getActiveNetwork()
1260 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001261 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -04001262 // Test getAllNetworks()
Hugo Benichifed512a2017-06-26 10:06:49 +09001263 assertEmpty(mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001264 }
1265
1266 /**
1267 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
1268 * broadcasts are received.
1269 */
1270 private ConditionVariable waitForConnectivityBroadcasts(final int count) {
1271 final ConditionVariable cv = new ConditionVariable();
1272 mServiceContext.registerReceiver(new BroadcastReceiver() {
1273 private int remaining = count;
1274 public void onReceive(Context context, Intent intent) {
1275 if (--remaining == 0) {
1276 cv.open();
1277 mServiceContext.unregisterReceiver(this);
1278 }
1279 }
1280 }, new IntentFilter(CONNECTIVITY_ACTION));
1281 return cv;
1282 }
1283
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001284 @Test
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001285 public void testNetworkTypes() {
1286 // Ensure that our mocks for the networkAttributes config variable work as expected. If they
1287 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
1288 // will fail. Failing here is much easier to debug.
1289 assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
1290 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001291 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
1292 assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
1293
1294 // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
1295 // mocks, this assert exercises the ConnectivityService code path that ensures that
1296 // TYPE_ETHERNET is supported if the ethernet service is running.
1297 assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001298 }
1299
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001300 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001301 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001302 verifyNoNetwork();
1303 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1304 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1305 assertNull(mCm.getActiveNetworkInfo());
1306 assertNull(mCm.getActiveNetwork());
1307 // Test bringing up validated cellular.
1308 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1309 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001310 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001311 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichifed512a2017-06-26 10:06:49 +09001312 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001313 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1314 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1315 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
1316 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
1317 // Test bringing up validated WiFi.
1318 cv = waitForConnectivityBroadcasts(2);
1319 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001320 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001321 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001322 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001323 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1324 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1325 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
1326 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
1327 // Test cellular linger timeout.
Lorenzo Colittid2706122017-01-30 17:45:49 +09001328 waitFor(mCellNetworkAgent.getDisconnectedCV());
Hugo Benichibb91c572017-05-22 10:44:02 +09001329 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09001330 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001331 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001332 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001333 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
1334 // Test WiFi disconnect.
1335 cv = waitForConnectivityBroadcasts(1);
1336 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001337 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001338 verifyNoNetwork();
1339 }
1340
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001341 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001342 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
1343 // Test bringing up unvalidated WiFi
1344 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1345 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1346 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001347 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001348 verifyActiveNetwork(TRANSPORT_WIFI);
1349 // Test bringing up unvalidated cellular
1350 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1351 mCellNetworkAgent.connect(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001352 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001353 verifyActiveNetwork(TRANSPORT_WIFI);
1354 // Test cellular disconnect.
1355 mCellNetworkAgent.disconnect();
Hugo Benichibb91c572017-05-22 10:44:02 +09001356 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001357 verifyActiveNetwork(TRANSPORT_WIFI);
1358 // Test bringing up validated cellular
1359 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1360 cv = waitForConnectivityBroadcasts(2);
1361 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001362 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001363 verifyActiveNetwork(TRANSPORT_CELLULAR);
1364 // Test cellular disconnect.
1365 cv = waitForConnectivityBroadcasts(2);
1366 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001367 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001368 verifyActiveNetwork(TRANSPORT_WIFI);
1369 // Test WiFi disconnect.
1370 cv = waitForConnectivityBroadcasts(1);
1371 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001372 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001373 verifyNoNetwork();
1374 }
1375
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001376 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001377 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
1378 // Test bringing up unvalidated cellular.
1379 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1380 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1381 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001382 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001383 verifyActiveNetwork(TRANSPORT_CELLULAR);
1384 // Test bringing up unvalidated WiFi.
1385 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1386 cv = waitForConnectivityBroadcasts(2);
1387 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001388 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001389 verifyActiveNetwork(TRANSPORT_WIFI);
1390 // Test WiFi disconnect.
1391 cv = waitForConnectivityBroadcasts(2);
1392 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001393 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001394 verifyActiveNetwork(TRANSPORT_CELLULAR);
1395 // Test cellular disconnect.
1396 cv = waitForConnectivityBroadcasts(1);
1397 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001398 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001399 verifyNoNetwork();
1400 }
1401
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001402 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001403 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04001404 // Test bringing up unvalidated WiFi.
Paul Jensene0988542015-06-25 15:30:08 -04001405 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001406 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1407 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -04001408 waitFor(cv);
1409 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001410 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001411 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -04001412 // Test bringing up validated cellular.
1413 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001414 cv = waitForConnectivityBroadcasts(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001415 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -04001416 waitFor(cv);
1417 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001418 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1419 NET_CAPABILITY_VALIDATED));
1420 // Test cellular disconnect.
1421 cv = waitForConnectivityBroadcasts(2);
1422 mCellNetworkAgent.disconnect();
1423 waitFor(cv);
1424 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001425 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001426 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001427 NET_CAPABILITY_VALIDATED));
1428 }
1429
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001430 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001431 public void testCellularOutscoresWeakWifi() throws Exception {
1432 // Test bringing up validated cellular.
1433 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1434 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1435 mCellNetworkAgent.connect(true);
1436 waitFor(cv);
1437 verifyActiveNetwork(TRANSPORT_CELLULAR);
1438 // Test bringing up validated WiFi.
1439 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1440 cv = waitForConnectivityBroadcasts(2);
1441 mWiFiNetworkAgent.connect(true);
1442 waitFor(cv);
1443 verifyActiveNetwork(TRANSPORT_WIFI);
1444 // Test WiFi getting really weak.
1445 cv = waitForConnectivityBroadcasts(2);
1446 mWiFiNetworkAgent.adjustScore(-11);
1447 waitFor(cv);
1448 verifyActiveNetwork(TRANSPORT_CELLULAR);
1449 // Test WiFi restoring signal strength.
1450 cv = waitForConnectivityBroadcasts(2);
1451 mWiFiNetworkAgent.adjustScore(11);
1452 waitFor(cv);
1453 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001454 }
1455
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001456 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001457 public void testReapingNetwork() throws Exception {
1458 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1459 // Expect it to be torn down immediately because it satisfies no requests.
1460 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1461 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
1462 mWiFiNetworkAgent.connectWithoutInternet();
1463 waitFor(cv);
1464 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1465 // Expect it to be torn down immediately because it satisfies no requests.
1466 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1467 cv = mCellNetworkAgent.getDisconnectedCV();
1468 mCellNetworkAgent.connectWithoutInternet();
1469 waitFor(cv);
1470 // Test bringing up validated WiFi.
1471 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1472 cv = waitForConnectivityBroadcasts(1);
1473 mWiFiNetworkAgent.connect(true);
1474 waitFor(cv);
1475 verifyActiveNetwork(TRANSPORT_WIFI);
1476 // Test bringing up unvalidated cellular.
1477 // Expect it to be torn down because it could never be the highest scoring network
1478 // satisfying the default request even if it validated.
1479 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1480 cv = mCellNetworkAgent.getDisconnectedCV();
1481 mCellNetworkAgent.connect(false);
1482 waitFor(cv);
1483 verifyActiveNetwork(TRANSPORT_WIFI);
1484 cv = mWiFiNetworkAgent.getDisconnectedCV();
1485 mWiFiNetworkAgent.disconnect();
1486 waitFor(cv);
1487 }
1488
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001489 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001490 public void testCellularFallback() throws Exception {
1491 // Test bringing up validated cellular.
1492 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1493 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1494 mCellNetworkAgent.connect(true);
1495 waitFor(cv);
1496 verifyActiveNetwork(TRANSPORT_CELLULAR);
1497 // Test bringing up validated WiFi.
1498 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1499 cv = waitForConnectivityBroadcasts(2);
1500 mWiFiNetworkAgent.connect(true);
1501 waitFor(cv);
1502 verifyActiveNetwork(TRANSPORT_WIFI);
1503 // Reevaluate WiFi (it'll instantly fail DNS).
1504 cv = waitForConnectivityBroadcasts(2);
1505 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1506 NET_CAPABILITY_VALIDATED));
1507 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1508 // Should quickly fall back to Cellular.
1509 waitFor(cv);
1510 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1511 NET_CAPABILITY_VALIDATED));
1512 verifyActiveNetwork(TRANSPORT_CELLULAR);
1513 // Reevaluate cellular (it'll instantly fail DNS).
1514 cv = waitForConnectivityBroadcasts(2);
1515 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1516 NET_CAPABILITY_VALIDATED));
1517 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1518 // Should quickly fall back to WiFi.
1519 waitFor(cv);
1520 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1521 NET_CAPABILITY_VALIDATED));
1522 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1523 NET_CAPABILITY_VALIDATED));
1524 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001525 }
1526
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001527 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001528 public void testWiFiFallback() throws Exception {
1529 // Test bringing up unvalidated WiFi.
1530 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1531 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1532 mWiFiNetworkAgent.connect(false);
1533 waitFor(cv);
1534 verifyActiveNetwork(TRANSPORT_WIFI);
1535 // Test bringing up validated cellular.
1536 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1537 cv = waitForConnectivityBroadcasts(2);
1538 mCellNetworkAgent.connect(true);
1539 waitFor(cv);
1540 verifyActiveNetwork(TRANSPORT_CELLULAR);
1541 // Reevaluate cellular (it'll instantly fail DNS).
1542 cv = waitForConnectivityBroadcasts(2);
1543 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1544 NET_CAPABILITY_VALIDATED));
1545 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1546 // Should quickly fall back to WiFi.
1547 waitFor(cv);
1548 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1549 NET_CAPABILITY_VALIDATED));
1550 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001551 }
1552
Lorenzo Colittied3168e2019-01-23 17:54:08 +09001553 @Test
1554 public void testRequiresValidation() {
1555 assertTrue(NetworkMonitorUtils.isValidationRequired(
1556 mCm.getDefaultRequest().networkCapabilities));
1557 }
1558
Paul Jensen3d911462015-06-12 06:40:24 -04001559 enum CallbackState {
1560 NONE,
1561 AVAILABLE,
Erik Klineacdd6392016-07-07 16:50:58 +09001562 NETWORK_CAPABILITIES,
1563 LINK_PROPERTIES,
Erik Kline1d3db322017-02-28 16:20:20 +09001564 SUSPENDED,
Chalard Jean804b8fb2018-01-30 22:41:41 +09001565 RESUMED,
Paul Jensen3d911462015-06-12 06:40:24 -04001566 LOSING,
Erik Kline3841a482015-11-25 12:49:38 +09001567 LOST,
Mike Yuf9729752018-08-17 15:22:05 +08001568 UNAVAILABLE,
1569 BLOCKED_STATUS
Paul Jensen3d911462015-06-12 06:40:24 -04001570 }
1571
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001572 private static class CallbackInfo {
1573 public final CallbackState state;
1574 public final Network network;
1575 public final Object arg;
1576 public CallbackInfo(CallbackState s, Network n, Object o) {
1577 state = s; network = n; arg = o;
1578 }
1579 public String toString() {
Erik Kline1d3db322017-02-28 16:20:20 +09001580 return String.format("%s (%s) (%s)", state, network, arg);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001581 }
1582 @Override
1583 public boolean equals(Object o) {
1584 if (!(o instanceof CallbackInfo)) return false;
1585 // Ignore timeMs, since it's unpredictable.
1586 CallbackInfo other = (CallbackInfo) o;
1587 return (state == other.state) && Objects.equals(network, other.network);
1588 }
1589 @Override
1590 public int hashCode() {
1591 return Objects.hash(state, network);
1592 }
1593 }
1594
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001595 /**
1596 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1597 * this class receives, by calling expectCallback() exactly once each time a callback is
1598 * received. assertNoCallback may be called at any time.
1599 */
Paul Jensen3d911462015-06-12 06:40:24 -04001600 private class TestNetworkCallback extends NetworkCallback {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001601 private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001602 private Network mLastAvailableNetwork;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001603
Erik Klineacdd6392016-07-07 16:50:58 +09001604 protected void setLastCallback(CallbackState state, Network network, Object o) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001605 mCallbacks.offer(new CallbackInfo(state, network, o));
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001606 }
Paul Jensen3d911462015-06-12 06:40:24 -04001607
Erik Klineacdd6392016-07-07 16:50:58 +09001608 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001609 public void onAvailable(Network network) {
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001610 mLastAvailableNetwork = network;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001611 setLastCallback(CallbackState.AVAILABLE, network, null);
Paul Jensen3d911462015-06-12 06:40:24 -04001612 }
1613
Erik Klineacdd6392016-07-07 16:50:58 +09001614 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001615 public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
1616 setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
1617 }
1618
1619 @Override
1620 public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
1621 setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
1622 }
1623
1624 @Override
Erik Kline3841a482015-11-25 12:49:38 +09001625 public void onUnavailable() {
1626 setLastCallback(CallbackState.UNAVAILABLE, null, null);
1627 }
1628
1629 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001630 public void onNetworkSuspended(Network network) {
1631 setLastCallback(CallbackState.SUSPENDED, network, null);
1632 }
1633
1634 @Override
Chalard Jean804b8fb2018-01-30 22:41:41 +09001635 public void onNetworkResumed(Network network) {
1636 setLastCallback(CallbackState.RESUMED, network, null);
1637 }
1638
1639 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001640 public void onLosing(Network network, int maxMsToLive) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001641 setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
Paul Jensen3d911462015-06-12 06:40:24 -04001642 }
1643
Erik Klineacdd6392016-07-07 16:50:58 +09001644 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001645 public void onLost(Network network) {
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001646 mLastAvailableNetwork = null;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001647 setLastCallback(CallbackState.LOST, network, null);
1648 }
1649
Mike Yuf9729752018-08-17 15:22:05 +08001650 @Override
1651 public void onBlockedStatusChanged(Network network, boolean blocked) {
1652 setLastCallback(CallbackState.BLOCKED_STATUS, network, blocked);
1653 }
1654
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001655 public Network getLastAvailableNetwork() {
1656 return mLastAvailableNetwork;
1657 }
1658
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001659 CallbackInfo nextCallback(int timeoutMs) {
1660 CallbackInfo cb = null;
1661 try {
1662 cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
1663 } catch (InterruptedException e) {
1664 }
1665 if (cb == null) {
1666 // LinkedBlockingQueue.poll() returns null if it timeouts.
1667 fail("Did not receive callback after " + timeoutMs + "ms");
1668 }
1669 return cb;
1670 }
1671
Erik Kline1d3db322017-02-28 16:20:20 +09001672 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs) {
1673 final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null;
1674 CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001675 CallbackInfo actual = nextCallback(timeoutMs);
1676 assertEquals("Unexpected callback:", expected, actual);
Erik Kline1d3db322017-02-28 16:20:20 +09001677
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001678 if (state == CallbackState.LOSING) {
1679 String msg = String.format(
1680 "Invalid linger time value %d, must be between %d and %d",
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001681 actual.arg, 0, mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001682 int maxMsToLive = (Integer) actual.arg;
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001683 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001684 }
Erik Kline1d3db322017-02-28 16:20:20 +09001685
1686 return actual;
Erik Klinea2d29402016-03-16 15:31:39 +09001687 }
1688
Erik Kline1d3db322017-02-28 16:20:20 +09001689 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001690 return expectCallback(state, agent, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001691 }
1692
Hugo Benichi16f0a942017-06-20 14:07:59 +09001693 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001694 return expectCallbackLike(fn, TEST_CALLBACK_TIMEOUT_MS);
Hugo Benichi16f0a942017-06-20 14:07:59 +09001695 }
1696
1697 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs) {
1698 int timeLeft = timeoutMs;
1699 while (timeLeft > 0) {
1700 long start = SystemClock.elapsedRealtime();
1701 CallbackInfo info = nextCallback(timeLeft);
1702 if (fn.test(info)) {
1703 return info;
1704 }
1705 timeLeft -= (SystemClock.elapsedRealtime() - start);
1706 }
1707 fail("Did not receive expected callback after " + timeoutMs + "ms");
1708 return null;
1709 }
1710
Lorenzo Colitti27334542018-01-12 16:22:21 +09001711 // Expects onAvailable and the callbacks that follow it. These are:
1712 // - onSuspended, iff the network was suspended when the callbacks fire.
1713 // - onCapabilitiesChanged.
1714 // - onLinkPropertiesChanged.
Mike Yuf9729752018-08-17 15:22:05 +08001715 // - onBlockedStatusChanged.
Lorenzo Colitti27334542018-01-12 16:22:21 +09001716 //
1717 // @param agent the network to expect the callbacks on.
1718 // @param expectSuspended whether to expect a SUSPENDED callback.
1719 // @param expectValidated the expected value of the VALIDATED capability in the
1720 // onCapabilitiesChanged callback.
1721 // @param timeoutMs how long to wait for the callbacks.
1722 void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended,
Mike Yuf9729752018-08-17 15:22:05 +08001723 boolean expectValidated, boolean expectBlocked, int timeoutMs) {
Erik Kline1d3db322017-02-28 16:20:20 +09001724 expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
Erik Klinec75d4fa2017-02-15 19:59:17 +09001725 if (expectSuspended) {
1726 expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001727 }
Lorenzo Colitti27334542018-01-12 16:22:21 +09001728 if (expectValidated) {
Chalard Jean1fa777d2018-02-16 16:07:53 +09001729 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001730 } else {
Chalard Jean1fa777d2018-02-16 16:07:53 +09001731 expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001732 }
Erik Klinec75d4fa2017-02-15 19:59:17 +09001733 expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs);
Mike Yuf9729752018-08-17 15:22:05 +08001734 expectBlockedStatusCallback(expectBlocked, agent);
Erik Kline1d3db322017-02-28 16:20:20 +09001735 }
1736
Lorenzo Colitti27334542018-01-12 16:22:21 +09001737 // Expects the available callbacks (validated), plus onSuspended.
1738 void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) {
Mike Yuf9729752018-08-17 15:22:05 +08001739 expectAvailableCallbacks(agent, true, expectValidated, false, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001740 }
1741
Lorenzo Colitti27334542018-01-12 16:22:21 +09001742 void expectAvailableCallbacksValidated(MockNetworkAgent agent) {
Mike Yuf9729752018-08-17 15:22:05 +08001743 expectAvailableCallbacks(agent, false, true, false, TEST_CALLBACK_TIMEOUT_MS);
1744 }
1745
1746 void expectAvailableCallbacksValidatedAndBlocked(MockNetworkAgent agent) {
1747 expectAvailableCallbacks(agent, false, true, true, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001748 }
1749
Lorenzo Colitti27334542018-01-12 16:22:21 +09001750 void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) {
Mike Yuf9729752018-08-17 15:22:05 +08001751 expectAvailableCallbacks(agent, false, false, false, TEST_CALLBACK_TIMEOUT_MS);
1752 }
1753
1754 void expectAvailableCallbacksUnvalidatedAndBlocked(MockNetworkAgent agent) {
1755 expectAvailableCallbacks(agent, false, false, true, TEST_CALLBACK_TIMEOUT_MS);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001756 }
1757
1758 // Expects the available callbacks (where the onCapabilitiesChanged must contain the
1759 // VALIDATED capability), plus another onCapabilitiesChanged which is identical to the
1760 // one we just sent.
1761 // TODO: this is likely a bug. Fix it and remove this method.
1762 void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001763 expectCallback(CallbackState.AVAILABLE, agent, TEST_CALLBACK_TIMEOUT_MS);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001764 NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001765 expectCallback(CallbackState.LINK_PROPERTIES, agent, TEST_CALLBACK_TIMEOUT_MS);
Mike Yuf9729752018-08-17 15:22:05 +08001766 // Implicitly check the network is allowed to use.
1767 // TODO: should we need to consider if network is in blocked status in this case?
1768 expectBlockedStatusCallback(false, agent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001769 NetworkCapabilities nc2 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1770 assertEquals(nc1, nc2);
1771 }
1772
1773 // Expects the available callbacks where the onCapabilitiesChanged must not have validated,
1774 // then expects another onCapabilitiesChanged that has the validated bit set. This is used
1775 // when a network connects and satisfies a callback, and then immediately validates.
1776 void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) {
1777 expectAvailableCallbacksUnvalidated(agent);
Erik Kline1d3db322017-02-28 16:20:20 +09001778 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1779 }
1780
Lorenzo Colitti27334542018-01-12 16:22:21 +09001781 NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001782 return expectCapabilitiesWith(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001783 }
1784
1785 NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent,
1786 int timeoutMs) {
1787 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001788 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1789 assertTrue(nc.hasCapability(capability));
Lorenzo Colitti27334542018-01-12 16:22:21 +09001790 return nc;
Erik Kline1d3db322017-02-28 16:20:20 +09001791 }
1792
Lorenzo Colitti27334542018-01-12 16:22:21 +09001793 NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001794 return expectCapabilitiesWithout(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001795 }
1796
1797 NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent,
1798 int timeoutMs) {
1799 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001800 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1801 assertFalse(nc.hasCapability(capability));
Lorenzo Colitti27334542018-01-12 16:22:21 +09001802 return nc;
Paul Jensen3d911462015-06-12 06:40:24 -04001803 }
1804
Chalard Jean0b214af2018-01-12 17:22:49 +09001805 void expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent) {
1806 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001807 assertTrue("Received capabilities don't match expectations : " + cbi.arg,
1808 fn.test((NetworkCapabilities) cbi.arg));
Chalard Jean0b214af2018-01-12 17:22:49 +09001809 }
1810
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09001811 void expectLinkPropertiesLike(Predicate<LinkProperties> fn, MockNetworkAgent agent) {
1812 CallbackInfo cbi = expectCallback(CallbackState.LINK_PROPERTIES, agent);
1813 assertTrue("Received LinkProperties don't match expectations : " + cbi.arg,
1814 fn.test((LinkProperties) cbi.arg));
1815 }
1816
Mike Yuf9729752018-08-17 15:22:05 +08001817 void expectBlockedStatusCallback(boolean expectBlocked, MockNetworkAgent agent) {
1818 CallbackInfo cbi = expectCallback(CallbackState.BLOCKED_STATUS, agent);
1819 boolean actualBlocked = (boolean) cbi.arg;
1820 assertEquals(expectBlocked, actualBlocked);
1821 }
1822
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001823 void assertNoCallback() {
Hugo Benichibb91c572017-05-22 10:44:02 +09001824 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001825 CallbackInfo c = mCallbacks.peek();
1826 assertNull("Unexpected callback: " + c, c);
1827 }
1828 }
1829
1830 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1831 // only be declared in a static or top level type".
1832 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1833 for (TestNetworkCallback c : callbacks) {
1834 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001835 }
1836 }
1837
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001838 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001839 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001840 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001841 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1842 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001843 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1844 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001845 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1846 .addTransportType(TRANSPORT_WIFI).build();
1847 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1848 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001849 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001850 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1851 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1852
1853 // Test unvalidated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001854 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1855 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1856 mCellNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001857 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1858 cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001859 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1860 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001861 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001862
Paul Jensen3d911462015-06-12 06:40:24 -04001863 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1864 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001865 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001866 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001867 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1868
Paul Jensen3d911462015-06-12 06:40:24 -04001869 cv = waitForConnectivityBroadcasts(2);
1870 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1871 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001872 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1873 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001874 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1875 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(2);
1879 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001880 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1881 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001882 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001883 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001884 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001885
Paul Jensen3d911462015-06-12 06:40:24 -04001886 cv = waitForConnectivityBroadcasts(1);
1887 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001888 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1889 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001890 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001891 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001892
1893 // Test validated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001894 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1895 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001896 genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1897 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001898 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001899 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001900
Paul Jensen3d911462015-06-12 06:40:24 -04001901 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1902 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001903 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001904 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001905 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1906
Paul Jensen3d911462015-06-12 06:40:24 -04001907 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1908 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001909 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001910 genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001911 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001912 wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001913 cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001914 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001915 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001916
Paul Jensen3d911462015-06-12 06:40:24 -04001917 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001918 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1919 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1920 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001921
Paul Jensen3d911462015-06-12 06:40:24 -04001922 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001923 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1924 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1925 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001926 }
1927
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001928 @Test
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001929 public void testMultipleLingering() {
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001930 // This test would be flaky with the default 120ms timer: that is short enough that
1931 // lingered networks are torn down before assertions can be run. We don't want to mock the
1932 // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
1933 // in detecting races.
1934 mService.mLingerDelayMs = 300;
1935
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001936 NetworkRequest request = new NetworkRequest.Builder()
1937 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1938 .build();
1939 TestNetworkCallback callback = new TestNetworkCallback();
1940 mCm.registerNetworkCallback(request, callback);
1941
1942 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1943 mCm.registerDefaultNetworkCallback(defaultCallback);
1944
1945 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1946 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1947 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
1948
1949 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1950 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1951 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1952
1953 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001954 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1955 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001956 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001957 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001958
1959 mWiFiNetworkAgent.connect(true);
1960 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1961 // We then get LOSING when wifi validates and cell is outscored.
Lorenzo Colitti27334542018-01-12 16:22:21 +09001962 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001963 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001964 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001965 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001966 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001967 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001968 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001969
1970 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001971 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001972 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001973 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001974 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001975 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001976 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001977 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001978
1979 mEthernetNetworkAgent.disconnect();
1980 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1981 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001982 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001983 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001984
1985 for (int i = 0; i < 4; i++) {
1986 MockNetworkAgent oldNetwork, newNetwork;
1987 if (i % 2 == 0) {
1988 mWiFiNetworkAgent.adjustScore(-15);
1989 oldNetwork = mWiFiNetworkAgent;
1990 newNetwork = mCellNetworkAgent;
1991 } else {
1992 mWiFiNetworkAgent.adjustScore(15);
1993 oldNetwork = mCellNetworkAgent;
1994 newNetwork = mWiFiNetworkAgent;
1995
1996 }
1997 callback.expectCallback(CallbackState.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001998 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1999 // longer lingering?
Lorenzo Colitti27334542018-01-12 16:22:21 +09002000 defaultCallback.expectAvailableCallbacksValidated(newNetwork);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002001 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
2002 }
2003 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2004
2005 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
2006 // if the network is still up.
2007 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
Erik Kline1d3db322017-02-28 16:20:20 +09002008 // We expect a notification about the capabilities change, and nothing else.
2009 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
2010 defaultCallback.assertNoCallback();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002011 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002012 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002013
2014 // Wifi no longer satisfies our listen, which is for an unmetered network.
2015 // But because its score is 55, it's still up (and the default network).
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002016 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2017
2018 // Disconnect our test networks.
2019 mWiFiNetworkAgent.disconnect();
2020 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002021 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002022 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002023 mCellNetworkAgent.disconnect();
2024 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002025 waitForIdle();
2026 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002027
2028 mCm.unregisterNetworkCallback(callback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002029 waitForIdle();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002030
2031 // Check that a network is only lingered or torn down if it would not satisfy a request even
2032 // if it validated.
2033 request = new NetworkRequest.Builder().clearCapabilities().build();
2034 callback = new TestNetworkCallback();
2035
2036 mCm.registerNetworkCallback(request, callback);
2037
2038 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2039 mCellNetworkAgent.connect(false); // Score: 10
Lorenzo Colitti27334542018-01-12 16:22:21 +09002040 callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2041 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002042 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002043 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002044
2045 // Bring up wifi with a score of 20.
2046 // Cell stays up because it would satisfy the default request if it validated.
2047 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2048 mWiFiNetworkAgent.connect(false); // Score: 20
Lorenzo Colitti27334542018-01-12 16:22:21 +09002049 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2050 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002051 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002052 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002053
2054 mWiFiNetworkAgent.disconnect();
2055 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2056 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002057 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002058 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002059 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002060
2061 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002062 // Cell is lingered because it would not satisfy any request, even if it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002063 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2064 mWiFiNetworkAgent.adjustScore(50);
2065 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti27334542018-01-12 16:22:21 +09002066 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002067 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002068 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002069 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002070 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002071
2072 // Tear down wifi.
2073 mWiFiNetworkAgent.disconnect();
2074 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2075 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002076 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002077 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002078 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002079
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002080 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
2081 // it's arguably correct to linger it, since it was the default network before it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002082 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2083 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002084 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002085 // TODO: Investigate sending validated before losing.
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002086 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002087 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002088 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002089 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002090 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002091
2092 mWiFiNetworkAgent.disconnect();
2093 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002094 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002095 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002096 mCellNetworkAgent.disconnect();
2097 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2098 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002099 waitForIdle();
2100 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002101
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002102 // If a network is lingering, and we add and remove a request from it, resume lingering.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002103 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2104 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002105 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2106 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002107 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002108 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2109 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002110 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2111 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002112 // TODO: Investigate sending validated before losing.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002113 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002114 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002115 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002116
2117 NetworkRequest cellRequest = new NetworkRequest.Builder()
2118 .addTransportType(TRANSPORT_CELLULAR).build();
2119 NetworkCallback noopCallback = new NetworkCallback();
2120 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002121 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
2122 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002123 mCm.unregisterNetworkCallback(noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002124 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002125
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002126 // Similar to the above: lingering can start even after the lingered request is removed.
2127 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002128 mWiFiNetworkAgent.disconnect();
2129 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002130 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002131 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002132 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002133
2134 // Cell is now the default network. Pin it with a cell-specific request.
2135 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
2136 mCm.requestNetwork(cellRequest, noopCallback);
2137
2138 // Now connect wifi, and expect it to become the default network.
2139 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2140 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002141 callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
2142 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002143 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002144 // The default request is lingering on cell, but nothing happens to cell, and we send no
2145 // callbacks for it, because it's kept up by cellRequest.
2146 callback.assertNoCallback();
2147 // Now unregister cellRequest and expect cell to start lingering.
2148 mCm.unregisterNetworkCallback(noopCallback);
2149 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2150
2151 // Let linger run its course.
2152 callback.assertNoCallback();
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09002153 final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
Hugo Benichidfb559a2016-12-20 14:57:49 +09002154 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002155
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002156 // Register a TRACK_DEFAULT request and check that it does not affect lingering.
2157 TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
2158 mCm.registerDefaultNetworkCallback(trackDefaultCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002159 trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002160 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2161 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002162 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002163 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
2164 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002165 trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
2166 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002167 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002168
2169 // Let linger run its course.
2170 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
2171
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002172 // Clean up.
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002173 mEthernetNetworkAgent.disconnect();
2174 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2175 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2176 trackDefaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002177
2178 mCm.unregisterNetworkCallback(callback);
2179 mCm.unregisterNetworkCallback(defaultCallback);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002180 mCm.unregisterNetworkCallback(trackDefaultCallback);
2181 }
2182
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002183 @Test
Chalard Jean1fa777d2018-02-16 16:07:53 +09002184 public void testNetworkGoesIntoBackgroundAfterLinger() {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002185 setAlwaysOnNetworks(true);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002186 NetworkRequest request = new NetworkRequest.Builder()
2187 .clearCapabilities()
2188 .build();
2189 TestNetworkCallback callback = new TestNetworkCallback();
2190 mCm.registerNetworkCallback(request, callback);
2191
2192 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2193 mCm.registerDefaultNetworkCallback(defaultCallback);
2194
2195 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2196 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2197
2198 mCellNetworkAgent.connect(true);
2199 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2200 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2201
2202 // Wifi comes up and cell lingers.
2203 mWiFiNetworkAgent.connect(true);
2204 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2205 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2206 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2207 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2208
2209 // File a request for cellular, then release it.
2210 NetworkRequest cellRequest = new NetworkRequest.Builder()
2211 .addTransportType(TRANSPORT_CELLULAR).build();
2212 NetworkCallback noopCallback = new NetworkCallback();
2213 mCm.requestNetwork(cellRequest, noopCallback);
2214 mCm.unregisterNetworkCallback(noopCallback);
2215 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2216
2217 // Let linger run its course.
Chalard Jeanb72b62d2018-02-16 16:08:35 +09002218 callback.assertNoCallback();
Chalard Jean1fa777d2018-02-16 16:07:53 +09002219 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2220 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
2221 lingerTimeoutMs);
2222
2223 // Clean up.
2224 mCm.unregisterNetworkCallback(defaultCallback);
2225 mCm.unregisterNetworkCallback(callback);
2226 }
2227
2228 @Test
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002229 public void testExplicitlySelected() {
2230 NetworkRequest request = new NetworkRequest.Builder()
2231 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2232 .build();
2233 TestNetworkCallback callback = new TestNetworkCallback();
2234 mCm.registerNetworkCallback(request, callback);
2235
2236 // Bring up validated cell.
2237 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2238 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002239 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002240
2241 // Bring up unvalidated wifi with explicitlySelected=true.
2242 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2243 mWiFiNetworkAgent.explicitlySelected(false);
2244 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002245 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002246
2247 // Cell Remains the default.
2248 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2249
2250 // Lower wifi's score to below than cell, and check that it doesn't disconnect because
2251 // it's explicitly selected.
2252 mWiFiNetworkAgent.adjustScore(-40);
2253 mWiFiNetworkAgent.adjustScore(40);
2254 callback.assertNoCallback();
2255
2256 // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
2257 // wifi even though it's unvalidated.
2258 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
2259 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2260 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2261
2262 // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
2263 mWiFiNetworkAgent.disconnect();
2264 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2265 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2266 mWiFiNetworkAgent.explicitlySelected(false);
2267 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002268 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002269
2270 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
2271 // network to disconnect.
2272 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
2273 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2274
2275 // Reconnect, again with explicitlySelected=true, but this time validate.
2276 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2277 mWiFiNetworkAgent.explicitlySelected(false);
2278 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002279 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002280 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2281 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2282 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2283
2284 // BUG: the network will no longer linger, even though it's validated and outscored.
2285 // TODO: fix this.
2286 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2287 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002288 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002289 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2290 callback.assertNoCallback();
2291
2292 // Clean up.
2293 mWiFiNetworkAgent.disconnect();
2294 mCellNetworkAgent.disconnect();
2295 mEthernetNetworkAgent.disconnect();
2296
2297 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2298 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2299 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002300 }
2301
Paul Jensen85cf78e2015-06-25 13:25:07 -04002302 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04002303 // Verify NOT_RESTRICTED is set appropriately
2304 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
2305 .build().networkCapabilities;
2306 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
2307 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
2308 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04002309 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04002310 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2311 } else {
2312 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2313 }
2314
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002315 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002316 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002317 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
2318 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04002319 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002320 mServiceContext, "testFactory", filter);
2321 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04002322 ConditionVariable cv = testFactory.getNetworkStartedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002323 testFactory.expectAddRequests(1);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002324 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002325 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002326 int expectedRequestCount = 1;
2327 NetworkCallback networkCallback = null;
2328 // For non-INTERNET capabilities we cannot rely on the default request being present, so
2329 // add one.
2330 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04002331 assertFalse(testFactory.getMyStartRequested());
2332 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
2333 networkCallback = new NetworkCallback();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002334 testFactory.expectAddRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002335 mCm.requestNetwork(request, networkCallback);
2336 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002337 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002338 }
Paul Jensen3d911462015-06-12 06:40:24 -04002339 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002340 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2341 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002342
Paul Jensen85cf78e2015-06-25 13:25:07 -04002343 // Now bring in a higher scored network.
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002344 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002345 // Rather than create a validated network which complicates things by registering it's
2346 // own NetworkRequest during startup, just bump up the score to cancel out the
2347 // unvalidated penalty.
2348 testAgent.adjustScore(40);
2349 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002350
2351 // When testAgent connects, ConnectivityService will re-send us all current requests with
2352 // the new score. There are expectedRequestCount such requests, and we must wait for all of
2353 // them.
2354 testFactory.expectAddRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002355 testAgent.connect(false);
2356 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04002357 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002358 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002359 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002360
Paul Jensen85cf78e2015-06-25 13:25:07 -04002361 // Bring in a bunch of requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002362 testFactory.expectAddRequests(10);
2363 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002364 ConnectivityManager.NetworkCallback[] networkCallbacks =
2365 new ConnectivityManager.NetworkCallback[10];
2366 for (int i = 0; i< networkCallbacks.length; i++) {
2367 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
2368 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002369 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002370 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
2371 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002372 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
2373 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002374
Paul Jensen85cf78e2015-06-25 13:25:07 -04002375 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002376 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002377 for (int i = 0; i < networkCallbacks.length; i++) {
2378 mCm.unregisterNetworkCallback(networkCallbacks[i]);
2379 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002380 testFactory.waitForNetworkRequests(expectedRequestCount);
2381 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002382
Paul Jensen85cf78e2015-06-25 13:25:07 -04002383 // Drop the higher scored network.
2384 cv = testFactory.getNetworkStartedCV();
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002385 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04002386 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002387 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2388 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002389
2390 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002391 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002392 handlerThread.quit();
2393 }
2394
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002395 @Test
Paul Jensen85cf78e2015-06-25 13:25:07 -04002396 public void testNetworkFactoryRequests() throws Exception {
2397 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
2398 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
2399 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
2400 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
2401 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
2402 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
2403 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
2404 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
2405 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
2406 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
2407 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
2408 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
2409 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
2410 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
2411 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
2412 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
2413 }
2414
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002415 @Test
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002416 public void testNoMutableNetworkRequests() throws Exception {
2417 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
Hugo Benichi16f0a942017-06-20 14:07:59 +09002418 NetworkRequest request1 = new NetworkRequest.Builder()
2419 .addCapability(NET_CAPABILITY_VALIDATED)
2420 .build();
2421 NetworkRequest request2 = new NetworkRequest.Builder()
2422 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
2423 .build();
2424
2425 Class<IllegalArgumentException> expected = IllegalArgumentException.class;
2426 assertException(() -> { mCm.requestNetwork(request1, new NetworkCallback()); }, expected);
2427 assertException(() -> { mCm.requestNetwork(request1, pendingIntent); }, expected);
2428 assertException(() -> { mCm.requestNetwork(request2, new NetworkCallback()); }, expected);
2429 assertException(() -> { mCm.requestNetwork(request2, pendingIntent); }, expected);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002430 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002431
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002432 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002433 public void testMMSonWiFi() throws Exception {
2434 // Test bringing up cellular without MMS NetworkRequest gets reaped
2435 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2436 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2437 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
2438 mCellNetworkAgent.connectWithoutInternet();
2439 waitFor(cv);
Hugo Benichibb91c572017-05-22 10:44:02 +09002440 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09002441 assertEmpty(mCm.getAllNetworks());
Paul Jensene0988542015-06-25 15:30:08 -04002442 verifyNoNetwork();
Hugo Benichibb91c572017-05-22 10:44:02 +09002443
Paul Jensene0988542015-06-25 15:30:08 -04002444 // Test bringing up validated WiFi.
2445 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2446 cv = waitForConnectivityBroadcasts(1);
2447 mWiFiNetworkAgent.connect(true);
2448 waitFor(cv);
2449 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002450
Paul Jensene0988542015-06-25 15:30:08 -04002451 // Register MMS NetworkRequest
2452 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2453 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2454 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2455 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002456
Paul Jensene0988542015-06-25 15:30:08 -04002457 // Test bringing up unvalidated cellular with MMS
2458 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2459 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002460 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002461 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002462 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002463
Paul Jensene0988542015-06-25 15:30:08 -04002464 // Test releasing NetworkRequest disconnects cellular with MMS
2465 cv = mCellNetworkAgent.getDisconnectedCV();
2466 mCm.unregisterNetworkCallback(networkCallback);
2467 waitFor(cv);
2468 verifyActiveNetwork(TRANSPORT_WIFI);
2469 }
2470
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002471 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002472 public void testMMSonCell() throws Exception {
2473 // Test bringing up cellular without MMS
2474 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2475 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2476 mCellNetworkAgent.connect(false);
2477 waitFor(cv);
2478 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002479
Paul Jensene0988542015-06-25 15:30:08 -04002480 // Register MMS NetworkRequest
2481 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2482 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2483 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2484 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002485
Paul Jensene0988542015-06-25 15:30:08 -04002486 // Test bringing up MMS cellular network
Paul Jensene0988542015-06-25 15:30:08 -04002487 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2488 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2489 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002490 networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002491 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002492
Paul Jensene0988542015-06-25 15:30:08 -04002493 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
2494 cv = mmsNetworkAgent.getDisconnectedCV();
2495 mCm.unregisterNetworkCallback(networkCallback);
2496 waitFor(cv);
2497 verifyActiveNetwork(TRANSPORT_CELLULAR);
2498 }
2499
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002500 @Test
Paul Jensencf4c2c62015-07-01 14:16:32 -04002501 public void testCaptivePortal() {
2502 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2503 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2504 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2505 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2506
2507 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2508 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2509 .addCapability(NET_CAPABILITY_VALIDATED).build();
2510 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002511
2512 // Bring up a network with a captive portal.
2513 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002514 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002515 String firstRedirectUrl = "http://example.com/firstPath";
2516 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002517 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002518 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002519
2520 // Take down network.
2521 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002522 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002523 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002524
2525 // Bring up a network with a captive portal.
2526 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002527 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002528 String secondRedirectUrl = "http://example.com/secondPath";
2529 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002530 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002531 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002532
2533 // Make captive portal disappear then revalidate.
2534 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002535 mWiFiNetworkAgent.setNetworkValid();
Paul Jensencf4c2c62015-07-01 14:16:32 -04002536 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002537 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002538
2539 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002540 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002541
2542 // Break network connectivity.
2543 // Expect NET_CAPABILITY_VALIDATED onLost callback.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002544 mWiFiNetworkAgent.setNetworkInvalid();
Paul Jensencf4c2c62015-07-01 14:16:32 -04002545 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002546 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002547 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002548
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002549 @Test
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002550 public void testCaptivePortalApp() throws RemoteException {
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002551 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2552 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2553 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2554 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2555
2556 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2557 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2558 .addCapability(NET_CAPABILITY_VALIDATED).build();
2559 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2560
2561 // Bring up wifi.
2562 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2563 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002564 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002565 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2566
2567 // Check that calling startCaptivePortalApp does nothing.
2568 final int fastTimeoutMs = 100;
2569 mCm.startCaptivePortalApp(wifiNetwork);
2570 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
2571
2572 // Turn into a captive portal.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002573 mWiFiNetworkAgent.setNetworkPortal("http://example.com");
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002574 mCm.reportNetworkConnectivity(wifiNetwork, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002575 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002576 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2577
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002578 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002579 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002580 verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
2581 .launchCaptivePortalApp();
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002582
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002583 // Report that the captive portal is dismissed, and check that callbacks are fired
2584 mWiFiNetworkAgent.setNetworkValid();
2585 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
Lorenzo Colitti27334542018-01-12 16:22:21 +09002586 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002587 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2588
2589 mCm.unregisterNetworkCallback(validatedCallback);
2590 mCm.unregisterNetworkCallback(captivePortalCallback);
2591 }
2592
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002593 @Test
Calvin On1f64f3f2016-10-11 15:10:46 -07002594 public void testAvoidOrIgnoreCaptivePortals() {
2595 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2596 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2597 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2598 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2599
2600 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2601 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2602 .addCapability(NET_CAPABILITY_VALIDATED).build();
2603 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2604
2605 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
2606 // Bring up a network with a captive portal.
2607 // Expect it to fail to connect and not result in any callbacks.
2608 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2609 String firstRedirectUrl = "http://example.com/firstPath";
2610
2611 ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
2612 ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
2613 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
2614 waitFor(disconnectCv);
2615 waitFor(avoidCv);
2616
2617 assertNoCallbacks(captivePortalCallback, validatedCallback);
Calvin On1f64f3f2016-10-11 15:10:46 -07002618 }
2619
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002620 private NetworkRequest.Builder newWifiRequestBuilder() {
2621 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
2622 }
2623
Etan Cohen836ad572018-12-30 17:59:59 -08002624 /**
2625 * Verify request matching behavior with network specifiers.
2626 *
2627 * Note: this test is somewhat problematic since it involves removing capabilities from
2628 * agents - i.e. agents rejecting requests which they previously accepted. This is flagged
2629 * as a WTF bug in
2630 * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but
2631 * does work.
2632 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002633 @Test
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002634 public void testNetworkSpecifier() {
Etan Cohen836ad572018-12-30 17:59:59 -08002635 // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
2636 class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
2637 Parcelable {
2638 @Override
2639 public boolean satisfiedBy(NetworkSpecifier other) {
2640 return true;
2641 }
2642
2643 @Override
2644 public int describeContents() {
2645 return 0;
2646 }
2647
2648 @Override
2649 public void writeToParcel(Parcel dest, int flags) {}
2650
2651 @Override
2652 public NetworkSpecifier redact() {
2653 return null;
2654 }
2655 }
2656
2657 // A network specifier that matches either another LocalNetworkSpecifier with the same
2658 // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
2659 class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2660 private String mString;
2661
2662 LocalStringNetworkSpecifier(String string) {
2663 mString = string;
2664 }
2665
2666 @Override
2667 public boolean satisfiedBy(NetworkSpecifier other) {
2668 if (other instanceof LocalStringNetworkSpecifier) {
2669 return TextUtils.equals(mString,
2670 ((LocalStringNetworkSpecifier) other).mString);
2671 }
2672 if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
2673 return false;
2674 }
2675
2676 @Override
2677 public int describeContents() {
2678 return 0;
2679 }
2680 @Override
2681 public void writeToParcel(Parcel dest, int flags) {}
2682 }
2683
2684
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002685 NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
Etan Cohena7434272017-04-03 12:17:51 -07002686 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002687 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
Etan Cohena7434272017-04-03 12:17:51 -07002688 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
2689 (NetworkSpecifier) null).build();
Etan Cohen836ad572018-12-30 17:59:59 -08002690 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
2691 new LocalStringNetworkSpecifier("foo")).build();
Etan Cohena7434272017-04-03 12:17:51 -07002692 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
Etan Cohen836ad572018-12-30 17:59:59 -08002693 new LocalStringNetworkSpecifier("bar")).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002694
2695 TestNetworkCallback cEmpty1 = new TestNetworkCallback();
2696 TestNetworkCallback cEmpty2 = new TestNetworkCallback();
2697 TestNetworkCallback cEmpty3 = new TestNetworkCallback();
Etan Cohena7434272017-04-03 12:17:51 -07002698 TestNetworkCallback cEmpty4 = new TestNetworkCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002699 TestNetworkCallback cFoo = new TestNetworkCallback();
2700 TestNetworkCallback cBar = new TestNetworkCallback();
2701 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
Etan Cohen836ad572018-12-30 17:59:59 -08002702 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002703
2704 mCm.registerNetworkCallback(rEmpty1, cEmpty1);
2705 mCm.registerNetworkCallback(rEmpty2, cEmpty2);
2706 mCm.registerNetworkCallback(rEmpty3, cEmpty3);
Etan Cohena7434272017-04-03 12:17:51 -07002707 mCm.registerNetworkCallback(rEmpty4, cEmpty4);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002708 mCm.registerNetworkCallback(rFoo, cFoo);
2709 mCm.registerNetworkCallback(rBar, cBar);
2710
Etan Cohen836ad572018-12-30 17:59:59 -08002711 LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
2712 LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
2713
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002714 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2715 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002716 cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2717 cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2718 cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2719 cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002720 assertNoCallbacks(cFoo, cBar);
2721
Etan Cohen836ad572018-12-30 17:59:59 -08002722 mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002723 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002724 for (TestNetworkCallback c: emptyCallbacks) {
Etan Cohen836ad572018-12-30 17:59:59 -08002725 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
2726 mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002727 }
Etan Cohen836ad572018-12-30 17:59:59 -08002728 cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
2729 mWiFiNetworkAgent);
2730 assertEquals(nsFoo,
2731 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002732 cFoo.assertNoCallback();
2733
Etan Cohen836ad572018-12-30 17:59:59 -08002734 mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002735 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002736 cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002737 for (TestNetworkCallback c: emptyCallbacks) {
Etan Cohen836ad572018-12-30 17:59:59 -08002738 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
2739 mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002740 }
Etan Cohen836ad572018-12-30 17:59:59 -08002741 cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
2742 mWiFiNetworkAgent);
2743 assertEquals(nsBar,
2744 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
2745 cBar.assertNoCallback();
2746
2747 mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
2748 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2749 for (TestNetworkCallback c : emptyCallbacks) {
2750 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
2751 mWiFiNetworkAgent);
2752 }
2753 cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
2754 mWiFiNetworkAgent);
2755 cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
2756 mWiFiNetworkAgent);
2757 assertNull(
2758 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
2759 cFoo.assertNoCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002760 cBar.assertNoCallback();
2761
2762 mWiFiNetworkAgent.setNetworkSpecifier(null);
Etan Cohen836ad572018-12-30 17:59:59 -08002763 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002764 cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2765 for (TestNetworkCallback c: emptyCallbacks) {
2766 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
2767 }
2768
Etan Cohen836ad572018-12-30 17:59:59 -08002769 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002770 }
2771
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002772 @Test
Etan Cohenddb9ef02015-11-18 10:56:15 -08002773 public void testInvalidNetworkSpecifier() {
Etan Cohenddb9ef02015-11-18 10:56:15 -08002774 try {
2775 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Etan Cohena7434272017-04-03 12:17:51 -07002776 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
2777 fail("NetworkRequest builder with MatchAllNetworkSpecifier");
2778 } catch (IllegalArgumentException expected) {
2779 // expected
Etan Cohenddb9ef02015-11-18 10:56:15 -08002780 }
2781
Etan Cohenddb9ef02015-11-18 10:56:15 -08002782 try {
2783 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
2784 networkCapabilities.addTransportType(TRANSPORT_WIFI)
Etan Cohena7434272017-04-03 12:17:51 -07002785 .setNetworkSpecifier(new MatchAllNetworkSpecifier());
Etan Cohenddb9ef02015-11-18 10:56:15 -08002786 mService.requestNetwork(networkCapabilities, null, 0, null,
2787 ConnectivityManager.TYPE_WIFI);
Etan Cohena7434272017-04-03 12:17:51 -07002788 fail("ConnectivityService requestNetwork with MatchAllNetworkSpecifier");
2789 } catch (IllegalArgumentException expected) {
2790 // expected
Etan Cohenddb9ef02015-11-18 10:56:15 -08002791 }
2792
Etan Cohena7434272017-04-03 12:17:51 -07002793 class NonParcelableSpecifier extends NetworkSpecifier {
2794 public boolean satisfiedBy(NetworkSpecifier other) { return false; }
2795 };
2796 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
2797 @Override public int describeContents() { return 0; }
2798 @Override public void writeToParcel(Parcel p, int flags) {}
2799 }
2800 NetworkRequest.Builder builder;
2801
2802 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
2803 try {
2804 builder.setNetworkSpecifier(new NonParcelableSpecifier());
2805 Parcel parcelW = Parcel.obtain();
2806 builder.build().writeToParcel(parcelW, 0);
2807 fail("Parceling a non-parcelable specifier did not throw an exception");
2808 } catch (Exception e) {
2809 // expected
2810 }
2811
2812 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
2813 builder.setNetworkSpecifier(new ParcelableSpecifier());
2814 NetworkRequest nr = builder.build();
2815 assertNotNull(nr);
2816
2817 try {
2818 Parcel parcelW = Parcel.obtain();
2819 nr.writeToParcel(parcelW, 0);
2820 byte[] bytes = parcelW.marshall();
2821 parcelW.recycle();
2822
2823 Parcel parcelR = Parcel.obtain();
2824 parcelR.unmarshall(bytes, 0, bytes.length);
2825 parcelR.setDataPosition(0);
2826 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
2827 fail("Unparceling a non-framework NetworkSpecifier did not throw an exception");
2828 } catch (Exception e) {
2829 // expected
2830 }
Etan Cohenddb9ef02015-11-18 10:56:15 -08002831 }
2832
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002833 @Test
Etan Cohen859748f2017-04-03 17:42:34 -07002834 public void testNetworkSpecifierUidSpoofSecurityException() {
2835 class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2836 @Override
2837 public boolean satisfiedBy(NetworkSpecifier other) {
2838 return true;
2839 }
2840
2841 @Override
2842 public void assertValidFromUid(int requestorUid) {
2843 throw new SecurityException("failure");
2844 }
2845
2846 @Override
2847 public int describeContents() { return 0; }
2848 @Override
2849 public void writeToParcel(Parcel dest, int flags) {}
2850 }
2851
2852 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2853 mWiFiNetworkAgent.connect(false);
2854
2855 UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
2856 NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier(
2857 networkSpecifier).build();
2858 TestNetworkCallback networkCallback = new TestNetworkCallback();
2859 try {
2860 mCm.requestNetwork(networkRequest, networkCallback);
2861 fail("Network request with spoofed UID did not throw a SecurityException");
2862 } catch (SecurityException e) {
2863 // expected
2864 }
2865 }
2866
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002867 @Test
Erik Klinea2d29402016-03-16 15:31:39 +09002868 public void testRegisterDefaultNetworkCallback() throws Exception {
2869 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
2870 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
2871 defaultNetworkCallback.assertNoCallback();
2872
2873 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
2874 // whenever Wi-Fi is up. Without this, the mobile network agent is
2875 // reaped before any other activity can take place.
2876 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2877 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2878 .addTransportType(TRANSPORT_CELLULAR).build();
2879 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2880 cellNetworkCallback.assertNoCallback();
2881
2882 // Bring up cell and expect CALLBACK_AVAILABLE.
2883 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2884 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002885 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2886 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002887 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002888
2889 // Bring up wifi and expect CALLBACK_AVAILABLE.
2890 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2891 mWiFiNetworkAgent.connect(true);
2892 cellNetworkCallback.assertNoCallback();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002893 defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002894 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002895
2896 // Bring down cell. Expect no default network callback, since it wasn't the default.
2897 mCellNetworkAgent.disconnect();
2898 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2899 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002900 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002901
2902 // Bring up cell. Expect no default network callback, since it won't be the default.
2903 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2904 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002905 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002906 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002907 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002908
2909 // Bring down wifi. Expect the default network callback to notified of LOST wifi
2910 // followed by AVAILABLE cell.
2911 mWiFiNetworkAgent.disconnect();
2912 cellNetworkCallback.assertNoCallback();
2913 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002914 defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002915 mCellNetworkAgent.disconnect();
2916 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2917 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002918 waitForIdle();
2919 assertEquals(null, mCm.getActiveNetwork());
2920
2921 final int uid = Process.myUid();
2922 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
2923 final ArraySet<UidRange> ranges = new ArraySet<>();
2924 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09002925 mMockVpn.setNetworkAgent(vpnNetworkAgent);
2926 mMockVpn.setUids(ranges);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002927 vpnNetworkAgent.connect(true);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09002928 mMockVpn.connect();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002929 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
2930 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2931
2932 vpnNetworkAgent.disconnect();
2933 defaultNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
2934 waitForIdle();
2935 assertEquals(null, mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002936 }
2937
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002938 @Test
Erik Kline1d3db322017-02-28 16:20:20 +09002939 public void testAdditionalStateCallbacks() throws Exception {
Erik Klineacdd6392016-07-07 16:50:58 +09002940 // File a network request for mobile.
Erik Kline1d3db322017-02-28 16:20:20 +09002941 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09002942 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2943 .addTransportType(TRANSPORT_CELLULAR).build();
2944 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2945
2946 // Bring up the mobile network.
2947 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2948 mCellNetworkAgent.connect(true);
2949
Erik Kline1d3db322017-02-28 16:20:20 +09002950 // We should get onAvailable(), onCapabilitiesChanged(), and
2951 // onLinkPropertiesChanged() in rapid succession. Additionally, we
2952 // should get onCapabilitiesChanged() when the mobile network validates.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002953 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09002954 cellNetworkCallback.assertNoCallback();
2955
2956 // Update LinkProperties.
2957 final LinkProperties lp = new LinkProperties();
2958 lp.setInterfaceName("foonet_data0");
2959 mCellNetworkAgent.sendLinkProperties(lp);
2960 // We should get onLinkPropertiesChanged().
2961 cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
2962 cellNetworkCallback.assertNoCallback();
2963
Erik Kline1d3db322017-02-28 16:20:20 +09002964 // Suspend the network.
2965 mCellNetworkAgent.suspend();
Chalard Jean804b8fb2018-01-30 22:41:41 +09002966 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
2967 mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002968 cellNetworkCallback.expectCallback(CallbackState.SUSPENDED, mCellNetworkAgent);
2969 cellNetworkCallback.assertNoCallback();
2970
Erik Klineacdd6392016-07-07 16:50:58 +09002971 // Register a garden variety default network request.
Chalard Jean804b8fb2018-01-30 22:41:41 +09002972 TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09002973 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09002974 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
2975 // as well as onNetworkSuspended() in rapid succession.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002976 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
Erik Klineacdd6392016-07-07 16:50:58 +09002977 dfltNetworkCallback.assertNoCallback();
Chalard Jean804b8fb2018-01-30 22:41:41 +09002978 mCm.unregisterNetworkCallback(dfltNetworkCallback);
2979
2980 mCellNetworkAgent.resume();
2981 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
2982 mCellNetworkAgent);
2983 cellNetworkCallback.expectCallback(CallbackState.RESUMED, mCellNetworkAgent);
2984 cellNetworkCallback.assertNoCallback();
2985
2986 dfltNetworkCallback = new TestNetworkCallback();
2987 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
2988 // This time onNetworkSuspended should not be called.
2989 dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
2990 dfltNetworkCallback.assertNoCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09002991
Erik Klineacdd6392016-07-07 16:50:58 +09002992 mCm.unregisterNetworkCallback(dfltNetworkCallback);
2993 mCm.unregisterNetworkCallback(cellNetworkCallback);
2994 }
2995
Calvin On1f64f3f2016-10-11 15:10:46 -07002996 private void setCaptivePortalMode(int mode) {
2997 ContentResolver cr = mServiceContext.getContentResolver();
2998 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
2999 }
3000
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003001 private void setAlwaysOnNetworks(boolean enable) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003002 ContentResolver cr = mServiceContext.getContentResolver();
3003 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003004 mService.updateAlwaysOnNetworks();
Hugo Benichibb91c572017-05-22 10:44:02 +09003005 waitForIdle();
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003006 }
3007
Erik Kline79c6d052018-03-21 07:18:33 -07003008 private void setPrivateDnsSettings(String mode, String specifier) {
3009 final ContentResolver cr = mServiceContext.getContentResolver();
3010 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
3011 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
3012 mService.updatePrivateDnsSettings();
3013 waitForIdle();
3014 }
3015
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003016 private boolean isForegroundNetwork(MockNetworkAgent network) {
3017 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
3018 assertNotNull(nc);
3019 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
3020 }
3021
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003022 @Test
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003023 public void testBackgroundNetworks() throws Exception {
3024 // Create a background request. We can't do this ourselves because ConnectivityService
3025 // doesn't have an API for it. So just turn on mobile data always on.
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003026 setAlwaysOnNetworks(true);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003027 final NetworkRequest request = new NetworkRequest.Builder().build();
3028 final NetworkRequest fgRequest = new NetworkRequest.Builder()
3029 .addCapability(NET_CAPABILITY_FOREGROUND).build();
3030 final TestNetworkCallback callback = new TestNetworkCallback();
3031 final TestNetworkCallback fgCallback = new TestNetworkCallback();
3032 mCm.registerNetworkCallback(request, callback);
3033 mCm.registerNetworkCallback(fgRequest, fgCallback);
3034
3035 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3036 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003037 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3038 fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003039 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3040
3041 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3042 mWiFiNetworkAgent.connect(true);
3043
3044 // When wifi connects, cell lingers.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003045 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003046 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003047 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003048 fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003049 fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003050 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003051 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3052 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3053
3054 // When lingering is complete, cell is still there but is now in the background.
Hugo Benichibb91c572017-05-22 10:44:02 +09003055 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003056 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
3057 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09003058 // Expect a network capabilities update sans FOREGROUND.
3059 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003060 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3061 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3062
3063 // File a cell request and check that cell comes into the foreground.
3064 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3065 .addTransportType(TRANSPORT_CELLULAR).build();
3066 final TestNetworkCallback cellCallback = new TestNetworkCallback();
3067 mCm.requestNetwork(cellRequest, cellCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09003068 // NOTE: This request causes the network's capabilities to change. This
3069 // is currently delivered before the onAvailable() callbacks.
3070 // TODO: Fix this.
3071 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003072 cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3073 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003074 // Expect a network capabilities update with FOREGROUND, because the most recent
3075 // request causes its state to change.
3076 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003077 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3078 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3079
3080 // Release the request. The network immediately goes into the background, since it was not
3081 // lingering.
3082 mCm.unregisterNetworkCallback(cellCallback);
3083 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003084 // Expect a network capabilities update sans FOREGROUND.
3085 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003086 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3087 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3088
3089 // Disconnect wifi and check that cell is foreground again.
3090 mWiFiNetworkAgent.disconnect();
3091 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3092 fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003093 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003094 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3095
3096 mCm.unregisterNetworkCallback(callback);
3097 mCm.unregisterNetworkCallback(fgCallback);
3098 }
3099
Hugo Benichi849b81b2017-05-25 13:42:31 +09003100 @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003101 public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003102 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003103 // Benchmarks connecting and switching performance in the presence of a large number of
3104 // NetworkRequests.
3105 // 1. File NUM_REQUESTS requests.
3106 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
3107 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
3108 // and NUM_REQUESTS onAvailable callbacks to fire.
3109 // See how long it took.
3110 final int NUM_REQUESTS = 90;
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003111 final int REGISTER_TIME_LIMIT_MS = 200;
3112 final int CONNECT_TIME_LIMIT_MS = 60;
3113 final int SWITCH_TIME_LIMIT_MS = 60;
Hugo Benichibb91c572017-05-22 10:44:02 +09003114 final int UNREGISTER_TIME_LIMIT_MS = 20;
3115
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003116 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
3117 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
3118 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
3119 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
3120
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003121 for (int i = 0; i < NUM_REQUESTS; i++) {
3122 callbacks[i] = new NetworkCallback() {
3123 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
3124 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
3125 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003126 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003127
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003128 assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
3129 for (NetworkCallback cb : callbacks) {
3130 mCm.registerNetworkCallback(request, cb);
3131 }
3132 });
3133
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003134 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3135 // Don't request that the network validate, because otherwise connect() will block until
3136 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
3137 // and we won't actually measure anything.
3138 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003139
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003140 long onAvailableDispatchingDuration = durationOf(() -> {
Hugo Benichibb91c572017-05-22 10:44:02 +09003141 awaitLatch(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003142 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003143 Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
3144 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
3145 onAvailableDispatchingDuration));
3146 assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
3147 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
3148 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003149
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003150 // Give wifi a high enough score that we'll linger cell when wifi comes up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003151 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003152 mWiFiNetworkAgent.adjustScore(40);
3153 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003154
3155 long onLostDispatchingDuration = durationOf(() -> {
Hugo Benichibb91c572017-05-22 10:44:02 +09003156 awaitLatch(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003157 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003158 Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
3159 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
3160 assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
3161 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
3162 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003163
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003164 assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
3165 for (NetworkCallback cb : callbacks) {
3166 mCm.unregisterNetworkCallback(cb);
3167 }
3168 });
3169 }
3170
3171 private long durationOf(Runnable fn) {
3172 long startTime = SystemClock.elapsedRealtime();
3173 fn.run();
3174 return SystemClock.elapsedRealtime() - startTime;
3175 }
3176
3177 private void assertTimeLimit(String descr, long timeLimit, Runnable fn) {
3178 long timeTaken = durationOf(fn);
3179 String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003180 Log.d(TAG, msg);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003181 assertTrue(msg, timeTaken <= timeLimit);
3182 }
3183
3184 private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
3185 try {
Hugo Benichibb91c572017-05-22 10:44:02 +09003186 return l.await(timeoutMs, TimeUnit.MILLISECONDS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003187 } catch (InterruptedException e) {}
3188 return false;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003189 }
3190
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003191 @Test
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003192 public void testMobileDataAlwaysOn() throws Exception {
3193 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3194 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3195 .addTransportType(TRANSPORT_CELLULAR).build();
3196 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3197
3198 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
3199 handlerThread.start();
3200 NetworkCapabilities filter = new NetworkCapabilities()
3201 .addTransportType(TRANSPORT_CELLULAR)
3202 .addCapability(NET_CAPABILITY_INTERNET);
3203 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3204 mServiceContext, "testFactory", filter);
3205 testFactory.setScoreFilter(40);
3206
3207 // Register the factory and expect it to start looking for a network.
3208 testFactory.expectAddRequests(1);
3209 testFactory.register();
3210 testFactory.waitForNetworkRequests(1);
3211 assertTrue(testFactory.getMyStartRequested());
3212
3213 // Bring up wifi. The factory stops looking for a network.
3214 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3215 testFactory.expectAddRequests(2); // Because the default request changes score twice.
3216 mWiFiNetworkAgent.connect(true);
3217 testFactory.waitForNetworkRequests(1);
3218 assertFalse(testFactory.getMyStartRequested());
3219
3220 ContentResolver cr = mServiceContext.getContentResolver();
3221
3222 // Turn on mobile data always on. The factory starts looking again.
3223 testFactory.expectAddRequests(1);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003224 setAlwaysOnNetworks(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003225 testFactory.waitForNetworkRequests(2);
3226 assertTrue(testFactory.getMyStartRequested());
3227
3228 // Bring up cell data and check that the factory stops looking.
Hugo Benichifed512a2017-06-26 10:06:49 +09003229 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003230 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3231 testFactory.expectAddRequests(2); // Because the cell request changes score twice.
3232 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003233 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003234 testFactory.waitForNetworkRequests(2);
3235 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
3236
3237 // Check that cell data stays up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003238 waitForIdle();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003239 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09003240 assertLength(2, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003241
3242 // Turn off mobile data always on and expect the request to disappear...
3243 testFactory.expectRemoveRequests(1);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003244 setAlwaysOnNetworks(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003245 testFactory.waitForNetworkRequests(1);
3246
3247 // ... and cell data to be torn down.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003248 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Hugo Benichifed512a2017-06-26 10:06:49 +09003249 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003250
3251 testFactory.unregister();
3252 mCm.unregisterNetworkCallback(cellNetworkCallback);
3253 handlerThread.quit();
3254 }
3255
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003256 @Test
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003257 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003258 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09003259 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003260 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
3261
Erik Kline065ab6e2016-10-02 18:02:14 +09003262 tracker.configRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003263 String[] values = new String[] {null, "0", "1"};
3264 for (int i = 0; i < values.length; i++) {
3265 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003266 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003267 waitForIdle();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003268 String msg = String.format("config=false, setting=%s", values[i]);
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003269 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003270 assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003271 }
3272
Erik Kline065ab6e2016-10-02 18:02:14 +09003273 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003274
3275 Settings.Global.putInt(cr, settingName, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09003276 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003277 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003278 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003279 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003280
3281 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003282 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003283 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003284 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003285 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003286
3287 Settings.Global.putString(cr, settingName, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09003288 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003289 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003290 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003291 assertTrue(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003292 }
3293
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003294 @Test
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003295 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09003296 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09003297 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003298
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003299 // Pretend we're on a carrier that restricts switching away from bad wifi.
Erik Kline065ab6e2016-10-02 18:02:14 +09003300 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003301
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003302 // File a request for cell to ensure it doesn't go down.
3303 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3304 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3305 .addTransportType(TRANSPORT_CELLULAR).build();
3306 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3307
3308 TestNetworkCallback defaultCallback = new TestNetworkCallback();
3309 mCm.registerDefaultNetworkCallback(defaultCallback);
3310
3311 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
3312 .addTransportType(TRANSPORT_WIFI)
3313 .addCapability(NET_CAPABILITY_VALIDATED)
3314 .build();
3315 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
3316 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
3317
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003318 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09003319 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003320
3321 // Bring up validated cell.
3322 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3323 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003324 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3325 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003326 Network cellNetwork = mCellNetworkAgent.getNetwork();
3327
3328 // Bring up validated wifi.
3329 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3330 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003331 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3332 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003333 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
3334
3335 // Fail validation on wifi.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09003336 mWiFiNetworkAgent.setNetworkInvalid();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003337 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003338 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003339 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3340
3341 // Because avoid bad wifi is off, we don't switch to cellular.
3342 defaultCallback.assertNoCallback();
3343 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3344 NET_CAPABILITY_VALIDATED));
3345 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3346 NET_CAPABILITY_VALIDATED));
3347 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3348
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003349 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
3350 // that we switch back to cell.
Erik Kline065ab6e2016-10-02 18:02:14 +09003351 tracker.configRestrictsAvoidBadWifi = false;
3352 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003353 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003354 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3355
3356 // Switch back to a restrictive carrier.
Erik Kline065ab6e2016-10-02 18:02:14 +09003357 tracker.configRestrictsAvoidBadWifi = true;
3358 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003359 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003360 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3361
3362 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
3363 mCm.setAvoidUnvalidated(wifiNetwork);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003364 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003365 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3366 NET_CAPABILITY_VALIDATED));
3367 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3368 NET_CAPABILITY_VALIDATED));
3369 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3370
3371 // Disconnect and reconnect wifi to clear the one-time switch above.
3372 mWiFiNetworkAgent.disconnect();
3373 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3374 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003375 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3376 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003377 wifiNetwork = mWiFiNetworkAgent.getNetwork();
3378
3379 // Fail validation on wifi and expect the dialog to appear.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09003380 mWiFiNetworkAgent.setNetworkInvalid();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003381 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003382 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003383 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3384
3385 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003386 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003387 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003388
3389 // We now switch to cell.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003390 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003391 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3392 NET_CAPABILITY_VALIDATED));
3393 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3394 NET_CAPABILITY_VALIDATED));
3395 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3396
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003397 // Simulate the user turning the cellular fallback setting off and then on.
3398 // We switch to wifi and then to cell.
3399 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09003400 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003401 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003402 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3403 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003404 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003405 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003406 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3407
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003408 // If cell goes down, we switch to wifi.
3409 mCellNetworkAgent.disconnect();
3410 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003411 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003412 validatedWifiCallback.assertNoCallback();
3413
3414 mCm.unregisterNetworkCallback(cellNetworkCallback);
3415 mCm.unregisterNetworkCallback(validatedWifiCallback);
3416 mCm.unregisterNetworkCallback(defaultCallback);
3417 }
3418
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003419 @Test
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003420 public void testMeteredMultipathPreferenceSetting() throws Exception {
3421 final ContentResolver cr = mServiceContext.getContentResolver();
3422 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
3423 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
3424
3425 for (int config : Arrays.asList(0, 3, 2)) {
3426 for (String setting: Arrays.asList(null, "0", "2", "1")) {
3427 tracker.configMeteredMultipathPreference = config;
3428 Settings.Global.putString(cr, settingName, setting);
3429 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003430 waitForIdle();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003431
3432 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
3433 String msg = String.format("config=%d, setting=%s", config, setting);
3434 assertEquals(msg, expected, mCm.getMultipathPreference(null));
3435 }
3436 }
3437 }
3438
Erik Kline3841a482015-11-25 12:49:38 +09003439 /**
3440 * Validate that a satisfied network request does not trigger onUnavailable() once the
3441 * time-out period expires.
3442 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003443 @Test
Erik Kline3841a482015-11-25 12:49:38 +09003444 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
3445 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3446 NetworkCapabilities.TRANSPORT_WIFI).build();
3447 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003448 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003449
3450 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3451 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003452 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003453 TEST_CALLBACK_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003454
3455 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003456 networkCallback.assertNoCallback();
3457 }
3458
3459 /**
3460 * Validate that a satisfied network request followed by a disconnected (lost) network does
3461 * not trigger onUnavailable() once the time-out period expires.
3462 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003463 @Test
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003464 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
3465 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3466 NetworkCapabilities.TRANSPORT_WIFI).build();
3467 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003468 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003469
3470 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3471 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003472 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003473 TEST_CALLBACK_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003474 mWiFiNetworkAgent.disconnect();
3475 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3476
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003477 // Validate that UNAVAILABLE is not called
Erik Kline3841a482015-11-25 12:49:38 +09003478 networkCallback.assertNoCallback();
3479 }
3480
3481 /**
3482 * Validate that when a time-out is specified for a network request the onUnavailable()
3483 * callback is called when time-out expires. Then validate that if network request is
3484 * (somehow) satisfied - the callback isn't called later.
3485 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003486 @Test
Erik Kline3841a482015-11-25 12:49:38 +09003487 public void testTimedoutNetworkRequest() {
3488 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3489 NetworkCapabilities.TRANSPORT_WIFI).build();
3490 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003491 final int timeoutMs = 10;
3492 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003493
3494 // pass timeout and validate that UNAVAILABLE is called
3495 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
3496
3497 // create a network satisfying request - validate that request not triggered
3498 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3499 mWiFiNetworkAgent.connect(false);
3500 networkCallback.assertNoCallback();
3501 }
3502
3503 /**
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003504 * Validate that when a network request is unregistered (cancelled), no posterior event can
3505 * trigger the callback.
Erik Kline3841a482015-11-25 12:49:38 +09003506 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003507 @Test
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003508 public void testNoCallbackAfterUnregisteredNetworkRequest() {
Erik Kline3841a482015-11-25 12:49:38 +09003509 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3510 NetworkCapabilities.TRANSPORT_WIFI).build();
3511 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003512 final int timeoutMs = 10;
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003513
Hugo Benichidfb559a2016-12-20 14:57:49 +09003514 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003515 mCm.unregisterNetworkCallback(networkCallback);
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003516 // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
3517 // that this callback will not be called.
Erik Kline3841a482015-11-25 12:49:38 +09003518 networkCallback.assertNoCallback();
3519
3520 // create a network satisfying request - validate that request not triggered
3521 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3522 mWiFiNetworkAgent.connect(false);
3523 networkCallback.assertNoCallback();
3524 }
3525
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003526 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
3527
3528 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3529
3530 private class CallbackValue {
3531 public CallbackType callbackType;
3532 public int error;
3533
3534 public CallbackValue(CallbackType type) {
3535 this.callbackType = type;
3536 this.error = PacketKeepalive.SUCCESS;
3537 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3538 }
3539
3540 public CallbackValue(CallbackType type, int error) {
3541 this.callbackType = type;
3542 this.error = error;
3543 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3544 }
3545
3546 @Override
3547 public boolean equals(Object o) {
3548 return o instanceof CallbackValue &&
3549 this.callbackType == ((CallbackValue) o).callbackType &&
3550 this.error == ((CallbackValue) o).error;
3551 }
3552
3553 @Override
3554 public String toString() {
3555 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
3556 }
3557 }
3558
3559 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
3560
3561 @Override
3562 public void onStarted() {
3563 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3564 }
3565
3566 @Override
3567 public void onStopped() {
3568 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3569 }
3570
3571 @Override
3572 public void onError(int error) {
3573 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3574 }
3575
3576 private void expectCallback(CallbackValue callbackValue) {
3577 try {
3578 assertEquals(
3579 callbackValue,
3580 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3581 } catch (InterruptedException e) {
3582 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
3583 }
3584 }
3585
3586 public void expectStarted() {
3587 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3588 }
3589
3590 public void expectStopped() {
3591 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3592 }
3593
3594 public void expectError(int error) {
3595 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3596 }
3597 }
3598
junyulai48eac1d42018-12-27 17:25:29 +08003599 private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
3600
3601 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3602
3603 private class CallbackValue {
3604 public CallbackType callbackType;
3605 public int error;
3606
3607 CallbackValue(CallbackType type) {
3608 this.callbackType = type;
3609 this.error = SocketKeepalive.SUCCESS;
3610 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3611 }
3612
3613 CallbackValue(CallbackType type, int error) {
3614 this.callbackType = type;
3615 this.error = error;
3616 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3617 }
3618
3619 @Override
3620 public boolean equals(Object o) {
3621 return o instanceof CallbackValue
3622 && this.callbackType == ((CallbackValue) o).callbackType
3623 && this.error == ((CallbackValue) o).error;
3624 }
3625
3626 @Override
3627 public String toString() {
3628 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
3629 error);
3630 }
3631 }
3632
3633 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
3634
3635 @Override
3636 public void onStarted() {
3637 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3638 }
3639
3640 @Override
3641 public void onStopped() {
3642 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3643 }
3644
3645 @Override
3646 public void onError(int error) {
3647 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3648 }
3649
3650 private void expectCallback(CallbackValue callbackValue) {
3651 try {
3652 assertEquals(
3653 callbackValue,
3654 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3655 } catch (InterruptedException e) {
3656 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
3657 }
3658 }
3659
3660 public void expectStarted() {
3661 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3662 }
3663
3664 public void expectStopped() {
3665 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3666 }
3667
3668 public void expectError(int error) {
3669 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3670 }
3671 }
3672
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003673 private Network connectKeepaliveNetwork(LinkProperties lp) {
3674 // Ensure the network is disconnected before we do anything.
3675 if (mWiFiNetworkAgent != null) {
3676 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
3677 }
3678
3679 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3680 ConditionVariable cv = waitForConnectivityBroadcasts(1);
3681 mWiFiNetworkAgent.connect(true);
3682 waitFor(cv);
3683 verifyActiveNetwork(TRANSPORT_WIFI);
3684 mWiFiNetworkAgent.sendLinkProperties(lp);
Hugo Benichibb91c572017-05-22 10:44:02 +09003685 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003686 return mWiFiNetworkAgent.getNetwork();
3687 }
3688
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003689 @Test
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003690 public void testPacketKeepalives() throws Exception {
3691 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
3692 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
3693 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
3694 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
3695 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
3696
Nathan Harold63dd8132018-02-14 13:09:45 -08003697 final int validKaInterval = 15;
3698 final int invalidKaInterval = 9;
3699
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003700 LinkProperties lp = new LinkProperties();
3701 lp.setInterfaceName("wlan12");
3702 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
3703 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
3704 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
3705 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
3706
3707 Network notMyNet = new Network(61234);
3708 Network myNet = connectKeepaliveNetwork(lp);
3709
3710 TestKeepaliveCallback callback = new TestKeepaliveCallback();
3711 PacketKeepalive ka;
3712
3713 // Attempt to start keepalives with invalid parameters and check for errors.
Nathan Harold63dd8132018-02-14 13:09:45 -08003714 ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003715 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3716
Nathan Harold63dd8132018-02-14 13:09:45 -08003717 ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003718 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
3719
Nathan Harold63dd8132018-02-14 13:09:45 -08003720 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003721 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3722
Nathan Harold63dd8132018-02-14 13:09:45 -08003723 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003724 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3725
Nathan Harold63dd8132018-02-14 13:09:45 -08003726 // NAT-T is only supported for IPv4.
3727 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
3728 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003729
Nathan Harold63dd8132018-02-14 13:09:45 -08003730 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003731 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3732
Nathan Harold63dd8132018-02-14 13:09:45 -08003733 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003734 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3735
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.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3738
Nathan Harold63dd8132018-02-14 13:09:45 -08003739 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003740 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3741
3742 // Check that a started keepalive can be stopped.
3743 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
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 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
3747 ka.stop();
3748 callback.expectStopped();
3749
3750 // Check that deleting the IP address stops the keepalive.
3751 LinkProperties bogusLp = new LinkProperties(lp);
Nathan Harold63dd8132018-02-14 13:09:45 -08003752 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003753 callback.expectStarted();
3754 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
3755 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
3756 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
3757 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3758 mWiFiNetworkAgent.sendLinkProperties(lp);
3759
3760 // Check that a started keepalive is stopped correctly when the network disconnects.
Nathan Harold63dd8132018-02-14 13:09:45 -08003761 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003762 callback.expectStarted();
3763 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003764 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003765 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3766
3767 // ... and that stopping it after that has no adverse effects.
Hugo Benichibb91c572017-05-22 10:44:02 +09003768 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003769 final Network myNetAlias = myNet;
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003770 assertNull(mCm.getNetworkCapabilities(myNetAlias));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003771 ka.stop();
3772
3773 // Reconnect.
3774 myNet = connectKeepaliveNetwork(lp);
3775 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
3776
3777 // Check things work as expected when the keepalive is stopped and the network disconnects.
Nathan Harold63dd8132018-02-14 13:09:45 -08003778 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003779 callback.expectStarted();
3780 ka.stop();
3781 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003782 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Hugo Benichibb91c572017-05-22 10:44:02 +09003783 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003784 callback.expectStopped();
3785
3786 // Reconnect.
3787 myNet = connectKeepaliveNetwork(lp);
3788 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
3789
3790 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
3791 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
Nathan Harold63dd8132018-02-14 13:09:45 -08003792 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003793 callback.expectStarted();
3794
3795 // The second one gets slot 2.
3796 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
3797 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08003798 PacketKeepalive ka2 = mCm.startNattKeepalive(
3799 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003800 callback2.expectStarted();
3801
3802 // Now stop the first one and create a third. This also gets slot 1.
3803 ka.stop();
3804 callback.expectStopped();
3805
3806 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
3807 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08003808 PacketKeepalive ka3 = mCm.startNattKeepalive(
3809 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003810 callback3.expectStarted();
3811
3812 ka2.stop();
3813 callback2.expectStopped();
3814
3815 ka3.stop();
3816 callback3.expectStopped();
3817 }
Udam Sainib7c24872016-01-04 12:16:14 -08003818
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003819 @Test
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09003820 public void testNattSocketKeepalives_SingleThreadExecutor() throws Exception {
junyulai06835112019-01-03 18:50:15 +08003821 final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
3822 doTestNattSocketKeepalivesWithExecutor(executorSingleThread);
3823 executorSingleThread.shutdown();
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09003824 }
junyulai06835112019-01-03 18:50:15 +08003825
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09003826 @Test
3827 public void testNattSocketKeepalives_InlineExecutor() throws Exception {
junyulai06835112019-01-03 18:50:15 +08003828 final Executor executorInline = (Runnable r) -> r.run();
3829 doTestNattSocketKeepalivesWithExecutor(executorInline);
3830 }
3831
3832 private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
junyulai48eac1d42018-12-27 17:25:29 +08003833 // TODO: 1. Move this outside of ConnectivityServiceTest.
junyulai06835112019-01-03 18:50:15 +08003834 // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
junyulai48eac1d42018-12-27 17:25:29 +08003835 final int srcPort = 12345;
3836 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
3837 final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
3838 final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
3839 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
3840 final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
3841
3842 final int validKaInterval = 15;
3843 final int invalidKaInterval = 9;
3844
3845 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
3846 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket(srcPort);
3847
junyulai48eac1d42018-12-27 17:25:29 +08003848 LinkProperties lp = new LinkProperties();
3849 lp.setInterfaceName("wlan12");
3850 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
3851 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
3852 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
3853 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
3854
3855 Network notMyNet = new Network(61234);
3856 Network myNet = connectKeepaliveNetwork(lp);
3857
3858 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback();
3859 SocketKeepalive ka;
3860
3861 // Attempt to start keepalives with invalid parameters and check for errors.
3862 // Invalid network.
3863 ka = mCm.createSocketKeepalive(notMyNet, testSocket, myIPv4, dstIPv4, executor, callback);
3864 ka.start(validKaInterval);
3865 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
3866
3867 // Invalid interval.
3868 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
3869 ka.start(invalidKaInterval);
3870 callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
3871
3872 // Invalid destination.
3873 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv6, executor, callback);
3874 ka.start(validKaInterval);
3875 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3876
3877 // Invalid source;
3878 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv6, dstIPv4, executor, callback);
3879 ka.start(validKaInterval);
3880 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3881
3882 // NAT-T is only supported for IPv4.
3883 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv6, dstIPv6, executor, callback);
3884 ka.start(validKaInterval);
3885 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3886
3887 // Sanity check before testing started keepalive.
3888 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
3889 ka.start(validKaInterval);
3890 callback.expectError(SocketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3891
3892 // Check that a started keepalive can be stopped.
3893 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
3894 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
3895 ka.start(validKaInterval);
3896 callback.expectStarted();
3897 mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS);
3898 ka.stop();
3899 callback.expectStopped();
3900
3901 // Check that deleting the IP address stops the keepalive.
3902 LinkProperties bogusLp = new LinkProperties(lp);
3903 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
3904 ka.start(validKaInterval);
3905 callback.expectStarted();
3906 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
3907 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
3908 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
3909 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3910 mWiFiNetworkAgent.sendLinkProperties(lp);
3911
3912 // Check that a started keepalive is stopped correctly when the network disconnects.
3913 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
3914 ka.start(validKaInterval);
3915 callback.expectStarted();
3916 mWiFiNetworkAgent.disconnect();
3917 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
3918 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
3919
3920 // ... and that stopping it after that has no adverse effects.
3921 waitForIdle();
3922 final Network myNetAlias = myNet;
3923 assertNull(mCm.getNetworkCapabilities(myNetAlias));
3924 ka.stop();
3925
3926 // Reconnect.
3927 myNet = connectKeepaliveNetwork(lp);
3928 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
3929
3930 // Check things work as expected when the keepalive is stopped and the network disconnects.
3931 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
3932 ka.start(validKaInterval);
3933 callback.expectStarted();
3934 ka.stop();
3935 mWiFiNetworkAgent.disconnect();
3936 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
3937 waitForIdle();
3938 callback.expectStopped();
3939
3940 // Reconnect.
3941 myNet = connectKeepaliveNetwork(lp);
3942 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
3943
3944 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
3945 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
3946 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
3947 ka.start(validKaInterval);
3948 callback.expectStarted();
3949
3950 // The second one gets slot 2.
3951 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
3952 final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket(6789);
3953 TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback();
3954 SocketKeepalive ka2 =
3955 mCm.createSocketKeepalive(myNet, testSocket2, myIPv4, dstIPv4, executor, callback2);
3956 ka2.start(validKaInterval);
3957 callback2.expectStarted();
3958
3959 ka.stop();
3960 callback.expectStopped();
3961
3962 ka2.stop();
3963 callback2.expectStopped();
junyulai06835112019-01-03 18:50:15 +08003964
3965 testSocket.close();
3966 testSocket2.close();
3967
3968 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09003969 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
junyulai48eac1d42018-12-27 17:25:29 +08003970 }
3971
3972 @Test
Udam Sainib7c24872016-01-04 12:16:14 -08003973 public void testGetCaptivePortalServerUrl() throws Exception {
3974 String url = mCm.getCaptivePortalServerUrl();
3975 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
3976 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09003977
3978 private static class TestNetworkPinner extends NetworkPinner {
3979 public static boolean awaitPin(int timeoutMs) {
3980 synchronized(sLock) {
3981 if (sNetwork == null) {
3982 try {
3983 sLock.wait(timeoutMs);
3984 } catch (InterruptedException e) {}
3985 }
3986 return sNetwork != null;
3987 }
3988 }
3989
3990 public static boolean awaitUnpin(int timeoutMs) {
3991 synchronized(sLock) {
3992 if (sNetwork != null) {
3993 try {
3994 sLock.wait(timeoutMs);
3995 } catch (InterruptedException e) {}
3996 }
3997 return sNetwork == null;
3998 }
3999 }
4000 }
4001
4002 private void assertPinnedToWifiWithCellDefault() {
4003 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4004 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4005 }
4006
4007 private void assertPinnedToWifiWithWifiDefault() {
4008 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4009 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4010 }
4011
4012 private void assertNotPinnedToWifi() {
4013 assertNull(mCm.getBoundNetworkForProcess());
4014 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4015 }
4016
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004017 @Test
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004018 public void testNetworkPinner() {
4019 NetworkRequest wifiRequest = new NetworkRequest.Builder()
4020 .addTransportType(TRANSPORT_WIFI)
4021 .build();
4022 assertNull(mCm.getBoundNetworkForProcess());
4023
4024 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4025 assertNull(mCm.getBoundNetworkForProcess());
4026
4027 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4028 mCellNetworkAgent.connect(true);
4029 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4030 mWiFiNetworkAgent.connect(false);
4031
4032 // When wi-fi connects, expect to be pinned.
4033 assertTrue(TestNetworkPinner.awaitPin(100));
4034 assertPinnedToWifiWithCellDefault();
4035
4036 // Disconnect and expect the pin to drop.
4037 mWiFiNetworkAgent.disconnect();
4038 assertTrue(TestNetworkPinner.awaitUnpin(100));
4039 assertNotPinnedToWifi();
4040
4041 // Reconnecting does not cause the pin to come back.
4042 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4043 mWiFiNetworkAgent.connect(false);
4044 assertFalse(TestNetworkPinner.awaitPin(100));
4045 assertNotPinnedToWifi();
4046
4047 // Pinning while connected causes the pin to take effect immediately.
4048 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4049 assertTrue(TestNetworkPinner.awaitPin(100));
4050 assertPinnedToWifiWithCellDefault();
4051
4052 // Explicitly unpin and expect to use the default network again.
4053 TestNetworkPinner.unpin();
4054 assertNotPinnedToWifi();
4055
4056 // Disconnect cell and wifi.
4057 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
4058 mCellNetworkAgent.disconnect();
4059 mWiFiNetworkAgent.disconnect();
4060 waitFor(cv);
4061
4062 // Pinning takes effect even if the pinned network is the default when the pin is set...
4063 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4064 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4065 mWiFiNetworkAgent.connect(false);
4066 assertTrue(TestNetworkPinner.awaitPin(100));
4067 assertPinnedToWifiWithWifiDefault();
4068
4069 // ... and is maintained even when that network is no longer the default.
4070 cv = waitForConnectivityBroadcasts(1);
4071 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4072 mCellNetworkAgent.connect(true);
4073 waitFor(cv);
4074 assertPinnedToWifiWithCellDefault();
4075 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004076
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004077 @Test
Hugo Benichi893a7622017-09-29 09:34:08 +09004078 public void testNetworkCallbackMaximum() {
Jeff Sharkeye0c29952018-02-20 17:24:55 -07004079 // We can only have 99 callbacks, because MultipathPolicyTracker is
4080 // already one of them.
4081 final int MAX_REQUESTS = 99;
4082 final int CALLBACKS = 89;
Hugo Benichi893a7622017-09-29 09:34:08 +09004083 final int INTENTS = 10;
4084 assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
4085
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004086 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
Hugo Benichi893a7622017-09-29 09:34:08 +09004087 ArrayList<Object> registered = new ArrayList<>();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004088
Hugo Benichi893a7622017-09-29 09:34:08 +09004089 int j = 0;
4090 while (j++ < CALLBACKS / 2) {
4091 NetworkCallback cb = new NetworkCallback();
4092 mCm.requestNetwork(networkRequest, cb);
4093 registered.add(cb);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004094 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004095 while (j++ < CALLBACKS) {
4096 NetworkCallback cb = new NetworkCallback();
4097 mCm.registerNetworkCallback(networkRequest, cb);
4098 registered.add(cb);
4099 }
4100 j = 0;
4101 while (j++ < INTENTS / 2) {
4102 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
4103 mCm.requestNetwork(networkRequest, pi);
4104 registered.add(pi);
4105 }
4106 while (j++ < INTENTS) {
4107 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
4108 mCm.registerNetworkCallback(networkRequest, pi);
4109 registered.add(pi);
4110 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004111
Hugo Benichi893a7622017-09-29 09:34:08 +09004112 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004113 try {
Hugo Benichi893a7622017-09-29 09:34:08 +09004114 mCm.requestNetwork(networkRequest, new NetworkCallback());
4115 fail("Registering " + MAX_REQUESTS + " network requests did not throw exception");
Hugo Benichicb883232017-05-11 13:16:17 +09004116 } catch (TooManyRequestsException expected) {}
Hugo Benichi893a7622017-09-29 09:34:08 +09004117 try {
4118 mCm.registerNetworkCallback(networkRequest, new NetworkCallback());
4119 fail("Registering " + MAX_REQUESTS + " network callbacks did not throw exception");
4120 } catch (TooManyRequestsException expected) {}
4121 try {
4122 mCm.requestNetwork(networkRequest,
4123 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0));
4124 fail("Registering " + MAX_REQUESTS + " PendingIntent requests did not throw exception");
4125 } catch (TooManyRequestsException expected) {}
4126 try {
4127 mCm.registerNetworkCallback(networkRequest,
4128 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0));
4129 fail("Registering " + MAX_REQUESTS
4130 + " PendingIntent callbacks did not throw exception");
4131 } catch (TooManyRequestsException expected) {}
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004132
Hugo Benichi893a7622017-09-29 09:34:08 +09004133 for (Object o : registered) {
4134 if (o instanceof NetworkCallback) {
4135 mCm.unregisterNetworkCallback((NetworkCallback)o);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004136 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004137 if (o instanceof PendingIntent) {
4138 mCm.unregisterNetworkCallback((PendingIntent)o);
4139 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004140 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004141 waitForIdle();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004142
4143 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
4144 for (int i = 0; i < MAX_REQUESTS; i++) {
4145 NetworkCallback networkCallback = new NetworkCallback();
4146 mCm.requestNetwork(networkRequest, networkCallback);
4147 mCm.unregisterNetworkCallback(networkCallback);
4148 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004149 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004150
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004151 for (int i = 0; i < MAX_REQUESTS; i++) {
4152 NetworkCallback networkCallback = new NetworkCallback();
4153 mCm.registerNetworkCallback(networkRequest, networkCallback);
4154 mCm.unregisterNetworkCallback(networkCallback);
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("e" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004161 mCm.requestNetwork(networkRequest, pendingIntent);
4162 mCm.unregisterNetworkCallback(pendingIntent);
4163 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004164 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004165
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004166 for (int i = 0; i < MAX_REQUESTS; i++) {
4167 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004168 PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004169 mCm.registerNetworkCallback(networkRequest, pendingIntent);
4170 mCm.unregisterNetworkCallback(pendingIntent);
4171 }
4172 }
Hugo Benichifed512a2017-06-26 10:06:49 +09004173
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004174 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004175 public void testNetworkInfoOfTypeNone() {
4176 ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1);
4177
4178 verifyNoNetwork();
Hugo Benichic1014502017-07-19 10:10:52 +09004179 MockNetworkAgent wifiAware = new MockNetworkAgent(TRANSPORT_WIFI_AWARE);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004180 assertNull(mCm.getActiveNetworkInfo());
4181
4182 Network[] allNetworks = mCm.getAllNetworks();
4183 assertLength(1, allNetworks);
4184 Network network = allNetworks[0];
4185 NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
4186 assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
4187
4188 final NetworkRequest request =
4189 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
4190 final TestNetworkCallback callback = new TestNetworkCallback();
4191 mCm.registerNetworkCallback(request, callback);
4192
Hugo Benichic1014502017-07-19 10:10:52 +09004193 // Bring up wifi aware network.
4194 wifiAware.connect(false, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09004195 callback.expectAvailableCallbacksUnvalidated(wifiAware);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004196
4197 assertNull(mCm.getActiveNetworkInfo());
4198 assertNull(mCm.getActiveNetwork());
Hugo Benichic1014502017-07-19 10:10:52 +09004199 // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
Hugo Benichi16f0a942017-06-20 14:07:59 +09004200 // of this test. Fix it and uncomment the assert below.
4201 //assertEmpty(mCm.getAllNetworkInfo());
4202
Hugo Benichic1014502017-07-19 10:10:52 +09004203 // Disconnect wifi aware network.
4204 wifiAware.disconnect();
4205 callback.expectCallbackLike((info) -> info.state == CallbackState.LOST, TIMEOUT_MS);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004206 mCm.unregisterNetworkCallback(callback);
4207
4208 verifyNoNetwork();
4209 if (broadcastCV.block(10)) {
4210 fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
4211 }
4212 }
4213
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004214 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004215 public void testDeprecatedAndUnsupportedOperations() throws Exception {
4216 final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
4217 assertNull(mCm.getNetworkInfo(TYPE_NONE));
4218 assertNull(mCm.getNetworkForType(TYPE_NONE));
4219 assertNull(mCm.getLinkProperties(TYPE_NONE));
4220 assertFalse(mCm.isNetworkSupported(TYPE_NONE));
4221
4222 assertException(() -> { mCm.networkCapabilitiesForType(TYPE_NONE); },
4223 IllegalArgumentException.class);
4224
4225 Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
4226 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
4227 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
4228 // TODO: let test context have configuration application target sdk version
4229 // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
4230 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
4231 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
4232 assertException(() -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); }, unsupported);
4233 }
4234
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004235 @Test
Rubin Xu1bb5c082017-09-05 18:40:49 +01004236 public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() {
4237 final NetworkRequest networkRequest = new NetworkRequest.Builder()
4238 .addTransportType(TRANSPORT_WIFI).build();
4239 final TestNetworkCallback networkCallback = new TestNetworkCallback();
4240 mCm.registerNetworkCallback(networkRequest, networkCallback);
4241
4242 LinkProperties lp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004243 lp.setInterfaceName(WIFI_IFNAME);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004244 LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
4245 RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
4246 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
4247 lp.addLinkAddress(myIpv4Address);
4248 lp.addRoute(myIpv4DefaultRoute);
4249
4250 // Verify direct routes are added when network agent is first registered in
4251 // ConnectivityService.
4252 MockNetworkAgent networkAgent = new MockNetworkAgent(TRANSPORT_WIFI, lp);
4253 networkAgent.connect(true);
4254 networkCallback.expectCallback(CallbackState.AVAILABLE, networkAgent);
4255 networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent);
4256 CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4257 networkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08004258 networkCallback.expectCallback(CallbackState.BLOCKED_STATUS, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004259 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
4260 networkCallback.assertNoCallback();
4261 checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address),
4262 Arrays.asList(myIpv4DefaultRoute));
4263 checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
4264 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
4265
4266 // Verify direct routes are added during subsequent link properties updates.
4267 LinkProperties newLp = new LinkProperties(lp);
4268 LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
4269 LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
4270 newLp.addLinkAddress(myIpv6Address1);
4271 newLp.addLinkAddress(myIpv6Address2);
4272 networkAgent.sendLinkProperties(newLp);
4273 cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, networkAgent);
4274 networkCallback.assertNoCallback();
4275 checkDirectlyConnectedRoutes(cbi.arg,
4276 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
4277 Arrays.asList(myIpv4DefaultRoute));
4278 mCm.unregisterNetworkCallback(networkCallback);
4279 }
4280
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004281 @Test
4282 public void testStatsIfacesChanged() throws Exception {
4283 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004284 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4285
Varun Anandd33cbc62019-02-07 14:13:13 -08004286 Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
4287 Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
4288
4289 LinkProperties cellLp = new LinkProperties();
4290 cellLp.setInterfaceName(MOBILE_IFNAME);
4291 LinkProperties wifiLp = new LinkProperties();
4292 wifiLp.setInterfaceName(WIFI_IFNAME);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004293
4294 // Simple connection should have updated ifaces
4295 mCellNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004296 mCellNetworkAgent.sendLinkProperties(cellLp);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004297 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004298 verify(mStatsService, atLeastOnce())
4299 .forceUpdateIfaces(
4300 eq(onlyCell),
4301 eq(new VpnInfo[0]),
4302 any(NetworkState[].class),
4303 eq(MOBILE_IFNAME));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004304 reset(mStatsService);
4305
4306 // Default network switch should update ifaces.
4307 mWiFiNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004308 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004309 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004310 assertEquals(wifiLp, mService.getActiveLinkProperties());
4311 verify(mStatsService, atLeastOnce())
4312 .forceUpdateIfaces(
4313 eq(onlyWifi),
4314 eq(new VpnInfo[0]),
4315 any(NetworkState[].class),
4316 eq(WIFI_IFNAME));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004317 reset(mStatsService);
4318
4319 // Disconnect should update ifaces.
4320 mWiFiNetworkAgent.disconnect();
4321 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004322 verify(mStatsService, atLeastOnce())
4323 .forceUpdateIfaces(
4324 eq(onlyCell),
4325 eq(new VpnInfo[0]),
4326 any(NetworkState[].class),
4327 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004328 reset(mStatsService);
4329
4330 // Metered change should update ifaces
4331 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4332 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004333 verify(mStatsService, atLeastOnce())
4334 .forceUpdateIfaces(
4335 eq(onlyCell),
4336 eq(new VpnInfo[0]),
4337 any(NetworkState[].class),
4338 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004339 reset(mStatsService);
4340
4341 mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4342 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004343 verify(mStatsService, atLeastOnce())
4344 .forceUpdateIfaces(
4345 eq(onlyCell),
4346 eq(new VpnInfo[0]),
4347 any(NetworkState[].class),
4348 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004349 reset(mStatsService);
4350
4351 // Captive portal change shouldn't update ifaces
4352 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
4353 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004354 verify(mStatsService, never())
4355 .forceUpdateIfaces(
4356 eq(onlyCell),
4357 eq(new VpnInfo[0]),
4358 any(NetworkState[].class),
4359 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004360 reset(mStatsService);
4361
4362 // Roaming change should update ifaces
4363 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
4364 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004365 verify(mStatsService, atLeastOnce())
4366 .forceUpdateIfaces(
4367 eq(onlyCell),
4368 eq(new VpnInfo[0]),
4369 any(NetworkState[].class),
4370 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004371 reset(mStatsService);
4372 }
4373
Erik Klinee89953b2018-01-11 16:11:10 +09004374 @Test
4375 public void testBasicDnsConfigurationPushed() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004376 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4377 ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class);
4378
4379 // Clear any interactions that occur as a result of CS starting up.
4380 reset(mNetworkManagementService);
4381
4382 final String[] EMPTY_STRING_ARRAY = new String[0];
Erik Klinee89953b2018-01-11 16:11:10 +09004383 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4384 waitForIdle();
4385 verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
Erik Kline79c6d052018-03-21 07:18:33 -07004386 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
4387 verifyNoMoreInteractions(mNetworkManagementService);
Erik Klinee89953b2018-01-11 16:11:10 +09004388
4389 final LinkProperties cellLp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004390 cellLp.setInterfaceName(MOBILE_IFNAME);
Erik Kline117e7f32018-03-04 21:01:01 +09004391 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4392 // "is-reachable" testing in order to not program netd with unreachable
4393 // nameservers that it might try repeated to validate.
4394 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
Erik Kline79c6d052018-03-21 07:18:33 -07004395 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4396 MOBILE_IFNAME));
Erik Kline117e7f32018-03-04 21:01:01 +09004397 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
Erik Kline79c6d052018-03-21 07:18:33 -07004398 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4399 MOBILE_IFNAME));
Erik Klinee89953b2018-01-11 16:11:10 +09004400 mCellNetworkAgent.sendLinkProperties(cellLp);
4401 mCellNetworkAgent.connect(false);
4402 waitForIdle();
Erik Klinee89953b2018-01-11 16:11:10 +09004403 // CS tells netd about the empty DNS config for this network.
Erik Kline79c6d052018-03-21 07:18:33 -07004404 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
4405 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
Erik Klinee89953b2018-01-11 16:11:10 +09004406 reset(mNetworkManagementService);
4407
4408 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4409 mCellNetworkAgent.sendLinkProperties(cellLp);
4410 waitForIdle();
Erik Kline79c6d052018-03-21 07:18:33 -07004411 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
Erik Kline117e7f32018-03-04 21:01:01 +09004412 anyInt(), mStringArrayCaptor.capture(), any(), any(),
Erik Kline79c6d052018-03-21 07:18:33 -07004413 eq(""), tlsServers.capture());
Erik Klinee89953b2018-01-11 16:11:10 +09004414 assertEquals(1, mStringArrayCaptor.getValue().length);
4415 assertTrue(ArrayUtils.contains(mStringArrayCaptor.getValue(), "2001:db8::1"));
Erik Kline79c6d052018-03-21 07:18:33 -07004416 // Opportunistic mode.
4417 assertTrue(ArrayUtils.contains(tlsServers.getValue(), "2001:db8::1"));
Erik Klinee89953b2018-01-11 16:11:10 +09004418 reset(mNetworkManagementService);
4419
4420 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4421 mCellNetworkAgent.sendLinkProperties(cellLp);
4422 waitForIdle();
Erik Kline79c6d052018-03-21 07:18:33 -07004423 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
Erik Kline117e7f32018-03-04 21:01:01 +09004424 anyInt(), mStringArrayCaptor.capture(), any(), any(),
Erik Kline79c6d052018-03-21 07:18:33 -07004425 eq(""), tlsServers.capture());
Erik Kline117e7f32018-03-04 21:01:01 +09004426 assertEquals(2, mStringArrayCaptor.getValue().length);
4427 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4428 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline79c6d052018-03-21 07:18:33 -07004429 // Opportunistic mode.
4430 assertEquals(2, tlsServers.getValue().length);
4431 assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
4432 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline117e7f32018-03-04 21:01:01 +09004433 reset(mNetworkManagementService);
4434
4435 final String TLS_SPECIFIER = "tls.example.com";
4436 final String TLS_SERVER6 = "2001:db8:53::53";
4437 final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
4438 final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004439 mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
4440 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
4441
Erik Kline117e7f32018-03-04 21:01:01 +09004442 waitForIdle();
Erik Kline79c6d052018-03-21 07:18:33 -07004443 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
Erik Kline117e7f32018-03-04 21:01:01 +09004444 anyInt(), mStringArrayCaptor.capture(), any(), any(),
4445 eq(TLS_SPECIFIER), eq(TLS_SERVERS));
Erik Klinee89953b2018-01-11 16:11:10 +09004446 assertEquals(2, mStringArrayCaptor.getValue().length);
4447 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4448 new String[]{"2001:db8::1", "192.0.2.1"}));
4449 reset(mNetworkManagementService);
4450 }
4451
Erik Kline79c6d052018-03-21 07:18:33 -07004452 @Test
4453 public void testPrivateDnsSettingsChange() throws Exception {
4454 final String[] EMPTY_STRING_ARRAY = new String[0];
4455 ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class);
4456
4457 // Clear any interactions that occur as a result of CS starting up.
4458 reset(mNetworkManagementService);
4459
4460 // The default on Android is opportunistic mode ("Automatic").
4461 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4462
dalyk1fcb7392018-03-05 12:42:22 -05004463 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4464 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4465 .addTransportType(TRANSPORT_CELLULAR).build();
4466 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4467
Erik Kline79c6d052018-03-21 07:18:33 -07004468 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4469 waitForIdle();
4470 // CS tells netd about the empty DNS config for this network.
4471 verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
4472 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
4473 verifyNoMoreInteractions(mNetworkManagementService);
4474
4475 final LinkProperties cellLp = new LinkProperties();
4476 cellLp.setInterfaceName(MOBILE_IFNAME);
4477 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4478 // "is-reachable" testing in order to not program netd with unreachable
4479 // nameservers that it might try repeated to validate.
4480 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
4481 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4482 MOBILE_IFNAME));
4483 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
4484 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4485 MOBILE_IFNAME));
4486 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4487 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4488
4489 mCellNetworkAgent.sendLinkProperties(cellLp);
4490 mCellNetworkAgent.connect(false);
4491 waitForIdle();
4492 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
4493 anyInt(), mStringArrayCaptor.capture(), any(), any(),
4494 eq(""), tlsServers.capture());
4495 assertEquals(2, mStringArrayCaptor.getValue().length);
4496 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4497 new String[]{"2001:db8::1", "192.0.2.1"}));
4498 // Opportunistic mode.
4499 assertEquals(2, tlsServers.getValue().length);
4500 assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
4501 new String[]{"2001:db8::1", "192.0.2.1"}));
4502 reset(mNetworkManagementService);
dalyk1fcb7392018-03-05 12:42:22 -05004503 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
4504 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
4505 mCellNetworkAgent);
4506 CallbackInfo cbi = cellNetworkCallback.expectCallback(
4507 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08004508 cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05004509 cellNetworkCallback.assertNoCallback();
4510 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4511 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
Erik Kline79c6d052018-03-21 07:18:33 -07004512
4513 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
4514 verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
4515 anyInt(), mStringArrayCaptor.capture(), any(), any(),
4516 eq(""), eq(EMPTY_STRING_ARRAY));
4517 assertEquals(2, mStringArrayCaptor.getValue().length);
4518 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4519 new String[]{"2001:db8::1", "192.0.2.1"}));
4520 reset(mNetworkManagementService);
dalyk1fcb7392018-03-05 12:42:22 -05004521 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07004522
4523 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4524 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
4525 anyInt(), mStringArrayCaptor.capture(), any(), any(),
4526 eq(""), tlsServers.capture());
4527 assertEquals(2, mStringArrayCaptor.getValue().length);
4528 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4529 new String[]{"2001:db8::1", "192.0.2.1"}));
4530 assertEquals(2, tlsServers.getValue().length);
4531 assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
4532 new String[]{"2001:db8::1", "192.0.2.1"}));
4533 reset(mNetworkManagementService);
dalyk1fcb7392018-03-05 12:42:22 -05004534 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07004535
dalyk1fcb7392018-03-05 12:42:22 -05004536 setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
4537 // Can't test dns configuration for strict mode without properly mocking
4538 // out the DNS lookups, but can test that LinkProperties is updated.
4539 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4540 mCellNetworkAgent);
4541 cellNetworkCallback.assertNoCallback();
4542 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
4543 assertEquals("strict.example.com", ((LinkProperties)cbi.arg).getPrivateDnsServerName());
4544 }
4545
4546 @Test
4547 public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
4548 // The default on Android is opportunistic mode ("Automatic").
4549 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4550
4551 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4552 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4553 .addTransportType(TRANSPORT_CELLULAR).build();
4554 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4555
4556 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4557 waitForIdle();
4558 LinkProperties lp = new LinkProperties();
4559 mCellNetworkAgent.sendLinkProperties(lp);
4560 mCellNetworkAgent.connect(false);
4561 waitForIdle();
4562 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
4563 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
4564 mCellNetworkAgent);
4565 CallbackInfo cbi = cellNetworkCallback.expectCallback(
4566 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08004567 cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05004568 cellNetworkCallback.assertNoCallback();
4569 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4570 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4571 Set<InetAddress> dnsServers = new HashSet<>();
4572 checkDnsServers(cbi.arg, dnsServers);
4573
4574 // Send a validation event for a server that is not part of the current
4575 // resolver config. The validation event should be ignored.
4576 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4577 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
4578 cellNetworkCallback.assertNoCallback();
4579
4580 // Add a dns server to the LinkProperties.
4581 LinkProperties lp2 = new LinkProperties(lp);
4582 lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
4583 mCellNetworkAgent.sendLinkProperties(lp2);
4584 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4585 mCellNetworkAgent);
4586 cellNetworkCallback.assertNoCallback();
4587 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4588 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4589 dnsServers.add(InetAddress.getByName("145.100.185.16"));
4590 checkDnsServers(cbi.arg, dnsServers);
4591
4592 // Send a validation event containing a hostname that is not part of
4593 // the current resolver config. The validation event should be ignored.
4594 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4595 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
4596 cellNetworkCallback.assertNoCallback();
4597
4598 // Send a validation event where validation failed.
4599 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4600 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
4601 cellNetworkCallback.assertNoCallback();
4602
4603 // Send a validation event where validation succeeded for a server in
4604 // the current resolver config. A LinkProperties callback with updated
4605 // private dns fields should be sent.
4606 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4607 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
4608 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4609 mCellNetworkAgent);
4610 cellNetworkCallback.assertNoCallback();
4611 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
4612 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4613 checkDnsServers(cbi.arg, dnsServers);
4614
4615 // The private dns fields in LinkProperties should be preserved when
4616 // the network agent sends unrelated changes.
4617 LinkProperties lp3 = new LinkProperties(lp2);
4618 lp3.setMtu(1300);
4619 mCellNetworkAgent.sendLinkProperties(lp3);
4620 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4621 mCellNetworkAgent);
4622 cellNetworkCallback.assertNoCallback();
4623 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
4624 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4625 checkDnsServers(cbi.arg, dnsServers);
4626 assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
4627
4628 // Removing the only validated server should affect the private dns
4629 // fields in LinkProperties.
4630 LinkProperties lp4 = new LinkProperties(lp3);
4631 lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
4632 mCellNetworkAgent.sendLinkProperties(lp4);
4633 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4634 mCellNetworkAgent);
4635 cellNetworkCallback.assertNoCallback();
4636 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4637 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4638 dnsServers.remove(InetAddress.getByName("145.100.185.16"));
4639 checkDnsServers(cbi.arg, dnsServers);
4640 assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
Erik Kline79c6d052018-03-21 07:18:33 -07004641 }
4642
Rubin Xu1bb5c082017-09-05 18:40:49 +01004643 private void checkDirectlyConnectedRoutes(Object callbackObj,
4644 Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
4645 assertTrue(callbackObj instanceof LinkProperties);
4646 LinkProperties lp = (LinkProperties) callbackObj;
4647
4648 Set<RouteInfo> expectedRoutes = new ArraySet<>();
4649 expectedRoutes.addAll(otherRoutes);
4650 for (LinkAddress address : linkAddresses) {
4651 RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
4652 // Duplicates in linkAddresses are considered failures
4653 assertTrue(expectedRoutes.add(localRoute));
4654 }
4655 List<RouteInfo> observedRoutes = lp.getRoutes();
4656 assertEquals(expectedRoutes.size(), observedRoutes.size());
4657 assertTrue(observedRoutes.containsAll(expectedRoutes));
4658 }
4659
dalyk1fcb7392018-03-05 12:42:22 -05004660 private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
4661 assertTrue(callbackObj instanceof LinkProperties);
4662 LinkProperties lp = (LinkProperties) callbackObj;
4663 assertEquals(dnsServers.size(), lp.getDnsServers().size());
4664 assertTrue(lp.getDnsServers().containsAll(dnsServers));
4665 }
4666
Hugo Benichifed512a2017-06-26 10:06:49 +09004667 private static <T> void assertEmpty(T[] ts) {
4668 int length = ts.length;
4669 assertEquals("expected empty array, but length was " + length, 0, length);
4670 }
4671
4672 private static <T> void assertLength(int expected, T[] got) {
4673 int length = got.length;
4674 assertEquals(String.format("expected array of length %s, but length was %s for %s",
4675 expected, length, Arrays.toString(got)), expected, length);
4676 }
Hugo Benichi16f0a942017-06-20 14:07:59 +09004677
4678 private static <T> void assertException(Runnable block, Class<T> expected) {
4679 try {
4680 block.run();
4681 fail("Expected exception of type " + expected);
4682 } catch (Exception got) {
4683 if (!got.getClass().equals(expected)) {
4684 fail("Expected exception of type " + expected + " but got " + got);
4685 }
4686 return;
4687 }
4688 }
Chalard Jean0b214af2018-01-12 17:22:49 +09004689
4690 @Test
4691 public void testVpnNetworkActive() {
4692 final int uid = Process.myUid();
4693
4694 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09004695 final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004696 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
4697 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004698 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09004699 final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
4700 final NetworkRequest genericRequest = new NetworkRequest.Builder()
4701 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
Chalard Jean0b214af2018-01-12 17:22:49 +09004702 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
4703 .addTransportType(TRANSPORT_WIFI).build();
4704 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
Chalard Jeanb552c462018-02-21 18:43:54 +09004705 .removeCapability(NET_CAPABILITY_NOT_VPN)
Chalard Jean0b214af2018-01-12 17:22:49 +09004706 .addTransportType(TRANSPORT_VPN).build();
4707 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Chalard Jeanb552c462018-02-21 18:43:54 +09004708 mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09004709 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
4710 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004711 mCm.registerDefaultNetworkCallback(defaultCallback);
4712 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004713
4714 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4715 mWiFiNetworkAgent.connect(false);
4716
4717 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004718 genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004719 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004720 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004721 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004722 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004723
4724 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4725 final ArraySet<UidRange> ranges = new ArraySet<>();
4726 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004727 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4728 mMockVpn.setUids(ranges);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004729 // VPN networks do not satisfy the default request and are automatically validated
4730 // by NetworkMonitor
Lorenzo Colittied3168e2019-01-23 17:54:08 +09004731 assertFalse(NetworkMonitorUtils.isValidationRequired(vpnNetworkAgent.mNetworkCapabilities));
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004732 vpnNetworkAgent.setNetworkValid();
4733
Chalard Jean0b214af2018-01-12 17:22:49 +09004734 vpnNetworkAgent.connect(false);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004735 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08004736 mMockVpn.setUnderlyingNetworks(new Network[0]);
Chalard Jean0b214af2018-01-12 17:22:49 +09004737
4738 genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004739 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004740 wifiNetworkCallback.assertNoCallback();
4741 vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004742 defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
4743 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004744
4745 genericNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004746 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jeanf19db372018-01-26 19:24:40 +09004747 vpnNetworkCallback.expectCapabilitiesLike(nc -> null == nc.getUids(), vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004748 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
4749 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004750
4751 ranges.clear();
4752 vpnNetworkAgent.setUids(ranges);
4753
4754 genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004755 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004756 wifiNetworkCallback.assertNoCallback();
4757 vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
4758
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004759 // TODO : The default network callback should actually get a LOST call here (also see the
4760 // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
4761 // ranges at all when determining whether a network should be rematched. In practice, VPNs
4762 // can't currently update their UIDs without disconnecting, so this does not matter too
4763 // much, but that is the reason the test here has to check for an update to the
4764 // capabilities instead of the expected LOST then AVAILABLE.
4765 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
4766
Chalard Jean0b214af2018-01-12 17:22:49 +09004767 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004768 mMockVpn.setUids(ranges);
Varun Anand4fa80e82019-02-06 10:13:38 -08004769 vpnNetworkAgent.setUids(ranges);
Chalard Jean0b214af2018-01-12 17:22:49 +09004770
4771 genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004772 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004773 wifiNetworkCallback.assertNoCallback();
4774 vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004775 // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
4776 // happen outside of the test, ConnectivityService does not rematch callbacks.
4777 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004778
4779 mWiFiNetworkAgent.disconnect();
4780
4781 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004782 genericNotVpnNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004783 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
4784 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004785 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004786
4787 vpnNetworkAgent.disconnect();
4788
4789 genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004790 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004791 wifiNetworkCallback.assertNoCallback();
4792 vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004793 defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
4794 assertEquals(null, mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004795
4796 mCm.unregisterNetworkCallback(genericNetworkCallback);
4797 mCm.unregisterNetworkCallback(wifiNetworkCallback);
4798 mCm.unregisterNetworkCallback(vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004799 mCm.unregisterNetworkCallback(defaultCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09004800 }
Chalard Jean26400492018-04-18 20:18:38 +09004801
4802 @Test
Varun Anand4fa80e82019-02-06 10:13:38 -08004803 public void testVpnWithoutInternet() {
Chalard Jean26400492018-04-18 20:18:38 +09004804 final int uid = Process.myUid();
4805
4806 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
4807 mCm.registerDefaultNetworkCallback(defaultCallback);
Chalard Jean26400492018-04-18 20:18:38 +09004808
4809 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4810 mWiFiNetworkAgent.connect(true);
4811
4812 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
4813 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4814
4815 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4816 final ArraySet<UidRange> ranges = new ArraySet<>();
4817 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004818 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4819 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09004820 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004821 mMockVpn.connect();
Chalard Jean26400492018-04-18 20:18:38 +09004822
4823 defaultCallback.assertNoCallback();
4824 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4825
4826 vpnNetworkAgent.disconnect();
4827 defaultCallback.assertNoCallback();
4828
Varun Anand4fa80e82019-02-06 10:13:38 -08004829 mCm.unregisterNetworkCallback(defaultCallback);
4830 }
4831
4832 @Test
4833 public void testVpnWithInternet() {
4834 final int uid = Process.myUid();
4835
4836 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
4837 mCm.registerDefaultNetworkCallback(defaultCallback);
4838
4839 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4840 mWiFiNetworkAgent.connect(true);
4841
4842 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
4843 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4844
4845 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4846 final ArraySet<UidRange> ranges = new ArraySet<>();
4847 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004848 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4849 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09004850 vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004851 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08004852
Chalard Jean26400492018-04-18 20:18:38 +09004853 defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
4854 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4855
4856 vpnNetworkAgent.disconnect();
4857 defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
4858 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
4859
Chalard Jean26400492018-04-18 20:18:38 +09004860 mCm.unregisterNetworkCallback(defaultCallback);
4861 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004862
4863 @Test
4864 public void testVpnSetUnderlyingNetworks() {
4865 final int uid = Process.myUid();
4866
4867 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
4868 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
4869 .removeCapability(NET_CAPABILITY_NOT_VPN)
4870 .addTransportType(TRANSPORT_VPN)
4871 .build();
4872 NetworkCapabilities nc;
4873 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
4874 vpnNetworkCallback.assertNoCallback();
4875
4876 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4877 final ArraySet<UidRange> ranges = new ArraySet<>();
4878 ranges.add(new UidRange(uid, uid));
4879 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4880 mMockVpn.connect();
4881 mMockVpn.setUids(ranges);
4882 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
4883
4884 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
4885 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
4886 assertTrue(nc.hasTransport(TRANSPORT_VPN));
4887 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
4888 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
4889 // For safety reasons a VPN without underlying networks is considered metered.
4890 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
4891
4892 // Connect cell and use it as an underlying network.
4893 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4894 mCellNetworkAgent.connect(true);
4895
4896 mService.setUnderlyingNetworksForVpn(
4897 new Network[] { mCellNetworkAgent.getNetwork() });
4898
4899 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4900 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
4901 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4902 vpnNetworkAgent);
4903
4904 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4905 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
4906 mWiFiNetworkAgent.connect(true);
4907
4908 mService.setUnderlyingNetworksForVpn(
4909 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
4910
4911 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4912 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
4913 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4914 vpnNetworkAgent);
4915
4916 // Don't disconnect, but note the VPN is not using wifi any more.
4917 mService.setUnderlyingNetworksForVpn(
4918 new Network[] { mCellNetworkAgent.getNetwork() });
4919
4920 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4921 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
4922 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4923 vpnNetworkAgent);
4924
4925 // Use Wifi but not cell. Note the VPN is now unmetered.
4926 mService.setUnderlyingNetworksForVpn(
4927 new Network[] { mWiFiNetworkAgent.getNetwork() });
4928
4929 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4930 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
4931 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4932 vpnNetworkAgent);
4933
4934 // Use both again.
4935 mService.setUnderlyingNetworksForVpn(
4936 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
4937
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);
4942
Chalard Jean6b65ec72018-05-18 22:02:56 +09004943 // Disconnect cell. Receive update without even removing the dead network from the
4944 // underlying networks – it's dead anyway. Not metered any more.
4945 mCellNetworkAgent.disconnect();
4946 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4947 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
4948 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4949 vpnNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004950
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09004951 // Disconnect wifi too. No underlying networks means this is now metered.
Chalard Jean6b65ec72018-05-18 22:02:56 +09004952 mWiFiNetworkAgent.disconnect();
4953 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4954 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09004955 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
Chalard Jean6b65ec72018-05-18 22:02:56 +09004956 vpnNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004957
4958 mMockVpn.disconnect();
4959 }
junyulai4a192e22018-06-13 15:00:37 +08004960
Mike Yuf9729752018-08-17 15:22:05 +08004961 @Test
Varun Anand4fa80e82019-02-06 10:13:38 -08004962 public void testNullUnderlyingNetworks() {
4963 final int uid = Process.myUid();
4964
4965 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
4966 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
4967 .removeCapability(NET_CAPABILITY_NOT_VPN)
4968 .addTransportType(TRANSPORT_VPN)
4969 .build();
4970 NetworkCapabilities nc;
4971 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
4972 vpnNetworkCallback.assertNoCallback();
4973
4974 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4975 final ArraySet<UidRange> ranges = new ArraySet<>();
4976 ranges.add(new UidRange(uid, uid));
4977 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4978 mMockVpn.connect();
4979 mMockVpn.setUids(ranges);
4980 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
4981
4982 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
4983 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
4984 assertTrue(nc.hasTransport(TRANSPORT_VPN));
4985 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
4986 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
4987 // By default, VPN is set to track default network (i.e. its underlying networks is null).
4988 // In case of no default network, VPN is considered metered.
4989 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
4990
4991 // Connect to Cell; Cell is the default network.
4992 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4993 mCellNetworkAgent.connect(true);
4994
4995 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4996 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
4997 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4998 vpnNetworkAgent);
4999
5000 // Connect to WiFi; WiFi is the new default.
5001 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5002 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5003 mWiFiNetworkAgent.connect(true);
5004
5005 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5006 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5007 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5008 vpnNetworkAgent);
5009
5010 // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
5011 // the capabilities.
5012 mCellNetworkAgent.disconnect();
5013
5014 // Disconnect wifi too. Now we have no default network.
5015 mWiFiNetworkAgent.disconnect();
5016
5017 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5018 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5019 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5020 vpnNetworkAgent);
5021
5022 mMockVpn.disconnect();
5023 }
5024
5025 @Test
Varun Anandc51b06d2019-02-25 17:22:02 -08005026 public void testIsActiveNetworkMeteredOverWifi() {
5027 // Returns true by default when no network is available.
5028 assertTrue(mCm.isActiveNetworkMetered());
5029 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5030 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5031 mWiFiNetworkAgent.connect(true);
5032 waitForIdle();
5033
5034 assertFalse(mCm.isActiveNetworkMetered());
5035 }
5036
5037 @Test
5038 public void testIsActiveNetworkMeteredOverCell() {
5039 // Returns true by default when no network is available.
5040 assertTrue(mCm.isActiveNetworkMetered());
5041 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5042 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5043 mCellNetworkAgent.connect(true);
5044 waitForIdle();
5045
5046 assertTrue(mCm.isActiveNetworkMetered());
5047 }
5048
5049 @Test
5050 public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() {
5051 // Returns true by default when no network is available.
5052 assertTrue(mCm.isActiveNetworkMetered());
5053 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5054 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5055 mCellNetworkAgent.connect(true);
5056 waitForIdle();
5057 assertTrue(mCm.isActiveNetworkMetered());
5058
5059 // Connect VPN network. By default it is using current default network (Cell).
5060 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5061 final ArraySet<UidRange> ranges = new ArraySet<>();
5062 final int uid = Process.myUid();
5063 ranges.add(new UidRange(uid, uid));
5064 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5065 mMockVpn.setUids(ranges);
5066 vpnNetworkAgent.connect(true);
5067 mMockVpn.connect();
5068 waitForIdle();
5069 // Ensure VPN is now the active network.
5070 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5071
5072 // Expect VPN to be metered.
5073 assertTrue(mCm.isActiveNetworkMetered());
5074
5075 // Connect WiFi.
5076 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5077 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5078 mWiFiNetworkAgent.connect(true);
5079 waitForIdle();
5080 // VPN should still be the active network.
5081 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5082
5083 // Expect VPN to be unmetered as it should now be using WiFi (new default).
5084 assertFalse(mCm.isActiveNetworkMetered());
5085
5086 // Disconnecting Cell should not affect VPN's meteredness.
5087 mCellNetworkAgent.disconnect();
5088 waitForIdle();
5089
5090 assertFalse(mCm.isActiveNetworkMetered());
5091
5092 // Disconnect WiFi; Now there is no platform default network.
5093 mWiFiNetworkAgent.disconnect();
5094 waitForIdle();
5095
5096 // VPN without any underlying networks is treated as metered.
5097 assertTrue(mCm.isActiveNetworkMetered());
5098
5099 vpnNetworkAgent.disconnect();
5100 mMockVpn.disconnect();
5101 }
5102
5103 @Test
5104 public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() {
5105 // Returns true by default when no network is available.
5106 assertTrue(mCm.isActiveNetworkMetered());
5107 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5108 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5109 mCellNetworkAgent.connect(true);
5110 waitForIdle();
5111 assertTrue(mCm.isActiveNetworkMetered());
5112
5113 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5114 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5115 mWiFiNetworkAgent.connect(true);
5116 waitForIdle();
5117 assertFalse(mCm.isActiveNetworkMetered());
5118
5119 // Connect VPN network.
5120 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5121 final ArraySet<UidRange> ranges = new ArraySet<>();
5122 final int uid = Process.myUid();
5123 ranges.add(new UidRange(uid, uid));
5124 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5125 mMockVpn.setUids(ranges);
5126 vpnNetworkAgent.connect(true);
5127 mMockVpn.connect();
5128 waitForIdle();
5129 // Ensure VPN is now the active network.
5130 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5131 // VPN is using Cell
5132 mService.setUnderlyingNetworksForVpn(
5133 new Network[] { mCellNetworkAgent.getNetwork() });
5134 waitForIdle();
5135
5136 // Expect VPN to be metered.
5137 assertTrue(mCm.isActiveNetworkMetered());
5138
5139 // VPN is now using WiFi
5140 mService.setUnderlyingNetworksForVpn(
5141 new Network[] { mWiFiNetworkAgent.getNetwork() });
5142 waitForIdle();
5143
5144 // Expect VPN to be unmetered
5145 assertFalse(mCm.isActiveNetworkMetered());
5146
5147 // VPN is using Cell | WiFi.
5148 mService.setUnderlyingNetworksForVpn(
5149 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5150 waitForIdle();
5151
5152 // Expect VPN to be metered.
5153 assertTrue(mCm.isActiveNetworkMetered());
5154
5155 // VPN is using WiFi | Cell.
5156 mService.setUnderlyingNetworksForVpn(
5157 new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
5158 waitForIdle();
5159
5160 // Order should not matter and VPN should still be metered.
5161 assertTrue(mCm.isActiveNetworkMetered());
5162
5163 // VPN is not using any underlying networks.
5164 mService.setUnderlyingNetworksForVpn(new Network[0]);
5165 waitForIdle();
5166
5167 // VPN without underlying networks is treated as metered.
5168 assertTrue(mCm.isActiveNetworkMetered());
5169
5170 vpnNetworkAgent.disconnect();
5171 mMockVpn.disconnect();
5172 }
5173
5174 @Test
5175 public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() {
5176 // Returns true by default when no network is available.
5177 assertTrue(mCm.isActiveNetworkMetered());
5178 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5179 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5180 mWiFiNetworkAgent.connect(true);
5181 waitForIdle();
5182 assertFalse(mCm.isActiveNetworkMetered());
5183
5184 // Connect VPN network.
5185 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5186 final ArraySet<UidRange> ranges = new ArraySet<>();
5187 final int uid = Process.myUid();
5188 ranges.add(new UidRange(uid, uid));
5189 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5190 mMockVpn.setUids(ranges);
5191 vpnNetworkAgent.connect(true);
5192 mMockVpn.connectAsAlwaysMetered();
5193 waitForIdle();
5194 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5195
5196 // VPN is tracking current platform default (WiFi).
5197 mService.setUnderlyingNetworksForVpn(null);
5198 waitForIdle();
5199
5200 // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
5201 assertTrue(mCm.isActiveNetworkMetered());
5202
5203 // VPN explicitly declares WiFi as its underlying network.
5204 mService.setUnderlyingNetworksForVpn(
5205 new Network[] { mWiFiNetworkAgent.getNetwork() });
5206 waitForIdle();
5207
5208 // Doesn't really matter whether VPN declares its underlying networks explicitly.
5209 assertTrue(mCm.isActiveNetworkMetered());
5210
5211 // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
5212 // anyways suppose to be metered.
5213 mWiFiNetworkAgent.disconnect();
5214 waitForIdle();
5215
5216 assertTrue(mCm.isActiveNetworkMetered());
5217
5218 vpnNetworkAgent.disconnect();
5219 }
5220
5221 @Test
Mike Yuf9729752018-08-17 15:22:05 +08005222 public void testNetworkBlockedStatus() {
5223 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5224 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5225 .addTransportType(TRANSPORT_CELLULAR)
5226 .build();
5227 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
5228
5229 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5230 mCellNetworkAgent.connect(true);
5231 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5232
5233 mService.setUidRulesChanged(RULE_REJECT_ALL);
5234 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5235
5236 // ConnectivityService should cache it not to invoke the callback again.
5237 mService.setUidRulesChanged(RULE_REJECT_METERED);
5238 cellNetworkCallback.assertNoCallback();
5239
5240 mService.setUidRulesChanged(RULE_NONE);
5241 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5242
5243 mService.setUidRulesChanged(RULE_REJECT_METERED);
5244 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5245
5246 // Restrict the network based on UID rule and NOT_METERED capability change.
5247 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5248 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5249 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5250 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5251 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
5252 mCellNetworkAgent);
5253 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5254 mService.setUidRulesChanged(RULE_ALLOW_METERED);
5255 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5256
5257 mService.setUidRulesChanged(RULE_NONE);
5258 cellNetworkCallback.assertNoCallback();
5259
5260 // Restrict the network based on BackgroundRestricted.
5261 mService.setRestrictBackgroundChanged(true);
5262 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5263 mService.setRestrictBackgroundChanged(true);
5264 cellNetworkCallback.assertNoCallback();
5265 mService.setRestrictBackgroundChanged(false);
5266 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5267 cellNetworkCallback.assertNoCallback();
5268
5269 mCm.unregisterNetworkCallback(cellNetworkCallback);
5270 }
5271
5272 @Test
5273 public void testNetworkBlockedStatusBeforeAndAfterConnect() {
5274 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5275 mCm.registerDefaultNetworkCallback(defaultCallback);
5276
5277 // No Networkcallbacks invoked before any network is active.
5278 mService.setUidRulesChanged(RULE_REJECT_ALL);
5279 mService.setUidRulesChanged(RULE_NONE);
5280 mService.setUidRulesChanged(RULE_REJECT_METERED);
5281 defaultCallback.assertNoCallback();
5282
5283 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5284 mCellNetworkAgent.connect(true);
5285 defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
5286 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
5287
5288 // Allow to use the network after switching to NOT_METERED network.
5289 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5290 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5291 mWiFiNetworkAgent.connect(true);
5292 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
5293
5294 // Switch to METERED network. Restrict the use of the network.
5295 mWiFiNetworkAgent.disconnect();
5296 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
5297 defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
5298
5299 // Network becomes NOT_METERED.
5300 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5301 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5302 defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5303
5304 // Verify there's no Networkcallbacks invoked after data saver on/off.
5305 mService.setRestrictBackgroundChanged(true);
5306 mService.setRestrictBackgroundChanged(false);
5307 defaultCallback.assertNoCallback();
5308
5309 mCellNetworkAgent.disconnect();
5310 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
5311 defaultCallback.assertNoCallback();
5312
5313 mCm.unregisterNetworkCallback(defaultCallback);
5314 }
5315
junyulai4a192e22018-06-13 15:00:37 +08005316 /**
5317 * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
5318 */
5319 private InterfaceConfiguration getClatInterfaceConfig(LinkAddress la) {
5320 InterfaceConfiguration cfg = new InterfaceConfiguration();
5321 cfg.setHardwareAddress("11:22:33:44:55:66");
5322 cfg.setLinkAddress(la);
5323 return cfg;
5324 }
5325
5326 /**
5327 * Make expected stack link properties, copied from Nat464Xlat.
5328 */
5329 private LinkProperties makeClatLinkProperties(LinkAddress la) {
5330 LinkAddress clatAddress = la;
5331 LinkProperties stacked = new LinkProperties();
5332 stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME);
5333 RouteInfo ipv4Default = new RouteInfo(
5334 new LinkAddress(Inet4Address.ANY, 0),
5335 clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME);
5336 stacked.addRoute(ipv4Default);
5337 stacked.addLinkAddress(clatAddress);
5338 return stacked;
5339 }
5340
5341 @Test
5342 public void testStackedLinkProperties() throws UnknownHostException, RemoteException {
5343 final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
5344 final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005345 final String kNat64PrefixString = "2001:db8:64:64:64:64::";
5346 final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
5347
junyulai4a192e22018-06-13 15:00:37 +08005348 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5349 .addTransportType(TRANSPORT_CELLULAR)
5350 .addCapability(NET_CAPABILITY_INTERNET)
5351 .build();
5352 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5353 mCm.registerNetworkCallback(networkRequest, networkCallback);
5354
Lorenzo Colittid593e292019-02-19 13:21:56 +09005355 // Prepare ipv6 only link properties.
junyulai4a192e22018-06-13 15:00:37 +08005356 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005357 final int cellNetId = mCellNetworkAgent.getNetwork().netId;
junyulai4a192e22018-06-13 15:00:37 +08005358 final LinkProperties cellLp = new LinkProperties();
5359 cellLp.setInterfaceName(MOBILE_IFNAME);
5360 cellLp.addLinkAddress(myIpv6);
5361 cellLp.addRoute(new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME));
5362 cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME));
5363 reset(mNetworkManagementService);
5364 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
5365 .thenReturn(getClatInterfaceConfig(myIpv4));
5366
Lorenzo Colittid593e292019-02-19 13:21:56 +09005367 // Connect with ipv6 link properties. Expect prefix discovery to be started.
junyulai4a192e22018-06-13 15:00:37 +08005368 mCellNetworkAgent.sendLinkProperties(cellLp);
5369 mCellNetworkAgent.connect(true);
5370 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005371 verify(mMockNetd, times(1)).resolverStartPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005372
Lorenzo Colittid593e292019-02-19 13:21:56 +09005373 // Switching default network updates TCP buffer sizes.
5374 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
5375
5376 // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
5377 // the NAT64 prefix was removed because one was never discovered.
5378 cellLp.addLinkAddress(myIpv4);
5379 mCellNetworkAgent.sendLinkProperties(cellLp);
5380 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
5381 verify(mMockNetd, times(1)).resolverStopPrefix64Discovery(cellNetId);
5382
5383 verifyNoMoreInteractions(mMockNetd);
5384 reset(mMockNetd);
5385
5386 // Remove IPv4 address. Expect prefix discovery to be started again.
5387 cellLp.removeLinkAddress(myIpv4);
5388 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5389 mCellNetworkAgent.sendLinkProperties(cellLp);
5390 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
5391 verify(mMockNetd, times(1)).resolverStartPrefix64Discovery(cellNetId);
5392
5393 // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005394 Nat464Xlat clat = mService.getNat464Xlat(mCellNetworkAgent);
5395 assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
Lorenzo Colittid593e292019-02-19 13:21:56 +09005396 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
5397 kNat64PrefixString, 96);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005398 LinkProperties lpBeforeClat = (LinkProperties) networkCallback.expectCallback(
5399 CallbackState.LINK_PROPERTIES, mCellNetworkAgent).arg;
5400 assertEquals(0, lpBeforeClat.getStackedLinks().size());
5401 assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
5402 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
5403
5404 // Clat iface comes up. Expect stacked link to be added.
junyulai4a192e22018-06-13 15:00:37 +08005405 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Lorenzo Colitti2412c132019-01-22 09:47:54 +09005406 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08005407 List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
5408 .getStackedLinks();
5409 assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
5410
5411 // Change trivial linkproperties and see if stacked link is preserved.
5412 cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
5413 mCellNetworkAgent.sendLinkProperties(cellLp);
junyulai4a192e22018-06-13 15:00:37 +08005414 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
5415
5416 List<LinkProperties> stackedLpsAfterChange =
5417 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
5418 assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
5419 assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
5420
Lorenzo Colittid593e292019-02-19 13:21:56 +09005421 // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
5422 // linkproperties are cleaned up.
junyulai4a192e22018-06-13 15:00:37 +08005423 cellLp.addLinkAddress(myIpv4);
5424 cellLp.addRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5425 mCellNetworkAgent.sendLinkProperties(cellLp);
junyulai4a192e22018-06-13 15:00:37 +08005426 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colitti9307ca22019-01-12 01:54:23 +09005427 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005428 verify(mMockNetd, times(1)).resolverStopPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005429
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005430 // As soon as stop is called, the linkproperties lose the stacked interface.
Lorenzo Colittid593e292019-02-19 13:21:56 +09005431 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005432 LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
5433 LinkProperties expected = new LinkProperties(cellLp);
5434 expected.setNat64Prefix(kNat64Prefix);
5435 assertEquals(expected, actualLpAfterIpv4);
5436 assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
5437
5438 // The interface removed callback happens but has no effect after stop is called.
5439 clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
5440 networkCallback.assertNoCallback();
5441
Lorenzo Colittid593e292019-02-19 13:21:56 +09005442 verifyNoMoreInteractions(mMockNetd);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005443 reset(mMockNetd);
5444
Lorenzo Colittid593e292019-02-19 13:21:56 +09005445 // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
5446 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
5447 kNat64PrefixString, 96);
5448 networkCallback.expectLinkPropertiesLike((lp) -> lp.getNat64Prefix() == null,
5449 mCellNetworkAgent);
5450
5451 // Remove IPv4 address and expect prefix discovery and clatd to be started again.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005452 cellLp.removeLinkAddress(myIpv4);
5453 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5454 cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
5455 mCellNetworkAgent.sendLinkProperties(cellLp);
5456 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005457 verify(mMockNetd, times(1)).resolverStartPrefix64Discovery(cellNetId);
5458 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
5459 kNat64PrefixString, 96);
5460 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005461 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
5462
Lorenzo Colittid593e292019-02-19 13:21:56 +09005463
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005464 // Clat iface comes up. Expect stacked link to be added.
5465 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005466 networkCallback.expectLinkPropertiesLike(
5467 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null,
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005468 mCellNetworkAgent);
5469
5470 // NAT64 prefix is removed. Expect that clat is stopped.
Lorenzo Colittid593e292019-02-19 13:21:56 +09005471 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
5472 kNat64PrefixString, 96);
5473 networkCallback.expectLinkPropertiesLike(
5474 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null,
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005475 mCellNetworkAgent);
5476 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
5477 networkCallback.expectLinkPropertiesLike((lp) -> lp.getStackedLinks().size() == 0,
5478 mCellNetworkAgent);
5479
5480 // Clean up.
junyulai4a192e22018-06-13 15:00:37 +08005481 mCellNetworkAgent.disconnect();
Lorenzo Colitti2412c132019-01-22 09:47:54 +09005482 networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
5483 networkCallback.assertNoCallback();
junyulai4a192e22018-06-13 15:00:37 +08005484 mCm.unregisterNetworkCallback(networkCallback);
5485 }
Chiachang Wanga6093042018-09-28 22:42:48 +08005486
5487 @Test
5488 public void testDataActivityTracking() throws RemoteException {
5489 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5490 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5491 .addCapability(NET_CAPABILITY_INTERNET)
5492 .build();
5493 mCm.registerNetworkCallback(networkRequest, networkCallback);
5494
5495 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5496 final LinkProperties cellLp = new LinkProperties();
5497 cellLp.setInterfaceName(MOBILE_IFNAME);
5498 mCellNetworkAgent.sendLinkProperties(cellLp);
5499 reset(mNetworkManagementService);
5500 mCellNetworkAgent.connect(true);
5501 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5502 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
5503 eq(ConnectivityManager.TYPE_MOBILE));
5504
5505 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5506 final LinkProperties wifiLp = new LinkProperties();
5507 wifiLp.setInterfaceName(WIFI_IFNAME);
5508 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
5509
5510 // Network switch
5511 reset(mNetworkManagementService);
5512 mWiFiNetworkAgent.connect(true);
5513 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5514 networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
5515 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5516 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
5517 eq(ConnectivityManager.TYPE_WIFI));
5518 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
5519
5520 // Disconnect wifi and switch back to cell
5521 reset(mNetworkManagementService);
5522 mWiFiNetworkAgent.disconnect();
5523 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
5524 assertNoCallbacks(networkCallback);
5525 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
5526 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
5527 eq(ConnectivityManager.TYPE_MOBILE));
5528
5529 // reconnect wifi
5530 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5531 wifiLp.setInterfaceName(WIFI_IFNAME);
5532 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
5533 mWiFiNetworkAgent.connect(true);
5534 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5535 networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
5536 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5537
5538 // Disconnect cell
5539 reset(mNetworkManagementService);
5540 mCellNetworkAgent.disconnect();
5541 networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
5542 // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
5543 // sent as network being switched. Ensure rule removal for cell will not be triggered
5544 // unexpectedly before network being removed.
5545 waitForIdle();
5546 verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
5547 verify(mNetworkManagementService, times(1)).removeNetwork(
5548 eq(mCellNetworkAgent.getNetwork().netId));
5549
5550 // Disconnect wifi
5551 ConditionVariable cv = waitForConnectivityBroadcasts(1);
5552 reset(mNetworkManagementService);
5553 mWiFiNetworkAgent.disconnect();
5554 waitFor(cv);
5555 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
5556
5557 // Clean up
5558 mCm.unregisterNetworkCallback(networkCallback);
5559 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005560
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005561 private void verifyTcpBufferSizeChange(String tcpBufferSizes) {
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005562 String[] values = tcpBufferSizes.split(",");
5563 String rmemValues = String.join(" ", values[0], values[1], values[2]);
5564 String wmemValues = String.join(" ", values[3], values[4], values[5]);
5565 waitForIdle();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005566 try {
5567 verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
5568 } catch (RemoteException e) {
5569 fail("mMockNetd should never throw RemoteException");
5570 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005571 reset(mMockNetd);
5572 }
5573
5574 @Test
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005575 public void testTcpBufferReset() {
5576 final String testTcpBufferSizes = "1,2,3,4,5,6";
5577
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005578 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5579 reset(mMockNetd);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005580 // Switching default network updates TCP buffer sizes.
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005581 mCellNetworkAgent.connect(false);
5582 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
5583
5584 // Change link Properties should have updated tcp buffer size.
5585 LinkProperties lp = new LinkProperties();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005586 lp.setTcpBufferSizes(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005587 mCellNetworkAgent.sendLinkProperties(lp);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005588 verifyTcpBufferSizeChange(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005589 }
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005590
5591 @Test
5592 public void testGetGlobalProxyForNetwork() {
5593 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
5594 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5595 final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
5596 when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
5597 assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
5598 }
5599
5600 @Test
5601 public void testGetProxyForActiveNetwork() {
5602 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
5603 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5604 mWiFiNetworkAgent.connect(true);
5605 waitForIdle();
5606 assertNull(mService.getProxyForNetwork(null));
5607
5608 final LinkProperties testLinkProperties = new LinkProperties();
5609 testLinkProperties.setHttpProxy(testProxyInfo);
5610
5611 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
5612 waitForIdle();
5613
5614 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
5615 }
5616
5617 @Test
5618 public void testGetProxyForVPN() {
5619 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
5620
5621 // Set up a WiFi network with no proxy
5622 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5623 mWiFiNetworkAgent.connect(true);
5624 waitForIdle();
5625 assertNull(mService.getProxyForNetwork(null));
5626
5627 // Set up a VPN network with a proxy
5628 final int uid = Process.myUid();
5629 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5630 final ArraySet<UidRange> ranges = new ArraySet<>();
5631 ranges.add(new UidRange(uid, uid));
5632 mMockVpn.setUids(ranges);
5633 LinkProperties testLinkProperties = new LinkProperties();
5634 testLinkProperties.setHttpProxy(testProxyInfo);
5635 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
5636 waitForIdle();
5637
5638 // Connect to VPN with proxy
5639 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5640 vpnNetworkAgent.connect(true);
5641 mMockVpn.connect();
5642 waitForIdle();
5643
5644 // Test that the VPN network returns a proxy, and the WiFi does not.
5645 assertEquals(testProxyInfo, mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
5646 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
5647 assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
5648
5649 // Test that the VPN network returns no proxy when it is set to null.
5650 testLinkProperties.setHttpProxy(null);
5651 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
5652 waitForIdle();
5653 assertNull(mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
5654 assertNull(mService.getProxyForNetwork(null));
5655
5656 // Set WiFi proxy and check that the vpn proxy is still null.
5657 testLinkProperties.setHttpProxy(testProxyInfo);
5658 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
5659 waitForIdle();
5660 assertNull(mService.getProxyForNetwork(null));
5661
5662 // Disconnect from VPN and check that the active network, which is now the WiFi, has the
5663 // correct proxy setting.
5664 vpnNetworkAgent.disconnect();
5665 waitForIdle();
5666 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5667 assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
5668 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
5669 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07005670}